文档章节

Java内嵌Groovy脚本引擎进行业务规则剥离(二)--JAVA解析

O龙猫O
 O龙猫O
发布于 2017/01/22 14:43
字数 1126
阅读 3705
收藏 25

继续上一篇:Java内嵌Groovy脚本引擎进行业务规则剥离(一)

既然是动态脚本,需要的就是动态执行,因此暂时不考虑groovy编译为字节码的情况,而直接使用java进行解析,并且运行。

考虑到程序的简单性,建立一个普通的java程序就好,导入以下两个jar包:

  • commons-io-2.2.jar 用于快速读取文本文件内容
  • groovy-all-2.3.10.jar

文件:HelloWord.groovy

package com.amarsoft.rax.rulengine

import java.text.SimpleDateFormat
import java.text.ParseException

class RuntimeContext {
    //以下是英文部分变量,一般通过程序自动装载得到,用于从数据库或其他持久层加载业务数据
    def collegeName = "EMBA业余大学"
    def tuitionFee = 80000
    def startDate = '2016/02/01', finishDate = '2016/09/01'
    def today = "2017/01/21"
    def student = ['id'            : 'E9527',
                   'name'          : '于小小',
                   'gender'        : 'F',
                   'kind'          : 'EMBA',
                   'className'     : '重庆理工大学MBA三年级四班',
                   'grade'         : 4,
                   'birth'         : '1989/03/02',
                   'address'       : '重庆市巴南区红光大道',
                   'salary'        : 50000,
                   'createTime'    : '2016/01/21 11:31:00',
                   'courses'       : [
                           ['id': 'GJC', name: '公共基础', 'classHour': 32],
                           ['id': 'ZXW', name: '组织行为学', 'classHour': 40],
                           ['id': 'TJX', name: '统计学', 'classHour': 20],
                           ['id': 'CJR', name: '财务与金融', 'classHour': 60],
                           ['id': 'JJF', name: '经济法', 'classHour': 48],
                           ['id': 'JSJ', name: '计算机技能', 'classHour': 16],
                   ],
                   'mainInstructor': ['id': 'TE007', 'name': '杨大大'],
                   'extra'         : [
                           'attendanceLog': ['2016/02/01 09:00:02', '2016/02/03 08:50:03', '2016/02/15 09:12:34', '2016/04/01 07:30:11'],
                           'progressState': 'finished'
                   ]


    ];
    def toDate(_date){
        try{
            return (new SimpleDateFormat("yyyy/MM/dd hh:mm:ss")).parse(_date);
        }catch(ParseException e){
            return (new SimpleDateFormat("yyyy/MM/dd")).parse(_date);
        }

    }


    def 规则集 = [
            '基础信息':
                    [
                            '是否90后': student.birth >= '1990/01/01'?'是':'否',
                            '性别'   : student.gender == 'M' ? '男' : '女',
                            '注册天数':toDate(today) - toDate(student.createTime),
                            '地区':{
                                def province = student.address.subSequence(0,3);
                                //做一个区域和省级行政单位的映射关系
                                def areaMapping = ['西南':['重庆市','四川省','贵州省','云南省'],'江浙沪':['上海市','江苏省','浙江省'],'京津冀':['北京市','天津市','河北省']];
                                //进行筛选
                                def entry = areaMapping.find {key,value ->
                                    value.contains(province);
                                }
                                entry.key
                            }()//最后这个"()"一定要,否则闭包不执行
                    ],

            '评级'  : [
                    //使用三元表达式,大于6W --> A ,4-6W --> B,2-4W -->C,2W以下 --> D
                    '学费档次' : tuitionFee>=60000?'A':(tuitionFee>=40000&&tuitionFee<60000?'B':(tuitionFee>=20000&&tuitionFee<40000)?'C':'D'),
                    '收入档次':{
                        if(student.salary>=20000) '高收入'
                        else if(student.salary>=10000) '中等收入'
                        else if(student.salary>=5000) '一般收入'
                        else '低收入'
                    }() //最后这个"()"一定要,否则闭包不执行
            ],
            '学习情况': [
                    '总学时':{
                        int totalHourse = 0;
                        student.courses.each { totalHourse += it.classHour}
                        totalHourse
                    }(),
                    '迟到次数':{
                        int _count = 0
                        student.extra.attendanceLog.each {
                            Date _date = toDate(it)
                            _count += (_date.hours>=9&&_date.seconds>=1)?1:0
                        }
                        _count
                    }(),
                    '出勤次数':student.extra.attendanceLog.size(),
                    '单门课程最长学时':{
                        int maxHour = 0;
                        student.courses.each { maxHour = Math.max(maxHour,it.classHour)}
                        student.courses.find({it.classHour == maxHour}) //默认最后一句为返回值
                    }(),
            ]
    ]

}

