博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
几种规则策略
阅读量:4474 次
发布时间:2019-06-08

本文共 6717 字,大约阅读时间需要 22 分钟。

规则的起因

软件开发中经常会有很多复杂的条件判断,满足不同条件的时候执行不同的操作,而这些规则可能并不是一直不变的。

以某市几条积分规则为例:

年龄(最高30分)

  * 56-60岁   积5分

  * 每减少1岁 加2分

 

教育背景(最高110分)

  * 1:大专(高职); 50分
  * 2:本科; 60分
  * 3:本科+学历; 90分
  * 4:硕士; 100分
  * 5:博士 110分

 

技能类国家职业资格等级(最高140分)

  * 1:一级或高级职称; 140分
  * 2:二级或中级职称; 100分
  * 3:三级; 60分
  * 4:四级; 30分
  * 5:五级 15分

 

社保缴纳年限

  * year * 3

基于method/bean的简易规则

 规则配置:

public class ScoreRule {    /**     * 规则id     */    private Integer ruleId;    /**     * 规则名     */    private String ruleName;    /**     * 规则执行者     */    private String ruleExecuter;    /**     * 规则表达式(可以提供后台修改配置)     * eg:{"maxScore":30,"minRegion":56,"maxRegion":60,"regionScore":5,"scorePeYear":2}     */    private String ruleExpression;    /**     * 规则执行顺序     */    private Integer sort;    /**     * 是否可用     */    private Boolean enable;}

规则执行:

/**     * 评估积分     */    public Integer getUserSettleRules(UserInfoDto dto) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {        Integer baseScore = 0;        List
scoreRuleList = getScoreRuleList().stream().filter(r -> r.getEnable().equals(Boolean.TRUE)).sorted((x, y) -> x.getSort().compareTo(y.getSort())).collect(Collectors.toList()); for (ScoreRule scoreRule : scoreRuleList) { Method method = this.getClass().getDeclaredMethod(scoreRule.getRuleExecuter(), UserInfoDto.class); Integer result = (Integer) method.invoke(this, dto); if (result > 0) { log.info("methodName:" + scoreRule.getRuleExecuter() + ",result:" + result); baseScore += result; } } return baseScore; }

实现简单,将易于变化的参数提供给业务方配置;新增或修改规则需要调整代码重新发布。

 

类似基于method的方式,将不同的规则实现到不同的bean里,利用 SpringContextUtil.getBean(sortRule.getRuleExecuter()) 获取实现规则的bean,执行对应的规则。

基于规则

引用依赖:

com.alibaba
QLExpress
3.2.0

调用的java的方法:

  • userService.getUserInfo(userId);//指定userId获取用户信息
  • settleScore.getBaseScoreByEdu(userInfo);//传入userInfo按年龄计算基础积分
  • settleScore.getBaseScoreByEdu(userInfo);//传入userInfo按学历计算基础积分

传入参数:

context.put("userId", 2);//给userService.getUserInfo(userId)传入参数

context.put("userService", SpringContextUtil.getBean("userService"));//注入userService。调用userService.getUserInfo(userId)方法
context.put("settleScore", SpringContextUtil.getBean("settleScore"));//注入settleScore。调用settleScore.getBaseScoreByEdu(userInfo)、settleScore.getBaseScoreByEdu(userInfo)方法

UserService获取用户信息示例:

@Service("userService")public class UserService {    public UserInfoDto getUserInfo(Integer userId) {        if (userId == 1) {            UserInfoDto userInfoDto = new UserInfoDto();            userInfoDto.setUserName("张三");            userInfoDto.setAge(35);            userInfoDto.setDegreeOfEdu(1);            userInfoDto.setSkillLevel(1);            userInfoDto.setSocialSecurity(1);            return userInfoDto;        }        UserInfoDto userInfoDto = new UserInfoDto();        userInfoDto.setUserName("张三");        userInfoDto.setAge(58);        userInfoDto.setDegreeOfEdu(1);        userInfoDto.setSkillLevel(1);        userInfoDto.setSocialSecurity(1);        return userInfoDto;    }}

规则完整示例:

