1.5 Spring表达式语言(SpEL)

server/2025/2/11 15:34:40/

1.5 Spring表达式语言(SpEL)

1.5.1 资源注入表达式实战(深度工程应用)

SpEL基础语法全景

表达式类型:├─ 字面量:#{'Hello World'}├─ 属性引用:#{systemProperties['user.timezone']}├─ 方法调用:#{T(java.lang.Math).random()}├─ 运算符:│    ├─ 算术:+,-,*,/,%,^│    ├─ 关系:eq,ne,lt,gt,le,ge│    └─ 逻辑:and,or,not└─ 集合操作:#{users.?[age > 18]}

动态配置注入案例

java">@Configuration
public class DynamicConfig {// 注入操作系统时区@Value("#{systemProperties['user.timezone']}")private String systemTimezone;// 注入随机端口(8000-9000)@Value("#{T(java.util.concurrent.ThreadLocalRandom).current().nextInt(8000,9000)}")private int serverPort;// 注入环境变量@Value("#{environment['DATABASE_URL'] ?: 'jdbc:mysql://localhost:3306/default'}")private String databaseUrl;// 注入集合元素@Value("#{'${allowed.ips}'.split(',')}")private List<String> allowedIps;// 注入Bean属性@Value("#{dataSource.url}")private String datasourceUrl;
}

多环境配置表达式方案

# application-dev.properties
app.notification.enabled=true
app.cache.size=1000# application-prod.properties
app.notification.enabled=false
app.cache.size=5000
java">@Service
public class SystemService {// 根据环境动态启用功能@Value("#{${app.notification.enabled} ? 'ENABLED' : 'DISABLED'}")private String notificationStatus;// 动态计算缓存超时时间@Value("#{${app.cache.size} * 60 * 1000}")private long cacheTimeout;
}

1.5.2 条件化配置的表达式技巧(生产级方案)

组合条件表达式实战

java">@Configuration
@Conditional( value = OnRequiredServicesCondition.class
)
public class ServiceConfiguration {@Bean@ConditionalOnExpression("#{environment.getProperty('app.mode') == 'cluster' && " +"T(java.net.InetAddress).getLocalHost().hostName.startsWith('node-')}")public ClusterService clusterService() {return new ClusterServiceImpl();}
}public class OnRequiredServicesCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {Environment env = context.getEnvironment();return env.containsProperty("DB_MASTER_URL") &&env.containsProperty("CACHE_SERVERS");}
}

表达式驱动特性开关

java">@RestController
public class FeatureController {// 根据配置动态启用API版本@GetMapping("/v2/data")@ConditionalOnExpression("#{environment['app.feature.v2-api'] == 'enabled'}")public ResponseEntity<?> getDataV2() {// 新版实现逻辑}// 根据日期范围启用功能@Scheduled(fixedRate = 60000)@ConditionalOnExpression("#{T(java.time.LocalDate).now().isAfter(T(java.time.LocalDate).parse('2024-01-01'))}")public void executeYearlyTask() {// 2024年后启用的任务}
}

1.5.3 安全权限表达式进阶用法(金融系统案例)

方法级安全控制

java">@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {// 启用方法级安全注解
}@Service
public class AccountService {// 账户必须属于当前用户@PreAuthorize("#account.owner == authentication.name")public void updateAccount(Account account) {// 更新逻辑}// 交易金额限制@PreAuthorize("#amount <= 100000 or hasRole('VIP')")public void transfer(BigDecimal amount) {// 转账逻辑}// 审计日志访问控制@PostFilter("filterObject.operator == authentication.name or hasAuthority('AUDIT_READ_ALL')")public List<AuditLog> getLogs() {// 查询日志逻辑}
}

自定义权限表达式

java">// 1. 定义根安全对象
public class CustomSecurityExpressionRoot extends SecurityExpressionRoot {public CustomSecurityExpressionRoot(Authentication a) {super(a);}public boolean isInDepartment(String deptCode) {User user = (User) this.authentication.getPrincipal();return user.getDepartments().contains(deptCode);}
}// 2. 注册自定义表达式处理器
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {@Overrideprotected SecurityExpressionRoot createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {return new CustomSecurityExpressionRoot(authentication);}
}// 3. 配置安全策略
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {@Overrideprotected MethodSecurityExpressionHandler createExpressionHandler() {return new CustomMethodSecurityExpressionHandler();}
}// 4. 业务层使用
@Service
public class FinanceService {@PreAuthorize("isInDepartment('FINANCE')")public void approvePayment() {// 财务审批逻辑}
}

1.5.4 SpEL高级特性实战(数据转换与校验)

类型安全转换表达式

java">public class DataValidator {// 强制类型转换@Value("#{T(java.time.LocalDate).parse('${app.startDate}')}")private LocalDate startDate;// 集合元素转换@Value("#{'${app.ports}'.split(',').?[T(java.lang.Integer).parseInt(#this)]}")private List<Integer> activePorts;// 映射转换@Value("#{${app.ratios}.entrySet().stream().collect(T(java.util.Map).Entry.comparingByValue())}")private Map<String, Double> sortedRatios;
}