// ========运行验证========

//创建运行时对象
def rctx = new RuntimeContext()
//输出结果看
//----简单的规则取值
println "基础信息.是否90后  =  ${rctx.规则集.基础信息.是否90后}"
println "基础信息.性别      = ${rctx.规则集.基础信息['性别']}"
println "基础信息.注册天数      = ${rctx.规则集.基础信息.注册天数}"
println "评级.学费档次      = ${rctx.规则集.评级.学费档次}"
//----使用闭包的方式取值
println "基础信息.地区      = ${rctx.规则集.基础信息.地区}"
println "评级.收入档次      = ${rctx.规则集.评级.收入档次}"
println "学习情况.总学时      = ${rctx.规则集.学习情况.总学时}"
println "学习情况.迟到次数      = ${rctx.规则集.学习情况.迟到次数}"
println "学习情况.出勤次数      = ${rctx.规则集.学习情况.出勤次数}"
println "学习情况.单门课程最长学时      = ${rctx.规则集.学习情况.单门课程最长学时}"

文件:JavaParseGroovy.java

package com.amarsoft.rax.rulengine;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

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

import org.apache.commons.io.IOUtils;

public class JavaParseGroovy {
	static String groovyFile = "com/amarsoft/rax/rulengine/HelloWord.groovy";

	public static void main(String[] args) throws ScriptException, FileNotFoundException, IOException {
		ScriptEngineManager engineManager = new ScriptEngineManager();
		ScriptEngine engine = engineManager.getEngineByName("groovy");
		//先测试下,行不行
		System.out.println("groovy解析结果:"+engine.eval("println 'HelloWord' \n 'HelloWordReturn'"));
		//读取源Groovy源程序
		String fileFullPath = rootDir()+"/src/"+groovyFile;
		String scriptContent = IOUtils.toString(new FileInputStream(fileFullPath));
		System.out.println("----------groovy-exec----------");
		engine.eval(scriptContent);
	}
	
	public static String rootDir(){
		String classDir=JavaParseGroovy.class.getClassLoader().getResource("").getPath();
		int idx = classDir.lastIndexOf("/",classDir.length()-2);
		return classDir.substring(0,idx);
	}

}

执行结果如下:

 

编写Groovy脚本没有好的IDE支持肿么行。

eclipse插件版,本人到现在都没有安装成功。

目前我尝试过了,成功的方案有以下种种

  1. 使用大名顶顶的IDEA,这个不用多说,原生就支持Groovy
  2. 使用GGTS(groovy-grails-tool-suite),下载地址:http://spring.io/tools/ggts/all

如果你愿意的话,使用文本编辑器也是个不错的选择,如atom,vscode,sublime等,相应的插件嘛,自行安装。

© 著作权归作者所有

O龙猫O

O龙猫O

粉丝 124
博文 39
码字总数 21143
作品 1
苏州
部门经理
私信 提问
加载中

评论(9)

Beaver_uic
Beaver_uic
这个阿里巴巴的风控引擎用的groovy,只不过,没用drools,全部用groovy,编译成class。效率高,他们业务量大
O龙猫O
O龙猫O 博主

引用来自“金龙”的评论

如果是用在项目中,java跟groovy之间数据交互怎么办啊?

引用来自“田舍先生”的评论

下一篇文章有说。这个系列,总共有三篇文章。

引用来自“金龙”的评论

恩,谢谢,找到了,请问,目前你们公司项目中已经开始在java中应用groovy了吗,效果如何?
在Activiti流程引擎中,有使用,效果还不错。
金龙
金龙

引用来自“金龙”的评论

如果是用在项目中,java跟groovy之间数据交互怎么办啊?

