欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[Drools Demos] 其 (四) : SpringBoot-Drools模板

程序员文章站 2022-05-28 11:37:29
...

前言

前几节我们说了Drools的快速启动、数据传递和动态加载.本章我们提供一个简单的 Drools-SpringBoot实例模板.

本章主要对应项目内的drools-springboot-dynamic内容.

基础配置: JDK 1.7 + Eclipse Mar + Maven
依赖: Drools插件(非必须)

本章主要对应项目内的drools-quickstart子模块.
Github地址: https://github.com/SeanYanxml/drools-train


详细内容(Demos-1-模板基础)

pom.xml(导入相关Jar包)

	<!-- drools jars -->
	<properties>
		<drools-version>6.5.0.Final</drools-version>
		<springboot.version>1.5.13.RELEASE</springboot.version>
	</properties>
	
	<dependencies>
	
		<!-- spring boot -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
			<version>${springboot.version}</version>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		
		<!-- spring boot log4j2 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j2</artifactId>
			<version>${springboot.version}</version>
		</dependency>
		
				<!--spring-boot -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<version>${springboot.version}</version>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		
	<!-- 	<dependency>
			<groupId>org.drools</groupId>
			<artifactId>drools-core</artifactId>
			<version>${drools-version}</version>
		</dependency> -->

		<dependency>
			<groupId>org.drools</groupId>
			<artifactId>drools-compiler</artifactId>
			<version>${drools-version}</version>
		</dependency>

		<!-- <dependency>
			<groupId>org.drools</groupId>
			<artifactId>knowledge-api</artifactId>
			<version>${drools-version}</version>
		</dependency>

		<dependency>
			<groupId>org.drools</groupId>
			<artifactId>drools-decisiontables</artifactId>
			<version>${drools-version}</version>
		</dependency>
		<dependency>
			<groupId>org.drools</groupId>
			<artifactId>drools-templates</artifactId>
			templates 模板
			<version>${drools-version}</version>
		</dependency>
		<dependency>
			<groupId>org.kie</groupId>
			<artifactId>kie-api</artifactId>
			<version>${drools-version}</version>
		</dependency> -->

		<dependency>
			<groupId>org.kie</groupId>
			<artifactId>kie-spring</artifactId>
			<version>${drools-version}</version>
			<exclusions>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-tx</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-beans</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-core</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-context</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<!-- other jars -->
		
		<!-- test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>

		<dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
            <scope>compile</scope>
        </dependency>
        
        <!--log4j-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        	
	</dependencies>

DroolsConfig.java(Drools动态加载配置类)

package com.yanxml.drools.springboot.config;

import java.io.IOException;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieModule;
import org.kie.api.builder.KieRepository;
import org.kie.api.builder.Message;
import org.kie.api.builder.ReleaseId;
import org.kie.api.builder.Results;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;
import org.kie.spring.KModuleBeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

@Configuration
public class DroolsConfig {
	private static final String RULES_PATH = "rules/";

	@Bean
	@ConditionalOnMissingBean(KieFileSystem.class)
	public KieFileSystem kieFileSystem() throws IOException {
		KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
		for (Resource file : getRuleFiles()) {
//			((org.kie.api.io.Resource) file).setResourceType(ResourceType.DRL);
			kieFileSystem.write(ResourceFactory.newClassPathResource(
					RULES_PATH + file.getFilename(), "UTF-8"));
//			FileInputStream fis = new FileInputStream( "src/main/resources/"+RULES_PATH + file.getFilename() );
//			kieFileSystem.write( "src/main/resources/"+RULES_PATH + file.getFilename(),
//					getKieServices().getResources().newInputStreamResource( fis ) );
		}
		return kieFileSystem;
	}

	private Resource[] getRuleFiles() throws IOException {
		ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
		return resourcePatternResolver
				.getResources("classpath*:" + RULES_PATH + "**/*.*");
	}

	@Bean
	@ConditionalOnMissingBean(KieContainer.class)
	public KieContainer kieContainer() throws IOException {
        KieServices kieServices =  getKieServices();
		final KieRepository kieRepository = kieServices.getRepository();

		// 这边出了问题
		kieRepository.addKieModule(new KieModule() {
			public ReleaseId getReleaseId() {
				return kieRepository.getDefaultReleaseId();
			}
		});

		KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem());
		 Results results = kieBuilder.getResults();
	        if (results.hasMessages(Message.Level.ERROR)) {
	            System.out.println(results.getMessages());
	            throw new IllegalStateException("### errors ###");
	        }
		kieBuilder.buildAll();

//		return getKieServices()
//				.newKieContainer(getKieServices().getRepository().getDefaultReleaseId());
        KieContainer kieContainer = kieServices.newKieContainer(kieRepository.getDefaultReleaseId());

		return kieContainer;
	}

	private KieServices getKieServices() {
		return KieServices.Factory.get();
	}

	@Bean
	@ConditionalOnMissingBean(KieBase.class)
	public KieBase kieBase() throws IOException {
		return kieContainer().getKieBase();
	}

	@Bean
	@ConditionalOnMissingBean(KieSession.class)
	public KieSession kieSession() throws IOException {
		return kieContainer().newKieSession();
	}

	@Bean
	@ConditionalOnMissingBean(KModuleBeanFactoryPostProcessor.class)
	public KModuleBeanFactoryPostProcessor kiePostProcessor() {
		return new KModuleBeanFactoryPostProcessor();
	}
}

