【问题标题】:javax.script package: How to import JavaScript files?javax.script 包:如何导入 JavaScript 文件?
【发布时间】:2012-10-19 11:33:58
【问题描述】:

我正在使用 javax.script 包在 Java 应用程序中运行外部 JavaScript 文件。

如何在不使用 Java 代码的情况下将一个 JavaScript 文件导入另一个 JavaScript 文件?

【问题讨论】:

    标签: javax.script


    【解决方案1】:

    当您说不使用 java 代码时,我不完全确定您的意思,但这是一个可以工作的纯 javascript(虽然它正在调用 java):

    importPackage(java.io);
    function loadJs(name, user) {
        println("Loading " + name);
        var f = new File(name);
        var br = new BufferedReader(new FileReader(f));
        var line = null;
        var script = "";
        while((line = br.readLine())!=null) {
            script += line;
        }
        println(script);
        eval(script);
        hello(user);
    }
    

    ...当然,前提是我有一个名为(比如 c:/temp/hellouser.js)的文件,其内容如下:

    function hello(name) { print('Hello, ' + name); }
    

    我使用 groovy 脚本测试了该脚本:

    import javax.script.*;
    
    sem = new ScriptEngineManager();
    engine = sem.getEngineByExtension("js");
    script1 = """
    importPackage(java.io);
    function loadJs(name, user) {
        println("Loading " + name);
        var f = new File(name);
        var br = new BufferedReader(new FileReader(f));
        var line = null;
        var script = "";
        while((line = br.readLine())!=null) {
            script += line;
        }
        println(script);
        eval(script);
        hello(user);
    }
    """;
    
    engine.eval(script1);
    Object obj = engine.get("obj");
    Invocable inv = (Invocable) engine;
    inv.invokeFunction("loadJs", "c:/temp/hellouser.js", "Nicholas");
    

    输出是:

    正在加载 c:/temp/hellouser.js

    function hello(name) { print('Hello, ' + name); }

    你好,尼古拉斯

    我希望这大约是您正在寻找的......

    ============================ 更新================ ===========

    这是一个扩展 Rhino 脚本引擎工厂的清理版本(因为引擎本身是最终版本):

    import javax.script.Bindings;
    import javax.script.ScriptContext;
    import javax.script.ScriptEngine;
    import javax.script.ScriptException;
    
    import com.sun.script.javascript.RhinoScriptEngineFactory;
    
    /**
     * <p>Title: LoadEnabledRhinoEngineFactory</p>
     * <p>Description: Adding a loadJs function to the standard JS engine</p> 
     * <p>Company: Helios Development Group LLC</p>
     * @author Whitehead (nwhitehead AT heliosdev DOT org)
     * <p><code>org.helios.apmrouter.js.LoadEnabledRhinoEngineFactory</code></p>
     */
    
    public class LoadEnabledRhinoEngineFactory extends RhinoScriptEngineFactory {
    
        /** The load script source */
        public static final String LOAD_JS = 
            "importPackage(java.io); " +
            "var script = ''; " +
            "var ctx = null; " +
            "function loadScript(name) { " +
                "var f = new File(name); " +
                "var br = new BufferedReader(new FileReader(f)); " +
                "var line = null; " +           
                "while((line = br.readLine())!=null) { " +
                    "    script += line; " +
                "} " +
                "_e_ngine.eval(script);" + 
            "} ";
        
        /**
         * {@inheritDoc}
         * @see com.sun.script.javascript.RhinoScriptEngineFactory#getScriptEngine()
         */
        @Override
        public ScriptEngine getScriptEngine() {
            ScriptEngine se = super.getScriptEngine();
            Bindings b = se.createBindings();
            b.put("_e_ngine", se);
            se.setBindings(b, ScriptContext.GLOBAL_SCOPE);
            try {
                se.eval(LOAD_JS);
            } catch (ScriptException e) {
                throw new RuntimeException(e);
            }
            return se;
        }
        
    

    现在,loadScript(fileName) 是引擎的一部分,您可以使用 JS 干净地调用它,例如:

    loadScript('c:/temp/hellouser.js'); 
    hello('Nicholas');"
    

    或者正如我在 Java 中测试的那样:

    ScriptEngine se = new LoadEnabledRhinoEngineFactory().getScriptEngine();
    try {
        se.eval("loadScript('c:/temp/hellouser.js'); hello('Nicholas');");
    } catch (Exception e) {
        e.printStackTrace(System.err);
    }
    

    干杯。

    【讨论】:

    • 我正在寻找类似于“importPackage”的东西,但我们称之为“importScript”。这就像 C++ 中的 #include 指令。我最终所做的是编写与您的提案类似的内容,并使用eval(loadScript("myscript.js")) 运行它(在全局范围级别)。我认为这是一个丑陋的补丁,所以除非有更优雅的解决方案,否则我会继续使用这种方法。
    • 酷,我喜欢这个主意。但是您确定允许调用 _e_ngine.eval(script),因为它是在同一引擎的另一个执行 eval (loadScript('c:/temp/hellouser.js'); hello('Nicholas');) 的上下文中执行的吗?
    • 它可以工作,至少在我的简单测试用例中是这样。您可以通过包装整个脚本引擎管理器并注入您在包装器的构造函数中创建的函数的编译版本来改进这个想法。
    猜你喜欢
    • 2023-02-15
    • 2011-03-11
    • 1970-01-01
    • 2020-10-12
    • 2020-08-16
    • 2017-07-17
    • 2017-12-04
    • 2014-02-22
    • 2016-05-10
    相关资源
    最近更新 更多