引用来自“田舍先生”的评论

下一篇文章有说。这个系列,总共有三篇文章。
恩,谢谢,找到了,请问,目前你们公司项目中已经开始在java中应用groovy了吗,效果如何?
O龙猫O
O龙猫O 博主

引用来自“金龙”的评论

如果是用在项目中,java跟groovy之间数据交互怎么办啊?
下一篇文章有说。这个系列,总共有三篇文章。
金龙
金龙
如果是用在项目中,java跟groovy之间数据交互怎么办啊?
金龙
金龙
你好
追峰路
追峰路
用drools呢?
O龙猫O
O龙猫O 博主

引用来自“linapex”的评论

我只想说,spring已经整合了groovy插件,我跟开涛也实现过 spring mvc 控制层使用 groovy 动态化实现。
你提供了一个非常有用的信息,我去查查,研究下。👍
linapex
linapex
我只想说,spring已经整合了groovy插件,我跟开涛也实现过 spring mvc 控制层使用 groovy 动态化实现。
java脚本引擎的设计原理浅析

本人在阿里巴巴长期担任和负责规则引擎、流程引擎相关的技术开发,另外还负责开发和维护开源项目: https://github.com/alibaba/QLExpress QLExpress是一个脚本引擎工具,类似Groovy,JRuby...

baobao_pandora
2018/08/01
0
0
Gradle入门系列(二)——groovy高级语法

groovy高级语法 一、json操作 使用groovy自带的json工具进行json操作 groovy.json.JsonSlurper:将json原数据转成实体对象 groovy.json.JsonOutput:将实体对象转成json数据 groovy是完全兼容...

GitLqr
01/05
0
0
activiti 中的一些信息

activiti 中的service script task 执行脚本任务(java自身脚本不在此列 如需关注看 javaservice) scriptFormat : 1. javascript(JDK 自带的脚步解析特性) 虽然早就知道 但是还未去看过 2. g...

triankg
2015/02/15
67
0
《Groovy极简教程》第1章 Groovy简介

《Groovy极简教程》第1章 Groovy简介 Groovy: 绝妙的; 流行的; 最佳状态的。 A multi-faceted language for the Java platform. (JVM平台上的多面体语言。) 官网文档:http://www.groovy-lan...

程序员诗人
2017/04/16
0
0
Groovy 能不能只允许代码中引入一部分java类库?

因为项目中想把groovy脚本放开给前台用户,让他们自定义一部分逻辑/规则,但又担心用户会输入 System.exit 之类的破坏性代码。所以想问 Groovy 能不能只允许代码中引入一部分java类库?或者是...

子木007
2013/03/28
844
6

没有更多内容

加载失败,请刷新页面

加载更多

使用zabbix自带的模板监控MySQL自带

一、安装zabbix server 略 二、安装zabbix agent 略 三、给主机套自带的模板 略 四、创建授权用户 mysql> grant all on *.* to 'zabbix'@'localhost' identified by 'musingtec2019';Quer......

雁南飞丶
10分钟前
4
0
notepad++快捷键

notepad++也情有独钟,最近发现了一个快捷键,就是选中单词,ctrl+shift+enter。不过现在想知道一个快捷键,假设有三行代码,选中后一般按TAB就可以三行全部缩进. Notepad++绝对是windows下进...

zhengzhixiang
32分钟前
5
0
区块链背景是什么?区块链的意义是什么?

一、前言 区块链技术的首次也是最著名的应用是比特币,一个在2009年1月初正式上线运行的去中心化数字货币应用,他的创始人叫中本聪,但目前大家并不知道此人的真实身份。 比特币不同于现代国...

daxiongdi
37分钟前
4
0
在Bash中循环浏览文件内容

如何使用Bash遍历文本文件的每一行? 使用此脚本: echo "Start!"for p in (peptides.txt)do echo "${p}"done 我在屏幕上得到以下输出: Start!./runPep.sh: line 3: syntax error......

技术盛宴
40分钟前
8
0
史上最强IP正则表达式

port ([0-9]|[1-9]\\d{1,3}|[1-5]\\d{4}|6[0-4]\\d{4}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5]) ipv4 ^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$ ipv4+mask......

蜗牛伊
43分钟前
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部