Application(SpringBoot启动类)

package com.yanxml.drools.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * 
 * 主程序的入口
 *
 */
@ComponentScan(basePackages={
		"com.yanxml.drools.springboot"
})
@SpringBootApplication

public class Application {
	
    public static Logger log = LogManager.getLogger(Application.class);

    public static void main(String[] args) {	
		try {
			SpringApplication app = new SpringApplication(Application.class);
			app.setWebEnvironment(true);
	        app.run(args);
	    	log.info("application started successfully");
		} catch (Exception e) {
			log.error("application main exception", e);
		}
	}
	
}

Message(POJO)

package com.yanxml.drools.springboot.beans.pojo;

public class Message {
	// status 4 种状态
	public static final int STATUS_1 = 1;
	public static final int STATUS_2 = 2;
	public static final int STATUS_3 = 3;
	public static final int STATUS_4 = 4;

	private String message;
	private int status;

	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
	public int getStatus() {
		return status;
	}
	public void setStatus(int status) {
		this.status = status;
	}
}

HelloWorld.drl

package com.yanxml.drools.springboot

import com.yanxml.drools.springboot.beans.pojo.Message;
no-loop true

rule "TransmitHelloworldRule"
	when 
		$m : Message( status == Message.STATUS_1, myMessage:message)
	then
		System.out.println("Hit Transmit HelloWorld Rule.");
		$m.setMessage("STATUS_2");
		$m.setStatus(Message.STATUS_2);
//		update($m);
//		update(m);
end

HelloworldController

package com.yanxml.drools.springboot.controller;

import javax.annotation.Resource;

import org.drools.core.base.RuleNameStartsWithAgendaFilter;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.yanxml.drools.springboot.beans.pojo.Message;


@RequestMapping("/test")
@Controller
public class HelloworldController {
	@Resource
	private KieContainer kieContainer;
	
//	@Resource
//	private KieSession kieSession;
	
  @ResponseBody
  @RequestMapping("/helloworld")
  public void test(){
	  // newKieSession with name will be NullPointerException.(Bug)
//	  	KieSession kieSession = kieContainer.newKieSession("kSessionHelloWorld");
	  	KieSession kieSession = kieContainer.newKieSession();
		Message message = new Message();
		message.setMessage("STATUS_1");
		message.setStatus(Message.STATUS_1);
		
		System.out.println("Rule Before - Message: "+message.getMessage()+" status:"+message.getStatus());
		
		// hit rule
		kieSession.insert(message);
		kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("Transmit"));
		
		// 同步等待 - 等待rule执行完毕后 后面的语句才被执行。
		System.out.println("Rule After - Message: "+message.getMessage()+" status:"+message.getStatus());
	}

	
}

测试结果:


[1] localhost:8080/test/helloworld

# output

Rule Before - Message: STATUS_1 status:1
Hit Transmit HelloWorld Rule.
Rule After - Message: STATUS_2 status:2

RELATING-CLASS:HelloworldController

详细内容(Demos-2-方法回调)

MessageServiceService

package com.yanxml.drools.springboot.service;

import org.springframework.stereotype.Service;
import com.yanxml.drools.springboot.beans.pojo.Message;

@Service
public class MessageServiceService {
	
	public void insert(Message message){
		// 数据库 Insert语句
		System.out.println("Message Service Insert SQL.");
	}
}

HelloWorld.drl 规则补充

rule "InvokeHelloWorldRule"
	when
		$m : Message()
		$messageServiceService : MessageServiceService()
	then
		System.out.println("Hit Invoke HelloWorld Rule.");
		$messageServiceService.insert($m);
end

MessageServiceController(新Controller)

package com.yanxml.drools.springboot.controller;

import javax.annotation.Resource;

import org.drools.core.base.RuleNameStartsWithAgendaFilter;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.yanxml.drools.springboot.beans.pojo.Message;
import com.yanxml.drools.springboot.service.MessageServiceService;

@Controller
@RequestMapping("/message")
public class MessageServiceController {
	@Resource 
	KieContainer kieContainer;
	
	@Autowired
	MessageServiceService messageServiceService;
	
	@ResponseBody
	@RequestMapping("/insert")
	public void insert(){
		KieSession kieSession = kieContainer.newKieSession();
		
		// insert Facts
		Message message = new Message();
		message.setMessage("Insert-0-Message");
		message.setStatus(Message.STATUS_1);
		kieSession.insert(message);
		
		// insert Service
		kieSession.insert(messageServiceService);
		
		kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("Invoke"));

		
	}

}

测试结果:


[2] http://localhost:8080/message/insert

# output

Hit Invoke HelloWorld Rule.
Message Service Insert SQL.

RELATING-CLASS:MessageServiceController

Reference

[1] 《Drools7.0.0.Final规则引擎教程》Springboot+规则重新加载

[2] Drools入门系列

相关标签: drools springboot