java规则实现_规则容器的实现

希望大家提出保贵意见~

优点:

1、规则规范业务流程,且现有规则已经实现不仅使用在流程平台上且可以其他模块,如:作业计划。仅需配置。

2、支持xml中配置表达式,工程人员将输入/输出参数使用表达式配置进行赋值(不需书写任何代码),故而影响流程的流向。

3、支持xml中配置规则分组,并将规则赋予优先级,规则会按照规则分组优先级执行规则,直到满足规则条件退出。

4、支持除表达式复杂的业务逻辑,工程人员可以开发java代码实现业务方法,在xml中简单配置即可以实现复杂业务逻辑。

5、支持listener,在调用规则之前、之后都会触发before(),after()方法。工程人员可按业务编写多个lisener,使lisener有效只需要简单xml配置。

6、支持输入输出参数的验证,根据二次开发人员的xml配置,按输入输出参数配置类型进行验证,若输入/输出参数不符合业务要求则抛出异常。

发展:

1、xml的web页面配置,提供eclipse plugin配置,将需要手动xml配置的地方使用web,eclipse plugin的方式实现工具配置,

其中可实现,若需要判断值,如执行类型,工程人员在配置xml时每次要查数据库对应找出值配上,而现在只要求二次二发人员提供取数据库表的方法,

规则配置工具会将表中的内存如:1,草稿;2,转派;这些内容以下拉列表方式供工程人员选对,以节省工程人员的麻烦。

2、支持drools。

3、与使用规则的组件更有机的结果,如流程平台、作业计划。

依赖关系:

1、文件配置

2、castor

3、ongl

使用:

规则关心的是输入/输出参数,也即将输入参数以java.util.Map传入,通过key="参数名称",value="参数类型"

根据传入的参数组合条件,将输出参数以java.util.Map类型返回,也通过key="参数名称",value="参数类型"

以com.boco.eoms.commons.rule.test.service.RuleServiceFacadeTest.java 为例测试自定义java规则及规则分组调用

为说明例子,我编写了com.boco.eoms.commons.rule.sample.Rule1InputParameter1Sample.java及同包下的Rule1InputParameter2Sample.java

做为输入参数

com.boco.eoms.commons.rule.Rule1OutputParameter1Sample.java及同包下Rule1OutputParameter2Sample.java做为输出参数

com.boco.eoms.commons.rule.Rule1Sample.java及com.boco.eoms.commons.rule.Rule2Sample.java为例说明自定义java规则及规则分组

com.boco.eoms.commons.rule.sample.Rule1ListenerSample.java为自定义listener

com.boco.eoms.commons.rule.sample.RuleSample.xml配置规则,先介绍轮廓,之后会详细介绍

rule的说明是个比较不好说明的东西,所以有些枯燥,:-)

配置文件如下说明:

style=" ( $parameter != $l{springbean.getNames} || false ) && $text ? $r{springbean.getName} : 3 " />

id="Rule1Sample">

type="com.boco.eoms.commons.rule.sample.Rule1InputParameter1Sample" />

type="com.boco.eoms.commons.rule.sample.Rule1InputParameter2Sample" />

expression=""

name="rule1OutputParameter1Sample"

type="com.boco.eoms.commons.rule.sample.Rule1OutputParameter1Sample"

drl=""

expStyleId="rule1Express" />

expression=""

name="rule1OutputParameter2Sample"

type="com.boco.eoms.commons.rule.sample.Rule1OutputParameter2Sample"

drl=""

expStyleId="rule1Express" />

name="com.boco.eoms.commons.rule.sample.Rule1ListenerSample" />

name="com.boco.eoms.commons.rule.listener.RuleCheckListener" />

id="Rule2Sample">

type="com.boco.eoms.commons.rule.sample.Rule1InputParameter1Sample" />

type="com.boco.eoms.commons.rule.sample.Rule1InputParameter2Sample" />

expression=" ( ${rule1InputParameter1Sample.name} != 'value3' || false) && true ? $b{springbean.getName} : 3 "

name="rule1OutputParameter1Sample"

type="com.boco.eoms.commons.rule.sample.Rule1OutputParameter1Sample"

drl="classpath:com.boco.eoms.commons.rule.sample.rule1Parameter1Sample.drl"

expStyleId="rule1Express" />

expression=" rule1InputParameter1Sample.name != '234' && rule1InputParameter1Sample.age >10 ? rule1InputParameter1Sample.name : rule1InputParameter1Sample.age "

