国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java使用Nashorn,調(diào)用Promise實(shí)現(xiàn)服務(wù)端渲染

Hwg / 890人閱讀

摘要:未來(lái)的主要發(fā)布基于。在中調(diào)用函數(shù)支持從代碼中直接調(diào)用定義在腳本文件中的函數(shù)。內(nèi)置了方法,提調(diào)用函數(shù)并返回結(jié)果。當(dāng)向方法傳遞新的時(shí),我們會(huì)在控制臺(tái)看到預(yù)期的結(jié)果實(shí)戰(zhàn)通過(guò)使用實(shí)現(xiàn)服務(wù)端渲染。工具類實(shí)例化工具類,通過(guò)該類操作對(duì)象。

Nashorn JavaScript引擎是Java SE 8 的一部分,并且和其它獨(dú)立的引擎例如 Google V8(用于Google Chrome和Node.js的引擎)互相競(jìng)爭(zhēng)。Nashorn通過(guò)在JVM上,以原生方式運(yùn)行動(dòng)態(tài)的JavaScript代碼來(lái)擴(kuò)展Java的功能。

使用Nashorn

Java代碼中簡(jiǎn)單的HelloWorld如下所示:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval("print("Hello World!");");

為了在Java中執(zhí)行JavaScript,你首先要通過(guò)javax.script包創(chuàng)建腳本引擎。
JavaScript代碼既可以通過(guò)傳遞JavaScript代碼字符串,也可以傳遞指向你的JS腳本文件的FileReader來(lái)執(zhí)行:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval(new FileReader("script.js"));

Nashorn JavaScript基于 ECMAScript 5.1,但是它的后續(xù)版本會(huì)對(duì)ES6提供支持:

Nashorn的當(dāng)前策略遵循ECMAScript規(guī)范。當(dāng)我們?cè)贘DK8中發(fā)布它時(shí),它將基于ECMAScript 5.1。Nashorn未來(lái)的主要發(fā)布基于ECMAScript 6。
在Java中調(diào)用JavaScript函數(shù)

Nashorn 支持從Java代碼中直接調(diào)用定義在腳本文件中的JavaScript函數(shù)。你可以將Java對(duì)象傳遞為函數(shù)參數(shù),并且從函數(shù)返回?cái)?shù)據(jù)來(lái)調(diào)用Java方法。

var fun1 = function(name) {
    print("Hi there from Javascript, " + name);
    return "greetings from javascript";
};

var fun2 = function (object) {
    print("JS Class Definition: " + Object.prototype.toString.call(object));
};

ScriptEngine內(nèi)置了invokeFunction方法,提調(diào)用javascript函數(shù)并返回結(jié)果。

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval(new FileReader("script.js"));

Object result = invocable.invokeFunction("fun1", "Peter Parker");
System.out.println(result);
System.out.println(result.getClass());

// Hi there from Javascript, Peter Parker
// greetings from javascript
// class java.lang.String
在JavaScript中調(diào)用Java方法

在JavaScript中調(diào)用Java方法十分容易。我們首先需要定義一個(gè)Java靜態(tài)方法。

static String fun1(String name) {
    System.out.format("Hi there from Java, %s", name);
    return "greetings from java";
}

Java類可以通過(guò)Java.typeAPI擴(kuò)展在JavaScript中引用。它就和Java代碼中的import類似。只要定義了Java類型,我們就可以自然地調(diào)用靜態(tài)方法fun1(),然后像sout打印信息。由于方法是靜態(tài)的,我們不需要首先創(chuàng)建實(shí)例。

var MyJavaClass = Java.type("my.package.MyJavaClass");

var result = MyJavaClass.fun1("John Doe");
print(result);

// Hi there from Java, John Doe
// greetings from java

在使用JavaScript原生類型調(diào)用Java方法時(shí),Nashorn 如何處理類型轉(zhuǎn)換?讓我們通過(guò)簡(jiǎn)單的例子來(lái)弄清楚。
下面的Java方法簡(jiǎn)單打印了方法參數(shù)的實(shí)際類型:

static void fun2(Object object) {
    System.out.println(object.getClass());
}

