Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >java 脚本引擎

java 脚本引擎

作者头像
netkiller old
发布于 2018-03-05 09:28:23
发布于 2018-03-05 09:28:23
1.8K00
代码可运行
举报
文章被收录于专栏:NetkillerNetkiller
运行总次数:0
代码可运行

本文节选自《Netkiller Java 手札》

第 18 章 java 脚本引擎

目录

  • 18.1. Maven
  • 18.2. Helloworld
  • 18.3. 运行脚本文件
  • 18.4. 变量传递
  • 18.5. 全局变量与局部变量定义
  • 18.6. 调用脚本中的函数或方法
  • 18.7. 脚本编译

什么是脚本引擎,脚本引擎是指在程序运行期间嵌入另一种脚本语言,并与其交互,产生最终运行结果

脚本引擎存在的意义是什么?脚本引擎可以改变编译语言的内部运行逻辑,弥补编译语言的不足,使编译语言具备动态语言的一部分特性。

是否有成功案例?最成功的案例就是基于C++和Lua语言开发的端游(网游一种,需要按照客户端),编译语言最大的缺点就是客户端升级需要重新安装并且安装之后重启应用程序才能生效。脚本引擎弥补了这项致命的缺点,用户只需升级剧情脚本,而不需要退出整个游戏然后重新进入。

18.1. Maven

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
		<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>cn.netkiller</groupId>
	<artifactId>script</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Java Script</name>
	<description>Java Script Engine</description>
	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-all</artifactId>
			<version>1.10.19</version>
		</dependency>
	</dependencies>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

18.2. Helloworld

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
		package javascript;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

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

public class Helloworld {

	public Helloworld() {
		ScriptEngineManager manager = new ScriptEngineManager();
		List<ScriptEngineFactory> factories = manager.getEngineFactories();
		for (ScriptEngineFactory f : factories) {
			System.out.println("egine name:" + f.getEngineName());
			System.out.println("engine version:" + f.getEngineVersion());
			System.out.println("language name:" + f.getLanguageName());
			System.out.println("language version:" + f.getLanguageVersion());
			System.out.println("names:" + f.getNames());
			System.out.println("mime:" + f.getMimeTypes());
			System.out.println("extension:" + f.getExtensions());
			System.out.println("-----------------------------------------------");
		}
	}

	public void hello() throws ScriptException {
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("JavaScript");
		// ScriptEngine engine = manager.getEngineByExtension("js");
		// ScriptEngine engine = manager.getEngineByMimeType("text/javascript");
		engine.eval("print('Hello, World')");
	}

	public static void main(String[] args) {
		try {
			new Helloworld().hello();
		} catch (ScriptException ex) {
			Logger.getLogger(Helloworld.class.getName()).log(Level.SEVERE, null, ex);
		}
	}
}

18.3. 运行脚本文件

将脚本放入外部文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
		package javascript;

import java.io.FileNotFoundException;
import java.net.URL;

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

public class EvalFile {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByExtension("js");
		// ScriptEngine engine = manager.getEngineByMimeType("text/javascript");

		try {

			URL location = EvalFile.class.getProtectionDomain().getCodeSource().getLocation();
			String file = location.getFile() + "test.js";
			System.out.println(file);

			engine.eval(new java.io.FileReader(file));

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ScriptException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}		

test.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
print("This is hello from test.js");		

18.4. 变量传递

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
		package javascript;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;

public class ScriptVars {

	ScriptEngine engine = null;

	public ScriptVars() {
		ScriptEngineManager manager = new ScriptEngineManager();
		engine = manager.getEngineByMimeType("text/javascript");
	}

	public void variable() throws ScriptException {
		engine.put("name", "Neo");
		engine.eval("var message = 'Hello, ' + name;");
		engine.eval("print(message);");
		Object obj = engine.get("message");
		System.out.println(obj);
	}

	public void simpleBindings() throws ScriptException {
		Bindings bindings = new SimpleBindings();
		bindings.put("name", "Neo");
		engine.eval("print('I am ' + name);", bindings);
	}

	public void function() throws ScriptException {
		engine.put("a", 4);
		engine.put("b", 6);
		Object maxNum = engine.eval("function max_num(a,b){return (a>b)?a:b;}max_num(a,b);");
		System.out.println("max_num:" + maxNum + ", (class = " + maxNum.getClass() + ")");

		Map<String, Integer> m = new HashMap<String, Integer>();
		m.put("c", 10);
		engine.put("m", m);
		engine.eval("var x= max_num(a,m.get('c'));");
		System.out.println("max_num:" + engine.get("x"));
	}

	public void object() throws ScriptException {
		File f = new File("test.txt");
		// expose File object as variable to script
		engine.put("file", f);

		// evaluate a script string. The script accesses "file"
		// variable and calls method on it
		engine.eval("print(file.getAbsolutePath())");
	}

