`
ivan
  • 浏览: 179472 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

在java应用中嵌入groovy

    博客分类:
  • java
阅读更多
需求:
某高校博士录取分数线录取算法是这样的:
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的方式差不多。
Binding binding = new Binding();
binding.setVariable("foo", new Integer(2));
GroovyShell shell = new GroovyShell(binding);

Object value = shell.evaluate("println 'Hello World!'; x = 123; return foo * 10");
assert value.equals(new Integer(20));
assert binding.getVariable("x").equals(new Integer(123));


第二种方式是通过GroovyClassLoader来动态加载groovy类,然后直接使用groovy类。这点得以实现的原因是每一个groovy类编译后都是合法的java类。这种方式没有太多意思,还不如直接集成java编译器,编译java类后动态加载java类?呵呵。
ClassLoader parent = getClass().getClassLoader();
GroovyClassLoader loader = new GroovyClassLoader(parent);
Class groovyClass = loader.parseClass(new File("src/test/groovy/script/HelloWorld.groovy"));

// let's call some method on an instance
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
Object[] args = {};
groovyObject.invokeMethod("run", args);


第三种方式是使用GroovyScriptEngine。如果要在应用中提供最完整的脚本支持,GroovyScriptEngine是不二之选。GSE会做依赖性检测,即某脚本依赖的脚本修改过了,整个脚本树都会重新编译、重新加载。
import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;

String[] roots = new String[] { "/my/groovy/script/path" };
GroovyScriptEngine gse = new GroovyScriptEngine(roots);
Binding binding = new Binding();
binding.setVariable("input", "world");
gse.run("hello.groovy", binding);
System.out.println(binding.getVariable("output"));


我们的应用暂时只需要简单的执行一段脚本就可以了,所以选用了第一种方式。将embeddable目录下的groovy-all-1.6.0.jar扔进类路径,在界面配置好脚本(见附图

):
result=false;
if(kslym=='12')
{
    zhcj=cszf*0.7+fscj*0.3;
    if(wgy>=45&&zhcj>=60)result=true;
}
else{
    if(yxsm!='001'){
        zhcj=cszf/3*0.7+fscj*0.3;
        if(wgy>=45&&ywk1>=60&&ywk2>=60&&zhcj>=60)result=true;
    }
    else{
         zhcj=cszf/3*0.7+fscj*0.3;
         if(wgy>=55&&ywk1>=60&&ywk2>=60&&zhcj>=60)result=true;
    }
}


后台判断博士考生是否上线的方法:
    public Boolean canPassed(DoctorRecruitScoreObj score)
    {
        Binding binding=new Binding();
        binding.setVariable("kslym",score.getDoctorResignup().getKslym());
        binding.setVariable("wgy",score.getEnglish());
        binding.setVariable("zzll",score.getZzll());
        binding.setVariable("ywk1",score.getCourseA());
        binding.setVariable("ywk2",score.getCourseB());
        binding.setVariable("cszf",score.getEnglish()+score.getZzll()+score.getCourseA()+score.getCourseB());
        binding.setVariable("fscj",score.getCourseC());
        binding.setVariable("yxsm",score.getDoctorResignup().getBkyxsm());

        GroovyShell shell=new GroovyShell(binding);
        DoctorCuttingscore cuttingScore=getCuttingScore();

        if(cuttingScore!=null)
        {
            shell.evaluate(cuttingScore.getRule());
            return (Boolean)binding.getVariable("result");
        }
        return false;
    }


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

完工!

执行效率还是不错的,不知道groovy evaluate同样的脚本后是否会用类似执行sql的方式缓存。在我们这里数据也比较少,只有几百条,毕竟博士考生还是比较少的,一般就几百人。不过呢,可能经过几年硕士就业率也不行了,又鼓励大家继续考博,那博士考生会不会上到几千呢?到时看要不要再优化程序吧,呵呵。
  • 大小: 56.8 KB
3
0
分享到:
评论
2 楼 ivan 2009-04-24  
spring里面要嵌入groovy也不算简单,就我以前了解的(参考http://www.ibm.com/developerworks/cn/java/j-groovierspring1.html),其实跟第二种方式差不多;而第二种方式是满足不了我的要求的,我不可能让老师到服务器上打开脚本文件来修改。(或者也可以让老师在系统里面配置,再保存到脚本文件里面?那其实也将问题复杂化了)
1 楼 stevezheng 2009-04-24  
为什么不用spring框架嵌入groovy呢,免得写那么多

相关推荐

    groovy-embedding:使用具有可重装功能的GroovyScriptEngine进行Groovy嵌入的示例测试

    这个想法是要运行该应用程序,并以Groovy的方式进行原型设计,使该应用程序运行,并可以选择将运行的代码最后转换为Java。 要运行,请输入gradle bootRun 要输入,请输入:curl 您将收到“ Hello World”问候: ...

    elasticsearch-plugin-ratpack:用于嵌入 Ratpack http 的 Elasticsearch 插件

    随着 Elasticsearch 中 Groovy 的认可,将 Ratpack 应用程序嵌入到 Elasticsearch 中是一个有趣的选择。 出于演示目的,您可以在插件安装后向 Elasticsearch 节点的 5050 端口发出 HTTP GET 请求。 curl '0:5050'...

    appengine-arbitrary-groovy-script-executor:Google App Engine上的Groovy脚本编辑器最终执行器

    App Engine身份验证和授权将脚本存储在Google Cloud Storage(可配置存储桶)中记住您上次编辑的脚本记住每个用户每次执行脚本的成功与否您可以将此编辑器嵌入到Spring Framework项目中,并通过绑定到执行环境的...

    ZK-devguide

    为了方便快速模型开发(prototyping)和定制,ZK允许开发人员嵌入EL表达式,以及您喜欢的脚本语言,包括但不限于 Java[3], JavaScript[4], Ruby[5] and Groovy[6]. 开发人员可以选择不嵌入任何脚本语言,如果他们喜欢...

    groovy-embedded

    常规嵌入 该示例显示了 ligthweigth 方法如何按需更改应用程序逻辑的业务逻辑。 Groovy 内部,Jetty 嵌入。

    Maven权威指南 很精典的学习教程,比ANT更好用

    验证你的Java安装 2.2. 下载Maven 2.3. 安装Maven 2.3.1. 在Mac OSX上安装Maven 2.3.2. 在Microsoft Windows上安装Maven 2.3.3. 在Linux上安装Maven 2.3.4. 在FreeBSD或OpenBSD上安装Maven 2.4. 验证Maven...

    dynamia-reports:使DynamiaTools应用创建并显示用户报告和图表的模块

    初始特征使用JPSQL或本机SQL创建查询创建或使用当前数据库数据源使用过滤器在屏幕上显示报告将报告导出到CVS,Excel和PDF 将报告发送到电子邮件查看报告将报告嵌入其他应用程序与任何DynamiaTools模块集成为模块未来...

    workshop-spring-4.0-to-4.2:Spring 4新功能研讨会

    工作坊-从Spring 4.0到4.2 ... 使用Groovy还使您可以轻松地将bean定义直接嵌入到引导代码中。 类固醇上的XML 可以用于使用逻辑来创建bean(有条件的) 可用于动态创建bean(迭代) 可以在运行时加载 泛型类型作

    hivmigration

    该项目代表了将HIV数据导出为适合导入到另一个系统中的格式所必需的代码,其中包括可以嵌入目标系统中以方便导入的Java API。 先决条件 这些步骤将设置HIV EMR1,Oracle,Pentaho和以下代码: 请遵循以下说明,使用...

Global site tag (gtag.js) - Google Analytics