依赖
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.12</version>
</dependency>
1.利用Spring Boot的CommandLineRunner注册SpringBean、GroovyBean
- 初始化加载项目中RuleFilter的Spring Bean
- 直接使用@Autowired注解配合List即可获取所有RuleFilter的子类
- 初始化Groovy动态扫描的监控间隔,目录配置
- 这里配置是每隔10秒扫描目录xxx,新增或修改的文件用于编译加载
@Component
public class GroovyRunner implements CommandLineRunner {
@Autowired
List<RuleFilter> ruleFilterList;
@Override
public void run(String... args) throws Exception {
// 初始化加载项目中RuleFilter的Springbean
RuleFilterLoader.getInstance().initSpringRuleFilter(ruleFilterList);
try {
// 每隔多少秒,扫描目录下的groovy文件
RuleFilterFileManager.init(5, "C:\\rule\\groovy");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
项目内不变的规则以java实现继承RuleFilter
@Component
public class JavaRule extends RuleFilter {
/**
* 具体规则执行
* @param msg
*/
@Override
public void run(String msg) {
System.out.println(" === Java 实现的业务规则 order = 1 , msg = " + msg + " === ");
}
/**
* 该规则是否被执行
* @return
*/
@Override
public boolean shouldRun() {
return true;
}
/**
* 该规则执行的顺序
* @return
*/
@Override
public int runOrder() {
return 1;
}
}
项目内经常变动的以Groovy来实现
public class GroovyRule extends RuleFilter {
@Override
public void run(String msg) {
System.out.println(" === Groovy 实现的业务规则 order = " + runOrder() + ", msg = " + msg + " === ");
}
@Override
public boolean shouldRun() {
return true;
}
@Override
public int runOrder() {
return 2;
}
}
使用RuleFilterProcessor来加载RuleFiler
@RestController
@RequestMapping("/groovy")
public class GroovyController {
@Autowired
private RuleFilterProcessor ruleFilterProcessor;
@GetMapping()
@ApiOperation("测试groovy的动态加载")
public void transaction(@RequestParam String msg) {
ruleFilterProcessor.runRuleFilters(msg);
}
}
启动并验证
浏览器访问:http://localhost:8080/groovy?msg=laker%20666
=== Java 实现的业务规则 order = 1 , msg = laker 666 ===
=== Groovy 实现的业务规则 order = 2 , msg = laker 666 ===
新增一个Groovy后
public class Groovy2Rule extends RuleFilter {
@Override
public void run(String msg) {
System.out.println(" === Groovy 实现的业务规则 order = " + runOrder() + ", msg = " + msg + " === ");
List<RuleFilter> ruleFilters = RuleFilterLoader.getInstance().getFilters();
for (RuleFilter ruleFilter : ruleFilters) {
System.out.println(ruleFilter.getClass().getName());
}
}
@Override
public boolean shouldRun() {
return true;
}
@Override
public int runOrder() {
return 3;
}
}
不用重启服务,浏览器访问:http://localhost:8080/groovy?msg=laker%20666
=== Groovy 实现的业务规则 order = 0 , msg = laker 666 ===
=== Java 实现的业务规则 order = 1 , msg = laker 666 ===
=== Groovy 实现的业务规则 order = 3, msg = laker 666 ===
com.laker.map.moudle.groovy.javarule.GroovyRule
com.laker.map.moudle.groovy.javarule.JavaRule
com.laker.map.moudle.groovy.Groovy2Rule
核心的模块
- RuleFilter :规则过滤器抽象类,用于扩展实现业务规则,供Java和Groovy继承
- RuleFilterLoader :规则过滤器加载器,用于加载基于Spring的RuleFilter实现类和动态编译指定文件基于Groovy的RuleFilter实现类
- RuleFilterFileManager : 一个独立线程轮询监听指定目录文件的变化配合RuleFilterLoader ( 规则过滤器加载器)使用
- RuleFilterProcessor: 业务规则处理器核心入口
RuleFilter.java
public abstract class RuleFilter implements IRule, Comparable<RuleFilter> {
abstract public int runOrder();
@Override
public int compareTo(RuleFilter ruleFilter) {
return Integer.compare(this.runOrder(), ruleFilter.runOrder());
}
...
}
RuleFilterLoader.java
public class RuleFilterLoader {
public boolean putFilter(File file) throws Exception {
String sName = file.getAbsolutePath() + file.getName();
if (filterClassLastModified.get(sName) != null && (file.lastModified() != filterClassLastModified.get(sName))) {
LOG.debug("reloading filter " + sName);
filterRegistry.remove(sName);
}
RuleFilter filter = filterRegistry.get(sName);
if (filter == null) {
Class clazz = compile(file);
if (!Modifier.isAbstract(clazz.getModifiers())) {
filter = (RuleFilter) clazz.newInstance();
filterRegistry.put(file.getAbsolutePath() + file.getName(), filter);
ruleFilters.clear();
filterClassLastModified.put(sName, file.lastModified());
return true;
}
}
return false;
}
public List<RuleFilter> getFilters() {
if (CollUtil.isNotEmpty(ruleFilters)) {
return ruleFilters;
}
ruleFilters.addAll(springRuleFilterList);
ruleFilters.addAll(this.filterRegistry.values());
Collections.sort(ruleFilters);
return ruleFilters;
}
private Class compile(File file) throws IOException {
GroovyClassLoader loader = getGroovyClassLoader();
Class groovyClass = loader.parseClass(file);
return groovyClass;
}
GroovyClassLoader getGroovyClassLoader() {
return new GroovyClassLoader();
}
...
}
RuleFilterFileManager.java
public class RuleFilterFileManager {
public static void init(int pollingIntervalSeconds, String... directories) {
if (INSTANCE == null) INSTANCE = new RuleFilterFileManager();
INSTANCE.aDirectories = directories;
INSTANCE.pollingIntervalSeconds = pollingIntervalSeconds;
INSTANCE.manageFiles();
INSTANCE.startPoller();
}
void startPoller() {
poller = new Thread("GroovyRuleFilterFileManagerPoller") {
@Override
public void run() {
while (bRunning) {
try {
sleep(pollingIntervalSeconds * 1000);
manageFiles();
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
poller.setDaemon(true);
poller.start();
}
void processGroovyFiles(List<File> aFiles) throws Exception, InstantiationException, IllegalAccessException {
for (File file : aFiles) {
RuleFilterLoader.getInstance().putFilter(file);
}
}
void manageFiles() throws Exception, IllegalAccessException, InstantiationException {
List<File> aFiles = getFiles();
processGroovyFiles(aFiles);
}
...
}
RuleFilterProcessor.java
@Component
public class RuleFilterProcessor {
public void runRuleFilters(String msg) {
List<RuleFilter> list = RuleFilterLoader.getInstance().getFilters();
if (list != null) {
list.forEach(ruleFilter -> {
if (ruleFilter.shouldRun()) {
ruleFilter.run(msg);
}
});
}
}
}