动态校验规则引擎

java">public class OrderValidationRules {// 从配置文件加载规则@Value("#{'${validation.order.amount}'.split(':')}")private List<String> amountRules;public boolean validateAmount(BigDecimal amount) {String operator = amountRules.get(0);BigDecimal limit = new BigDecimal(amountRules.get(1));switch (operator) {case "gt": return amount.compareTo(limit) > 0;case "lt": return amount.compareTo(limit) < 0;default: throw new IllegalArgumentException("无效运算符");}}
}// 配置示例
validation.order.amount=gt:1000

http://www.ppmy.cn/server/166787.html

相关文章

VMware 虚拟机中 Ubuntu 20 网络不通问题解决总结

VMware 虚拟机中 Ubuntu 20 网络不通问题解决总结 一、问题描述 在 VMware 虚拟机中的 Ubuntu 20 系统出现网络不通的问题&#xff0c;具体表现为无法 ping 通百度且无法访问网页。ip addr 命令显示 ens33 网络接口处于异常状态&#xff0c;如显示 NO - CARRIER、DOWN 等&…

Qt、C++软件开发之table控件:tableview和tablewidget的区别以及C++详细用法。

` 文章目录 前言区别一、数据模型‌:二、灵活性和定制性‌:三、性能和内存使用‌:四、适用场景‌:使用方法QTableView创建数据模型‌:设置模型到QTableView‌:设置表头和数据‌:自定义委托‌:QTableWidget‌创建QTableWidget‌:设置表头‌:插入数据‌:插入新行和列‌…

COBOL语言的区块链

COBOL语言与区块链技术的结合 引言 在当今数字化的时代&#xff0c;区块链技术以其去中心化、透明性和安全性等特点&#xff0c;成为了金融、供应链管理、物联网等领域的热门话题。与此同时&#xff0c;COBOL&#xff08;Common Business-Oriented Language&#xff09;作为一…

React 第二十三节 useTransition Hook 的使用注意事项详解

文章内容 基于 React 18 &#xff0c;如有错误&#xff0c;欢迎批评指正&#xff1b; 一、概述&#xff1a; useTransition 是一个在不阻塞UI渲染的情况下更新数据状态&#xff0c;它会降低当前视图的渲染优先级&#xff0c;而优先执行视图中其它用户交互操作&#xff0c;比如…

linux 中毒 脚本 .system 服务器中毒占用CPU,进程名称.system

服务器使用的是centOS 7 云服务 近期发现服务器CPU使用率100% 使用 top free -h 等命令查找无果。怀疑是服务器命令可能被修改了或者进程隐藏无法查询。查询隐藏服务器的插件 下载不要积分 这是一个linux可执行文件&#xff0c;我改成top了。下载到任意目录后指定。/top即可。 …

探索B-树系列

&#x1f308;前言&#x1f308; 本文将讲解B树系列&#xff0c;包含 B-树&#xff0c;B树&#xff0c;B*树&#xff0c;其中主要讲解B树底层原理&#xff0c;为什么用B树作为外查询的数据结构&#xff0c;以及B-树插入操作并用代码实现&#xff1b;介绍B树、B*树。 &#x1f4…

c/c++蓝桥杯经典编程题100道(15)字符串匹配

字符串匹配 ->返回c/c蓝桥杯经典编程题100道-目录 目录 字符串匹配 一、题型解释 二、例题问题描述 三、C语言实现 解法1&#xff1a;暴力匹配&#xff08;难度★&#xff09; 解法2&#xff1a;KMP算法&#xff08;难度★★★&#xff09; 解法3&#xff1a;Boyer-…

【Milvus】向量数据库pymilvus使用教程

以下是根据 Milvus 官方文档整理的详细 PyMilvus 使用教程&#xff0c;基于 Milvus 2.5.x 版本&#xff1a; PyMilvus 使用教程 目录 安装与环境准备连接 Milvus 服务数据模型基础概念创建集合&#xff08;Collection&#xff09;插入数据创建索引向量搜索删除操作完整示例注…