java应用中嵌入groovy

需求: 
某高校博士录取分数线录取算法是这样的: 
1、    硕博连读考生为外语45分以上(含45分,下同), 综合成绩(初试总分*0.7+复试分数*0.3)不低于60分; 
2、    普通考生(经济管理学院除外)为外语45分以上,专业课60分以上,综合成绩(初试总分/3*0.7+复试分数*0.3)不低于60分; 
3、    经济管理学院(001)考生外语55分以上,专业课60分以上,综合成绩(初试总分/3*0.7+复试分数*0.3)不低于60分。 

这段算法简单、清楚,用java实现是a piece of cake,但是考虑到我们的招生系统是为全国很多高校服务的,每个学校的录取算法可能有不同,不能在代码里面写死,最好是能让用户自己配置这段算法。这么简单的算法(高校研究生招生明规则还是比较简单的,潜规则就不清楚了)如果用规则引擎,显然是杀鸡用牛刀了。在目前的需求而言,用脚本语言来处理可能是更好的选择。 

java里面对脚本语言的支持很好,以前的话beanshell流行一点(印象中shark、jbpm里面都支持beanshell,不过很久没跟踪了,不知道现在这两大workflow engine的情况怎样了),现在groovy是越来越流行了,最新的groovy 1.6更号称性能有了巨大的改进。( http://www.infoq.com/articles/groovy-1-6 ),所以这里先尝试groovy。 

g了一下,发现在应用里嵌入groovy有三种方式(参考 http://groovy.codehaus.org/Embedding+Groovy ) 

第一种是比较传统的,通过GroovyShell的方式,跟用beanshell的方式差不多。 
Java代码   收藏代码
  1. Binding binding = new Binding();  
  2. binding.setVariable("foo"new Integer(2));  
  3. GroovyShell shell = new GroovyShell(binding);  
  4.   
  5. Object value = shell.evaluate("println 'Hello World!'; x = 123; return foo * 10");  
  6. assert value.equals(new Integer(20));  
  7. assert binding.getVariable("x").equals(new Integer(123));  


第二种方式是通过GroovyClassLoader来动态加载groovy类,然后直接使用groovy类。这点得以实现的原因是每一个groovy类编译后都是合法的java类。这种方式没有太多意思,还不如直接集成java编译器,编译java类后动态加载java类?呵呵。 
Java代码   收藏代码
  1. ClassLoader parent = getClass().getClassLoader();  
  2. GroovyClassLoader loader = new GroovyClassLoader(parent);  
  3. Class groovyClass = loader.parseClass(new File("src/test/groovy/script/HelloWorld.groovy"));  
  4.   
  5. // let's call some method on an instance  
  6. GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();  
  7. Object[] args = {};  
  8. groovyObject.invokeMethod("run", args);  


第三种方式是使用GroovyScriptEngine。如果要在应用中提供最完整的脚本支持,GroovyScriptEngine是不二之选。GSE会做依赖性检测,即某脚本依赖的脚本修改过了,整个脚本树都会重新编译、重新加载。 
Java代码   收藏代码
  1. import groovy.lang.Binding;  
  2. import groovy.util.GroovyScriptEngine;  
  3.   
  4. String[] roots = new String[] { "/my/groovy/script/path" };  
  5. GroovyScriptEngine gse = new GroovyScriptEngine(roots);  
  6. Binding binding = new Binding();  
  7. binding.setVariable("input""world");  
  8. gse.run("hello.groovy", binding);  
  9. System.out.println(binding.getVariable("output"));  


我们的应用暂时只需要简单的执行一段脚本就可以了,所以选用了第一种方式。将embeddable目录下的groovy-all-1.6.0.jar扔进类路径,在界面配置好脚本(见附图 
 
): 
Java代码   收藏代码
  1. result=false;  
  2. if(kslym=='12')  
  3. {  
  4.     zhcj=cszf*0.7+fscj*0.3;  
  5.     if(wgy>=45&&zhcj>=60)result=true;  
  6. }  
  7. else{  
  8.     if(yxsm!='001'){  
  9.         zhcj=cszf/3*0.7+fscj*0.3;  
  10.         if(wgy>=45&&ywk1>=60&&ywk2>=60&&zhcj>=60)result=true;  
  11.     }  
  12.     else{  
  13.          zhcj=cszf/3*0.7+fscj*0.3;  
  14.          if(wgy>=55&&ywk1>=60&&ywk2>=60&&zhcj>=60)result=true;  
  15.     }  
  16. }  


后台判断博士考生是否上线的方法: 
Java代码   收藏代码
  1. public Boolean canPassed(DoctorRecruitScoreObj score)  
  2. {  
  3.     Binding binding=new Binding();  
  4.     binding.setVariable("kslym",score.getDoctorResignup().getKslym());  
  5.     binding.setVariable("wgy",score.getEnglish());  
  6.     binding.setVariable("zzll",score.getZzll());  
  7.     binding.setVariable("ywk1",score.getCourseA());  
  8.     binding.setVariable("ywk2",score.getCourseB());  
  9.     binding.setVariable("cszf",score.getEnglish()+score.getZzll()+score.getCourseA()+score.getCourseB());  
  10.     binding.setVariable("fscj",score.getCourseC());  
  11.     binding.setVariable("yxsm",score.getDoctorResignup().getBkyxsm());  
  12.   
  13.     GroovyShell shell=new GroovyShell(binding);  
  14.     DoctorCuttingscore cuttingScore=getCuttingScore();  
  15.   
  16.     if(cuttingScore!=null)  
  17.     {  
  18.         shell.evaluate(cuttingScore.getRule());  
  19.         return (Boolean)binding.getVariable("result");  
  20.     }  
  21.     return false;  
  22. }  


简单说明:我痛恨变量命名采用拼音缩写,但是高校研*部很多的数据结构都是用拼音缩写来命名,所以这里的脚本只能跟他们接轨。脚本最终是要给老师改的。 

完工! 

执行效率还是不错的,不知道groovy evaluate同样的脚本后是否会用类似执行sql的方式缓存。在我们这里数据也比较少,只有几百条,毕竟博士考生还是比较少的,一般就几百人。不过呢,可能经过几年硕士就业率也不行了,又鼓励大家继续考博,那博士考生会不会上到几千呢?到时看要不要再优化程序吧,呵呵。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值