name="rule1OutputParameter2Sample"

type="com.boco.eoms.commons.rule.sample.Rule1OutputParameter2Sample"

drl="classpath:com.boco.eoms.commons.rule.sample.rule1Parameter2Sample.drl"

expStyleId="rule1Express" />

name="com.boco.eoms.commons.rule.sample.Rule1ListenerSample" />

name="com.boco.eoms.commons.rule.listener.RuleCheckListener" />

OK,现在我们看看自定义java写了什么

public class Rule1Sample extends RuleService {

/**

* @param ruleListeners

* @param rules

* @param rule

* @param xmlPath

*/

public Rule1Sample(List ruleListeners, RuleEngine rules, Rule rule,

String xmlPath) {

super(ruleListeners, rules, rule, xmlPath);

}

/**

* 二次开发人员需实现的业务接口

*

* @param map

*            根据配置文件中input的配置,二次开发人员取出配置的参数,

*            如sample配置key="rule1InputParameter1Sample",value="com.boco.eoms.commons.rule.sample.Rule1InputParameter1Sample"

*            key="rule1Parameter2InputSample",value="com.boco.eoms.commons.rule.sample.Rule1InputParameter2Sample"

*            这时二次发人员在execute中按这种方式取参数

*            com.boco.eoms.commons.rule.sample.Rule1InputParameter1Sample

*            param1=(com.boco.eoms.commons.rule.sample.Rule1InputParameter1Sample)

*            map.get("rule1InputParameter1Sample");

*            com.boco.eoms.commons.rule.sample.Rule1InputParameter2Sample

*            param2=(com.boco.eoms.commons.rule.sample.Rule1InputParameter1Sample)

*            map.get("rule1InputParameter2Sample");

*

* @return 根据配置文件output的配置,二次开发人员需返回配置的参数 如sample配置

*         key="rule1OutputParameter1Sample",value="com.boco.eoms.commons.rule.sample.Rule1OutputParameter1Sample"

*         key="rule1OutputParameter2Sample",value="com.boco.eoms.commons.rule.sample.Rule1OutputParameter2Sample"

*         配置人员需按业务要求,返回

*         map.put("rule1OutputParameter1Sample",com.boco.eoms.commons.rule.sample.Rule1OutputParameter1Sample);

*         map.put("rule1OutputParameter2Sample",com.boco.eoms.commons.rule.sample.Rule1OutputParameter2Sample);

*         return map;

* @throws RuleException

*/

public Map execute(Map map,Rule rule) throws RuleException {

// 规则业务

// 取输入参数

Rule1InputParameter1Sample inputParam1 = (Rule1InputParameter1Sample) map

.get("rule1InputParameter1Sample");

Rule1InputParameter2Sample inputParam2 = (Rule1InputParameter2Sample) map

.get("rule1InputParameter2Sample");

Map outMap = new HashMap();

Rule1OutputParameter1Sample outParam1 = new Rule1OutputParameter1Sample();

Rule1OutputParameter2Sample outParam2 = new Rule1OutputParameter2Sample();

// 模拟规则,年龄大于10数,姓名不为匿名,则outParam1设为可通过

if (inputParam1.getAge() > 10

&& !"anonym".equals(inputParam1.getName())) {

// 为说明业务逻辑所以将setName放入判断条件

outParam1.setName(inputParam1.getName());

outParam1.setOk(true);

} else {

// 为说明业务逻辑所以将setName放入判断条件

outParam1.setName(inputParam1.getName());

outParam1.setOk(false);

}

// 性别为男则通过

if ("male".equals(inputParam2.getSex())) {

outParam2.setSex("male");

outParam2.setOk(true);

} else {

outParam2.setSex("male");

outParam2.setOk(false);

}

outMap.put("rule1OutputParameter1Sample", outParam1);

outMap.put("rule1OutputParameter2Sample", outParam2);

// 返回输出参数

return outMap;

}

}

以Rule1Sample.java为例,需继承RuleService并实现execute方法,业务逻辑写在该方法内,如Rule1Sample.java

按照配置的输入/输出参数进行操作。

同时开发人员需要 像RuleServiceFacadeTest这样调用,按注释调用,请看注释