	public void outputToFile() throws IOException, ScriptException {
		ScriptContext context = engine.getContext();
		context.setWriter(new FileWriter("script.log"));
		engine.eval("print('Hello World!');");
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		try {
			ScriptVars sv = new ScriptVars();
			sv.variable();
			sv.simpleBindings();
			sv.outputToFile();
			sv.function();
			sv.object();
			sv.outputToFile();

		} catch (ScriptException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

18.5. 全局变量与局部变量定义

ScriptContext.GLOBAL_SCOPE 作用于 ScriptEngineManager, ScriptContext.ENGINE_SCOPE 作用于 ScriptEngine

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
		package javascript;

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

public class ContextVariable {

	public static void main(String[] args) throws ScriptException {
		// TODO Auto-generated method stub
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("JavaScript");
		ScriptContext context = engine.getContext();  
	    context.setAttribute("name", "Netkiller", ScriptContext.GLOBAL_SCOPE);  
	    context.setAttribute("name", "Neo", ScriptContext.ENGINE_SCOPE);  
	    //context.getAttribute("name"); 
	    engine.eval("print('I am ' + name);", context);
	    
	    // engine1,context1 并没有定义 name 但输出结果却显示 Netkiller,所以ScriptContext.GLOBAL_SCOPE定义的变量是全局的。 
	    ScriptEngine engine1 = manager.getEngineByName("JavaScript");
	    ScriptContext context1 = engine1.getContext();  
	    engine.eval("print('I am ' + name);", context1);
	    
	}

}		

18.6. 调用脚本中的函数或方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
		package javascript;

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

public class InvokeScriptFunction {

	public static void main(String[] args) throws ScriptException, NoSuchMethodException {
		// TODO Auto-generated method stub
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("JavaScript");

		// JavaScript code in a String
		String script = "function hello(name) { print('Hello, ' + name); }";
		// evaluate script
		engine.eval(script);

		// javax.script.Invocable is an optional interface.
		// Check whether your script engine implements or not!
		// Note that the JavaScript engine implements Invocable interface.
		Invocable inv = (Invocable) engine;

		// invoke the global function named "hello"
		inv.invokeFunction("hello", "Scripting!!");

		// JavaScript code in a String. This code defines a script object 'obj'
		// with one method called 'hello'.
		script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";
		// evaluate script
		engine.eval(script);
		// get script object on which we want to call the method
		Object obj = engine.get("obj");

		// invoke the method named "hello" on the script object "obj"
		inv.invokeMethod(obj, "hello", "Script Method !!");
	}
}		

18.7. 脚本编译

只有重复执行脚本时才需要编译。只运行一次不建议编译运行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
		package javascript;

import javax.script.*;

public class ScriptCompile {
	public CompiledScript compile(String script) throws ScriptException {

		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("JavaScript");

		return ((Compilable) engine).compile(script);

	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ScriptCompile sc = new ScriptCompile();
		try {

			CompiledScript script = sc.compile("print('Helloworld!!!');");

			for (int i = 0; i < 100; i++) {
				script.eval();
			}

		} catch (ScriptException ex) {
			ex.printStackTrace();
		}
	}

}		
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-09-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Netkiller 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
《23种设计模式(Java版)》| 单例模式(内附源码案例)。
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。
百思不得小赵
2022/12/01
2780
《23种设计模式(Java版)》| 单例模式(内附源码案例)。
设计模式——单例模式
设计模式——单例模式
Java架构师必看
2021/05/14
2230
设计模式——单例模式
单例模式的八种写法比较
单例模式是最常用到的设计模式之一,熟悉设计模式的朋友对单例模式都不会陌生。一般介绍单例模式的书籍都会提到 饿汉式 和 懒汉式 这两种实现方式。但是除了这两种方式,本文还会介绍其他几种实现单例的方式,让我们来一起看看吧。
Spark学习技巧
2018/12/28
6310
设计模式 (二)单例模式(提供代码,浅显易懂)
设计模式分为至种类型,共 23 种 ● 1)创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式 ● 2)结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式 ● 3)行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter 模式)、状态模式、策略模式、职责链模式(责任链模式)
一写代码就开心
2022/06/19
2540
单例设计模式解读
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。
一个风轻云淡
2023/10/15
2360
单例设计模式解读
这 9 种单例模式你都会吗?
在学单例模式之前,我想大家都会自己问自己:“单例模式存在的意义是什么?我们为什么要用单例模式?”
陈宇明
2020/12/16
7870
设计模式 ☞ 创新型模式之单例模式
  单例(Singleton)模式的定义:是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。在计算机系统中,还有 Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、系统中的缓存等常常被设计成单例。单例模式在现实生活中的应用也非常广泛,例如,早上进公司一看,呵!这不是部门经理嘛,还是那个味,还是昨天那个人,妥妥的单例。
