drools 决策表

正如我在之前的文章中所展示的那样, JBoss Drools是一个非常有用的规则引擎 。 唯一的问题是,对于非技术人员而言,以Rule语言创建规则可能会非常复杂。 这就是为什么人们可以提供一种简便的方法来创建业务规则-在电子表格中创建决策表!

在下面的示例中,我将向您展示一个非常复杂的业务规则示例,该示例已转换为电子表格中的决策表。 作为后端,我们将有Drools,Camel和Spring。首先,让我们看一下我们想象中的业务问题。 让我们假设我们经营一家专注于销售产品(医疗或电子产品)的业务。 我们将产品运输到几个国家(PL,美国,GER,SWE,英国,ESP),并且根据国家/地区,存在不同的法律法规

关于买方的年龄。 在某些国家/地区,您可以比其他国家/地区年轻的时候购买产品。 更重要的是,取决于购买者和产​​品所来自的国家/地区以及产品的数量,购买者可能会获得折扣。 如您所见,在这种情况下,要实现全域需要大量条件(想象对它进行编程所需的if数量)。

另一个问题是业务方面(与往常一样)。 任何从事项目工作的人都知道需求变化的速度。 如果一个人在代码中输入了所有规则,则每次需求更改时,他都必须重新部署该软件。 因此,将业务逻辑与代码本身分开是一个好习惯。 无论如何,让我们回到例子。 首先,让我们看一下电子表格(在值得一看的JBoss网站上,对决策表的外观进行精确描述之前 ):我们程序的入口是第一个检查电子表格的地方。如果应授予给定用户购买产品的可能性(最好是下载电子表格并从Too Much Coding的Bitbucket存储库中使用电子表格: user_table.xls和product_table.xls或Github user_table.xls和product_table.xls ):

user_table.xls(表工作表)

用户获得批准后,他可能会获得折扣:

product_table.xls(表工作表)

product_table.xls(列出工作表)

正如您在图中看到的,业务问题非常复杂。 每行代表一个规则,每列代表一个条件。 您还记得我最近的帖子中的rules语法吗? 因此,您应该了解电子表格的隐藏部分,该部分在第一行可见行的正上方:

从2到6的行代表一些固定的配置值,例如规则集,导入( 您已经在最近的文章中看到了 )和函数。 在第7行中,您可以找到RuleTable的名称。 然后,在第8行中,在我们的场景中,您将拥有CONDITION或ACTION –换句话说,分别是LHS或rhe RHS。 行号9既表示条件中表示的类型,又表示对变量的绑定。 在第10行中,我们具有确切的LHS条件。 第11行显示列的标签。 从第12行开始,我们有一条规则。 您可以在源代码中找到电子表格。

现在让我们看一下代码。 让我们从定义产品和用户的模式开始。

人格

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:include schemaLocation="user.xsd"/><xsd:element name="Product"><xsd:complexType><xsd:sequence><xsd:element name="Name" type="xsd:string"/><xsd:element name="Type" type="ProductType"/><xsd:element name="Price" type="xsd:double"/><xsd:element name="CountryOfOrigin" type="CountryType"/><xsd:element name="AdditionalInfo" type="xsd:string"/><xsd:element name="Quantity" type="xsd:int"/></xsd:sequence></xsd:complexType></xsd:element><xsd:simpleType name="ProductType"><xsd:restriction base="xsd:string"><xsd:enumeration value="MEDICAL"/><xsd:enumeration value="ELECTRONIC"/></xsd:restriction></xsd:simpleType></xsd:schema>

