整体思路:
- 从数据库查询脚本配置
- 利用groovy编译器编辑脚本,编译器工具类见https://blog.csdn.net/tszxlzc/article/details/100535735
- 利用编译的class对象创建GroovyObject对象,并做缓存
上工具类
import groovy.lang.GroovyObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* groovy对象工程,并对对象做缓存
*/
@Slf4j
public class GroovyObjectFactory {
// key : 脚本编码 value : 脚本的编译类
private static Map<String, GroovyObject> groovyClassMap = new ConcurrentHashMap<>();
// key : 脚本编码 value : 脚本修改时间
private static Map<String, Date> groovyModifyTimeMap = new ConcurrentHashMap<>();
/**
* 根据脚本编码、脚本内容获取编译类
* @param reconScriptConf
* @return
*/
public static GroovyObject getScriptObject(ReconScriptConf reconScriptConf){
Assert.notNull(reconScriptConf,"脚本配置不能为空");
Assert.hasText(reconScriptConf.getScriptCode(),"脚本编码不能为空");
Assert.notNull(reconScriptConf.getModifyTime(),"脚本修改时间不能为空");
String scriptCode = reconScriptConf.getScriptCode();
//脚本没有修改过,且缓存中存在直接返回对象
GroovyObject groovyObject= groovyClassMap.get(scriptCode);
if(groovyModifyTimeMap.get(scriptCode) != null &&
groovyModifyTimeMap.get(scriptCode).equals(reconScriptConf.getModifyTime()) &&
groovyObject != null){
return groovyObject;
}
//编译脚本并生成对象
String scriptContent = reconScriptConf.getScriptContent();
Assert.hasText(scriptContent,"脚本内容为空");
Class<?> aClass = GroovyCompiler.compile(scriptContent);
try {
groovyObject = (GroovyObject) aClass.newInstance();
groovyClassMap.put(scriptCode,groovyObject);
groovyModifyTimeMap.put(scriptCode,reconScriptConf.getModifyTime());
} catch (Exception e) {
log.warn("脚本实例化异常,脚本编码={},脚本内容={}", scriptCode, scriptContent);
log.warn("错误信息为",e);
throw new RuntimeException("脚本实例化异常");
}
return groovyObject;
}
/**
* 清除缓存的groovy类
* @param scriptCode
*/
public static void removeClass(String scriptCode){
groovyClassMap.remove(scriptCode);
}
}