本文目录导读:

基础案例
基础表达式
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class SpELBasicCase {
public static void main(String[] args) {
SpelExpressionParser parser = new SpelExpressionParser();
// 字符串表达式
Expression exp = parser.parseExpression("'Hello World'");
String message = (String) exp.getValue();
System.out.println(message); // Hello World
// 数学运算
Expression exp2 = parser.parseExpression("10 + 5 * 2");
int result = (int) exp2.getValue();
System.out.println(result); // 20
// 字符串拼接
Expression exp3 = parser.parseExpression("'Hello' + ' ' + 'World'");
System.out.println(exp3.getValue()); // Hello World
}
}
使用 EvaluationContext
public class SpELContextCase {
@Data
static class User {
private String name;
private int age;
private List<String> hobbies;
private Address address;
}
@Data
static class Address {
private String city;
private String street;
}
public static void main(String[] args) {
// 创建用户对象
User user = new User();
user.setName("张三");
user.setAge(25);
user.setHobbies(Arrays.asList("编程", "阅读", "运动"));
Address address = new Address();
address.setCity("北京");
address.setStreet("长安街");
user.setAddress(address);
SpelExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("user", user);
// 访问对象属性
Expression exp1 = parser.parseExpression("name");
System.out.println(exp1.getValue(user)); // 张三
// 嵌套属性
Expression exp2 = parser.parseExpression("address.city");
System.out.println(exp2.getValue(user)); // 北京
// 方法调用
Expression exp3 = parser.parseExpression("name.length()");
System.out.println(exp3.getValue(user)); // 2
// 集合访问
Expression exp4 = parser.parseExpression("hobbies[0]");
System.out.println(exp4.getValue(user)); // 编程
}
}
集合操作案例
列表和映射操作
public class SpELCollectionCase {
public static void main(String[] args) {
SpelExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
// 创建集合
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 25);
context.setVariable("numbers", numbers);
context.setVariable("map", map);
// 列表推导(过滤)
Expression exp1 = parser.parseExpression("#numbers.?[#this > 3]");
List<Integer> filtered = (List<Integer>) exp1.getValue(context);
System.out.println(filtered); // [4, 5]
// 列表推导(映射)
Expression exp2 = parser.parseExpression("#numbers.![#this * 2]");
List<Integer> mapped = (List<Integer>) exp2.getValue(context);
System.out.println(mapped); // [2, 4, 6, 8, 10]
// 筛选第一个匹配项
Expression exp3 = parser.parseExpression("#numbers.^[#this > 2]");
Integer firstMatch = (Integer) exp3.getValue(context);
System.out.println(firstMatch); // 3
// 筛选最后一个匹配项
Expression exp4 = parser.parseExpression("#numbers.$[#this < 4]");
Integer lastMatch = (Integer) exp4.getValue(context);
System.out.println(lastMatch); // 3
// 集合判断
Expression exp5 = parser.parseExpression("#numbers.?[#this > 2].size() > 2");
Boolean result = exp5.getValue(context, Boolean.class);
System.out.println(result); // true
}
}
对象列表操作
public class SpELListObjectCase {
@Data
@AllArgsConstructor
static class Product {
private String name;
private Double price;
private Integer stock;
private String category;
}
public static void main(String[] args) {
SpelExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
List<Product> products = Arrays.asList(
new Product("iPhone", 5999.0, 100, "手机"),
new Product("华为", 3999.0, 200, "手机"),
new Product("MacBook", 12999.0, 50, "电脑"),
new Product("iPad", 3499.0, 150, "平板")
);
context.setVariable("products", products);
// 筛选价格大于4000的产品
Expression exp1 = parser.parseExpression("#products.?[price > 4000]");
List<Product> expensiveProducts = (List<Product>) exp1.getValue(context);
System.out.println("高价产品: " + expensiveProducts);
// 筛选特定类别并按价格排序
Expression exp2 = parser.parseExpression("#products.?[category == '手机'].![name]");
List<String> phoneNames = (List<String>) exp2.getValue(context);
System.out.println("手机品牌: " + phoneNames);
// 统计平均值
Expression exp3 = parser.parseExpression("#products.![price].^[true]");
List<Double> prices = (List<Double>) exp3.getValue(context);
double average = prices.stream().mapToDouble(Double::doubleValue).average().orElse(0);
System.out.println("平均价格: " + average);
// 条件判断所有产品
Expression exp4 = parser.parseExpression("#products.![stock > 0].^[true]");
System.out.println("所有产品有库存: " + exp4.getValue(context));
}
}
条件逻辑案例
条件表达式
public class SpELConditionCase {
public static void main(String[] args) {
SpelExpressionParser parser = new SpelExpressionParser();
// 三元运算符
Expression exp1 = parser.parseExpression("10 > 5 ? '正确' : '错误'");
String result1 = (String) exp1.getValue();
System.out.println(result1); // 正确
// Elvis运算符(类似三元)
Expression exp2 = parser.parseExpression("name != null ? name : '默认值'");
// 等价于
Expression exp3 = parser.parseExpression("name ?: '默认值'");
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("name", null);
System.out.println(exp3.getValue(context)); // 默认值
// 安全导航操作符(避免空指针)
context.setVariable("user", null);
Expression exp4 = parser.parseExpression("user?.name?.toUpperCase()");
Object result = exp4.getValue(context);
System.out.println("安全导航结果: " + result); // null(不会抛异常)
// 复杂的逻辑判断
Expression exp5 = parser.parseExpression(
"(age > 18 && age < 65) || (age >= 65 && isRetired)"
);
StandardEvaluationContext userContext = new StandardEvaluationContext();
userContext.setVariable("age", 70);
userContext.setVariable("isRetired", true);
System.out.println(exp5.getValue(userContext)); // true
}
}
业务规则案例
public class SpELBusinessRuleCase {
@Data
@AllArgsConstructor
static class Order {
private double amount;
private Customer customer;
private List<OrderItem> items;
}
@Data
@AllArgsConstructor
static class Customer {
private String level; // VIP / NORMAL
private int loyaltyYears;
}
@Data
@AllArgsConstructor
static class OrderItem {
private String productName;
private double price;
private int quantity;
}
public static void main(String[] args) {
SpelExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
// 创建订单
Customer vipCustomer = new Customer("VIP", 5);
List<OrderItem> items = Arrays.asList(
new OrderItem("电脑", 8000, 1),
new OrderItem("鼠标", 100, 2)
);
Order order = new Order(8200, vipCustomer, items);
context.setVariable("order", order);
// 规则1:VIP客户且忠诚度超过3年,享受95折
String vipRule =
"#order.customer.level == 'VIP' and #order.customer.loyaltyYears > 3";
boolean isVipEligible = parser.parseExpression(vipRule)
.getValue(context, Boolean.class);
System.out.println("VIP折扣资格: " + isVipEligible);
// 规则2:订单金额超过5000,可以免运费
String freeShippingRule = "#order.amount > 5000";
boolean freeShipping = parser.parseExpression(freeShippingRule)
.getValue(context, Boolean.class);
System.out.println("免运费资格: " + freeShipping);
// 规则3:包含特定商品
String hasComputerRule =
"#order.items.?[productName == '电脑'].size() > 0";
boolean hasComputer = parser.parseExpression(hasComputerRule)
.getValue(context, Boolean.class);
System.out.println("包含电脑: " + hasComputer);
// 规则4:计算折扣金额
String discountRule =
"#order.amount * (#order.customer.level == 'VIP' ? 0.95 : 1.0)";
double finalAmount = parser.parseExpression(discountRule)
.getValue(context, Double.class);
System.out.println("最终金额: " + finalAmount);
}
}
Spring 注解使用案例
@Value 注解
@Component
public class SpELValueAnnotationCase {
// 字符串字面量
@Value("'Hello World'")
private String message;
// 系统属性
@Value("#{systemProperties['user.home']}")
private String userHome;
// 引用其他Bean属性
@Value("#{databaseConfig.url}")
private String databaseUrl;
// 调用方法
@Value("#{propertiesUtil.getProperty('app.name', '默认应用名')}")
private String appName;
// 静态常量
@Value("#{T(java.lang.Math).PI}")
private double pi;
// 复杂表达式
@Value("#{systemProperties['user.region'] == 'CN' ? '中国大陆' : '其他地区'}")
private String region;
// 列表
@Value("#{{'spring', 'mybatis', 'redis'}}")
private List<String> frameworks;
// Map
@Value("#{{'key1': 'value1', 'key2': 'value2'}}")
private Map<String, String> configMap;
// 数组
@Value("#{new String[]{'item1', 'item2', 'item3'}}")
private String[] items;
// 引用配置文件中的值
@Value("${app.name:默认名称}")
private String appNameFromConfig;
public void showConfigs() {
System.out.println("Message: " + message);
System.out.println("User Home: " + userHome);
System.out.println("Database URL: " + databaseUrl);
System.out.println("App Name: " + appName);
System.out.println("PI: " + pi);
System.out.println("Region: " + region);
System.out.println("Frameworks: " + frameworks);
System.out.println("Config Map: " + configMap);
System.out.println("Items: " + Arrays.toString(items));
}
}
@PreAuthorize 注解(Spring Security)
@RestController
public class SpELSecurityCase {
// 基于角色的权限控制
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin/data")
public String adminData() {
return "Admin Data";
}
// 基于用户名
@PreAuthorize("#username == authentication.principal.username")
@GetMapping("/user/{username}")
public String userData(@PathVariable String username) {
return "User: " + username;
}
// 自定义方法
@PreAuthorize("@securityService.checkPermission(authentication, #request)")
@PostMapping("/api/secure")
public String secureEndpoint(@RequestBody ApiRequest request,
Authentication authentication) {
return "Secure response";
}
// 复杂的权限表达式
@PreAuthorize("hasAnyRole('ADMIN', 'MANAGER') AND " +
"(hasPermission(#id, 'READ') OR #userId == authentication.principal.id)")
@GetMapping("/document/{id}")
public String getDocument(@PathVariable Long id, @RequestParam Long userId) {
return "Document: " + id;
}
}
高级案例
自定义函数
public class SpELCustomFunctionCase {
public static String formatDate(LocalDate date) {
return date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
public static double calculateDiscount(double price, double discountRate) {
return price * (1 - discountRate);
}
public static void main(String[] args) {
SpelExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
// 注册静态方法
context.registerFunction("formatDate",
SpELCustomFunctionCase.class.getDeclaredMethod("formatDate", LocalDate.class));
context.registerFunction("calculateDiscount",
SpELCustomFunctionCase.class.getDeclaredMethod("calculateDiscount", double.class, double.class));
// 使用自定义函数
Expression exp1 = parser.parseExpression("#formatDate(T(java.time.LocalDate).now())");
String dateStr = (String) exp1.getValue(context);
System.out.println("格式化日期: " + dateStr);
// 计算折扣
Expression exp2 = parser.parseExpression("#calculateDiscount(1000, 0.15)");
double price = (double) exp2.getValue(context);
System.out.println("折扣价格: " + price);
}
}
动态规则引擎案例
public class SpringELRuleEngine {
static class Rule {
private String name;
private String condition;
private String action;
private int priority;
}
@Data
@AllArgsConstructor
static class Transaction {
private double amount;
private String type; // TRANSFER / PURCHASE / WITHDRAW
private String from;
private String to;
}
public static void main(String[] args) {
SpelExpressionParser parser = new SpelExpressionParser();
// 定义规则
List<Rule> rules = Arrays.asList(
new Rule("大额转账",
"#trans.amount > 10000 and #trans.type == 'TRANSFER'",
"执行大额转账审核流程", 1),
new Rule("频繁交易",
"#trans.amount > 5000 and #trans.type == 'PURCHASE'",
"标记为高消费用户", 2),
new Rule("异常取现",
"#trans.type == 'WITHDRAW' and #trans.amount > 50000",
"触发取现风控", 1)
);
// 测试事务
Transaction t1 = new Transaction(15000, "TRANSFER", "A001", "B002");
Transaction t2 = new Transaction(8000, "PURCHASE", "A001", "SHOP001");
Transaction t3 = new Transaction(60000, "WITHDRAW", "A001", "CASH");
for (Transaction trans : Arrays.asList(t1, t2, t3)) {
System.out.println("\n=== 事务检查: " + trans.getType() + " " + trans.getAmount() + " ===");
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("trans", trans);
for (Rule rule : rules) {
boolean matched = parser.parseExpression(rule.condition)
.getValue(context, Boolean.class);
if (matched) {
System.out.println("触发规则: " + rule.name + " -> " + rule.action);
}
}
}
}
}
性能优化案例
public class SpELPerformanceCase {
static class ExpressionCache {
private static final ConcurrentHashMap<String, Expression> CACHE = new ConcurrentHashMap<>();
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
public static Expression getExpression(String expr) {
return CACHE.computeIfAbsent(expr, PARSER::parseExpression);
}
}
public static void main(String[] args) {
// 编译模式的性能优化
SpelParserConfiguration config = new SpelParserConfiguration(
SpelCompilerMode.IMMEDIATE,
ExpressionCache.class.getClassLoader()
);
SpelExpressionParser compilerParser = new SpelExpressionParser(config);
// 使用编译模式
String expression = "name.toUpperCase() + ' - ' + age";
StandardEvaluationContext context = new StandardEvaluationContext();
User user = new User();
user.setName("张三");
user.setAge(25);
// 缓存表达式避免重复解析
Expression exp = ExpressionCache.getExpression(expression);
// 性能测试
long start = System.nanoTime();
for (int i = 0; i < 100000; i++) {
Object result = exp.getValue(user);
}
long end = System.nanoTime();
System.out.println("执行100000次耗时: " + (end - start) / 1_000_000 + "ms");
}
}
这些案例展示了 SpEL 在不同场景下的应用:
- 基础表达式:字面量、运算符、方法调用
- 集合操作:过滤、映射、投影、聚合
- 条件逻辑:三元运算符、安全导航
- Spring 注解:@Value、@PreAuthorize
- 自定义函数:注册和使用自定义方法
- 规则引擎:动态业务规则处理
- 性能优化:编译模式、表达式缓存
SpEL 非常灵活,可以处理复杂的表达式,但要注意:
- 复杂表达式可能影响性能
- 避免在循环中重复创建表达式
- 适当使用缓存提高性能
- 注意表达式安全性(避免注入攻击)
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播