Demo_Null
2020/12/25
3890
设计模式:单例模式 (关于饿汉式和懒汉式)
单例模式是比较常见的一种设计模式,目的是保证一个类只能有一个实例,而且自行实例化并向整个系统提供这个实例,避免频繁创建对象,节约内存。
一诺千金
2021/03/16
9950
一篇通俗易懂的文章让你彻底了解设计模式中的单例模式
之前给大家讲了关于设计模式的七大原则,这一次给大家带来了设计模式中的单例模式,以后会将23种设计模式一一为大家准备好。接下来让我们来看看单例模式吧。
@派大星
2023/06/28
2210
一篇通俗易懂的文章让你彻底了解设计模式中的单例模式
Java单例模式8种方式 详解
1、单例模式(Singleton Pattern):确保某一个类最多只有一个实例,并向整个系统提供这个实例,即该类需提供一个访问唯一实例的全局方法,这个类称为单例类。单例模式的目的是使得某个类最多只有一个实例。
全栈程序员站长
2022/09/22
1K0
Java单例模式8种方式 详解
史上最全讲解单例模式以及分析源码中的应用
1、单例模式介绍所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。比如Hibernate 的SessionFactory,它充当数据存储源的代理,并负责创建Session 对象。SessionFactory 并不是轻量级的,一般情况下,一个项目通常只需要一个SessionFactory 就够,这是就会使用到单例模式。2、单例模式的种类饿汉式(静态常量)饿汉式(静态代码块)懒汉式(线程不安全)懒汉式(线程安全,同步
小熊学Java
2022/09/04
3930
给大忙人写的单例模式的八种实现方法
介绍 文章作者:TrueDei 作者博客首页:http://truedei.blog.csdn.net 文章原文地址:https://truedei.blog.csdn.net/article/details/105758405 一、单例模式介绍 单例模式就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。 二、单例模式的八种方式: 1、饿汗式(静态常量) 2、饿汗式(静态代码块) 3、懒汉式(线程不安全) 4、懒汉式(线程
手撕代码八百里
2020/07/29
3610
Java 设计模式(一)之单例模式 理论代码相结合
单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)–来自百度百科
宁在春
2022/10/31
3070
Java 设计模式(一)之单例模式 理论代码相结合
Java单例模式
Java中单例(Singleton)模式是一种广泛使用的设计模式。单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在,一些管理器和控制器常被设计成单例模式。
用户10358987
2024/04/23
1050
设计模式—单例模式
例如在Java开发中,我们都知道类和对象实例可以通过new来创建一个或者多个,而单例模式就是采取一定的办法保证整个系统中某一个类只能存在唯一一个对象实例,并且获取该类实例的方法只能是该类自己提供的一个获取其实例的静态方法。
炒香菇的书呆子
2022/04/18
3420
图解Java设计模式之单例设计模式
1)设计模式是程序员在面对同类软件工程设计问题所总结出来的有用的经验,模式不是代码,而是某类问题的通用解决方案,设计模式(Design pattern)代码了最佳的实践。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。 2)设计模式的本质提高软件的维护性、通用性和扩展性,并降低软件的复杂度。 3)《设计模式》是经典的书,作者是Erich Gamma\Richard Helm\ Ralph Johnson和John Vlissides Design(俗称“四人组GOF”) 4)设计模式并不局限于某种语言,Java、PHP、C++都有设计模式。
海仔
2020/03/19
2560
图解Java设计模式之单例设计模式
JAVA设计模式之单例模式
作者:炸斯特 出处:https://blog.csdn.net/jason0539 概念:   java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。 单例模式有以下特点:   1、单例类只能有一个实例。   2、单例类必须自己创建自己的唯一实例。   3、单例类必须给所有其他对象提供这一实例。   单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对
Tanyboye
2018/07/02
3880
孔乙己的疑问:单例模式有几种写法
上面三种写法本质上其实是一样的,也是各类文章在介绍饿汉式时常用的方式。但使用静态final的实例对象或者使用静态代码块依旧不能解决在反序列化、反射、克隆时重新生成实例对象的问题。
哲洛不闹
2019/01/23
6760
今天再来聊聊单例设计模式
今天我们再来探讨一下单例设计模式,可以说,单例设计模式在面试考察中是最常出现的,单例模式看似简单,每个人可能都可以写出来,但是能不能写好就是一个问题,往深了考察,又能考察出面试者对于并发、类加载、序列化的掌握程度。
故里
2020/11/25
2700
今天再来聊聊单例设计模式
设计模式-单例模式
单例模式 什么是单例模式? 单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例。 特点: 一个类只能有一个实例 自己创建这个实例 整个系统都要使用这个实例 什么时候用单例模式?
潇洒
2023/10/20
2300
推荐阅读
相关推荐
《23种设计模式(Java版)》| 单例模式(内附源码案例)。
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验