• 规则引擎drools封装


    一.前言

        网上规则引擎drools介绍很多,并且有很多细致的说明,作者也不敢托大说自己的好用,但作者经过2个项目使用过规则引擎后,自己对规则引擎的理解并进行封装,对规则内容及如何使用,有自己的一番实践,并提供源代码,供大家参考


    二.设计思路及具体代码

        首先我希望是轻量级的使用drools,不希望使用太过复杂的架构,以这种思路入手,就可以与任何项目轻易融入,这样就需要能够将drools规则的来源,从规则文件(drl)中可以从maven和自己的数据库中获取,脚本是动态的,配合drools6.5支持通过maven接入的规则的API,就可以做到从任何处获取规则内容

    一个工具类DroolsUtils

    1. package com.vip.jie.rule.util;
    2. import org.drools.compiler.kie.builder.impl.InternalKieModule;
    3. import org.kie.api.KieServices;
    4. import org.kie.api.builder.KieBuilder;
    5. import org.kie.api.builder.KieFileSystem;
    6. import org.kie.api.builder.ReleaseId;
    7. import org.kie.api.builder.model.KieBaseModel;
    8. import org.kie.api.builder.model.KieModuleModel;
    9. import org.kie.api.builder.model.KieSessionModel;
    10. import org.kie.api.conf.EqualityBehaviorOption;
    11. import org.kie.api.conf.EventProcessingOption;
    12. import java.io.IOException;
    13. /**
    14. * 动态生成kjar
    15. * @author jie01.zhu
    16. * @DateTime 2018/3/19 22:14
    17. */
    18. public class DroolsUtils {
    19. /**
    20. * 创建默认的kbase和stateful的kiesession
    21. *
    22. * @param ks
    23. * @param isdefault
    24. * @return
    25. */
    26. private static KieFileSystem createKieFileSystemWithKProject(KieServices ks, boolean isdefault) {
    27. KieModuleModel kproj = ks.newKieModuleModel();
    28. KieBaseModel kieBaseModel1 = kproj.newKieBaseModel("KBase").setDefault(isdefault)
    29. .setEqualsBehavior(EqualityBehaviorOption.EQUALITY)
    30. .setEventProcessingMode(EventProcessingOption.STREAM);
    31. // Configure the KieSession.
    32. kieBaseModel1.newKieSessionModel("KSession").setDefault(isdefault)
    33. .setType(KieSessionModel.KieSessionType.STATEFUL);
    34. KieFileSystem kfs = ks.newKieFileSystem();
    35. kfs.writeKModuleXML(kproj.toXML());
    36. return kfs;
    37. }
    38. /**
    39. * 创建kjar的pom
    40. *
    41. * @param releaseId
    42. * @param dependencies
    43. * @return
    44. */
    45. private static String getPom(ReleaseId releaseId, ReleaseId... dependencies) {
    46. String pom = "<?xml version="1.0" encoding="UTF-8"?> "
    47. + "<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" "
    48. + " xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> "
    49. + " <modelVersion>4.0.0</modelVersion> " + " " + " <groupId>" + releaseId.getGroupId()
    50. + "</groupId> " + " <artifactId>" + releaseId.getArtifactId() + "</artifactId> " + " <version>"
    51. + releaseId.getVersion() + "</version> " + " ";
    52. if (dependencies != null && dependencies.length > 0) {
    53. pom += "<dependencies> ";
    54. for (ReleaseId dep : dependencies) {
    55. pom += "<dependency> ";
    56. pom += " <groupId>" + dep.getGroupId() + "</groupId> ";
    57. pom += " <artifactId>" + dep.getArtifactId() + "</artifactId> ";
    58. pom += " <version>" + dep.getVersion() + "</version> ";
    59. pom += "</dependency> ";
    60. }
    61. pom += "</dependencies> ";
    62. }
    63. pom += "</project>";
    64. return pom;
    65. }
    66. /**
    67. * 初始化一个kjar:把原有的drl包含进新建的kjar中
    68. *
    69. * @param ks
    70. * @param releaseId
    71. * @return
    72. * @throws IOException
    73. */
    74. public static InternalKieModule initKieJar(KieServices ks, ReleaseId releaseId) throws IOException {
    75. KieFileSystem kfs = createKieFileSystemWithKProject(ks, true);
    76. kfs.writePomXML(getPom(releaseId));
    77. KieBuilder kieBuilder = ks.newKieBuilder(kfs);
    78. if (!kieBuilder.buildAll().getResults().getMessages().isEmpty()) {
    79. throw new IllegalStateException("Error creating KieBuilder.");
    80. }
    81. return (InternalKieModule) kieBuilder.getKieModule();
    82. }
    83. public static InternalKieModule createKieJar(KieServices ks, ReleaseId releaseId, DroolsResource droolsResource) {
    84. KieFileSystem kfs = createKieFileSystemWithKProject(ks, true);
    85. kfs.writePomXML(getPom(releaseId));
    86. kfs.write("src/main/resources/" + droolsResource.getTargetResourceName(), droolsResource.getResource());
    87. KieBuilder kieBuilder = ks.newKieBuilder(kfs);
    88. if (!kieBuilder.getResults().getMessages().isEmpty()) {
    89. throw new IllegalStateException(
    90. "Error creating KieBuilder. errorMsg:" + kieBuilder.getResults().getMessages());
    91. }
    92. return (InternalKieModule) kieBuilder.getKieModule();
    93. }
    94. }

    重点调用参考:

    1. String fileName = "jie-" + group + "-rules";
    2. /**
    3.  * 指定kjar包
    4.  */
    5. final ReleaseId releaseId = kieServices.newReleaseId("com.vip.jie", fileName, "1.0.0");
    6. log.info("DroolsGetKieSession fileName:{}", fileName);
    7. log.info("[DroolsGetKieSession] drlStr:{}", drlStr);
    8. // 创建初始化的kjar
    9. InternalKieModule kJar = DroolsUtils.createKieJar(kieServices, releaseId,
    10. new DroolsResource(ResourceFactory.newByteArrayResource(drlStr.getBytes()),
    11. fileName + ".drl"));

        其次再将如何让使用者可以很灵活的接入,利用可变参数类型,将入参对象无限制传入,由规则脚本去决定入参的变化,通过此种方式可以比较好的实现业务灵活接入

    如下单元测试类:

    1. package com.vip.jie.rule.service.impl;
    2. import com.vip.jie.rule.object.User;
    3. import com.vip.jie.rule.service.RuleManager;
    4. import lombok.extern.slf4j.Slf4j;
    5. import org.junit.Test;
    6. import static junit.framework.TestCase.fail;
    7. /**
    8. * 规则测试
    9. * @author jie01.zhu
    10. * @DateTime 2018/3/19 21:17
    11. *
    12. */
    13. @Slf4j
    14. public class RuleManagerImplTest {
    15. private RuleManager ruleManager = new RuleManagerImpl();
    16. private String getRuleContent() {
    17. StringBuilder stringBuilder = new StringBuilder();
    18. stringBuilder.append("import com.vip.jie.rule.object.User; ");
    19. stringBuilder.append("rule test1 when ");
    20. stringBuilder.append("user : User(age==20) ");
    21. stringBuilder.append("then ");
    22. stringBuilder.append("user.setName("张三"); ");
    23. stringBuilder.append("end ");
    24. return stringBuilder.toString();
    25. }
    26. @Test
    27. public void executeRule1() throws Exception {
    28. User user = new User();
    29. user.setAge(20);
    30. //调用规则
    31. ruleManager.executeRule("test1", getRuleContent(), user);
    32. log.info("test result:{}", user.toString());
    33. if (!"张三".equals(user.getName())) {
    34. fail("error rule");
    35. }
    36. }
    37. @Test
    38. public void executeRule2() throws Exception {
    39. User user = new User();
    40. user.setAge(21);
    41. //调用规则
    42. ruleManager.executeRule("test1", getRuleContent(), user);
    43. log.info("test result:{}", user.toString());
    44. if ("张三".equals(user.getName())) {
    45. fail("error rule");
    46. }
    47. }
    48. }

    三.对应示例源代码获取方式

    githup:

    https://github.com/jie01/drools-demo

    csdn资源下载地址:

    https://download.csdn.net/download/vipshop_fin_dev/10296393


    还有一些关于安全性及与spring的封装思路,作者表示还会继续完善,并还不是最终版本,有需要可以持续关注-_-!


    与当前文章有关联的链接

    业务框架之个性化监控方案



    vipshop_ebs/朱杰

    2018-03-19


    原文地址:https://blog.csdn.net/vipshop_fin_dev/article/details/79618067
  • 相关阅读:
    JavaScript 技巧
    网页打开客户端本机程序,未安装则提示要求安装
    IIS(World Wide Web Publishing Service)127 无法响应的解决方法
    Jquery hover事件 示例
    JavaScript MVC
    jquery调用基于.NET Framework 3.5的WebService返回JSON数据
    文件下载类
    网页打印局部示例
    未能执行URL(FCK)
    网页中各种宽高
  • 原文地址:https://www.cnblogs.com/jpfss/p/12018133.html
Copyright © 2020-2023  润新知