借鉴:基于JAVA的功能强大的开源规则引擎-Drools业务管理系统实战视频教程_哔哩哔哩_bilibili 1、什么是规则引擎? 规则引擎,全称为业务规则管理系统,英文名为BRMS(即Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模板编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。 需要注意的的规则引擎并不是一个具体的技术框架,而是指的一类系统,即业务规则管理系统。目前市面上具体的规则引擎产品有:drools、VisualRules、iLog等。 规则引擎实现了将业务决策从应用程序代码中分离出来,接收数据输入,解释业务规则,并根据业务规则做出业务决策。规则引擎其实就是一个输入输出平台。 2、Drools介绍 drools是一款由JBoss组织提供的基于java语言开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件或特定的存储介质中(如存放在数据库中),使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效。 drools官网:https://www.drools.org/ drools中文网:Drools中文网 | 基于java的功能强大的开源规则引擎 drools源码下载地址:https://github.com/kiegroup/drools 在项目中使用drools时,既可以单独使用也可以整合spring使用。如果单独使用只需导入如下maven坐标即可:
1 2 3 4 5 |
<dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <version>7.6.0.Final</version> </dependency> |
3、Drools入门案例 1、业务场景说明 业务场景:消费者在图书商城购买图书,下单后需要在支付页面显示订单优惠后的价格。具体优惠规则如下: 现在需要根据上面的规则计算优惠后的价格。 2、开发实现 第一步:创建maven工程并导入drools相关maven坐标
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!-- drools规则引擎 --> <dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <version>7.6.0.Final</version> </dependency> <!-- junit单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> |
第二部:根据drools要求创建resources/META-INF/kmodule.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> <!-- name:指定kbase的名称,可以任意,但是需要唯一 packages:指定规则文件的目录,需要根据实际情况填写,否则无法加载到规则文件 default:指定当前kbase是否为默认 --> <kbase name="myKbase1" packages="rules" default="true"> <!-- name:指定ksession的名称,可以任意,但需要唯一 default:指定当前session是否为默认 --> <ksession name="ksession-rule" default="true"/> </kbase> </kmodule> |
注意:上面配置文件的名字和位置都是固定写法,不能更改。 第三步:创建实体类Order
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.ws.soon.entity; import lombok.Data; /** * 订单 */ @Data public class Order { private Double originalPrice; // 订单原始价格,即优惠前的价格 private Double realPrice; // 订单真实价格,即优惠后的价格 } |
第四步:创建规则文件resources/rules/bookDiscount.drl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
// 图书优惠规则 package book.discount import com.ws.soon.entity.Order // 规则一:所购图书总价在100元以下的没有优惠 rule "book_discount_1" when $order: Order(originalPrice < 100) // 匹配模式,到规则引擎中(工作内存)查找Order对象,命名为$order then $order.setRealPrice($order.getOriginalPrice()); System.out.println("成功匹配到规则一,所购图书总价在100元以下无优惠"); end // 规则二:所购图书总价在100~200的优惠20元 rule "book_discount_2" when $order: Order(originalPrice >= 100 && originalPrice < 200) then $order.setRealPrice($order.getOriginalPrice() - 20); System.out.println("成功匹配到规则二,所购图书总价在100~200元之间"); end // 规则三:所购图书总价在200~300元的优惠50元 rule "book_discount_3" when $order: Order(originalPrice >= 200 && originalPrice < 300) then $order.setRealPrice($order.getOriginalPrice() - 50); System.out.println("成功匹配到规则三,所购图书总价在200~300元之间"); end // 规则四:所购图书总价在300元及以上的优惠100元 rule "book_discount_4" when $order: Order(originalPrice >= 300) then $order.setRealPrice($order.getOriginalPrice() - 100); System.out.println("成功匹配到规则四,所购图书总价在300元及以上"); end |
第五步:编写单元测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package com.ws.soon.test; import com.ws.soon.entity.Order; import org.junit.Test; import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; public class DroolsTest { @Test public void test() { KieServices kieServices = KieServices.Factory.get(); // 获取Kie容器对象(默认容器对象 KieContainer kieContainer = kieServices.newKieClasspathContainer(); // 从Kie容器对象中获取会话对象(默认session对象 KieSession kieSession = kieContainer.newKieSession(); Order order = new Order(); order.setOriginalPrice(160d); // 将order对象插入工作内存 kieSession.insert(order); System.out.println("匹配规则前优惠后价格:" + order.getRealPrice()); // 匹配对象 // 激活规则,由drools框架自动进行规则匹配。若匹配成功,则执行 kieSession.fireAllRules(); // 关闭会话 kieSession.dispose(); System.out.println("优惠前价格:" + order.getOriginalPrice() + "\n优惠后价格:" + order.getRealPrice()); } } |
控制台输出如下: 通过上面的入门案例可以发现,使用drools引擎规则主要工作就是编写规则文件,在规则文件中定义和业务相关的业务规则,例如本案例定义的就是图书的优惠规则。规则定义好后就需要调用drools提供的api将数据提供给规则引擎进行规则模式匹配,规则引擎会执行匹配成功的规则,并将计算的结果返回。 可能大家会有疑问,虽然没有在代码中编写规则的判断逻辑,但是还是在规则文件中编写了业务规则,这跟在代码中编写规则有什么本质的区别? 前面已经提到,使用规则引擎时,规则可以做到动态管理。业务人员可以像管理数据一样对业务规则进行管理,比如查询、添加、更新、统计、提交业务规则等。这样就可以做到在不重启服务的情况下调整业务规则。 4、小结 1、规则引擎构成 drools规则引擎由以下三部分构成: Working Memory(工作内存) Rule Base(规则库) Inference Engine(推理引擎) 其中Inference Engine(推理引擎)又包括: Pattern Matcher(匹配器) Agenda(议程) Execution Engine(执行引擎) 如下图所示: 2、相关概念说明 Working Memory:工作内存,drools规则引擎会从Working Memory中获取数据并和规则文件中定义的规则进行模式匹配,所以我们开发的应用程序只需要将我们的数据插入到Working Memory中即可,例如本案例中我们调用kieSession.insert(order);就是将order对象插入到工作内存中。 Fact:事实,是指在drools规则应用当中,将一个普通的javaBean插入到Working Memory后的对象就是Fact对象,例如本案例中的Order对象就属于Fact对象。Fact对象是我们的应用和规则引擎进行交互的桥梁或通道。 Rule Base:规则库,我们在规则文件中定义的规则都会被加载到规则库中。 Pattern Matcher:匹配器,将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,匹配成功则被激活并放入Agenda中。 Agenda:议程,用于存放通过匹配器进行模式匹配后被激活的规则。 Execution Engine:执行引擎,执行Agenda中被激活的规则。 3、KIE介绍 我们在操作Drools时经常使用的API以及他们之间的关系如下图: 通过上面的API可以发现,大部分类都是以Kie开头。Kie全称为Knowledge is Everything,即“只是就是一切”的缩写,是Jboss一系列项目的总称。如下图所示,Kie的主要模块有OptaPlanner、Drools、UberFire、jBPM。 通过上图可以看到,Drools是整个KIE项目中的一个组件,Drools中还包括一个Drools-WB的模块,他是一个可视化的规则编辑器。 5、Drools基础语法 1、规则文件构成 在使用Drools时非常重要的一个工作就是编写规则文件,通常规则文件的后缀为.drl。 drl是Drools Rule Language的缩写。在规则文件中编写具体的规则内容。 […]
View DetailsJava 语言按照错误严重性,从 throwale 根类衍生出 Error 和 Exception 两大派系。
Error(错误):
程序在执行过程中所遇到的硬件或操作系统的错误。错误对程序而言是致命的,将导致程序无法运行。常见的错误有内存溢出,jvm 虚拟机自身的非正常运行,calss 文件没有主方法。程序本生是不能处理错误的,只能依靠外界干预。Error 是系统内部的错误,由 jvm 抛出,交给系统来处理。
Exception(异常):
程序正常运行中,可以预料的意外情况。比如数据库连接中断,空指针,数组下标越界。异常出现可以导致程序非正常终止,也可以预先检测,被捕获处理掉,使程序继续运行。Exception(异常)按照性质,又分为编译异常(受检异常)和运行时异常(非受检异常)。
◦ 编译异常:
又叫可检查异常,通常时由语法错和环境因素(外部资源)造成的异常。比如输入输出异常 IOException,数据库操作 SQLException。其特点是,Java 语言强制要求捕获和处理所有非运行时异常。通过行为规范,强化程序的健壮性和安全性。
◦ 运行时异常:
又叫不检查异常 RuntimeException,这些异常一般是由程序逻辑错误引起的,即语义错。比如算术异常,空指针异常 NullPointerException,下标越界 IndexOutOfBoundsException。运行时异常应该在程序测试期间被暴露出来,由程序员去调试,而避免捕获。
View Details前阵子做题遇到了大数的精确计算,再次认识了bigdecimal 关于Bigdecimal意外的有许多小知识点和坑,这里特此整理一下为方便以后学习,希望能帮助到其他的萌新 BigDecimal的运算——加减乘除 首先是bigdecimal的初始化 这里对比了两种形式,第一种直接value写数字的值,第二种用string来表示
View Details环境:Windows, Linux发布.net 6 API 发起接口请求报错:Request body too large. The max request body size is 30000000 bytes. 解决方式,Startup.cs添加如下代码:
1 2 3 4 5 |
//接口请求限制 services.Configure<KestrelServerOptions>(options => { options.Limits.MaxRequestBodySize = int.MaxValue; }); |
下面是github的issue,基本上可以解决大部分请求遇到的大小限制问题,可根据自己需要添加相关代码: https://github.com/dotnet/aspnetcore/issues/20369 from:https://blog.csdn.net/The_Moon_/article/details/127996098
View Detailsapplication.properties
1 2 3 4 5 6 |
spring.servlet.multipart.enabled=true spring.servlet.multipart.max-file-size=100MB spring.servlet.multipart.max-request-size=100MB spring.servlet.multipart.file-size-threshold=0 spring.servlet.multipart.location=/usr/local/project/file spring.servlet.multipart.resolve-lazily=false |
application.yml
1 2 3 4 5 6 7 8 |
spring.servlet: multipart: enabled: true location: /usr/local/project/file max-file-size: 100MB max-request-size: 100MB file-size-threshold: 0 resolve-lazily: false |
from:https://blog.csdn.net/qq_44730827/article/details/115719202
View Details最常见的初始化 List 方法为:
1 2 3 4 5 |
List<String> languages = new ArrayList<>(); languages.add("Java"); languages.add("PHP"); languages.add("Python"); System.out.println(languages); |
但是实际上,我们并不会直接使用 new ArrayList 来初始化 List。 你可以使用 Guava 的 newArrayList 来直接初始化。 List<String> languages = Lists.newArrayList(); 上面 2 种方法初始化的 List 是可变的,因此你可以对初始化成功的 List 进行添加和删除。 Arrays 使用这个方法初始化的 List 是不可变的。 考虑使用下面的代码来初始化一个 List。 List<Integer> list1 = Arrays.asList(1,2); Arrays 是 JDK 的一个类,你可以使用这个类来初始化一个 List。 考察下面的代码:
1 2 |
List<Integer> list1 = Arrays.asList(1,2); list1.add(3); |
将会给你一个:java.lang.UnsupportedOperationException 异常。 这是一个运行时错误,不是编译错误。 因此你在编译的时候是不会提示的。 List 使用这个方法初始化的 List 是不可变的。 考虑使用下面的代码来初始化一个 List。 List<Integer> list = List.of(1,2); List 是 JDK 的一个类,你可以使用这个类来初始化一个 List。 考察下面的代码:
1 2 |
List<Integer> list1 = List.of(1,2); list1.add(3); |
将会给你一个:java.lang.UnsupportedOperationException 异常。 将不可变 List 变成可变 如果 List 是不可变的。 我们可以使用 new ArrayList<> 来包装下就可以了 考察下面的代码:
1 2 |
List<Integer>list2 = new ArrayList<>(Arrays.asList(1,2)); list2.add(3); |
如果使用上面的代码的话,你创建的 List 就可以是可变的了,可以对创建的 List 进行修改和删除。 Java 初始化 List 的几种方法 – Java […]
View Details在实际开发项目中,我们开发环境、测试环境、补丁环境都是有不同的配置的。各个环境可能用不同的数据库,为了便于开发,spring提供了多环境配置文件切换功能。比如:application-dev.yml表示测试环境配置、application-test.yml表示测试环境配置、application-prod.yml表示补丁环境配置、application.yml则是默认环境。如此,我们让那个配置生效,只需要指定对应的配置文件即可。
View Details文件上传是一个项目最基础的功能,按道理说应该有不会有多困难,但恶心就恶心在 SpringBoot 最方便的优点上!!!
因为 SpringBoot 是内置 Tomcat 的,所以我们并不需要部署到 Tomcat 的服务器,但当打包后(jar包)就出现了问题。
在 IDE 时,因为是正常的文件目录,所以原来的文件上传功能就可以实现,但是打包后,所有的静态文件都变成了 jar 包!!!
这就很头疼,因为当访问 /static 时,实质上访问的是 jar 包文件内容。
最近前端页面需要使用百度的Ueditor富文本编辑器,本来以为只需要前端适配就可以了,没想到Ueditor需要使用一个服务器统一请求接口,各种百度,历时一天终于弄懂了是怎么一回事,下面是我整了的三种整合的方式,从使用Ueditor的后端代码,到引入Ueditor依赖,到最后完全接管Ueditor后端,都是验证可行的。
View Details用maven来构建过jar文件的朋友可能知道,默认情况下,maven因为不会给我们添加我们项目中需要的依赖,以及不会在MANIFEST.MF文件中添加Main-Class这一条目,造成我们构建完成的jar文件不能通过java -jar命令而直接执行,必须通过java -cp命令,指定类路径来执行.这无疑是非常麻烦的. Google了之后,找到了解决问题的方案.在pom.xml文件中,添加下面的snippet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<build> <plugins> <!-- any other plugins --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.5.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>org.longsheng.noobchain.NoobChain</mainClass> </manifest> </archive> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> |
把上面的snippet中的mainClass替换成你自己的主类的路径. 然后,就可以通过java -jar命令来执行构建好的jar文件了. 作者:AlstonWilliams 链接:https://www.jianshu.com/p/868889e32bd6 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Details