一、常用函数实例实现
java
复制
下载
// 数学函数类
public class MathFunctions {
public static double round(double value, int precision) {
double scale = Math.pow(10, precision);
return Math.round(value * scale) / scale;
}
public static double percentage(double value) {
return value * 100;
}
public static double toRadians(double degrees) {
return Math.toRadians(degrees);
}
}
// 日期函数类
public class DateFunctions {
public static String formatDate(Date date, String pattern) {
return new SimpleDateFormat(pattern).format(date);
}
public static Date addDays(Date date, int days) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.DATE, days);
return cal.getTime();
}
public static long daysBetween(Date start, Date end) {
return TimeUnit.DAYS.convert(
end.getTime() - start.getTime(),
TimeUnit.MILLISECONDS
);
}
public static boolean isWeekend(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int day = cal.get(Calendar.DAY_OF_WEEK);
return day == Calendar.SATURDAY || day == Calendar.SUNDAY;
}
}
二、Spring集成实现
java
复制
下载
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.expression.Expression;
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;
@Configuration
public class ExpressionConfig {
// 表达式解析器Bean(线程安全)
@Bean
public ExpressionParser spelExpressionParser() {
return new SpelExpressionParser(
new SpelParserConfiguration(
SpelCompilerMode.IMMEDIATE,
getClass().getClassLoader()
)
);
}
// 表达式缓存Bean
@Bean
public Map<String, Expression> expressionCache() {
return new ConcurrentHashMap<>();
}
// 提取器Bean
@Bean
public ExpressionExtractor expressionExtractor(
@Autowired ExpressionParser parser,
@Autowired Map<String, Expression> cache) {
return new ExpressionExtractor(parser, cache);
}
}
@Service
public class ExpressionExtractor {
private final ExpressionParser parser;
private final Map<String, Expression> expressionCache;
@Autowired
public ExpressionExtractor(
ExpressionParser parser,
Map<String, Expression> expressionCache) {
this.parser = parser;
this.expressionCache = expressionCache;
}
/**
* 执行取值操作
* @param data 原始数据
* @param elExpress SpEL表达式
* @param resultCode 结果标识码
* @return 提取结果
*/
public Map<String, Object> extract(
Map<String, Object> data,
String elExpress,
String resultCode) {
try {
Object value = evaluateExpression(data, elExpress);
return Collections.singletonMap(resultCode, value);
} catch (Exception e) {
return errorResult(resultCode, "表达式解析失败: " + e.getMessage());
}
}
private Object evaluateExpression(Map<String, Object> data, String expression) {
Expression expr = expressionCache.computeIfAbsent(expression, parser::parseExpression);
StandardEvaluationContext context = createEvaluationContext(data);
return expr.getValue(context);
}
private StandardEvaluationContext createEvaluationContext(Map<String, Object> data) {
StandardEvaluationContext context = new StandardEvaluationContext(data);
context.setRootObject(data);
registerFunctions(context);
return context;
}
private void registerFunctions(StandardEvaluationContext context) {
// 注册数学函数
registerMathFunctions(context);
// 注册日期函数
registerDateFunctions(context);
// 注册工具函数
registerUtilityFunctions(context);
}
private void registerMathFunctions(StandardEvaluationContext context) {
try {
context.registerFunction("mathRound",
MathFunctions.class.getDeclaredMethod("round", double.class, int.class));
context.registerFunction("mathPercentage",
MathFunctions.class.getDeclaredMethod("percentage", double.class));
context.registerFunction("mathToRadians",
MathFunctions.class.getDeclaredMethod("toRadians", double.class));
} catch (Exception e) {
throw new RuntimeException("数学函数注册失败", e);
}
}
private void registerDateFunctions(StandardEvaluationContext context) {
try {
context.registerFunction("dateFormat",
DateFunctions.class.getDeclaredMethod("formatDate", Date.class, String.class));
context.registerFunction("dateAddDays",
DateFunctions.class.getDeclaredMethod("addDays", Date.class, int.class));
context.registerFunction("dateDaysBetween",
DateFunctions.class.getDeclaredMethod("daysBetween", Date.class, Date.class));
context.registerFunction("dateIsWeekend",
DateFunctions.class.getDeclaredMethod("isWeekend", Date.class));
} catch (Exception e) {
throw new RuntimeException("日期函数注册失败", e);
}
}
private void registerUtilityFunctions(StandardEvaluationContext context) {
try {
context.registerFunction("size",
ExpressionUtils.class.getDeclaredMethod("size", Object.class));
context.registerFunction("empty",
ExpressionUtils.class.getDeclaredMethod("empty", Object.class));
context.registerFunction("coalesce",
ExpressionUtils.class.getDeclaredMethod("coalesce", Object[].class));
} catch (Exception e) {
throw new RuntimeException("工具函数注册失败", e);
}
}
private Map<String, Object> errorResult(String resultCode, String message) {
Map<String, Object> result = new HashMap<>();
result.put(resultCode, null);
result.put("error", message);
return result;
}
}
// 工具函数类
public class ExpressionUtils {
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;
}
public static Object coalesce(Object... values) {
for (Object value : values) {
if (value != null) return value;
}
return null;
}
}
三、设计模式应用
1. 工厂方法模式 - 创建不同安全级别的上下文
java
复制
下载
public interface EvaluationContextFactory {
StandardEvaluationContext createContext(Map<String, Object> data);
}
// 完全权限上下文工厂
@Service
@Profile("dev") // 仅开发环境使用
public class FullAccessContextFactory implements EvaluationContextFactory {
@Override
public StandardEvaluationContext createContext(Map<String, Object> data) {
StandardEvaluationContext context = new StandardEvaluationContext(data);
context.setRootObject(data);
return context;
}
}
// 安全限制上下文工厂
@Service
@Profile("!dev") // 非开发环境使用
public class RestrictedContextFactory implements EvaluationContextFactory {
@Override
public StandardEvaluationContext createContext(Map<String, Object> data) {
StandardEvaluationContext context = new StandardEvaluationContext(data);
// 禁用危险操作
context.setPropertyAccessors(Collections.singletonList(
new ReflectivePropertyAccessor() {
@Override
public boolean canRead(EvaluationContext context, Object target, String name) {
// 禁止访问以"system"开头的属性
return !name.startsWith("system") && super.canRead(context, target, name);
}
}
));
return context;
}
}
// 在ExpressionExtractor中使用工厂
@Service
public class ExpressionExtractor {
private final EvaluationContextFactory contextFactory;
@Autowired
public ExpressionExtractor(
ExpressionParser parser,
Map<String, Expression> cache,
EvaluationContextFactory contextFactory) {
// ...
this.contextFactory = contextFactory;
}
private StandardEvaluationContext createEvaluationContext(Map<String, Object> data) {
StandardEvaluationContext context = contextFactory.createContext(data);
registerFunctions(context);
return context;
}
}
2. 策略模式 - 表达式执行策略
java
复制
下载
public interface ExpressionExecutionStrategy {
Object execute(Expression expression, StandardEvaluationContext context);
}
// 直接执行策略
@Service
public class DirectExecutionStrategy implements ExpressionExecutionStrategy {
@Override
public Object execute(Expression expression, StandardEvaluationContext context) {
return expression.getValue(context);
}
}
// 安全执行策略(添加审计日志)
@Service
public class AuditedExecutionStrategy implements ExpressionExecutionStrategy {
private static final Logger logger = LoggerFactory.getLogger(AuditedExecutionStrategy.class);
@Override
public Object execute(Expression expression, StandardEvaluationContext context) {
String expressionString = expression.getExpressionString();
long startTime = System.currentTimeMillis();
try {
Object result = expression.getValue(context);
long duration = System.currentTimeMillis() - startTime;
logger.info("表达式执行成功: {} | 耗时: {}ms", expressionString, duration);
return result;
} catch (Exception e) {
logger.error("表达式执行失败: {} | 错误: {}", expressionString, e.getMessage());
throw e;
}
}
}
// 在ExpressionExtractor中使用策略
@Service
public class ExpressionExtractor {
private final ExpressionExecutionStrategy executionStrategy;
@Autowired
public ExpressionExtractor(
// ... 其他依赖
ExpressionExecutionStrategy executionStrategy) {
// ...
this.executionStrategy = executionStrategy;
}
private Object evaluateExpression(Map<String, Object> data, String expression) {
Expression expr = expressionCache.computeIfAbsent(expression, parser::parseExpression);
StandardEvaluationContext context = createEvaluationContext(data);
return executionStrategy.execute(expr, context);
}
}
3. 装饰器模式 - 添加缓存装饰器
java
复制
下载
public class CachedExpressionDecorator implements Expression {
private final Expression target;
private final Map<EvaluationContext, Object> cache = new ConcurrentHashMap<>();
public CachedExpressionDecorator(Expression target) {
this.target = target;
}
@Override
public Object getValue(EvaluationContext context) throws EvaluationException {
return cache.computeIfAbsent(context, ctx -> target.getValue(ctx));
}
// 其他方法委托给target...
}
// 在ExpressionExtractor中应用装饰器
@Service
public class ExpressionExtractor {
private Object evaluateExpression(Map<String, Object> data, String expression) {
Expression expr = expressionCache.computeIfAbsent(expression, exp ->
new CachedExpressionDecorator(parser.parseExpression(exp))
);
// ...
}
}
四、完整使用示例
java
复制
下载
@Service
public class DataProcessingService {
@Autowired
private ExpressionExtractor extractor;
public void processResponse(Map<String, Object> apiResponse) {
// 1. 基本取值
Map<String, Object> cityResult = extractor.extract(
apiResponse,
"#root['user']['address']['city']",
"CITY_CODE"
);
// 2. 数学函数
Map<String, Object> discountResult = extractor.extract(
apiResponse,
"#mathRound(#root['price'] * 0.85, 2)",
"DISCOUNT_PRICE"
);
// 3. 日期函数
Map<String, Object> deliveryResult = extractor.extract(
apiResponse,
"#dateAddDays(T(java.util.Date).from(java.time.Instant.now()), 3)",
"DELIVERY_DATE"
);
// 4. 复杂逻辑
Map<String, Object> statusResult = extractor.extract(
apiResponse,
"#root['orderStatus'] == 'PAID' && #root['inventory'] > 0 ? 'READY_TO_SHIP' : 'PENDING'",
"SHIPPING_STATUS"
);
// 5. 安全函数
Map<String, Object> safeResult = extractor.extract(
apiResponse,
"#safeEscapeHtml(#root['userComment'])",
"SAFE_COMMENT"
);
}
}
五、设计模式优势总结
-
工厂方法模式:
- 根据不同环境创建不同安全级别的上下文
- 符合开闭原则,易于扩展新的上下文类型
- 通过Spring Profile实现环境隔离
-
策略模式:
- 灵活切换表达式执行策略
- 支持添加审计、监控等横切关注点
- 符合单一职责原则
-
装饰器模式:
- 为表达式添加缓存功能而不修改原有逻辑
- 提高重复表达式的执行效率
- 透明地增强对象功能
-
模板方法模式(隐含在流程中):
- 固定表达式处理流程(解析→上下文准备→执行→结果处理)
- 允许子步骤自由变化
-
依赖注入:
- 通过Spring容器管理组件生命周期
- 解耦组件依赖关系
- 支持配置化切换实现
六、安全增强建议
- 表达式白名单机制:
java
复制
下载
@Service
public class ExpressionValidator {
private final Set<String> allowedPatterns = Set.of(
"user\..*",
"order\..*",
"product\..*"
);
public boolean validate(String expression) {
return allowedPatterns.stream()
.anyMatch(pattern -> expression.matches(pattern));
}
}
// 在ExpressionExtractor中使用
public Map<String, Object> extract(...) {
if (!validator.validate(expression)) {
return errorResult(resultCode, "表达式未授权");
}
// ...
}
- 执行时间限制:
java
复制
下载
public class TimeLimitedExecutionStrategy implements ExpressionExecutionStrategy {
@Override
public Object execute(Expression expression, StandardEvaluationContext context) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Object> future = executor.submit(() -> expression.getValue(context));
try {
return future.get(500, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
future.cancel(true);
throw new EvaluationException("表达式执行超时");
} catch (Exception e) {
throw new EvaluationException("执行错误: " + e.getMessage());
} finally {
executor.shutdownNow();
}
}
}
这个完整方案提供了:
- 丰富的数学/日期函数实例
- Spring容器集成管理
- 多种设计模式应用
- 生产级安全防护
- 灵活的扩展点
系统可根据实际需求选择不同的上下文工厂和执行策略,平衡功能与安全性,满足各种复杂场景下的表达式解析需求。