Java 脚本 引擎 jsr223 与 javascript 文件交互
来源:互联网 发布:录音软件 比特率 编辑:程序博客网 时间:2024/06/05 21:14
JDK1.6开始,Java引入了jsr223,就是可以用一致的形式在JVM上执行一些脚本语言,如js脚本,本文详细说明了java脚本引擎的使用方式,并贴出了大量的经过实际测试的java源代码,请各位参考:
Java 脚本引擎技术相关内容,都已经在Java代码中以注释的形式说明了,请测评:
package jaas;import javax.naming.Context;import javax.naming.InitialContext;import javax.script.*;import java.io.File;import java.util.*;public class Test { /** * 文中的某些示例用到了 JNDI,需要提供 JNDI 实现者,参数:-Djava.naming.factory.initial=org.apache.naming.java.javaURLContextFactory * 使用了 Tomcat 的 JNDI 实现,添加依赖: * <dependency> * <groupId>org.apache.tomcat</groupId> * <artifactId>tomcat-catalina</artifactId> * <version>8.5.6</version> * </dependency> */ public static void main(String[] args) throws Exception { // 获取脚本引擎管理器 ScriptEngineManager manager = new ScriptEngineManager(); List<ScriptEngineFactory> engineFactories = manager.getEngineFactories(); System.out.println("当前 JVM 支持的脚本引擎:"); for (ScriptEngineFactory sef : engineFactories) { System.out.println("引擎名称:" + sef.getEngineName()); System.out.println("\t 别名:" + sef.getNames()); System.out.println("\t MimeTypes:" + Arrays.asList(sef.getMimeTypes())); } System.out.println(); // 获取指定的 js 脚本引擎 ScriptEngine jsEngine = manager.getEngineByName("js");// ScriptEngine jsEngine = manager.getEngineByName("javascript");// ScriptEngine jsEngine = new ScriptEngineManager().getEngineByMimeType("text/javascript"); // 引擎测试 /** * 脚本语言支持API使用语言绑定对象实现Java语言编写的程序与脚本语言间的数据传递。 * 语言绑定对象实际上就是一个简单的哈希表,用来存放和获取需要共享的数据, * 其定义的接口为javax.script.Bindings,继承自java.util.Map接口。 * 一个脚本引擎在执行过程中可能会使用多个语言绑定对象,不同语言绑定对象的作用域不同。 * ScriptEngine类提供out和get方法对脚本引擎中特定作用域的默认语言绑定对象进行操作。 */ testEngine(jsEngine); // testContext_Java_Params(jsEngine); } public static void testEngine(ScriptEngine engine) throws Exception { engine.put("name", "张三");// 参数 engine.eval("var msg = '你好, ' + name;");// 使用某作用域的参数 engine.eval("println('js println: '+msg);");// 使用某作用域的参数 Object obj = engine.get("msg");// java 可获取到 js 脚本返回的对象 System.out.println("java println: " + obj); System.out.println(); // 自定义语言绑定对象(如语言绑定对象中包含程序自己独有的数据等情形……) Bindings bindings = new SimpleBindings(); bindings.put("fruit", "Apples"); engine.eval("println('I like ' + fruit);", bindings); System.out.println(); ScriptContext context = engine.getContext();// 获取引擎默认的上下文 // 重定向输出到文件// context.setWriter(new FileWriter("/home/conquer/Desktop/a.txt")); engine.eval("println('Hello World, I am from Js script.');"); System.out.println(); // 绑定对象作用域1 context.setAttribute("name", "张三", ScriptContext.GLOBAL_SCOPE);//从同一引擎工厂中创建的所有脚本引擎对象 context.setAttribute("name", "李四", ScriptContext.ENGINE_SCOPE);//当前的脚本引擎对象 Object name = context.getAttribute("name");//值按优先级为 李四 System.out.println(name); System.out.println(); // 绑定对象作用域2 Bindings bindings1 = engine.createBindings(); bindings1.put("name", "张三"); context.setBindings(bindings1, ScriptContext.GLOBAL_SCOPE); Bindings bindings2 = engine.createBindings(); bindings2.put("name", "李四"); context.setBindings(bindings2, ScriptContext.ENGINE_SCOPE); engine.eval("println('脚本按优先级得到参数:'+name);"); //李四 System.out.println(); Bindings bindings3 = context.getBindings(ScriptContext.ENGINE_SCOPE);// 直接获取当前引擎作用域参数集合 Bindings bindings4 = context.getBindings(ScriptContext.GLOBAL_SCOPE);// 直接获取所有引擎作用域参数集合 context.setAttribute("name", "张三", ScriptContext.GLOBAL_SCOPE);// 属性设置也具有作用域的选择// engine.eval("println(name);"); // b编译运行,提升脚本运行效率 if (engine instanceof Compilable) { String performanceTest = "var a = 100;\n" + "var b = 100+a;\n" + "var c = a+b;\n" + "println(c);" + "println('');"; Compilable compilable = (Compilable) engine; CompiledScript compiledScript = compilable.compile(performanceTest); compiledScript.eval(); } // 脚本中 调用 java 方法 File file = new File("/home/conquer/mine/work_space/idea/Eden/jse/src/main/java/jaas/loginscript.js"); engine.put("file", file); Bindings engineBindings = engine.getBindings(ScriptContext.ENGINE_SCOPE); engineBindings.put("file2", file); engine.eval("println('脚本中执行java对象方法:'+file.getAbsoluteFile())"); engine.eval("println('脚本中执行java对象方法2:'+file.getAbsoluteFile())"); engine.eval("println(file.getAbsolutePath());"); Object eval1 = engine.eval("file.getAbsolutePath();"); System.out.println("打印js从java得到的数据:" + eval1); engine.eval("println(file.isHidden());"); Properties temp = new Properties(); temp.setProperty("aaa", "aaaaa"); engineBindings.put("properties", temp); engine.eval("println(properties.toString());"); Object eval2 = engine.eval("properties.toString();"); System.out.println("打印js从java中读取Properties:" + eval2); engine.eval("println(properties.getProperty('aaa'));"); Object eval3 = engine.eval("properties.getProperty('aaa');"); System.out.println("打印js从java中读取Properties,key 为 aaa:" + eval3); SayHello sayHello = new SayHello(); engine.put("sayHello1", sayHello); engine.getBindings(ScriptContext.ENGINE_SCOPE).put("sayHello2", sayHello); engine.eval("println(sayHello1.hello('张三111'))");// 注意类必需声明为 public的 Object hello = engine.eval("sayHello2.hello('张三222')");// 注意类必需声明为 public的 System.out.println("js 获取到的java返回:" + hello);// ok // 也可以通过下面的方式将 实参 放到 jndi 上下文中获取,脚本中仍然使用形式参数 ScriptContext scriptContext = new SimpleScriptContext(); Bindings bindings5 = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE); bindings5.put("name", "张三"); Context ctx = new InitialContext();// 这里是启动之前设置的 tomcat的 jndi 实现 ctx.bind("jndiObj", sayHello); Object eval = engine.eval("var ctx = new javax.naming.InitialContext();\n" + "var myBean = ctx.lookup(\"jndiObj\");\n" + "myBean.hello(name);", scriptContext);// "myBean.hello('name');", scriptContext);// 使用 jndi 保存参数,这里不需要传递 实际参数 System.out.println("js 调用 java 方法返回值:" + eval); System.out.println(); // 方法调用,Java 调用 脚本中定义的方法 /** * 虚拟机支持脚本的意义在于实现函数式的编程,脚本中最重要的便是方法, * 脚本引擎允许使用者单独调用脚本中的某个方法, * 支持此操作的脚本引擎可以通过实现javax.script.Invocable接口。 * JavaSE中的JavaScript引擎已实现了Invocable接口。 */ if (engine instanceof Invocable) { String scriptText = "function greet(name) { println('Hello, ' + name); } "; engine.eval(scriptText);// 这里是在定义 greet 方法,只有定义以后才能进行调用:invokeFunction Invocable invocable = (Invocable) engine; invocable.invokeFunction("greet", "张三");// 调用方法,并传递参数 // 调用成员方法 String scriptText2 = "var obj = { getGreeting : function(name) { return 'Hello, ' + name; } }; "; engine.eval(scriptText2);// 定义脚本对象,并且定义对象成员方法 Object scriptObj = engine.get("obj");//获取到脚本中的实例化的对象 Object result = invocable.invokeMethod(scriptObj, "getGreeting", "张三"); //第一个参数为方法所属对象,后面调用对象的方法和参数 System.out.println(result); // 脚本方法 Java 化 !!! 是指将 java 的调用自动映射到脚本中方法执行上, // 需要用到java 接口,接口的方法定义和脚本中方法定义一致,即:脚本作为 接口 的实现类 String scriptText3 = "function getGreeting(name) { " + "println('我是 Java 定义的 Greet 接口的具体实现哦...');" + "return '你好, ' + name; } "; engine.eval(scriptText3); Greet greet = invocable.getInterface(Greet.class); System.out.println(greet.getGreeting("Alex")); } } interface Greet { String getGreeting(String name); } public static void testContext_Java_Params(ScriptEngine engine) throws Exception { Map<String, String> params = new HashMap() {{ // 脚本中需要的形参名称及对应的实参值 put("user", "admin");// 必需包含 js 脚本中调用的LoginBean.authenticate类方法需要的参数 put("password", "pwd");// 必需包含 js 脚本中调用的LoginBean.authenticate类方法需要的参数 }}; // 脚本需要的 ScriptContext 对象,脚本中引起的参数都需要从这个对象里面获取 ScriptContext scriptContext = new SimpleScriptContext();//也可以在这里直接 new 出来// ScriptContext scriptContext = engine.getContext();// 构造参数里面也是直接 new 出来的 /** * 绑定参数两个作用域: * ScriptContext.ENGINE_SCOPE(当前的脚本引擎) * ScriptContext.GLOBAL_SCOPE(从同一引擎工厂中创建的所有脚本引擎对象) */ // 绑定方式1 Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE); // 脚本中需要的形参名称及对应的实参值// bindings.put("user", "admin");// bindings.put("password", "pwd"); bindings.putAll(params); // 绑定方式2// for (Map.Entry<String, String> e : params.entrySet()) {// scriptContext.setAttribute(e.getKey(), e.getValue(), ScriptContext.GLOBAL_SCOPE);// } // 写自己的这个 JNDI 上下文,是因为 js 脚本中的内容要用到 应用自定义的对象,而在脚本中不能创建 非 java 的对象 // 所以我们事先创建好,放到 JNDI 上下文,以供脚本中 lookup 查找并使用对象 InitialContext context = new InitialContext(); context.bind("script_ref_obj", new LoginBean()); String scriptText = getScriptText(); System.out.println("脚本内容:"); System.out.println(scriptText); System.out.println(); List<String> myGroups = (List<String>) engine.eval(scriptText, scriptContext);// 脚本的最后以后具有返回值的可以在这里获取到!! System.out.println("脚本执行后的返回值:"); System.out.println(myGroups); } /** * Scanner 类用于扫描、接收、分段处理字符串,可以指定分割符号, * 通过 一系列的 nextXXX() 可以依次获取到分割的内容片段 * <p> * Scanner 可以接入一个 InputStream 或者一个 File(内部转为FileInputStream)以作为字符输入端 */ private static String getScriptText() throws Exception {// 测试的话,可以将脚本内容直接硬编码写在这里: String jsText = "println(\"js begin invoke...\");\n" + "var ctx = new javax.naming.InitialContext();\n" + "var myBean = ctx.lookup(\"script_ref_obj\");\n" + "myBean.authenticate(user, password);"; return jsText;// 从文件中读取脚本// Scanner 可以采用正则表达式分段读取字符串内容,分段符合可以使用 useDelimiter 方法指定// 如果不写,默认是空格分割 scanner.useDelimiter(",") 表示以“,”分割读取内容// File script = new File("/home/conquer/mine/work_space/idea/Eden/jse/src/main/java/jaas/loginscript.js");// Scanner scanner = new Scanner(script).useDelimiter("\\Z");// return scanner.next(); }}
package jaas;import javax.security.auth.login.FailedLoginException;import java.util.Arrays;import java.util.List;public class LoginBean { public List<String> authenticate(String user, String password) throws FailedLoginException { System.out.println("从 js 脚本调入进来的 java 方法开始执行..."); System.out.println("user:" + user); System.out.println("password:" + password); if (true) {// test return Arrays.asList("adminRole", "tomcatRole"); } if ("paul".equals(user) && "michelle".equals(password)) { return Arrays.asList("Manager", "rockstar", "beatle"); } if ("eddie".equals(user) && "jump".equals(password)) { return Arrays.asList("Employee", "rockstar", "vanhalen"); } throw new FailedLoginException("Bad user or password!"); }}
package jaas;public class SayHello { public String hello(String name) { System.out.println("java 方法执行"); return "你好," + name; }}
loginscript.js 脚本文件内容:
println("js begin invoke...");var ctx = new javax.naming.InitialContext();var myBean = ctx.lookup("script_ref_obj");myBean.authenticate(user, password);
阅读全文
0 0
- Java 脚本 引擎 jsr223 与 javascript 文件交互
- Java 中使用rhno引擎,运行JavaScript脚本,实现变量的交互、引入、传递
- Java 8 Nashorn Javascript脚本引擎
- Java脚本引擎执行 javascript 代码
- Java与js脚本交互Java
- JDK8中Java调用Javascript脚本引擎动态定义与执行代码
- java 与servlet交互,java与JavaScript交互
- JavaScript脚本引擎Rhino
- JavaScript脚本引擎SpiderMonkey
- com自动化控件与JavaScript脚本交互数组方法
- .net 与 javascript脚本的几种交互方法
- .net 与 javascript脚本的几种交互方法
- iOS UIWebView 与 JavaScript 交互 代码实现 嵌入 js 脚本
- Java学习之动态编译-动态脚本引擎-脚本引擎执行javascript代码
- Javascript与Java在浏览器中的交互
- webview中,javascript与java交互
- Android WebView Java与JavaScript的交互
- Java与Javascript交互(使用Protobuf协议)
- Python利用WMI实现ping命令
- MTK 6.0 Alarm机制分析
- 有关网站虚拟目录的解释
- Javascript 异步加载详解
- Dialog中Screen logic的处理逻辑原则
- Java 脚本 引擎 jsr223 与 javascript 文件交互
- React--在model中调用model
- 转载-使用IDEA搭建SpringMvc框架
- ButterCMS架构:完成数百万次调用的关键任务API
- 设计模式(整理)
- 18.4Sum
- C#DLL托管c++ (CLI) String^ 到 std::string 的相互转化
- 推荐一个好用的权限申请框架
- DependencyHandler