使用require.js和Java / Rhino解析模块
我正在尝试让require.js在服务器端使用Java 6和Rhino加载模块。
我能够自己加载require.js就好了。 Rhino可以看到require()
函数。 我可以告诉,因为当我将require()
更改为requireffdkj()
类的东西时,Rhino抱怨它无法找到该函数。
但是当我尝试甚至需要一个简单的JS时,比如hello.js
var hello = 'hello';
使用以下任一方法:
require('hello'); require('./hello');
它不起作用。 我明白了
Caused by: javax.script.ScriptException: sun.org.mozilla.javascript.internal.JavaScriptException: [object Error] (#31) in 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)
我在Java类路径的顶部有我的hello.js
. 这也是我需要的地方require.js
。 我尝试将hello.js
移动hello.js
我认为可能发生的任何地方,包括我的硬盘驱动器的根目录,用户目录的根目录,运行Java应用程序的目录等等。没有任何作用。
我查看了CommonJS规范( http://wiki.commonjs.org/wiki/Modules/1.0 ),它说顶级ID(如hello
)是从“概念模块名称空间根”解析的,而相对ID (如./hello
)是针对调用模块解决的。 我不确定这些基线在哪里,我怀疑这是问题所在。
有什么建议么? 我甚至可以使用Rhino的require.js吗?
编辑:我认为我需要根据Pointy的建议在下面的评论中设置环境,我也尝试评估r.js
(我在评估require.js
之后尝试进行评估,然后在require.js
之前再次进行require.js
。)在任何一种情况下我都会收到错误:
Caused by: javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "arguments" is not defined. (#19) in at line number 19 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配合得很好。 最近,我在一个项目中使用它。
- 你必须确保使用r.js (不是require.js),修改版本的require.js用于rhino。
- 您必须扩展
ScritableObject
类以实现load
和print
function。 当你调用require(["a"])
,将调用此类中的load函数,你可以调整这个函数来从任何位置加载js文件。 在下面的示例中,我从classpath
加载。 - 您必须在sharedscope中定义属性
arguments
,如示例代码中所示 - (可选)您可以使用
require.config
配置子路径,以指定js文件所在的类路径中的子目录。
JsRuntimeSupport
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(); } }
示例代码
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(); } }
loader.js
require.config({ baseUrl: "js/app" }); require (["a", "b"], function(a, b) { print('modules loaded'); });
js/app
目录应该在你的类路径中。