Drools与SpringMVC整合

本文主要介绍Drools6.4.Final版本与SpringMVC的整合。网上现有的教程大多数不能完整运行,本文将会提供具体的操作过程以及相应的注意事项,保证Demo代码是可以跑通的。

开发环境

  • macOS High Sierra
  • Intellij IDEA 2017.2
  • Drools 6.4.0.Final
  • SpringMVC 4.3.12.RELEASE
  • JDK 1.8.0_144

搭建Maven项目

关于具体如何创建一个Maven的Webapp项目我就不赘述了,其实在IDEA中可以一步一步选择的,下面贴出本项目的pom.xml文件。

pom.xml

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qinjiangbo</groupId>
<artifactId>DroolsSpring</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Drools SpringMVC</name>
<url>http://maven.apache.org</url>

<!-- 各个框架的版本 -->
<properties>
<spring.version>4.3.12.RELEASE</spring.version>
<drools.version>6.4.0.Final</drools.version>
<slf4j.version>1.7.25</slf4j.version>
<fastjson.version>1.2.39</fastjson.version>
</properties>

<dependencies>
<!-- Spring框架 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Drools框架 -->
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>${drools.version}</version>
</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.kie</groupId>
<artifactId>kie-spring</artifactId>
<version>${drools.version}</version>
</dependency>
<!-- Tomcat相关包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- JUnit框架 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- Slf4j日志框架 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Fastjson框架 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>

</dependencies>

<build>
<finalName>DroolsSpring</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>

接着在web.xml中配置相关的SpringMVC环境。

web.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Archetype Created Web Application</display-name>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:springContext.xml</param-value>
</context-param>

<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:springContext.xml</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

在介绍springContext.xml文件之前,有必要贴出一下项目的结构,以便于大家有一个更明确的认知。

项目主体结构

好,现在分别介绍springContext.xmlspringDrools.xml以及springMVC.xml三个文件。

springContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 配置包扫描路径 -->
<context:component-scan base-package="com.qinjiangbo"/>

<!-- 导入其他配置 -->
<import resource="springDrools.xml"/>
<import resource="springMVC.xml"/>

</beans>

springDrools.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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:kie="http://drools.org/schema/kie-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://drools.org/schema/kie-spring http://drools.org/schema/kie-spring.xsd">
<!-- Drools配置 -->
<bean id="kiePostProcessor"
class="org.kie.spring.annotations.KModuleAnnotationPostProcessor"/>
<kie:kmodule id="kModule">
<kie:kbase name="kBase" packages="rules">
<kie:ksession name="kSession" type="stateful"/>
</kie:kbase>
</kie:kmodule>
</beans>

springMVC.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 开启MVC注解 -->
<mvc:annotation-driven/>

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>

Fact模型

在Drools中我们使用的Model被称之为事实(Fact)模型,本例中的事实模型是Message.java

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
package com.qinjiangbo.model;

public class Message {

public static final int DEAD = 0;
public static final int ALIVE = 1;

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;
}

}

rules文件

我们来编写一下相关的规则文件,一般是以.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
package rules;
import com.qinjiangbo.model.*;

rule "rule1"
when
/**
* 当该实体的status属性为DEAD的时候,将该实体赋值给m,
* 实体的message属性赋值给printMsg
*/
m:Message(status == Message.DEAD, printMsg: message);
then
// 系统输出和重新设置实体属性
System.out.println(printMsg);
m.setMessage("I'm alive~");
m.setStatus(Message.ALIVE);

// 更新实体,触发规则
update(m);
end

rule "rule2"
when
Message(status == Message.ALIVE, printMsg: message);
then
System.out.println(printMsg);
end

Service类和Controller类

在Service类中调用规则引擎相关的逻辑,在Controller中进行Web页面的交互。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.qinjiangbo.service;

import com.alibaba.fastjson.JSON;
import com.qinjiangbo.model.Message;
import org.kie.api.cdi.KSession;
import org.kie.api.runtime.KieSession;
import org.springframework.stereotype.Service;

@Service
public class MessageService {

@KSession("kSession")
private KieSession kieSession;

public String updateMessage() {
Message message = new Message();
message.setMessage("Left 4 Dead 2");
message.setStatus(Message.DEAD);
kieSession.insert(message);
kieSession.fireAllRules();
return JSON.toJSONString(message);
}

}

注意上面的@KSession("kSession")注解在使用的时候要在springDrools.xml文件中声明kiePostProcessor为注解类型的org.kie.spring.annotations.KModuleAnnotationPostProcessor,否则会失效的。另外,这里使用的KieSession其实就是指代的StatefulKieSession类,不要使用KieSession去声明一个StatelessKieSession类的对象。这里要在springDrools.xml文件中把<kie:ksession name="kSession" type="stateful"/>类型声明为stateful

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
package com.qinjiangbo.controller;

import com.qinjiangbo.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/")
public class MessageController {

@Autowired
private MessageService messageService;

@RequestMapping("/")
public String index() {
return "index";
}

@RequestMapping("/update")
public ModelAndView update() {
ModelAndView modelAndView = new ModelAndView("success");
String message = messageService.updateMessage();
modelAndView.addObject("message", message);
return modelAndView;
}
}

测试结果

在浏览器中输入http://localhost:8080/update,就可以看到如下页面:

Bingo,那就证明整合成功啦!

分享到