drools规则引擎小案例一

1、基于drools规则引擎实现的动态创建规则语法生成结果如下:

package com.drools.rule.req
import com.drools.rule.req.LoginActionReq
rule login_rule_1 
when
 $s:LoginActionReq(loginNum==1) 
then
 $s.amount=10; 
update($s); 
end 

代码实现:

public class RuleReq {

    //LOGIN、登陆,PAY、支付
    private String actionType;

    //LOGIN_NUM、登陆了次数,LOGON_TIME、登陆时间
    //PAY_NUM、支付次数,PAY_TYPE、支付类型
    private String subActionType;

    //次数
    private Integer num;

    //开始时间
    private Date beginTime;

    //结束时间
    private Date endTime;

    //金额
    private Integer amount;

    public String getActionType() {
        return actionType;
    }

    public void setActionType(String actionType) {
        this.actionType = actionType;
    }

    public String getSubActionType() {
        return subActionType;
    }

    public void setSubActionType(String subActionType) {
        this.subActionType = subActionType;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }

    public Date getBeginTime() {
        return beginTime;
    }

    public void setBeginTime(Date beginTime) {
        this.beginTime = beginTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }

    public Integer getAmount() {
        return amount;
    }

    public void setAmount(Integer amount) {
        this.amount = amount;
    }
}
public class LoginActionReq extends ActionReq{

    //LOGIN_NUM、登陆了次数,LOGON_TIME、登陆时间
    private String loginActionType;

    //登陆次数
    private Integer loginNum;

    //登陆时间
    private Date loginTime;

    //增加积分金额
    public Integer amount;


    public boolean flag;


    public String getLoginActionType() {
        return loginActionType;
    }

    public void setLoginActionType(String loginActionType) {
        this.loginActionType = loginActionType;
    }

    public Integer getLoginNum() {
        return loginNum;
    }

    public void setLoginNum(Integer loginNum) {
        this.loginNum = loginNum;
    }

    public Date getLoginTime() {
        return loginTime;
    }

    public void setLoginTime(Date loginTime) {
        this.loginTime = loginTime;
    }

    public Integer getAmount() {
        return amount;
    }

    public void setAmount(Integer amount) {
        this.amount = amount;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}
public interface  BaseRuleBuild<T extends RuleReq>{

    DrlContext.Builder BUILDER = new DrlContext.Builder();

    default DrlContext getDrlContext(T ruleReq){
        setPackage();
        setImport();
        setRuleId(ruleReq);
        setExpireDate(ruleReq);
        setSalience(ruleReq);
        setActivationGroup(ruleReq);
        setWhenAndThen(ruleReq);
        return BUILDER.build();
    }

    default void setPackage(){
        BUILDER.setDrlPackage("package com.drools.rule.req \n");
    }

    void setImport();

    void setRuleId(T ruleReq);

    default void setExpireDate(T ruleReq){
        BUILDER.setDataExpires(
                new StringBuilder()
                        .append(DATE_EFFECTIVE)
                        .append(BLANK)
                        .append("\"")
                        .append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(ruleReq.getBeginTime()))
                        .append("\"")
                        .append(WRAP)
                        .append(DATE_EXPIRES)
                        .append(BLANK)
                        .append("\"")
                        .append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(ruleReq.getEndTime()))
                        .append("\"")
                        .append(WRAP).toString());
    }

    void setSalience(T ruleReq);

    void setActivationGroup(RuleReq ruleReq);

    void setWhenAndThen(RuleReq ruleReq);
}
@Service
public class LoginRuleBuild implements BaseRuleBuild<RuleReq> , InitializingBean{


    @Override
    public void setImport() {
        BUILDER.setDrlImport("import com.drools.rule.req.LoginActionReq \n");

        //BUILDER.setDrlImport("global java.util.ArrayList result \n");
    }

    @Override
    public void setRuleId(RuleReq ruleReq) {
        BUILDER.setDrlRuleId(new StringBuilder().append(RULE).append(BLANK).append("login_rule_id").append(WRAP).toString());
    }

    @Override
    public void setSalience(RuleReq ruleReq) {
        BUILDER.setSalience(
                new StringBuilder()
                        .append(SALIENCE)
                        .append(BLANK)
                        .append(100)
                        .append(BLANK)
                        .append(WRAP).toString());
    }

    @Override
    public void setActivationGroup(RuleReq ruleReq) {
        BUILDER.setActivationGroup(
                new StringBuilder()
                        .append(ACTIVATION_GROUP)
                        .append(BLANK)
                        .append("\"")
                        .append("LOGIN-GROUP-001")
                        .append("\"")
                        .append(BLANK)
                        .append(WRAP).toString());
    }