public void testQlExpress() throws Exception {        String qlExpress = "score = 0;" +                            "userInfo = userService.getUserInfo(userId);\n" +                                "if(userInfo.age > 0 && userInfo.age <= 60) {\n" +                                "result = settleScore.getBaseScoreByAge(userInfo);\n" +                                "System.out.println('>>>cal age score..........result:'+result);" +                                "score = score + result;" +                            "} if(userInfo.degreeOfEdu >= 1 && userInfo.degreeOfEdu <= 5) {\n" +                                "result = settleScore.getBaseScoreByEdu(userInfo);\n" +                                "System.out.println('>>>cal edu score..........result:'+result);" +                                "score = score + result;" +                            "}\n" +                            "System.out.println('return result:'+result);" +                            "return score;";        ExpressRunner runner = new ExpressRunner();        DefaultContext
context = new DefaultContext<>(); context.put("userId", 2); context.put("userService", SpringContextUtil.getBean("userService")); context.put("settleScore", SpringContextUtil.getBean("settleScore")); Object result = runner.execute(qlExpress, context, null, true, false); System.out.println("score result:" + result); }

执行结果:

2018-06-25 13:38:07.634 [INFO][http-nio-8088-exec-1]:c.demo.scorerule.SettleScore [getBaseScoreByAge:73] 基础积分计算>>>年龄积分:5

>>>cal age score..........result:5
2018-06-25 13:38:07.639 [INFO][http-nio-8088-exec-1]:c.demo.scorerule.SettleScore [getBaseScoreByEdu:121] 基础积分计算>>>教育背景:50
>>>cal edu score..........result:50
return result:50
score result:55

 

基于规则

将规则实现在drl文件里,java读取drl文件执行规则,可以做到动态更新drl规则而不需要发布。

引用drools包():

org.eclipse.jdt.core.compiler
ecj
4.5.1
org.drools
drools-core
5.5.0.Final
org.drools
drools-compiler
5.5.0.Final
org.eclipse.jdt.core.compiler
ecj

drl规则实现:

package com.drools.demo.pointimport com.logback.demo.scorerule.UserInfoDto;import com.logback.demo.scorerule.UserBaseScore;rule "ageBaseScore"//    salience 2    lock-on-active true    when        $userInfo : UserInfoDto(age >= 56 && age <= 60);    then        UserBaseScore.addScore(5);        System.out.println("age between 56 and 60");        $userInfo.recordPointLog($userInfo.getUserName(),"ageBaseScore");endrule "ageCalScore"//    salience 3//优先级,值越大越先执行    lock-on-active true    when        $userInfo : UserInfoDto(age < 56);    then        System.out.println("age less than 56. age:"+$userInfo.getAge());        Integer ageScore = (56 - $userInfo.getAge()) * 2;        UserBaseScore.addScore(ageScore > 30 ? 30 : ageScore);        $userInfo.recordPointLog($userInfo.getUserName(),"ageCalScore");endrule "eduLevel1Score"//    salience 3//优先级,值越大越先执行    lock-on-active true    when        $userInfo : UserInfoDto(degreeOfEdu == 1);    then        System.out.println("edu level is:"+$userInfo.getDegreeOfEdu());        UserBaseScore.addScore(50);        $userInfo.recordPointLog($userInfo.getUserName(),"eduLevel1Score");end

 

转载于:https://www.cnblogs.com/mr-yang-localhost/p/9204208.html

你可能感兴趣的文章
洛谷——P1602 Sramoc问题
查看>>
【MySQL笔记】字符串、时间日期转换
查看>>
jQuery实战之仿淘宝商城左侧导航效果
查看>>
AC日记——「SCOI2016」幸运数字 LiBreOJ 2013
查看>>
unmount
查看>>
数据库连接池
查看>>
javascript获得和设置以及移除元素属性的三个方法
查看>>
windwos iis 7.5 使用html 报405错误
查看>>
Java面向对象学习1——概念等
查看>>
redis集群搭建(简单简单)一台机器多redis
查看>>
【生活篇】微信运动刷步,高达98000!微信运动计步作弊教程!
查看>>
JAVA中获取工程路径的方法
查看>>
执行命令类
查看>>
hbase SingleColumnValueFilter 列不存在 无法过滤
查看>>
第一天
查看>>
linux ls -l 详解
查看>>
48、C++ Primer 4th 笔记,句柄类,继承,虚函数等的一个综合例子(未完)
查看>>
Tomcat搭建&配置
查看>>
2015535俞昆《网络对抗技术》恶意代码分析
查看>>
四种以太网数据包详解
查看>>