為了理解背后如何處理類型轉(zhuǎn)換,我們使用不同的JavaScript類型來(lái)調(diào)用這個(gè)方法:

MyJavaClass.fun2(123);
// class java.lang.Integer

MyJavaClass.fun2(49.99);
// class java.lang.Double

MyJavaClass.fun2(true);
// class java.lang.Boolean

MyJavaClass.fun2("hi there")
// class java.lang.String

MyJavaClass.fun2(new Number(23));
// class jdk.nashorn.internal.objects.NativeNumber

MyJavaClass.fun2(new Date());
// class jdk.nashorn.internal.objects.NativeDate

MyJavaClass.fun2(new RegExp());
// class jdk.nashorn.internal.objects.NativeRegExp

MyJavaClass.fun2({foo: "bar"});
// class jdk.nashorn.internal.scripts.JO4

JavaScript原始類型轉(zhuǎn)換為合適的Java包裝類,而JavaScript原生對(duì)象會(huì)使用內(nèi)部的適配器類來(lái)表示。要記住jdk.nashorn.internal中的類可能會(huì)有所變化,所以不應(yīng)該在客戶端面向這些類來(lái)編程。

ScriptObjectMirror

在向Java傳遞原生JavaScript對(duì)象時(shí),你可以使用ScriptObjectMirror類,它實(shí)際上是底層JavaScript對(duì)象的Java表示。ScriptObjectMirror實(shí)現(xiàn)了Map接口,位于jdk.nashorn.api中。這個(gè)包中的類可以用于客戶端代碼。

下面的例子將參數(shù)類型從Object改為ScriptObjectMirror,所以我們可以從傳入的JavaScript對(duì)象中獲得一些信息。

static void fun3(ScriptObjectMirror mirror) {
    System.out.println(mirror.getClassName() + ": " +
        Arrays.toString(mirror.getOwnKeys(true)));
}

當(dāng)向這個(gè)方法傳遞對(duì)象(哈希表)時(shí),在Java端可以訪問(wèn)其屬性:

MyJavaClass.fun3({
    foo: "bar",
    bar: "foo"
});

// Object: [foo, bar]

我們也可以在Java中調(diào)用JavaScript的成員函數(shù)。讓我們首先定義JavaScript Person類型,帶有屬性firstNamelastName,以及方法getFullName

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.getFullName = function() {
        return this.firstName + " " + this.lastName;
    }
}

JavaScript方法getFullName可以通過(guò)callMember()ScriptObjectMirror上調(diào)用。

static void fun4(ScriptObjectMirror person) {
    System.out.println("Full Name is: " + person.callMember("getFullName"));
}

當(dāng)向Java方法傳遞新的Person時(shí),我們會(huì)在控制臺(tái)看到預(yù)期的結(jié)果:

var person1 = new Person("Peter", "Parker");
MyJavaClass.fun4(person1);

// Full Name is: Peter Parker
實(shí)戰(zhàn)

通過(guò)使用promise實(shí)現(xiàn)服務(wù)端渲染。

polyfill

由于當(dāng)前Nashorn基于es5,不支持部分es6對(duì)象,我們需要引入polyfill文件,nashorn-polyfill。
該polyfill通過(guò)java與JavaScript的結(jié)合使用,使Nashorn支持console, process, Blob, Promise等對(duì)象和setTimeout, clearTimeout, setInterval, clearInterval等函數(shù)。

Nashorn工具類

實(shí)例化工具類,通過(guò)該類操作Javascript對(duì)象。

public class NashornHelper {

    /**
     * 用于本類的日志
     */
    private static final Logger       logger                       = LoggerFactory.getLogger(NashornHelper.class);

    private static final String       JAVASCRIPT_DIR               = "static"; // js文件目錄

    private static final String       LIB_DIR                      = JAVASCRIPT_DIR + File.separator + "lib";

    private static final String[]     VENDOR_FILE_NAME             = {"vendor.js"}; // webpack打包的三方庫(kù),如react,lodash

    private static final String       SRC_DIR                      = JAVASCRIPT_DIR + File.separator + "src"; // 文件目錄

    private static final String       POLYFILL_FILE_NAME           = "nashorn-polyfill.js";

