Groovy 是什么?
Apache的Groovy是Java平台上设计的面向对象编程语言。Groovy是一门基于JVM的脚本语言,这门动态语言拥有类似Python、Ruby和Smalltalk中的一些特性,可以作为Java平台的脚本语言使用,Groovy代码动态地编译成运行于Java虚拟机(JVM)上的Java字节码,并与其他Java代码和库进行互操作。
Java 为何需要 Groovy ?
Groovy 特性如下:
语法上支持动态类型,闭包等新一代语言特性
无缝集成所有已经存在的Java类库
既支持面向对象编程也支持面向过程编程
执行方式可以将groovy编写的源文件编译成class字节码文件,然后交给JVM去执行,也可以直接将groovy源文件解释执行。
Groovy可以与Java完美结合,而且可以使用java所有的库
举例说明:
业务场景中
不同的流程模板生成的事项在完结时可以做不同的逻辑处理,因为流程模板有很多,且这些逻辑都是很定制化的内容,如果维护在java代码中则很冗余且开发成本高,可无法对用户开放,这时使用groovry的话,在java代码中开发一个入口,事项完结时执行,这个入口可以去调用groovry代码(可以维护在配置文件中,可以维护在数据库中),以实现逻辑定制处理;
具体使用:
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.codehaus.groovy.control.CompilerConfiguration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class GroovyUtils {
private static CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
static {
compilerConfiguration.setScriptBaseClass(GroovyCustom.class.getName());
}
public static GroovyShell bindShell(Map map){
return new GroovyShell(new Binding(map), compilerConfiguration);
}
public static void removeBindingByKeys(GroovyShell groovyShell, String... keys){
Map resource = groovyShell.getContext().getVariables();
for (String key: keys) {
resource.remove(key);
}
}
// 此静态类InitCroovy 中维护一个map和字符串script属性
//map是new Binding(map)时使用的,放到map中的值,在groovry脚本中可以使用
//script是groovyShell.evaluate(initCroovy.getScript() + actionScript)时使用的,因为grovvry代码中也需要使用一些工具类或者其他的类的引入,这里可以将一些常用的公共的引入放到script中维护,比如utilParam中维护了常用的工具类
public static class InitCroovy {
private Map<String, Object> map;
private StringBuffer script;
private InitCroovy() {
initParam();
}
private InitCroovy(Map map) {
this.map = map;
initParam();
}
public static InitCroovy of(Map map) {
return new InitCroovy(map);
}
private void initParam(){
if (MapUtils.isEmpty(map)) {
map = new HashMap<>();
}
if (script == null) {
script = new StringBuffer();
}
}
public InitCroovy utilParam() {
script.append("import org.apache.commons.lang3.StringUtils;");
script.append("import java.util.Collections;");
script.append("import java.util.Arrays;");
script.append("import org.apache.commons.collections.CollectionUtils;");
script.append("import org.apache.commons.collections.MapUtils;");
script.append("import com.alibaba.aecp.app.common.util.EmployeeUtils;");
script.append("import com.alibaba.aecp.app.common.util.CommonUtils;");
script.append("import com.alibaba.aecp.app.common.util.PatternUtil;");
script.append("import com.alibaba.aecp.app.common.util.StripHtmlUtils;");
script.append("import com.alibaba.fastjson.TypeReference;");
return this;
}
public InitCroovy customParam(Map<String, Object> map, String script) {
if (MapUtils.isNotEmpty(map)) {
this.map.putAll(map);
}
if (StringUtils.isNotBlank(script)) {
this.script.append(script);
}
return this;
}
public void setVariable(String name, Object value) {
map.put(name, value);
}
public void removeVariableByKeys(String... keys) {
Arrays.stream(keys).forEach(key -> map.remove(key));
}
public Map<String, Object> getParam() {
return map;
}
public String getScript() {
return script.toString();
}
}
}
public class GroovyCustom extends Script {
@Override
public Object run() {
return GroovyCustom.class.getDeclaredMethods();
}
//获取 Object 类型 对象集合中 某一元素 的 集合
public static Object arrayValue(Object array, String key, String type) {
List<Object> keyList = new ArrayList<>();
try {
if (!(array instanceof List) || CollectionUtils.isEmpty((List) array)) {
return null;
}
keyList = ((List<Map>) (JsonUtils.shift((List) array, Map.class))).stream().map(map -> map.get(key)).collect(Collectors.toList());
} catch (Exception e) {
log.error("arrayValue :", e);
}
return CommonUtils.resultType(keyList, type);
}
}
调用代码
1. 构建InitCroovy中的map属性,map是new Binding(map)时使用的,放到map中的值,在groovry脚本中可以使用
GroovyUtils.InitCroovy initCroovy = GroovyUtils.InitCroovy.of(new HashMap()) .utilParam();
2.使用GroovyShell对象 执行脚本
Binding binding=new Binding(map);
GroovyShell groovyShell=GroovyUtils.bindShell(binding);
groovyShell.evaluate(/具体的groovry脚本/)
也可以写成:Object value = GroovyUtils.bindShell(initGroovy.getParam()).evaluate(initGroovy.getScript());
3.compilerConfiguration.setScriptBaseClass(GroovyCustom.class.getName());
CompilerConfiguration提供内置的支持能力与自定义脚本能力;在GroovyCustom中自定义一些方法,在evaluate方法中可以直接使用
public static void main(String[] args) {
Map<String, Object> map = new HashMap<>();
List<Map<String, Object>> mapList = new ArrayList<>();
mapList.add(new HashMap<String, Object>() {{ put("name", "name1"); }} );
mapList.add(new HashMap<String, Object>() {{ put("name", "name2"); }} );
map.put("aaa", new HashMap<String, Object>() {{ put("bbb", mapList); }});
Object value = GroovyUtils.bindShell(map).evaluate("arrayValue(aaa.bbb, /name/, /String/)");
System.out.println(value);
}
4.groovry脚本的定义
//代码中需要用的类型都要引入
import com.alibaba.aecp.app.common.constants.HadleyConstants;
//groovry脚本中无法打印日志,可以拼接字符串返回字符串,在调用执行groovyShell.evaluate的地方获取返回值然后打印
StringBuffer logger = new StringBuffer();
//if判断也需要;结尾
if (CollectionUtils.isEmpty(businessOwnershipList)) {
//groovry的字符串需要用/abcdefg/双斜杠标识
logger.append(/abcdefg\r\n/);
return logger;
};
//lambada表达式的写法和java不太一样,每个Function、Predicate函数式接口的参数都需要加上{}和 as Function<? super 处理的数据类型, ? super 返回的数据类型>
Map<String, People> eventsExtraDataDOMap = peopleList.stream().collect(
Collectors.toMap({ k -> k.getName() } as Function<? super People, ? super String>,
{ v -> v } as Function<? super People, ? super People>)
);
List<peopleExt> businessTypeObligationList = peopleList.stream().map(
{ people ->
PeopleExt peopleExt = new PeopleExt();
return peopleExt;
} as Function<? super People, ? extends PeopleExt>)
.collect(
Collectors.toList());
return logger;