Spel 表达式
SpelUtils工具类
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.util.TypeUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.context.expression.MapAccessor;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.ClassUtils;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* SpelUtils
*
* @author kancy
* @date 2022/8/27 20:51
*/
public class SpelUtils {
/**
* 用于SpEL表达式解析.
*/
private static final SpelExpressionParser parser = new SpelExpressionParser();
/**
* 用于获取方法参数定义名字.
*/
private static final DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
/**
* 解析
*
* @param spel spel
* @param params 参数 map或者实体
* @param returnClass 返回类
* @return {@link T}
*/
public static <T> T parse(String spel, Object params, Class<T> returnClass){
return TypeUtils.cast(parse(spel, params), returnClass, ParserConfig.getGlobalInstance());
}
/**
* 解析
*
* @param spel spel
* @param params 参数 map或者实体
* @return {@link Object}
*/
public static Object parse(String spel, Object params){
// 解析过后的Spring表达式对象
Expression expression = parser.parseExpression(spel);
// spring的表达式上下文对象
EvaluationContext context = new StandardEvaluationContext(params);
if (ClassUtils.isPrimitiveOrWrapper(params.getClass())
|| params instanceof String
|| params instanceof Collection){
return expression.getValue(context);
}
if (params instanceof Map){
// 这里很关键,如果没有配置MapAccessor,那么只能用['c']['a']这种解析方式
context.getPropertyAccessors().add(new MapAccessor());
} else {
if (!params.getClass().getName().startsWith("java.")){
BeanMap beanMap = BeanMap.create(params);
// 设置变量
beanMap.forEach((k,v) -> context.setVariable(String.valueOf(k), v));
}
}
return expression.getValue(context);
}
/**
* 通过spel生成key
*
* @param spELString spel
* @param method 方法
* @param args 参数
* @return {@link String}
*/
public static String generateKeyBySpEL(String spELString, Method method, Object[] args) {
// 解析过后的Spring表达式对象
Expression expression = parser.parseExpression(spELString);
// 使用spring的DefaultParameterNameDiscoverer获取方法形参名数组
String[] paramNames = nameDiscoverer.getParameterNames(method);
// 初始化上下文
if (Objects.isNull(paramNames) || method.getParameterCount() <= 0 || Objects.isNull(args) || args.length <= 0){
return String.valueOf(expression.getValue());
}
// spring的表达式上下文对象
EvaluationContext context;
if (method.getParameterCount() == 1 && Objects.nonNull(args[0])){
// 一个EvaluationContext只能有一个RootObject,引用它的属性时,可以不加前缀
context = new StandardEvaluationContext(args[0]);
if (args[0] instanceof Map){
// 这里很关键,如果没有配置MapAccessor,那么只能用['c']['a']这种解析方式
context.getPropertyAccessors().add(new MapAccessor());
}
context.setVariable(paramNames[0], args[0]);
} else {
Map<String, Object> rootObject = new HashMap<>();
for (int i = 0; i < method.getParameterCount(); i++) {
rootObject.put(paramNames[i], args[i]);
}
context = new StandardEvaluationContext(rootObject);
// 这里很关键,如果没有配置MapAccessor,那么只能用['c']['a']这种解析方式
context.getPropertyAccessors().add(new MapAccessor());
// 设置变量
rootObject.forEach(context::setVariable);
}
return String.valueOf(expression.getValue(context));
}
/**
* 通过spel生成key
*
* @param spELString spel
* @param joinPoint 连接点
* @return {@link String}
*/
public static String generateKeyBySpEL(String spELString, JoinPoint joinPoint) {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
Object[] args = joinPoint.getArgs();
return generateKeyBySpEL(spELString, method, args);
}
}
参考文档
kancy