import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.SpelCompilerMode;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SpelExpressionExtractor {
// 表达式解析器(带编译优化)
private static final ExpressionParser PARSER = new SpelExpressionParser(
new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, getClass().getClassLoader())
);
// 表达式缓存(提升性能)
private static final Map<String, Expression> EXPRESSION_CACHE = new ConcurrentHashMap<>();
// 自定义函数注册
static {
registerCustomFunctions();
}
/**
* 执行取值操作
* @param data 原始数据(接口返回的Map)
* @param elExpress SpEL表达式
* @param resultCode 结果标识码
* @return 包含提取结果的单条目Map
*/
public Map<String, Object> extract(
Map<String, Object> data,
String elExpress,
String resultCode) {
try {
Object value = evaluateSpelExpression(data, elExpress);
return Collections.singletonMap(resultCode, value);
} catch (Exception e) {
// 异常处理:返回错误信息
Map<String, Object> errorResult = new HashMap<>();
errorResult.put(resultCode, null);
errorResult.put("error", "表达式解析失败: " + e.getMessage());
return errorResult;
}
}
/**
* 评估SpEL表达式
*/
private Object evaluateSpelExpression(Map<String, Object> data, String expression) {
// 从缓存获取或创建表达式
Expression expr = EXPRESSION_CACHE.computeIfAbsent(expression, PARSER::parseExpression);
// 创建评估上下文
StandardEvaluationContext context = new StandardEvaluationContext(data);
// 设置根对象
context.setRootObject(data);
// 注册自定义函数
registerContextFunctions(context);
// 执行表达式
return expr.getValue(context);
}
/**
* 注册自定义函数(静态注册)
*/
private static void registerCustomFunctions() {
try {
// 注册数学函数
MathFunctions.register();
// 注册字符串处理函数
StringFunctions.register();
// 注册日期处理函数
DateFunctions.register();
} catch (Exception e) {
System.err.println("自定义函数注册失败: " + e.getMessage());
}
}
/**
* 注册上下文函数(每次评估时注册)
*/
private void registerContextFunctions(StandardEvaluationContext context) {
// 注册实用函数
context.registerFunction("size", SpelFunctions.class.getDeclaredMethod("size", Object.class));
context.registerFunction("empty", SpelFunctions.class.getDeclaredMethod("empty", Object.class));
}
// 测试用例
public static void main(String[] args) {
// 构建测试数据
Map<String, Object> data = new HashMap<>();
Map<String, Object> user = new HashMap<>();
Map<String, Object> address = new HashMap<>();
address.put("city", "Beijing");
address.put("streets", new String[]{"Main St", "Second St"});
user.put("address", address);
user.put("age", 30);
user.put("scores", new int[]{85, 92, 78});
data.put("user", user);
data.put("status", "active");
data.put("price", 123.45);
SpelExpressionExtractor extractor = new SpelExpressionExtractor();
// 测试SpEL表达式
System.out.println("1. 基本取值: " +
extractor.extract(data, "#root['user']['address']['city']", "CITY_CODE"));
System.out.println("2. 数组取值: " +
extractor.extract(data, "user.address.streets[1]", "STREET_CODE"));
System.out.println("3. 条件表达式: " +
extractor.extract(data, "user.age > 18 ? 'adult' : 'child'", "AGE_GROUP"));
System.out.println("4. 安全导航: " +
extractor.extract(data, "user?.phone?.number ?: 'N/A'", "PHONE_CODE"));
System.out.println("5. 集合投影: " +
extractor.extract(data, "user.scores.![#this > 80]", "PASS_SCORES"));
System.out.println("6. 方法调用: " +
extractor.extract(data, "T(java.lang.Math).round(price)", "ROUNDED_PRICE"));
System.out.println("7. 自定义函数: " +
extractor.extract(data, "#size(user.scores)", "SCORE_COUNT"));
System.out.println("8. 复杂表达式: " +
extractor.extract(data,
"user.age > 25 && user.address.city contains 'jing' ? 'valid' : 'invalid'",
"VALIDATION"));
}
}
/**
* SpEL实用函数类
*/
class SpelFunctions {
public static int size(Object obj) {
if (obj == null) return 0;
if (obj instanceof Map) return ((Map<?, ?>) obj).size();
if (obj instanceof Iterable) return ((Iterable<?>) obj).spliterator().getExactSizeIfKnown();
if (obj.getClass().isArray()) return java.lang.reflect.Array.getLength(obj);
return 0;
}
public static boolean empty(Object obj) {
return size(obj) == 0;
}
}
/**
* 数学函数注册器
*/
class MathFunctions {
public static void register() throws NoSuchMethodException {
// 可注册更多数学函数
}
}
/**
* 字符串函数注册器
*/
class StringFunctions {
public static void register() throws NoSuchMethodException {
// 可注册字符串处理函数
}
}
/**
* 日期函数注册器
*/
class DateFunctions {
public static void register() throws NoSuchMethodException {
// 可注册日期处理函数
}
}