User.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:include schemaLocation="product.xsd"/><xsd:element name="User"><xsd:complexType><xsd:sequence><xsd:element name="UserName" type="xsd:string"/><xsd:element name="UserAge" type="xsd:int"/><xsd:element name="UserCountry" type="CountryType"/><xsd:element name="Decision" type="DecisionType"/><xsd:element name="DecisionDescription" type="xsd:string"/></xsd:sequence></xsd:complexType></xsd:element><xsd:simpleType name="CountryType"><xsd:restriction base="xsd:string"><xsd:enumeration value="PL"/><xsd:enumeration value="USA"/><xsd:enumeration value="GER"/><xsd:enumeration value="SWE"/><xsd:enumeration value="UK"/><xsd:enumeration value="ESP"/></xsd:restriction></xsd:simpleType><xsd:simpleType name="DecisionType"><xsd:restriction base="xsd:string"><xsd:enumeration value="ACCEPTED"/><xsd:enumeration value="REJECTED"/></xsd:restriction></xsd:simpleType></xsd:schema>

由于我们正在使用Maven,因此我们可能会使用一个将XSD转换为Java类的插件。

pom.xml的一部分

<build><pluginManagement><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.5.1</version></plugin></plugins></pluginManagement><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>jaxb2-maven-plugin</artifactId><version>1.5</version><executions><execution><id>xjc</id><goals><goal>xjc</goal></goals></execution></executions><configuration><packageName>pl.grzejszczak.marcin.drools.decisiontable.model</packageName><schemaDirectory>${project.basedir}/src/main/resources/xsd</schemaDirectory></configuration></plugin></plugins></build>

多亏了这个插件,我们才可以在pl.grzejszczczak.marcin.decisiontable.model包中由JAXB类生成。 现在转到drools-context.xml文件,其中我们就Drools定义了所有必需的bean:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:drools="http://drools.org/schema/drools-spring"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://drools.org/schema/drools-spring http://drools.org/schema/drools-spring.xsd"><!-- Grid Node identifier that is registered in the CamelContext --><drools:grid-node id="node1"/><drools:kbase id="productsKBase" node="node1"><drools:resources><drools:resource type="DTABLE" source="classpath:rules/product_table.xls"/></drools:resources></drools:kbase><drools:ksession id="productsKSession" name="productsKSession" type="stateless" kbase="productsKBase" node="node1"/><drools:kbase id="usersKBase" node="node1"><drools:resources><drools:resource type="DTABLE" source="classpath:rules/user_table.xls"/></drools:resources></drools:kbase><drools:ksession id="usersKSession" name="usersKSession" type="stateless" kbase="usersKBase" node="node1"/></beans>

如您所见,与最近发布的应用程序上下文相比,存在一些差异。 首先,我们没有提供DRL文件作为知识库中的资源,而是提供了决策表(DTABLE)。 我决定传递两个单独的文件,但是您可以为一个文件提供几个工作表并访问这些工作表(通过Decisiontable-conf元素)。 另外还有一个名为node的附加元素。 我们必须选择Node接口(执行,网格…)的实现,以使Camel路由正常工作,就像您在Spring应用程序上下文文件中看到的那样。

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:camel="http://camel.apache.org/schema/spring"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring-2.8.0.xsd"><import resource="classpath:drools-context.xml"/><!-- Show Spring where to search for the beans (in which packages) --><context:component-scan base-package="pl.grzejszczak.marcin.drools.decisiontable" /><camel:camelContext id="camelContext"><camel:route id="acceptanceRoute"><camel:from uri="direct:acceptanceRoute"/><camel:to uri="drools:node1/usersKSession"/></camel:route><camel:route id="discountRoute"><camel:from uri="direct:discountRoute"/><camel:to uri="drools:node1/productsKSession"/></camel:route></camel:camelContext></beans>

如您所见,为了访问Drools Camel组件,我们必须提供一个节点,通过它我们可以访问适当的知识会话 。 我们定义了两条路线-第一条路线终止于Drools组件,该组件访问用户知识会话,而另一条产品知识会话。

我们有一个称为ProductServiceImpl的ProductService接口实现,给定输入User和Product对象,它们将通过Camel的Producer模板传递到两条以Drools组件结尾的Camel路由。 该产品服务背后的概念是,我们首先处理用户是否可以购买该软件,然后再检查他将获得什么样的折扣。 实际上,从服务的角度来看,我们只是将对象发送出去并等待响应。 最终,我们收到了响应,我们将用户和产品传递给金融服务实施部门,该实施部门将根据用户购买的产品或在需要时拒绝其要约的价格向用户收费。

