繁体   English   中英

Java 7 + Rhino 1.7R3支持CommonJS模块?

[英]Java 7 + Rhino 1.7R3 support for CommonJS modules?

我需要帮助让CommonJS使用Java 7和Rhino 1.7R3。

Rhino 1.7R3支持CommonJS模块:

Java 7与Rhino 1.7R3捆绑在一起。 不幸的是,Java 7的Rhino是一个修改版本,它不包括org.mozilla.javascript.commonjs包:

我想通过javax.script API使用Rhino 1.7R3对CommonJS的支持,如下所示:

ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
engine.put("markdown", markdown);
engine.eval("var html = require('./Markdown.Sanitizer').getSanitizingConverter().makeHtml(markdown);");
return (String) engine.get("html");

(我通过ScriptEngineManager验证我确实使用的是Rhino 1.7R3引擎。)我想也许我可以将以下依赖项添加到类路径中

<dependency>
    <groupId>org.mozilla</groupId>
    <artifactId>rhino</artifactId>
    <version>1.7R3</version>
</dependency>

和CommonJS一样, require() - 将开始工作。 但事实并非如此。 当我尝试使用require()我得到了

Caused by: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "require" is not defined. (<Unknown source>#2)
    at sun.org.mozilla.javascript.internal.ScriptRuntime.constructError(ScriptRuntime.java:3773)
    at sun.org.mozilla.javascript.internal.ScriptRuntime.constructError(ScriptRuntime.java:3751)
    at sun.org.mozilla.javascript.internal.ScriptRuntime.notFoundError(ScriptRuntime.java:3836)

如何让Java 7与完整版Rhino 1.7R3一起使用,以便获得CommonJS支持?

编辑:我发现了以下问题,它涉及完全相同的主题:

完整性检查:Rhino没有require函数,对吧?

受访者表示也许可以用CommonJS Rhino 1.7R3替换有限的Rhino 1.7R3,但没有说明如何做到这一点。 这就是我在这里问的问题。

编辑 :看起来你毕竟不需要使用JVM引导程序类加载器。 Sun已将默认的Rhino实现类放入其中

sun.org.mozilla.javascript.*

包。 但是你加载的Rhino实现将会占用

org.mozilla.javascript.*

因此他们不应该碰撞。 但是, 如果出现问题,您可以在bootstrap类加载器的帮助下覆盖JDK中的类。 您有两种选择:

基本上你需要覆盖类路径,以便你的Rhino类优先于内置而不是内置类。

  1. 只需将rhino-1.7R3.jar放到-JRE-path \\ lib \\ ext中。 这样,Rhino jar将被添加到Java Bootsrap类加载器中,并将在内置JavaScript jar之前加载。
  2. 或者,如果您无法访问../lib/ext,则可以使用命令行选项:

     -Xbootclasspath/a:path/to/rhino-1.7R3.jar 

Rhino本身实现Java Scripting API。 为了将Rhino集成到JDK中,Sun已经实现了自己的ScriptEngineScriptEngineFactory 因此,如果您加载自己的rhino-1.7R3.jar ,如果加载脚本,则无法使用Common JS

ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");

相反,你有两个选择。

  1. 在Rhino API之上 实现您自己的 ScriptEngineScriptEngineFactory 和其他相关类。 了解Oracle如何做到这一点 但请注意,JDK源代码属于GPL 2许可证,因此您应该为Rhino发布自定义脚本引擎包装器,或者仅将这些类用作参考,不要复制代码。

  2. 直接使用Rhino API 我强烈推荐这种方法。 Mozilla网站上有文档和示例,但基本API相对简单:

     // Execution environment for Rhino // there should be only one context in a giver thread Context cx = Context.enter(); // Object.prototype, Function prototype, etc. Scriptable scope = cx.initStandardObjects(); // Execute script from a given java.io.Reader Object result = cx.evaluateReader(scope, reader, 0, null); // If returning result isn't sufficient for your needs // you can do something like this: Object someVar = scope.get("someVar"); // Don't forget to close the context when you're done Context.exit(); 

或者,我可以为您提供一些仅限JS的解决方案。

  1. 看看Browserify 它是一个JavaScript预处理器,它将您的源代码组合到一个包中。
  2. 重写您的模块,以便他们使用AMDUMD ,然后将它们与r.js工具结合使用。

这两个选项都要求您在构建过程中添加一个js预处理步骤,并且可能会使调试代码变得有点困难。

这个问题已经过时了,但对于那些来自谷歌的人来说,您可以使用以下方法在Rhino中设置CommonJS支持(以下只是一种方式):

(我只是直接调用Rhino,而不是使用Java的Scripting API)

List<URI> paths = Arrays.asList(new URI[] { new File("js/require/paths/here").toURI() });
Context ctx = Context.enter();
Scriptable scope = ctx.initStandardObjects();

new RequireBuilder()
    .setModuleScriptProvider(new SoftCachingModuleScriptProvider(
        new UrlModuleSourceProvider(paths, null)))
    .setSandboxed(true)
    .createRequire(ctx, scope)
    .install(scope);

//
// now you can ctx.evaluateString(...) and use require()
//

Context.exit();

现在您可能有两个文件:

main.js

require('require-test.js')()

要求-test.js

module.exports = function() {
    java.lang.System.out.println('The CommonJS require function works!')
}

如果您使用Gradle构建系统。 我通过在项目gradle文件中添加此依赖项成功修复了此问题。 (基于这里

compile group: 'org.mozilla', name: 'rhino', version: '1.7.10'

并且您必须将导入的包名称从sun.org.mozilla.javascript.internal为java类文件中的org.mozilla.javascript

// import sun.org.mozilla.javascript.internal.NativeObject; // <=== Do not use this package.
import org.mozilla.javascript.NativeObject;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

一切正常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM