从Java代码调用外部JavaScript函数

51

通过使用Java Scripting API,我可以在Java中执行JavaScript。但是,请问我需要添加什么代码才能调用存储在C:/Scripts/Jsfunctions.js中的函数?

import javax.script.*;

public class InvokeScriptFunction {
public static void main(String[] args) throws Exception {
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("JavaScript");

    // JavaScript code in a String
    String script1 = "function hello(name) {print ('Hello, ' + name);}";
    String script2 = "function getValue(a,b) { if (a===\"Number\") return 1; 
                     else return b;}";
    // evaluate script
    engine.eval(script1);
    engine.eval(script2);

    Invocable inv = (Invocable) engine;

    inv.invokeFunction("hello", "Scripting!!");  //This one works.      
 }
}
3个回答

60

使用ScriptEngine.eval(java.io.Reader)方法来读取脚本。

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
// read script file
engine.eval(Files.newBufferedReader(Paths.get("C:/Scripts/Jsfunctions.js"), StandardCharsets.UTF_8));

Invocable inv = (Invocable) engine;
// call function from script file
inv.invokeFunction("yourFunction", "param");

2
是的,很有用,谢谢。由于Java代码中不会有浏览器,我们如何在提供的JavaScript中使用Window? - sandeep kale
你指的是哪个窗口或浏览器? - MRK187
解决方案是什么? - Fahim
2
如果相对路径加载出现困难,请使用以下代码。URL fileUrl = getClass().getResource("js/WebWorker.js"); engine.eval(Files.newBufferedReader(Paths.get(fileUrl.toURI()),StandardCharsets.UTF_8)); - Mano
嗨,我有疑问, 我尝试调用具有moment.js库依赖项的函数。所以我只是像这样添加了库脚本engine.eval(Files.newBufferedReader(Paths.get("/Volumes/Bala/Eclipse Mars/Workspace/ClientWebAccessFullHistory/war/js/Library/Moment.js"), StandardCharsets.UTF_8)); engine.eval(Files.newBufferedReader(Paths.get("/Volumes/Bala/Eclipse Mars/Workspace/ClientWebAccessFullHistory/war/js/newLayout/FullHistory/fullHistory.js"), StandardCharsets.UTF_8));但它在全局范围内不可用。 - Bala.Raj
@Bala.Raj 你可以在你的脚本中尝试使用 load('path/to/Mom‌​ent.js'); - Ben

2
try {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        System.out.println("okay1");
        FileInputStream fileInputStream = new FileInputStream("C:/Users/Kushan/eclipse-workspace/sureson.lk/src/main/webapp/js/back_end_response.js");
        System.out.println("okay2");
        if (fileInputStream != null){
         BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream));
         engine.eval(reader);
         System.out.println("okay3");
        // Invocable javascriptEngine = null;
         System.out.println("okay4");
        Invocable invocableEngine = (Invocable)engine;
         System.out.println("okay5");
         int x=0;
         System.out.println("invocableEngine is : "+invocableEngine);
         Object object = invocableEngine.invokeFunction("backend_message",x);

         System.out.println("okay6");
        }
        }catch(Exception e) {
            System.out.println("erroe when calling js function"+ e);
        }

1
感谢您提供的这段代码片段,它可能会提供一些有限的、即时的帮助。一个适当的解释将极大地提高其长期价值,通过展示为什么这是一个好的解决方案,并使其对未来读者(有其他类似问题的人)更有用。请[编辑]您的答案添加一些解释,包括您所做的假设。 - Mogsdad

1
假设您的jsfunctions.js文件中有一个名为"display"的函数,且该文件存储在C:/Scripts/Jsfunctions.js中。

jsfunctions.js

var display = function(name) {
print("Hello, I am a Javascript display function",name);
return "display function return"
}

现在,在你的Java代码中,我建议你使用Java8 Nashorn。 在你的Java类中,
import java.io.FileNotFoundException;
import java.io.FileReader;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

class Test {
public void runDisplay() {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
try {
  engine.eval(new FileReader("C:/Scripts/Jsfunctions.js"));
  Invocable invocable = (Invocable) engine;
  Object result;
  result = invocable.invokeFunction("display", helloWorld);
  System.out.println(result);
  System.out.println(result.getClass());
  } catch (FileNotFoundException | NoSuchMethodException | ScriptException e) {
    e.printStackTrace();
    }
  }
}

注意:获取您的JavaScript文件的绝对路径并在FileReader()中替换,然后运行Java代码。它应该可以工作。

3
FYI...对于那些因为Oracle的Java许可证更改或其他原因而转移到OpenJDK的人,需要注意的是,Nashorn在OpenJDK中已被弃用。https://openjdk.java.net/jeps/335 - HankNessip

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接