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);
}
}
参考文档
__EOF__

本文作者:゛鱼记忆不止七秒つ
本文链接:https://www.cnblogs.com/kancy/p/spel.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/kancy/p/spel.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
kancy
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步