drools 决策表_骆驼和春天的Drools决策表
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存儲庫中獲得。
翻譯自: https://www.javacodegeeks.com/2013/04/drools-decision-tables-with-camel-and-spring.html
drools 決策表
總結
以上是生活随笔為你收集整理的drools 决策表_骆驼和春天的Drools决策表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Boot中带有CKEdit
- 下一篇: 安卓解压软件(解压软件安卓)