ProductServiceImpl.java

package pl.grzejszczak.marcin.drools.decisiontable.service;import org.apache.camel.CamelContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import pl.grzejszczak.marcin.drools.decisiontable.model.Product;
import pl.grzejszczak.marcin.drools.decisiontable.model.User;import static com.google.common.collect.Lists.newArrayList;/*** Created with IntelliJ IDEA.* User: mgrzejszczak* Date: 14.01.13*/
@Component("productServiceImpl")
public class ProductServiceImpl implements ProductService {private static final Logger LOGGER = LoggerFactory.getLogger(ProductServiceImpl.class);@AutowiredCamelContext camelContext;@AutowiredFinancialService financialService;@Overridepublic void runProductLogic(User user, Product product) {LOGGER.debug("Running product logic - first acceptance Route, then discount Route");camelContext.createProducerTemplate().sendBody("direct:acceptanceRoute", newArrayList(user, product));camelContext.createProducerTemplate().sendBody("direct:discountRoute", newArrayList(user, product));financialService.processOrder(user, product);}}

要记住的另一件至关重要的事情是,Camel Drools组件需要Command对象作为输入。 如您所见,在主体中,我们正在发送对象列表(这些不是Command对象)。 我这样做是有目的的,因为我认为最好不要将我们的代码绑定到具体的解决方案。 如果我们发现有比Drools更好的解决方案怎么办? 我们是要更改已创建的所有代码,还是只是更改骆驼路线以指向我们的新解决方案? 这就是骆驼拥有TypeConverters的原因。 我们在这里也有我们自己的。 首先让我们看一下实现。

ProductTypeConverter.java

package pl.grzejszczak.marcin.drools.decisiontable.converter;import org.apache.camel.Converter;
import org.drools.command.Command;
import org.drools.command.CommandFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pl.grzejszczak.marcin.drools.decisiontable.model.Product;import java.util.List;/*** Created with IntelliJ IDEA.* User: mgrzejszczak* Date: 30.01.13* Time: 21:42*/
@Converter
public class ProductTypeConverter {private static final Logger LOGGER = LoggerFactory.getLogger(ProductTypeConverter.class);@Converterpublic static Command toCommandFromList(List inputList) {LOGGER.debug("Executing ProductTypeConverter's toCommandFromList method");return CommandFactory.newInsertElements(inputList);}@Converterpublic static Command toCommand(Product product) {LOGGER.debug("Executing ProductTypeConverter's toCommand method");return CommandFactory.newInsert(product);}
}

在Camel网站上有一个关于TypeConverters的很好的教程–如果您需要一些更深入的信息。 无论如何,我们正在注释我们的类和用于将不同类型相互转换的函数。 这里重要的是,我们正在向骆驼展示如何将列表和单个产品转换为Commands。 由于类型擦除,不管提供的类型如何,该方法都将起作用,这就是为什么即使我们提供了产品和用户列表,toCommandFromList函数也将被执行。 除此之外,为了使类型转换器正常工作,我们还必须在/ META-INF / services / org / apache / came / TypeConverter文件中提供类(FQN)的完全准名称。

类型转换器

pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter

为了正确测试我们的功能,应该编写许多测试来验证规则。 一种不错的方法是将输入文件存储在测试资源文件夹中,然后将其传递给规则引擎,然后将结果与经过验证的输出进行比较(不幸的是,要让业务部门开发这样的参考集是相当不可能的输出)。 无论如何,让我们看一下仅验证一些规则的单元测试以及运行这些规则所产生的日志:

ProductServiceImplTest.java