public class RuleServiceFacadeTest extends TestCase {

private RuleServiceFacade facade;

private Map inputMap;

private Rule1InputParameter1Sample inputParam1;

private Rule1InputParameter2Sample inputParam2;

private String xmlPath = "";

private String groupId = "";

/**

* 输入参数初始化

*/

protected void setUp() throws Exception {

facade = RuleServiceFacade.create();

// 测试输入参数类弄与xml是否匹配

inputMap = new HashMap();

inputParam1 = new Rule1InputParameter1Sample();

inputParam2 = new Rule1InputParameter2Sample();

inputParam1.setAge(10);

inputParam1.setName("qjb");

inputParam2.setSex("male");

inputMap.put("rule1InputParameter1Sample", inputParam1);

inputMap.put("rule1InputParameter2Sample", inputParam2);

xmlPath = "classpath:com/boco/eoms/commons/rule/sample/RuleSample.xml";

groupId = "group1";

super.setUp();

}

protected void tearDown() throws Exception {

super.tearDown();

}

/**

* 以classpath:com/boco/eoms/commons/rule/sample/RuleSample.xml为配置文件,调用rule1Sample为ruleId,以inputMap为输入参数,

*

*/

public void testInvokeRuleService() {

try {

facade.invokeRuleService(xmlPath, "Rule1Sample", inputMap);

} catch (RuleException e) {

fail();

}

}

/**

* 以规则分组(路由)方式调用,调用groupId即group1,按照xml配置是调用了两个rule,按照优先级(数字由大到小)先后调用

* 以不同输入参数调用

*/

public void testInvokeRuleGroupForDiffInputMap() {

Map map = new HashMap();

Map outMap = null;

// 以不同输入参数调用

map.put("Rule1Sample", inputMap);

map.put("Rule2Sample", inputMap);

try {

outMap = facade.invokeRuleGroupForDiffInputMap(xmlPath, groupId,

map);

} catch (RuleException e) {

fail();

}

checkOutMap(outMap);

}

/**

* 以规则分组(路由)方式调用,调用groupId即group1,按照xml配置是调用了两个rule,按照优先级(数字由大到小)先后调用

* 以相同输入参数调用

*

*/

public void testInvokeRuleGroupForSampeInputMap() {

Map outMap = null;

try {

outMap = facade.invokeRuleGroupForSampeInputMap(xmlPath, groupId,

inputMap);

} catch (RuleException e) {

e.printStackTrace();

fail();

}

checkOutMap(outMap);

}

/**

* 验证输出参数,用于测试

*

* @param outMap

*/

private void checkOutMap(Map outMap) {

Rule1OutputParameter2Sample outPram2 = (Rule1OutputParameter2Sample) outMap

.get("rule1OutputParameter2Sample");

assertEquals(outPram2.getSex(), "male");

assertEquals(outPram2.isOk(), true);

}

}

这时再看自定义的listener

com.boco.eoms.commons.rule.sample.Rule1ListenerSample.java

public class Rule1ListenerSample implements IRuleListener {

private Logger logger = Logger.getLogger(this.getClass());

/**

* 执行规则后调用

*/

public void after(Map inputMap, Rule rule) throws RuleException {

logger.debug(rule.getId() + " after");

}

/**

* 执行规则前调用

*/

public void before(Map outputMap, Rule rule) throws RuleException {

logger.debug(rule.getId() + " before");

}

}

需要实现IRuleListener.java的after及before方法

ok,运行com.boco.eoms.commons.rule.RuleServiceFacadeTest.java测试用例。

晕了吧~,重新看下,OK,以上内容为自定义调用,下面说说表达式方式调用

以com.boco.eoms.commons.rule.test.service.ExpressionRuleServiceTest.java 为例测试表达式的规则

按com.boco.eoms.commons.rule.sample.ExpressionRuleSample.xml中配置

style=" ( $parameter != $l{springbean.getNames} || false ) && $text ? $r{springbean.getName} : 3 " />

className="com.boco.eoms.commons.rule.service.ExpressionRuleService"

id="ExpressionRule">

type="com.boco.eoms.commons.rule.sample.Rule1InputParameter1Sample" />

type="com.boco.eoms.commons.rule.sample.Rule1InputParameter2Sample" />

expression="#rule1InputParameter1Sample.age>5 && #rule1InputParameter1Sample.name=='qjb'?#rule1InputParameter1Sample.result:#rule1InputParameter1Sample.getStr(#rule1InputParameter1Sample.name)"

name="rule1OutputParameter1Sample"

type="java.lang.String"