    @Override
    public void setWhenAndThen(RuleReq ruleReq) {

        StringBuilder stringBuilder = new StringBuilder();

        switch (UserLoginActionEnum.get(ruleReq.getSubActionType())){
            case LOGIN_NUM:
                stringBuilder = getLoginNumWhenAndThen(ruleReq);
                break;
            case LOGIN_TIME:
                //stringBuilder = getLoginTimeThen(ruleReq);
                break;

            default:
                break;
        }
        BUILDER.setDrlWhenAndThen(stringBuilder.toString());
    }


    private StringBuilder getLoginNumWhenAndThen(RuleReq ruleReq) {
        //这里提出另一种思路,如果when then条件比较复杂这样写必将导致这个方法膨胀的很厉害
        //可以设计一个drl模板文件加载到程序里面每次新增规则的时候动态替换里面的内容就好
        //什么时候有时间我再按这种思路实现一个
        //或者哪位小伙伴想做可以微信 yaoyaowuyuanqi 联系我给你开放修改权限
        return new StringBuilder().append(WHEN)
                .append(WRAP)
                .append(BLANK)
                .append("$s:LoginActionReq(")
                .append("loginNum").append("==").append(""+ruleReq.getNum()+"")
                .append(")")
                .append(BLANK)
                .append(WRAP)
                .append(THEN)
                .append(WRAP)
                .append(BLANK)
                .append("$s.setAmount(" + ruleReq.getAmount() + ");")
                //.append("result.add(\" hello world !\");")
                .append(WRAP)
                .append(BLANK)
                .append("update($s);")
                .append(WRAP)
                .append(END);
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        RuleBuildFactory.registerService(UserAction.UserActionEnum.LOGIN.name(), this);
    }
}
public class RuleBuildFactory {

    private static Map<String, BaseRuleBuild> buildService = new ConcurrentHashMap<>();

    private static Map<String, List<String>> rulesMap = new ConcurrentHashMap<>();

    public static void registerService(String actionType, BaseRuleBuild baseRuleBuild){
        buildService.putIfAbsent(actionType, baseRuleBuild);
    }

    public static BaseRuleBuild getBuildService(String actionType){
        return buildService.get(actionType);
    }

    public static void addRules(String subActionType, String ruleContext){
        if(rulesMap.containsKey(subActionType)){
            rulesMap.get(subActionType).add(ruleContext);
            return;
        }
        List<String> ruleContextList = new ArrayList<String>();
        ruleContextList.add(ruleContext);
        rulesMap.putIfAbsent(subActionType, ruleContextList);
    }

    public static List<String> getRules(String subActionType){
        return rulesMap.get(subActionType);
    }
}

@RestController
@RequestMapping("/rule")
public class CreateDrlController {

    @Resource
    private RuleService ruleService;

    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public Boolean create(@RequestBody RuleReq ruleReq){
        return ruleService.create(ruleReq);
    }

    @RequestMapping(value = "/login/action/execute", method = RequestMethod.POST)
    public Boolean execute(@RequestBody LoginActionReq actionReq){
        return ruleService.execute(actionReq);
    }

}

@Service
public class RuleServiceImpl implements RuleService {

    @Resource
    private RuleExecute ruleExecute;

    @Override
    public Boolean create(RuleReq ruleReq) {
        BaseRuleBuild baseRuleBuild = RuleBuildFactory.getBuildService(ruleReq.getActionType());
        DrlContext drlContext = baseRuleBuild.getDrlContext(ruleReq);

        //在实际项目中 drlContext.toString() 个内容需要落库存储并做一些防重验证等逻辑
        RuleBuildFactory.addRules(ruleReq.getSubActionType(), drlContext.toString());

        System.out.println(drlContext.toString());
        return true;
    }

    @Override
    public Boolean execute(LoginActionReq loginActionReq) {
        //这里需要去数据库查询出用户的登录次数,这里测试方便就用传过来的值
        loginActionReq.setLoginNum(loginActionReq.getLoginNum());

        List<String> rulesContext = RuleBuildFactory.getRules(loginActionReq.getLoginActionType());
        ActionReq actionReq = ruleExecute.execute(rulesContext, loginActionReq);
        System.out.println(JSONObject.toJSONString(actionReq));
        return true;
    }
}

最后使用postman body json 参数 {"actionType":"LOGIN","subActionType":"LOGIN_NUM","num":"1","amount":"10","beginTime":"2020-01-01 00:00:00","endTime":"2030-01-01 00:00:00"} 

调用 /rule/create 即可得到如下结果:

package com.drools.rule.req
import com.drools.rule.req.LoginActionReq
rule login_rule_1 
when
 $s:LoginActionReq(loginNum==1) 
then
 $s.amount=10; 
update($s); 
end 

调用  /rule/login/action/execute body json 参数 {"loginActionType":"LOGIN_NUM","loginNum":"1"} 即可看到执行结果

有问题可加微信

本案例已提交,有兴趣的可加微信获取

补充一句,加微信别老是您您您的,都是打工人,不必这么客气,我也才18啊哈哈

也请大家关注下博客谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值