package pl.grzejszczak.marcin.drools.decisiontable.service.drools;import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import pl.grzejszczak.marcin.drools.decisiontable.model.*;
import pl.grzejszczak.marcin.drools.decisiontable.service.ProductService;import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;/*** Created with IntelliJ IDEA.* User: mgrzejszczak* Date: 03.02.13* Time: 16:06*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class ProductServiceImplTest {private static final Logger LOGGER = LoggerFactory.getLogger(ProductServiceImplTest.class);@AutowiredProductService objectUnderTest;@Testpublic void testRunProductLogicUserPlUnderageElectronicCountryPL() throws Exception {int initialPrice = 1000;int userAge = 6;int quantity = 10;User user = createUser("Smith", CountryType.PL, userAge);Product product = createProduct("Electronic", initialPrice, CountryType.PL, ProductType.ELECTRONIC, quantity);printInputs(user, product);objectUnderTest.runProductLogic(user, product);printInputs(user, product);assertTrue(product.getPrice() == initialPrice);assertEquals(DecisionType.REJECTED, user.getDecision());}@Testpublic void testRunProductLogicUserPlHighAgeElectronicCountryPLLowQuantity() throws Exception {int initialPrice = 1000;int userAge = 19;int quantity = 1;User user = createUser("Smith", CountryType.PL, userAge);Product product = createProduct("Electronic", initialPrice, CountryType.PL, ProductType.ELECTRONIC, quantity);printInputs(user, product);objectUnderTest.runProductLogic(user, product);printInputs(user, product);assertTrue(product.getPrice() == initialPrice);assertEquals(DecisionType.ACCEPTED, user.getDecision());}@Testpublic void testRunProductLogicUserPlHighAgeElectronicCountryPLHighQuantity() throws Exception {int initialPrice = 1000;int userAge = 19;int quantity = 8;User user = createUser("Smith", CountryType.PL, userAge);Product product = createProduct("Electronic", initialPrice, CountryType.PL, ProductType.ELECTRONIC, quantity);printInputs(user, product);objectUnderTest.runProductLogic(user, product);printInputs(user, product);double expectedDiscount = 0.1;assertTrue(product.getPrice() == initialPrice * (1 - expectedDiscount));assertEquals(DecisionType.ACCEPTED, user.getDecision());}@Testpublic void testRunProductLogicUserUsaLowAgeElectronicCountryPLHighQuantity() throws Exception {int initialPrice = 1000;int userAge = 19;int quantity = 8;User user = createUser("Smith", CountryType.USA, userAge);Product product = createProduct("Electronic", initialPrice, CountryType.PL, ProductType.ELECTRONIC, quantity);printInputs(user, product);objectUnderTest.runProductLogic(user, product);printInputs(user, product);assertTrue(product.getPrice() == initialPrice);assertEquals(DecisionType.REJECTED, user.getDecision());}@Testpublic void testRunProductLogicUserUsaHighAgeMedicalCountrySWELowQuantity() throws Exception {int initialPrice = 1000;int userAge = 22;int quantity = 4;User user = createUser("Smith", CountryType.USA, userAge);Product product = createProduct("Some name", initialPrice, CountryType.SWE, ProductType.MEDICAL, quantity);printInputs(user, product);objectUnderTest.runProductLogic(user, product);printInputs(user, product);assertTrue(product.getPrice() == initialPrice);assertEquals(DecisionType.ACCEPTED, user.getDecision());}@Testpublic void testRunProductLogicUserUsaHighAgeMedicalCountrySWEHighQuantity() throws Exception {int initialPrice = 1000;int userAge = 22;int quantity = 8;User user = createUser("Smith", CountryType.USA, userAge);Product product = createProduct("Some name", initialPrice, CountryType.SWE, ProductType.MEDICAL, quantity);printInputs(user, product);objectUnderTest.runProductLogic(user, product);printInputs(user, product);double expectedDiscount = 0.25;assertTrue(product.getPrice() == initialPrice * (1 - expectedDiscount));assertEquals(DecisionType.ACCEPTED, user.getDecision());}private void printInputs(User user, Product product) {LOGGER.debug(ReflectionToStringBuilder.reflectionToString(user, ToStringStyle.MULTI_LINE_STYLE));LOGGER.debug(ReflectionToStringBuilder.reflectionToString(product, ToStringStyle.MULTI_LINE_STYLE));}private User createUser(String name, CountryType countryType, int userAge){User user = new User();user.setUserName(name);user.setUserCountry(countryType);user.setUserAge(userAge);return user;}private Product createProduct(String name, double price, CountryType countryOfOrigin, ProductType productType, int quantity){Product product = new Product();product.setPrice(price);product.setCountryOfOrigin(countryOfOrigin);product.setName(name);product.setType(productType);product.setQuantity(quantity);return product;}}

当然,测试中的log.debugs完全是多余的,但是我希望您能快速看到这些规则是可行的。 很抱歉记录的长度,但是我写了一些测试来显示不同的规则组合(实际上最好有太多的记录而不是相反的记录)

pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:150 pl.grzejszczak.marcin.drools.decisiontable.model.User@1d48043[userName=SmithuserAge=6userCountry=PLdecision=<null>decisionDescription=<null>
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:151 pl.grzejszczak.marcin.drools.decisiontable.model.Product@1e8f2a0[name=Electronictype=ELECTRONICprice=1000.0countryOfOrigin=PLadditionalInfo=<null>quantity=10
]
pl.grzejszczak.marcin.drools.decisiontable.service.ProductServiceImpl:31 Running product logic - first acceptance Route, then discount Route
pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter:25 Executing ProductTypeConverter's toCommandFromList method
pl.grzejszczak.marcin.drools.decisiontable.service.ProductService:8 Sorry, according to your age (< 18) and country (PL) you can't buy this product
pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter:25 Executing ProductTypeConverter's toCommandFromList method
pl.grzejszczak.marcin.drools.decisiontable.service.FinancialServiceImpl:29 Sorry, user has been rejected...
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:150 pl.grzejszczak.marcin.drools.decisiontable.model.User@1d48043[userName=SmithuserAge=6userCountry=PLdecision=REJECTEDdecisionDescription=Sorry, according to your age (< 18) and country (PL) you can't buy this product
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:151 pl.grzejszczak.marcin.drools.decisiontable.model.Product@1e8f2a0[name=Electronictype=ELECTRONICprice=1000.0countryOfOrigin=PLadditionalInfo=<null>quantity=10
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:150 pl.grzejszczak.marcin.drools.decisiontable.model.User@b28f30[userName=SmithuserAge=19userCountry=PLdecision=<null>decisionDescription=<null>
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:151 pl.grzejszczak.marcin.drools.decisiontable.model.Product@d6a0e0[name=Electronictype=ELECTRONICprice=1000.0countryOfOrigin=PLadditionalInfo=<null>quantity=1
]
pl.grzejszczak.marcin.drools.decisiontable.service.ProductServiceImpl:31 Running product logic - first acceptance Route, then discount Route
pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter:25 Executing ProductTypeConverter's toCommandFromList method
pl.grzejszczak.marcin.drools.decisiontable.service.ProductService:8 Congratulations, you have successfully bought the product
pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter:25 Executing ProductTypeConverter's toCommandFromList method
pl.grzejszczak.marcin.drools.decisiontable.service.ProductService:8 Sorry, no discount will be granted.
pl.grzejszczak.marcin.drools.decisiontable.service.FinancialServiceImpl:25 User has been approved - processing the order...
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:150 pl.grzejszczak.marcin.drools.decisiontable.model.User@b28f30[userName=SmithuserAge=19userCountry=PLdecision=ACCEPTEDdecisionDescription=Congratulations, you have successfully bought the product
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:151 pl.grzejszczak.marcin.drools.decisiontable.model.Product@d6a0e0[name=Electronictype=ELECTRONICprice=1000.0countryOfOrigin=PLadditionalInfo=Sorry, no discount will be granted.quantity=1
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:150 pl.grzejszczak.marcin.drools.decisiontable.model.User@14510ac[userName=SmithuserAge=19userCountry=PLdecision=<null>decisionDescription=<null>
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:151 pl.grzejszczak.marcin.drools.decisiontable.model.Product@1499616[name=Electronictype=ELECTRONICprice=1000.0countryOfOrigin=PLadditionalInfo=<null>quantity=8
]
pl.grzejszczak.marcin.drools.decisiontable.service.ProductServiceImpl:31 Running product logic - first acceptance Route, then discount Route
pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter:25 Executing ProductTypeConverter's toCommandFromList method
pl.grzejszczak.marcin.drools.decisiontable.service.ProductService:8 Congratulations, you have successfully bought the product
pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter:25 Executing ProductTypeConverter's toCommandFromList method
pl.grzejszczak.marcin.drools.decisiontable.service.ProductService:8 Congratulations - you've been granted a 10% discount!
pl.grzejszczak.marcin.drools.decisiontable.service.FinancialServiceImpl:25 User has been approved - processing the order...
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:150 pl.grzejszczak.marcin.drools.decisiontable.model.User@14510ac[userName=SmithuserAge=19userCountry=PLdecision=ACCEPTEDdecisionDescription=Congratulations, you have successfully bought the product
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:151 pl.grzejszczak.marcin.drools.decisiontable.model.Product@1499616[name=Electronictype=ELECTRONICprice=900.0countryOfOrigin=PLadditionalInfo=Congratulations - you've been granted a 10% discount!quantity=8
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:150 pl.grzejszczak.marcin.drools.decisiontable.model.User@17667bd[userName=SmithuserAge=19userCountry=USAdecision=<null>decisionDescription=<null>
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:151 pl.grzejszczak.marcin.drools.decisiontable.model.Product@ad9f5d[name=Electronictype=ELECTRONICprice=1000.0countryOfOrigin=PLadditionalInfo=<null>quantity=8
]
pl.grzejszczak.marcin.drools.decisiontable.service.ProductServiceImpl:31 Running product logic - first acceptance Route, then discount Route
pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter:25 Executing ProductTypeConverter's toCommandFromList method
pl.grzejszczak.marcin.drools.decisiontable.service.ProductService:8 Sorry, according to your age (< 18) and country (USA) you can't buy this product
pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter:25 Executing ProductTypeConverter's toCommandFromList method
pl.grzejszczak.marcin.drools.decisiontable.service.FinancialServiceImpl:29 Sorry, user has been rejected...
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:150 pl.grzejszczak.marcin.drools.decisiontable.model.User@17667bd[userName=SmithuserAge=19userCountry=USAdecision=REJECTEDdecisionDescription=Sorry, according to your age (< 18) and country (USA) you can't buy this product
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:151 pl.grzejszczak.marcin.drools.decisiontable.model.Product@ad9f5d[name=Electronictype=ELECTRONICprice=1000.0countryOfOrigin=PLadditionalInfo=<null>quantity=8
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:150 pl.grzejszczak.marcin.drools.decisiontable.model.User@9ff588[userName=SmithuserAge=22userCountry=USAdecision=<null>decisionDescription=<null>
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:151 pl.grzejszczak.marcin.drools.decisiontable.model.Product@1b0d2d0[name=Some nametype=MEDICALprice=1000.0countryOfOrigin=SWEadditionalInfo=<null>quantity=4
]
pl.grzejszczak.marcin.drools.decisiontable.service.ProductServiceImpl:31 Running product logic - first acceptance Route, then discount Route
pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter:25 Executing ProductTypeConverter's toCommandFromList method
pl.grzejszczak.marcin.drools.decisiontable.service.ProductService:8 Congratulations, you have successfully bought the product
pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter:25 Executing ProductTypeConverter's toCommandFromList method
pl.grzejszczak.marcin.drools.decisiontable.service.FinancialServiceImpl:25 User has been approved - processing the order...
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:150 pl.grzejszczak.marcin.drools.decisiontable.model.User@9ff588[userName=SmithuserAge=22userCountry=USAdecision=ACCEPTEDdecisionDescription=Congratulations, you have successfully bought the product
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:151 pl.grzejszczak.marcin.drools.decisiontable.model.Product@1b0d2d0[name=Some nametype=MEDICALprice=1000.0countryOfOrigin=SWEadditionalInfo=<null>quantity=4
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:150 pl.grzejszczak.marcin.drools.decisiontable.model.User@1b27882[userName=SmithuserAge=22userCountry=USAdecision=<null>decisionDescription=<null>
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:151 pl.grzejszczak.marcin.drools.decisiontable.model.Product@5b84b[name=Some nametype=MEDICALprice=1000.0countryOfOrigin=SWEadditionalInfo=<null>quantity=8
]
pl.grzejszczak.marcin.drools.decisiontable.service.ProductServiceImpl:31 Running product logic - first acceptance Route, then discount Route
pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter:25 Executing ProductTypeConverter's toCommandFromList method
pl.grzejszczak.marcin.drools.decisiontable.service.ProductService:8 Congratulations, you have successfully bought the product
pl.grzejszczak.marcin.drools.decisiontable.converter.ProductTypeConverter:25 Executing ProductTypeConverter's toCommandFromList method
pl.grzejszczak.marcin.drools.decisiontable.service.ProductService:8 Congratulations, you are granted a discount
pl.grzejszczak.marcin.drools.decisiontable.service.FinancialServiceImpl:25 User has been approved - processing the order...
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:150 pl.grzejszczak.marcin.drools.decisiontable.model.User@1b27882[userName=SmithuserAge=22userCountry=USAdecision=ACCEPTEDdecisionDescription=Congratulations, you have successfully bought the product
]
pl.grzejszczak.marcin.drools.decisiontable.service.drools.ProductServiceImplTest:151 pl.grzejszczak.marcin.drools.decisiontable.model.Product@5b84b[name=Some nametype=MEDICALprice=750.0countryOfOrigin=SWEadditionalInfo=Congratulations, you are granted a discountquantity=8
]

在这篇文章中,我介绍了如何通过给他一个他可以使用的工具(电子表格中的决策表)来将您的一些开发工作推向BA。 而且,您现在将如何将Drools与Camel集成在一起。 希望您会看到如何简化业务规则的实现(从而将实现和支持的成本降至最低),同时牢记它们的更改可能性。 我希望这个示例能够比以前关于Drools的文章更好地说明用Java实现所有业务规则的难度。 如果您在决策表,与Spring和Camel集成方面对Drools有任何经验,请随时发表评论-让我们进行讨论。 所有代码都可以从Bitbucket和GitHub的 Too Much Coding存储库中获得。

参考:来自Blog上的 JCG合作伙伴 Marcin Grzejszczak的Camel和Spring的Drools决策表, 用于编码成瘾者博客。

翻译自: https://www.javacodegeeks.com/2013/04/drools-decision-tables-with-camel-and-spring.html

drools 决策表

drools 决策表_骆驼和春天的Drools决策表相关推荐

  1. 骆驼和春天的Drools决策表

    正如我在之前的文章中所展示的那样, JBoss Drools是一个非常有用的规则引擎 . 唯一的问题是,对于非技术人员而言,以Rule语言创建规则可能会非常复杂. 这就是为什么可以提供一种轻松的方式来 ...

  2. java排班_使用java规则引擎Drools自动排班前言.doc

    使用java规则引擎Drools自动排班前言 使用java规则引擎Drools自动排班前言本文以一个经简化的运输车队自动排班需求为例,详细讲解了如何使用java规则引擎Drools进行商业规则的形式语 ...

  3. 骆驼祥子大事件时间轴_骆驼中的事件处理

    骆驼祥子大事件时间轴 在上一篇有关骆驼-小水车的文章中,我介绍了骆驼-小水车的组件,并使用骆驼路线中的规则实现了一些简单的面向任务的过程. 今天,我将展示如何通过添加事件处理来扩展此示例. 那么如何描 ...

  4. 装车机器人_智造春天脚步近 青岛这家机器人公司着手打造模块化、标准化技术平台...

    智造春天脚步近,青岛机器人加紧"练内功" 科捷机器人针对未来更多的机器换人需求,加速研发行业首创装车机器人:针对智能化需求由点到面的变化,着手打造模块化.标准化技术平台 某矿泉水厂 ...

  5. 超级电容怎么才能把内阻做小_骆驼电瓶怎么样?

    [ 中华网 行情 ] 最近准备装一驻车空调,有车友给我推荐骆驼,想问问骆驼电瓶怎么样?也有人给我推荐旭派超级重卡电池,我对比了一下,发现这款电池亮点有很多,可以说是风靡卡车市场!在卡友圈里呼声很高!它 ...

  6. perl大骆驼和小骆驼_骆驼路线的主/从故障转移

    perl大骆驼和小骆驼 一种实现主/从故障转移模式的方法是拥有一个应用程序的实例集群,其中一个实例(主实例)当前处于活动状态,而其他实例(从属实例)处于待机状态,随时可以在主实例发生故障时接管该实例. ...

  7. drools 7.x 决策表使用

    1.何时使用决策表 何时使用决策表--如果规则能够被表达为模板+数据的格式,那你 应该考虑使用决策表.决策表中的每一行就是对应模板的一行数据,将产生一个规则. 运行决策表--Drools 引擎所部署的 ...

  8. Drools决策表+SpringBoot使用及语法详解

    SpringBoot+Drools决策表的使用 简介 Drools决策表 决策表部分关键字 规则部分关键字 总结 SpringBoot 项目中决策表的使用 pom配置 验证决策表格式是否正确 利用Ki ...

  9. drools规则引擎可视化_一文看懂开源工作流引擎 Flowable「转」

    原文链接:[https://xie.infoq.cn/article/ece75889c715e0bc87a73e44c]. 一.工作流引擎使用场景 工作流在企业管理系统中是高频使用的功能,一个最常见 ...

最新文章

  1. T-SQL WITH 分号问题
  2. 从源码分析DEARGUI之画图和删图
  3. ThinkPHP U方法
  4. Spark 架构原理介绍 以及 job、task、stag 概念
  5. Burpsuite中宏的使用
  6. android blcr 编译,BLCR 基本环境搭建【zz~】
  7. SSH 框架 没加commons-beanutils-1.7.0.jar包的错误提示
  8. gpu服务器性能测试用例,多目标测试用例预优化方法及其在GPU上的应用研究
  9. 使用Eclipse Babel语言包汉化eclipse
  10. Hive常用命令之MSCK REPAIR TABLE命令概述
  11. 2023年最新微信记账小程序源码+简约大气
  12. c++17好用的新特性总结
  13. 香港流行乐黄金二十年——经典歌手(音乐人)全面回顾 一
  14. Problem: 美丽的黄山 (指针)
  15. python无法打开_python程序无法打开是怎么回事
  16. 苹果手机直播怎么投屏 苹果手机投影电脑屏幕
  17. C#:实现Euclidean distance欧氏距离算法(附完整源码)
  18. FPGA中ROM IP与RAM IP核配置与调用
  19. Kafka的灵魂伴侣Logi-KafkaManger(2)之kafka针对Topic粒度的配额管理(限流)
  20. VTK笔记——点(point)和向量(vector)投影到平面(plane)

热门文章

  1. 深入解读Service Mesh背后的技术细节
  2. Java IO: 异常处理
  3. Maven精选系列--POM文件解析
  4. nginx部署laravel需要修改的配置
  5. 请设计一个栈,实现十进制数转任意进制数。
  6. vue利用级联选择器实现全国省市区乡村五级菜单联动
  7. GatewayMetricsFilter网关度量过滤器(服务监控)
  8. 稀疏数组与二维数组相互转化
  9. Kafka启动出现Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Pr
  10. 查找前端依赖 jquery css js 时间控件 不要用远程依赖 会变化的 card