java动态正则表达式_Java中动态规则的实现⽅式
背景
业务系统在应⽤过程中,有时候要处理“经常变化”的部分,这部分需求可能是“业务规则”,也可能是“不同的数据处理逻辑”,这部分动态规则的问题,往往需要可配置,并对性能和实时性有⼀定要求。
Java不是解决动态层问题的理想语⾔,在实践中发现主要有以下⼏种⽅式可以实现:
表达式语⾔(expression language)
动态语⾔(dynamic/script language language),如Groovy
规则引擎(rule engine)
表达式语⾔
Java Unified Expression Language,简称JUEL,是⼀种特殊⽤途的编程语⾔,主要在Java Web应⽤程序⽤于将表达式嵌⼊到web页⾯。Java规范制定者和Java Web领域技术专家⼩组制定了统⼀的表达式语⾔。JUEL最初包含在JSP 2.1规范JSR-245中,后来成为Java EE 7的⼀部分,改在JSR-341中定义。
这⾥主要介绍在实践中使⽤较多的MVEL、OGNL和SpEL。
OGNL(Object Graph Navigation Library)
在Struts 2 的标签库中都是使⽤OGNL表达式访问ApplicationContext中的对象数据,简单⽰例:
Foo foo = newFoo();
foo.setName("test");
Map context = new HashMap();
context.put("foo",foo);
String expression = "foo.name == 'test'";
try{
Boolean result =(Boolean) Value(expression,context);
System.out.println(result);
} catch(OgnlException e) {
e.printStackTrace();
}
MVEL
MVEL最初作为Mike Brock创建的 Valhalla项⽬的表达式计算器(expression evaluator),相⽐最初的OGNL、JEXL和JUEL等项⽬,⽽它具有远超它们的性能、功能和易⽤性 - 特别是集成⽅⾯。它不会尝试另⼀种JVM语⾔,⽽是着重解决嵌⼊式脚本的问题。
MVEL主要使⽤在Drools,是Drools规则引擎不可分割的⼀部分。
MVEL语法较为丰富,不仅包含了基本的属性表达式,布尔表达式,变量复制和⽅法调⽤,还⽀持函数定义,详情参见MVEL Language Guide 。
MVEL在执⾏语⾔时主要有解释模式(Interpreted Mode)和编译模式(Compiled Mode )两种:
解释模式(Interpreted Mode)是⼀个⽆状态的,动态解释执⾏,不需要负载表达式就可以执⾏相应的脚本。
编译模式(Compiled Mode)需要在缓存中产⽣⼀个完全规范化表达式之后再执⾏。
//解释模式
Foo foo = newFoo();
foo.setName("test");
Map context = newHashMap();
String expression = "foo.name == 'test'";
VariableResolverFactory functionFactory = newMapVariableResolverFactory(context);
context.put("foo",foo);
Boolean result =(Boolean) MVEL.eval(expression,functionFactory);
System.out.println(result);
//编译模式
Foo foo = new Foo();foo.setName("test");
Map context = newHashMap();
String expression = "foo.name == 'test'";
VariableResolverFactory functionFactory = new MapVariableResolverFactory(context);context.put("foo",foo);
Serializable compileExpression =MVELpileExpression(expression);
Boolean result = (Boolean) uteExpression(compileExpression, context, functionFactory);
SpEL
SpEl(Spring表达式语⾔)是⼀个⽀持查询和操作运⾏时对象导航图功能的强⼤的表达式语⾔。 它的语法类似于传统EL,但提供额外的功能,最出⾊的就是函数调⽤和简单字符串的模板函数。SpEL类似于Struts2x中使⽤的OGNL表达式语⾔,能在运⾏时构建复杂表达式、存取对象图属性、对象⽅法调⽤等等,并且能与Spring功能完美整合,如能⽤来配置Bean定义。
SpEL主要提供基本表达式、类相关表达式及集合相关表达式等,详细参见Spring 表达式语⾔ (SpEL) 。
类似与OGNL,SpEL具有expression(表达式),Parser(解析器),EvaluationContext(上下⽂)等基本概念;类似与MVEL,SpEl也提供了解释模式和编译模式两种运⾏模式。
//解释器模式
Foo foo = newFoo();
foo.setName("test");
// Turn on:
// - auto null reference initialization
// - auto collection growing
SpelParserConfiguration config = new SpelParserConfiguration(true,true);
ExpressionParser parser = newSpelExpressionParser(config);
String expressionStr = "#foo.name == 'test'";
StandardEvaluationContext context = newStandardEvaluationContext();
context.setVariable("foo",foo);
Expression expression =parser.parseExpression(expressionStr);
Boolean result = Value(context,Boolean.class);
//编译模式
config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, ClassLoader()); parser = newSpelExpressionParser(config);
context = newStandardEvaluationContext();
context.setVariable("foo",foo);
expression =parser.parseExpression(expressionStr);
result = Value(context,Boolean.class);
规则引擎
AviatorScript 是⼀门⾼性能、轻量级寄宿于 JVM 之上的脚本语⾔。
使⽤场景包括:
规则判断及规则引擎
公式计算
动态脚本控制
集合数据 ELT 等
public classTest {public static voidmain(String[] args) {
String expression= "a+(b-c)>100";//编译表达式
Expression compiledExp =AviatorEvaluatorpile(expression);
Map env = new HashMap<>();
env.put("a", 100.3);
env.put("b", 45);
env.put("c", -199.100);//执⾏表达式
Boolean result =(Boolean) ute(env);
System.out.println(result);
}
}
Easy Rules is a Java rules engine。
使⽤POJO定义规则:
@Rule(name = "weather rule", description = "if it rains then take an umbrella")public classWeatherRule { @Conditionpublic boolean itRains(@Fact("rain") booleanrain) {returnrain;
}
@Actionpublic voidtakeAnUmbrella() {
System.out.println("It rains, take an umbrella!");
}
}
Rule weatherRule= newRuleBuilder()
.name("weather rule")
.description("if it rains then take an umbrella")
.when(facts-> ("rain").equals(true))
.then(facts-> System.out.println("It rains, take an umbrella!"))
.build();
⽀持使⽤表达式语⾔(MVEL/SpEL)来定义规则:
name: "weather rule"description:"if it rains then take an umbrella"condition:"rain == true"actions:- "System.out.println(\"It rains, take an umbrella!\");"
MVELRuleFactory ruleFactory = new MVELRuleFactory(newYamlRuleDefinitionReader());
Rule weatherRule= ateRule(new FileReader("l"));
触发规则:
public classTest {public static voidmain(String[] args) {//define facts
Facts facts = newFacts();
facts.put("rain", true);//define rules
Rule weatherRule =...
Rules rules= newRules();
RulesEngine rulesEngine = newDefaultRulesEngine();
rulesEngine.fire(rules, facts);
}
}
An open source rule engine, DMN engine and complex event processing (CEP) engine for Java and the JVM Platform.
定义规则:
import com.lrq.wechatDemo.domain.User //导⼊类
dialect "mvel"rule"age" //规则名,唯⼀
when
$user : User(age<15 || age>60) //规则的条件部分
then
System.out.println("年龄不符合要求!");
end
参考例⼦:
public classTestUser {private static KieContainer container = null;private KieSession statefulKieSession = null;
@Testpublic voidtest(){
KieServices kieServices=();
KieClasspathContainer();
statefulKieSession= wKieSession("myAgeSession");
User user= new User("duval yang",12);
statefulKieSession.insert(user);
statefulKieSession.fireAllRules();
statefulKieSession.dispose();
}
}
drools是⽐较重的规则引擎,有⾃⼰的状态存储,详见其官⽅⽂档。
Esper is a component for complex event processing (CEP), streaming SQL and event series analysis, available for Java as Esper, and for .NET as NEsper.
⼀个例⼦:
public classTest {public static void main(String[] args) throwsInterruptedException {
EPServiceProvider DefaultProvider();
EPAdministrator EPAdministrator();
String product= Name();
String epl= "select avg(price) from " + product + ".win:length_batch(3)";
EPStatement ateEPL(epl);
state.addListener(newAppleListener());
EPRuntime EPRuntime();
Apple apple1= newApple();
apple1.setId(1);
apple1.setPrice(5);
java技术专家runtime.sendEvent(apple1);
Apple apple2= newApple();
apple2.setId(2);
apple2.setPrice(2);
runtime.sendEvent(apple2);
Apple apple3= newApple();
apple3.setId(3);
apple3.setPrice(5);
runtime.sendEvent(apple3);

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。