Java中原生解析JavaScript脚本语言

前言

由于一些需求,现在需要在Java中解析字符串,做一些简单的算数运算和逻辑运算,那么最先想的是模板引擎这个东西,但是Java中的模板引擎是针对View层的,也就是JSP的,在Service层中使用不是太方便,因此选用了原生的JavaScript脚本解析引擎。实际上Java原生支持解析大部分脚本语言,像JavaScript,PHP,Python等。

那么,先贴一下核心实现类的代码:

import java.io.FileNotFoundException;
import java.util.Map;

import javax.script.ScriptException;

public interface TempletEngineService {
	
	public Object eval(String script) throws ScriptException, FileNotFoundException;
	
	public Object eval(String script, Map<String, Object> vars) throws ScriptException, FileNotFoundException;
	
}

然后是实现类:


import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

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

@Service
public class TempletEngineServiceImpl implements TempletEngineService {

	private ScriptEngine jsEngine;
	
	public TempletEngineServiceImpl() {
		ScriptEngineManager manager = new ScriptEngineManager();
		jsEngine = manager.getEngineByName("JavaScript");
	}
	
	@Override
	public Object eval(String script) throws ScriptException, FileNotFoundException {
		if (script == null || script.equals("")) {
			return null;
		}
		String jsfile = "/home/phw/Workspaces/MyEclipseProjects/gomoo-fu/src/com/gomoo/util/script/template.js";
		jsEngine.eval(new FileReader(new File(jsfile)));
		return jsEngine.eval(script);
	}
	
	@Override
	public Object eval(String script, Map<String, Object> vars) throws ScriptException, FileNotFoundException {
		if (script == null || script.equals("")) {
			return null;
		}
		if (vars == null || vars.isEmpty()) {
			for (Map.Entry<String, Object> entry: vars.entrySet()) {
				jsEngine.put(entry.getKey(), entry.getValue());
			}
		} 
		return eval(script);
	}

}

主要的核心类就是这两个文件,可以看到,用到的解析引擎是javax.script包下的引擎。

脚本是自定义的一串符合JavaScript规则的字符串,像简单点的字符串“5 + 6”、"9 - (6 + 5) * 5"等等,可以直接执行eval函数;若需要计算一些复杂的逻辑,那可以写到你自定义的一个js文件里,然后在脚本中运行那个函数;那再复杂一点,在函数中或者脚本中带自定义参数,这时就用到了eval(String script, Map vars)函数了。

下面是一些例子:

/**
	 * 简单字符串的测试
	 * @throws ScriptException 
	 * @throws FileNotFoundException 
	 */
	@Test
	public void testEval() throws FileNotFoundException, ScriptException {

		String script = "(65 - 5) / (3 * 6)";
		String script2 = "15 > 10 ? 15 : 10";
		String script3 = "15 > 10";
		
		Object val1 = templetEngineService.eval(script);
		System.out.println("脚本1的结果为:" + val1);
		Object val2 = templetEngineService.eval(script2);
		System.out.println("脚本2的结果为:" + val2);
		Object val3 = templetEngineService.eval(script3);
		System.out.println("脚本3的结果为:" + val3);
		
	}

	/**
	 * 脚本1的结果为:3.3333333333333335
	 * 脚本2的结果为:15
	 * 脚本3的结果为:true
	 */

	/**
	 * 带函数的脚本测试
	 * @throws ScriptException 
	 * @throws FileNotFoundException 
	 */
	@Test
	public void testEval2() throws FileNotFoundException, ScriptException {
		String script = "random()";
		String script2 = "random() + random()";
		Object val1 = templetEngineService.eval(script);
		System.out.println("脚本1的结果为:" + val1);
		Object val2 = templetEngineService.eval(script2);
		System.out.println("脚本2的结果为:" + val2);
	}
	
	/**
	 * 脚本1的结果为:63.0
	 * 脚本2的结果为:163.0
	 */

	/**
	 * 带参数的脚本测试
	 * @throws FileNotFoundException
	 * @throws ScriptException
	 */

	@Test
	public void testEval3() throws FileNotFoundException, ScriptException {
		
		String script = "random(min, max)";
		String script2 = "random(min, max) + min - max";
		
		Map<String, Object> vars = new HashMap<>();
		vars.put("min", 10);
		vars.put("max", 100);
		Object val1 = templetEngineService.eval(script, vars);
		System.out.println("脚本1的结果为:" + val1);
		
		Map<String, Object> vars2 = new HashMap<>();
		vars.put("min", 100);
		vars.put("max", 1000);
		Object val2 = templetEngineService.eval(script2, vars2);
		System.out.println("脚本2的结果为:" + val2);
	}

	/**
	 * 脚本1的结果为:69.0
	 * 脚本2的结果为:-65.0
	 */

/**
	 * 参数为类时的脚本测试
	 * @throws FileNotFoundException
	 * @throws ScriptException
	 */
	@Test
	public void testEval4() throws FileNotFoundException, ScriptException {
		
		User user = new User();
		user.setRealName("phw");
		String script = "out(user)";
		Map<String, Object> vars = new HashMap<>();
		vars.put("user", user);
		Object val = templetEngineService.eval(script, vars);
		System.out.println("脚本1的结果为:" + val);
	}
	
	/**
	 * 脚本1的期望结果:phw
	 */

下面贴一下template.js,也就是我们预定义的Js function的文件:

/**
 * 生成100内的随机数
 */
function random() {
	return Math.floor(Math.random() * 100);
}

/**
 * 生成区间内的随机整数[m, n]
 */
function random(minNum,maxNum){
  switch(arguments.length){ 
      case 1: 
          return parseInt(Math.random()*minNum+1,10); 
      break; 
      case 2: 
          return parseInt(Math.random()*(maxNum-minNum+1)+minNum,10); 
      break; 
          default: 
              return 0; 
          break; 
  } 
}

function out(obj) {
	return obj.realName;
}

以上就是测试里用到的js function函数,再说一下,脚本不支持es6的语法,所以老老实实用var,不要用let。

以上。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值