    private final NashornScriptEngine engine;

    private static NashornHelper      nashornHelper;

    private static ScriptContext            sc                        = new SimpleScriptContext();

    private static ScheduledExecutorService globalScheduledThreadPool = Executors.newScheduledThreadPool(20);

    // 單例模式
    public static synchronized NashornHelper getInstance() {
        if (nashornHelper == null) {
            long start = System.currentTimeMillis();
            nashornHelper = new NashornHelper();
            long end = System.currentTimeMillis();
            logger.error("init nashornHelper cost time {}ms", (end - start));
        }
        return nashornHelper;
    }

    private NashornHelper(){
        long start = System.currentTimeMillis();
        engine = (NashornScriptEngine) new ScriptEngineManager().getEngineByName("nashorn");
        Bindings bindings = new SimpleBindings();
        bindings.put("logger", logger); // 向nashorn引擎注入logger對(duì)象
        sc.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
        sc.getBindings(ScriptContext.ENGINE_SCOPE).putAll(bindings);
        sc.setAttribute("__IS_SSR__", true, ScriptContext.ENGINE_SCOPE);
        sc.setAttribute("__NASHORN_POLYFILL_TIMER__", globalScheduledThreadPool, ScriptContext.ENGINE_SCOPE);
        engine.setBindings(sc.getBindings(ScriptContext.ENGINE_SCOPE), ScriptContext.ENGINE_SCOPE);

        long end = System.currentTimeMillis();
        logger.info("init nashornHelper cost time {}ms", (end - start));

        try {  // 執(zhí)行js文件
            engine.eval(read(LIB_DIR + File.separator + POLYFILL_FILE_NAME));
            for (String fileName : NashornHelper.VENDOR_FILE_NAME) {
                engine.eval(read(SRC_DIR + File.separator + fileName));
            }
            engine.eval(read(SRC_DIR + File.separator + "app.js"));
        } catch (ScriptException e) {
            logger.error("load javascript failed.", e);
        }
    }
    // 獲取Nashorn作用域下的對(duì)象
    public ScriptObjectMirror getGlobalGlobalMirrorObject(String objectName) {
        return (ScriptObjectMirror) engine.getBindings(ScriptContext.ENGINE_SCOPE).get(objectName);
    }
    // 調(diào)用全局方法
    public Object callRender(String methodName, Object... input) {
        try {
            return engine.invokeFunction(methodName, input);
        } catch (ScriptException e) {
            logger.error("run javascript failed.", e);
            return null;
        } catch (NoSuchMethodException e) {
            logger.error("no such method.", e);
            return null;
        }
    }
    // 讀取文件
    private Reader read(String path) {
        InputStream in = getClass().getClassLoader().getResourceAsStream(path);
        return new InputStreamReader(in);
    }

實(shí)例化工具類

NashornHelper engine = NashornHelper.getInstance();

執(zhí)行調(diào)用javasript,java中獲取promise對(duì)象

ScriptObjectMirror promise = (ScriptObjectMirror) engine.callRender("ssr_render");

執(zhí)行promisethen方法,等待執(zhí)行完成并回調(diào)

    promise.callMember("then", fnResolve);
    ScriptObjectMirror nashornEventLoop = engine.getGlobalGlobalMirrorObject("nashornEventLoop");

    nashornEventLoop.callMember("process"); // 執(zhí)行nashornEventLoops.process()使主線程執(zhí)行回調(diào)函數(shù)
    int i = 0;
    int jsWaitTimeout = 1000 * 60;
    int interval = 200; // 等待時(shí)間間隔
    int totalWaitTime = 0; // 實(shí)際等待時(shí)間
    while (!promiseResolved && totalWaitTime < jsWaitTimeout) {
        nashornEventLoop.callMember("process");
        try {
            Thread.sleep(interval);
        } catch (InterruptedException e) {
        }
        totalWaitTime = totalWaitTime + interval;
        if (interval < 500) interval = interval * 2;
        i = i + 1;
    }

回調(diào)函數(shù)

