使用require.js和Java/Rhino解析模块
我正试图让require.js使用Java 6和Rhino在服务器端加载模块 我可以很好地加载require.js本身。Rhino可以看到使用require.js和Java/Rhino解析模块,java,javascript,require,requirejs,rhino,Java,Javascript,Require,Requirejs,Rhino,我正试图让require.js使用Java 6和Rhino在服务器端加载模块 我可以很好地加载require.js本身。Rhino可以看到require()函数。我知道,因为Rhino抱怨说,当我将require()更改为类似requireffdkj()的其他内容时,它找不到该函数 但是当我试图要求一个简单的JS时,比如hello.JS var hello = 'hello'; 使用以下任一项: require('hello'); require('./hello'); 它不起作用。我明白了
require()
函数。我知道,因为Rhino抱怨说,当我将require()
更改为类似requireffdkj()
的其他内容时,它找不到该函数
但是当我试图要求一个简单的JS时,比如hello.JS
var hello = 'hello';
使用以下任一项:
require('hello');
require('./hello');
它不起作用。我明白了
Caused by: javax.script.ScriptException: sun.org.mozilla.javascript.internal.JavaScriptException: [object Error] (<Unknown source>#31) in <Unknown source> at line number 31
at com.sun.script.javascript.RhinoScriptEngine.eval(RhinoScriptEngine.java:153)
at com.sun.script.javascript.RhinoScriptEngine.eval(RhinoScriptEngine.java:167)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:247)
“arguments”似乎是
r.js
中的一个变量。我认为它是用于命令行参数的,所以我不认为r.js
是我要做的事情的正确路径。不过不确定。require.js与rhino配合得很好。最近,我在一个项目中使用了它
ScriptableObject
类来实现load
和print
功能。当您调用require([“a”])
时,将调用此类中的load函数,您可以调整此函数以从任何位置加载js文件。在下面的示例中,我从classpath
加载参数
,如下示例代码所示require.config
配置子路径,以指定类路径中js文件所在的子目录public class JsRuntimeSupport extends ScriptableObject {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(JsRuntimeSupport.class);
private static final boolean silent = false;
@Override
public String getClassName() {
return "test";
}
public static void print(Context cx, Scriptable thisObj, Object[] args,
Function funObj) {
if (silent)
return;
for (int i = 0; i < args.length; i++)
logger.info(Context.toString(args[i]));
}
public static void load(Context cx, Scriptable thisObj, Object[] args,
Function funObj) throws FileNotFoundException, IOException {
JsRuntimeSupport shell = (JsRuntimeSupport) getTopLevelScope(thisObj);
for (int i = 0; i < args.length; i++) {
logger.info("Loading file " + Context.toString(args[i]));
shell.processSource(cx, Context.toString(args[i]));
}
}
private void processSource(Context cx, String filename)
throws FileNotFoundException, IOException {
cx.evaluateReader(this, new InputStreamReader(getInputStream(filename)), filename, 1, null);
}
private InputStream getInputStream(String file) throws IOException {
return new ClassPathResource(file).getInputStream();
}
}
loader.js
require.config({
baseUrl: "js/app"
});
require (["a", "b"], function(a, b) {
print('modules loaded');
});
js/app
目录应该在您的类路径中。必须提供require.js期望从浏览器获得的API;也就是说,库使用web浏览器功能加载脚本。您正在做什么来提供这些?可能什么都没有。:-)我需要什么?如果你想使用Clojure编译器,我看到有一个compiler.jar,但那不是我。我还看到了rhino.jar,但它看起来像是针对rhino本身的,Java 6已经包括了它。我不完全确定require.js是做什么的,但例如,许多这样的库通过在浏览器中构造新的
标记来获取脚本。您可能会发现,简单地用Java编写自己的导入服务,然后为JavaScript环境提供绑定会更容易;这就是我一直在做的事情(尽管从未直接使用Rhino API;我一直使用JSEScriptEngine
工具)。还要记住,如果您编写自己的基于Java的脚本导入服务,它将是同步的,因此,它将消除require.js在web浏览器环境中必须处理的许多复杂性。在本例中,我使用的是RequireJS,因为它提供了一个CommonJS环境,所以我可以使用PageDown库,它显然希望服务器端有一个CommonJS环境。RequireJS支持同步和异步加载,我相信上面的调用(将字符串传递到require())而不是传递数组)是同步版本。谢谢sperumal。我会查一查。现在我正在研究另一种方法(Java7,它有Rhino1.7R3,它实现CommonJS模块,因此我不需要require.js)。但我更希望能够在Java6中实现这一点,并且您的答案看起来很有帮助。我会让你知道的。这在我的电脑上运行得很好,但在Android上运行失败,原因是org.mozilla.javascript.EvaluatorExpression:解析时递归太深(r.js#1)
。通过在堆栈较大的线程中加载r.js
解决了Android的递归太深问题。不幸的是,现在当loader.js
试图要求一个类似于define({value:42})的简单模块时代码>,我得到以下错误:org.mozilla.javascript.EcmaError:ReferenceError:“define”没有定义。
Blarg@sperumal你太棒了。但是有没有一种方法可以与envjs一起使用呢?我没有为这两个方面增加支持。这似乎是一个或另一个:(我应该提到,当我测试时,我也将sealed设置为false
public class RJsDemo {
@Test
public void simpleRhinoTest() throws FileNotFoundException, IOException {
Context cx = Context.enter();
final JsRuntimeSupport browserSupport = new JsRuntimeSupport();
final ScriptableObject sharedScope = cx.initStandardObjects(browserSupport, true);
String[] names = { "print", "load" };
sharedScope.defineFunctionProperties(names, sharedScope.getClass(), ScriptableObject.DONTENUM);
Scriptable argsObj = cx.newArray(sharedScope, new Object[] {});
sharedScope.defineProperty("arguments", argsObj, ScriptableObject.DONTENUM);
cx.evaluateReader(sharedScope, new FileReader("./r.js"), "require", 1, null);
cx.evaluateReader(sharedScope, new FileReader("./loader.js"), "loader", 1, null);
Context.exit();
}
}
require.config({
baseUrl: "js/app"
});
require (["a", "b"], function(a, b) {
print('modules loaded');
});