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

Wil*_*ler 7 javascript rhino require commonjs java-7

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

Rhino 1.7R3支持CommonJS模块:

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

我想通过javax.scriptAPI 使用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");
Run Code Online (Sandbox Code Playgroud)

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

<dependency>
    <groupId>org.mozilla</groupId>
    <artifactId>rhino</artifactId>
    <version>1.7R3</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

而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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

And*_*кин 11

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

sun.org.mozilla.javascript.*
Run Code Online (Sandbox Code Playgroud)

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

org.mozilla.javascript.*
Run Code Online (Sandbox Code Playgroud)

因此他们不应该碰撞.但是,如果出现问题,您可以在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
    
    Run Code Online (Sandbox Code Playgroud)

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

ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
Run Code Online (Sandbox Code Playgroud)

相反,你有两个选择.

  1. 实现你自己的 ScriptEngine,ScriptEngineFactory对犀牛API之上和其它相关的类. 了解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();
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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