  private Consumer fnResolve = object -> {
    synchronized (promiseLock) {
        html = (String) object;
        promiseResolved = true;
    }
  };

最后結(jié)果已字符串形式存在html中,可將其渲染到頁(yè)面中.

最后

適用場(chǎng)景非瀏覽器渲染頁(yè)面,如java離線渲染前端頁(yè)面到Pdf。
實(shí)戰(zhàn) github地址, 前端js項(xiàng)目地址

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/92615.html

相關(guān)文章

  • Java使用Nashorn調(diào)用Promise實(shí)現(xiàn)服務(wù)渲染

    摘要:未來(lái)的主要發(fā)布基于。在中調(diào)用函數(shù)支持從代碼中直接調(diào)用定義在腳本文件中的函數(shù)。內(nèi)置了方法,提調(diào)用函數(shù)并返回結(jié)果。當(dāng)向方法傳遞新的時(shí),我們會(huì)在控制臺(tái)看到預(yù)期的結(jié)果實(shí)戰(zhàn)通過(guò)使用實(shí)現(xiàn)服務(wù)端渲染。工具類實(shí)例化工具類,通過(guò)該類操作對(duì)象。 Nashorn JavaScript引擎是Java SE 8 的一部分,并且和其它獨(dú)立的引擎例如 Google V8(用于Google Chrome和Node.j...

    SimonMa 評(píng)論0 收藏0
  • [譯] Java 8 Nashorn 教程

    摘要:未來(lái)的主要發(fā)布基于。在中調(diào)用函數(shù)支持從代碼中直接調(diào)用定義在腳本文件中的函數(shù)。下面的函數(shù)稍后會(huì)在端調(diào)用為了調(diào)用函數(shù),你首先需要將腳本引擎轉(zhuǎn)換為。調(diào)用函數(shù)將結(jié)果輸出到,所以我們會(huì)首先看到輸出。幸運(yùn)的是,有一套補(bǔ)救措施。 原文:Java 8 Nashorn Tutorial 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 這個(gè)教程中,你會(huì)通過(guò)簡(jiǎn)單易懂的代碼示例,來(lái)了解Nashorn Ja...

    _ivan 評(píng)論0 收藏0
  • [譯] 在 Nashron 中使用 Backbone.js

    摘要:原文譯者飛龍協(xié)議這個(gè)例子展示了如何在的引擎中使用模型。在年三月首次作為的一部分發(fā)布,并通過(guò)以原生方式在上運(yùn)行腳本擴(kuò)展了的功能。將二者放在一起下一個(gè)目標(biāo)是在中,例如在服務(wù)器上復(fù)用模型。最后,我們?cè)谥姓{(diào)用函數(shù)。總結(jié)在中復(fù)用現(xiàn)存的庫(kù)十分簡(jiǎn)單。 原文:Using Backbone.js with Nashorn 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 這個(gè)例子展示了如何在Java8...

    tabalt 評(píng)論0 收藏0
  • [譯] 在 Nashron 中使用 Backbone.js

    摘要:原文譯者飛龍協(xié)議這個(gè)例子展示了如何在的引擎中使用模型。在年三月首次作為的一部分發(fā)布,并通過(guò)以原生方式在上運(yùn)行腳本擴(kuò)展了的功能。將二者放在一起下一個(gè)目標(biāo)是在中,例如在服務(wù)器上復(fù)用模型。最后,我們?cè)谥姓{(diào)用函數(shù)。總結(jié)在中復(fù)用現(xiàn)存的庫(kù)十分簡(jiǎn)單。 原文:Using Backbone.js with Nashorn 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 這個(gè)例子展示了如何在Java8...

    gotham 評(píng)論0 收藏0
  • Java9模塊化學(xué)習(xí)筆記一之快速入門

    摘要:如果你想查看運(yùn)行時(shí)模塊的加載過(guò)程輸出結(jié)果表示為模塊,由于我限制了不再往下輸出了,而我們模塊又沒有別的額外依賴,所以僅有這行輸出。 jdk9模塊快速入門 列出自帶模塊:java --list-modulesmac多版本jdk共存:http://adolphor.com/blog/2016...模塊規(guī)則示意圖:showImg(https://segmentfault.com/img/bVb...

    cjie 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<