drl="" expStyleId="" />

expression="#rule1InputParameter1Sample.age>5?#rule1InputParameter1Sample.setAge(5):#rule1InputParameter1Sample.setAge(6),#rule1InputParameter1Sample"

name="rule1OutputParameter2Sample"

type="com.boco.eoms.commons.rule.sample.Rule1InputParameter1Sample"

drl="" expStyleId="" />

name="com.boco.eoms.commons.rule.sample.Rule1ListenerSample" />

name="com.boco.eoms.commons.rule.listener.RuleCheckListener" />

运行com.boco.eoms.commons.rule.test.service.ExpressionRuleServiceTest.java测试用例

仔细看下测试用例,应该很好理解,

恭喜,恭喜,熟练掌握rule了吧?:-)

痛苦的再写下去,再说说rule的扩展吧~

基于rule去扩展是很简单的~

举个例子,其实表达式的支持,就是我扩展的一个类,看下

com.boco.eoms.commons.rule.service.ExpressionRuleService.java

public class ExpressionRuleService extends RuleService {

@Override

protected Map execute(Map inputMap,

Rule rule) throws RuleException {

// 创建表达式解析service

OgnlExpressionService oes = OgnlExpressionService.create(null);

Map outMap = new HashMap();

// 取输出参数

for (Iterator it = rule.getOutput().getParameters().iterator(); it

.hasNext();) {

Parameter para = (Parameter) it.next();

// 将输出参数配置的表达式结果按照配置名称写入outMap

outMap.put(para.getName(), oes.getValue(para.getExpression(),

inputMap));

}

return outMap;

}

/**

* @param ruleListeners

* @param rules

* @param rule

* @param xmlPath

*/

public ExpressionRuleService(List ruleListeners, RuleEngine rules,

Rule rule, String xmlPath) {

super(ruleListeners, rules, rule, xmlPath);

}

}

看下,没什么内容吧,只需继承RuleService,重写execute方法,在里面实现你的业务逻辑,

其实就是自定义规则,但也可以写成通用的呀。就像将来要扩展的drools一样,将来新增个

DroolsRuleService就OK了。这时在xml配置时,在className配置刚刚写的DroolsRuleService的类就OK了。

这样就实现了对drools的支持

className="com.boco.eoms.commons.rule.service.ExpressionRuleService"

id="ExpressionRule">

type="com.boco.eoms.commons.rule.sample.Rule1InputParameter1Sample" />

type="com.boco.eoms.commons.rule.sample.Rule1InputParameter2Sample" />

再说说监听,有人说你的监听不是没用的吗,我要实现自定义业务逻辑,只需在execute方法最前端及后端加上我要在listener中要做的事,

这不一样能解决吗,OK,我们来看下,完全没错,可以解决,除非你想将listener的东西藕荷在业务逻辑,当然listener的before(),after()方法

不包含你的业务逻辑。再说下,若你不实现自定义规则呢,你怎么实现在before(),after()方法的内容呢,哈哈。再以一个例子说明,其实rule的

参数验证机制就是一个listener实现的,看一下com.boco.eoms.rule.listener.RuleCheckListener.java

public class RuleCheckListener implements IRuleListener {

public void after(Map map, Rule rule) throws RuleException {

// 取输入参数

for (Iterator outputIt = rule.getOutput().getParameters().iterator(); outputIt

.hasNext();) {

Parameter para = (Parameter) outputIt.next();

// 验证map中的所存的对象与xml配置是否相符

RuleConfigWrapper.checkMapType(map, para);

}

}

public void before(Map map, Rule rule) throws RuleException {

// 取输入参数

for (Iterator inputIt = rule.getInput().getParameters().iterator(); inputIt

.hasNext();) {

Parameter para = (Parameter) inputIt.next();

// 验证map中的所存的对象与xml配置是否相符

RuleConfigWrapper.checkMapType(map, para);

}

}

}

这就是输入/输出参数与xml配置的验证呀,呵呵~

OK,现在编写你的listenr吧

只需实现IRuleListener,并实现after(),befor()方法,

配置时在xml中配置,贴一段

name="com.boco.eoms.commons.rule.sample.Rule1ListenerSample" />

name="com.boco.eoms.commons.rule.listener.RuleCheckListener" />

很简单吧~

posted on 2007-04-28 09:49 曲静波 阅读(1199) 评论(0)  编辑  收藏 所属分类: others

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值