8

私はrequire.jsを取得して、Java6とRhinoを使用してサーバー側でモジュールをロードしようとしています。

require.js自体を問題なくロードできます。Rhinoは関数を見ることができrequire()ます。require()のようなものに変更すると、Rhinoが関数を見つけることができないと文句を言うのでわかります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)

私はhello.jsJavaクラスパスの一番上にいます。それは私も持っrequire.jsているところです。hello.jsハードドライブのルート、ユーザーディレクトリのルート、Javaアプリを実行しているディレクトリなど、移動する可能性のある場所に移動してみました。何も機能しません。

CommonJS仕様(http://wiki.commonjs.org/wiki/Modules/1.0)を調べたところ、トップレベルID(のようなhello)は「概念的なモジュール名前空間ルート」から解決されるのに対し、相対ID( like ./hello)は、呼び出し元のモジュールに対して解決されます。これらのベースラインのどちらがどこにあるのかわかりませんが、それが問題だと思います。

助言がありますか?Rhinoのrequire.jsを使用することもできますか?

編集:下のコメントのPointyの提案に従って環境を設定する必要があると考えて、私も評価r.jsしてみました。require.js(私は評価した後、そして再び前に評価しようとしましたrequire.js。)どちらの場合でも、私はエラーを受け取ります:

Caused by: javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "arguments" is not defined. (<Unknown source>#19) in <Unknown source> 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)

「引数」はの変数のようですr.js。コマンドライン引数用だと思うので、私r.jsがやろうとしていることの正しい道ではないと思います。でもわからない。

4

1 に答える 1

14

require.js は rhino でうまく機能します。最近、プロジェクトで使用しました。

  1. r.js (require.js ではない)を使用する必要があります。rhino用の require.js の修正版です。
  2. 実装して機能するには、ScritableObjectクラスを拡張する必要があります。を呼び出すと、このクラスのロード関数が呼び出されます。この関数を微調整して、任意の場所から js ファイルをロードできます。以下の例では、からロードします。loadprintrequire(["a"])classpath
  3. arguments以下のサンプル コードに示すように、sharedscope でプロパティを定義する必要があります。
  4. 必要に応じて、 を使用してサブパスを構成し、require.configjs ファイルが配置されているクラスパス内のサブディレクトリを指定できます。

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ディレクトリはクラスパスにある必要があります。

于 2012-06-17T23:42:57.723 に答える