当前位置: 首页 > news >正文

SpEL 表达式详解

SpEL表达式(Spring Expression Language)详解

SpEL(Spring Expression Language)是Spring框架提供的一种强大的表达式语言,用于在运行时查询和操作对象图,支持字面量、运算符、方法调用、属性访问、正则匹配、集合操作等,可独立使用或集成到Spring框架(如注解、XML配置、Bean定义)中。

一、核心特点

  1. 动态求值:运行时解析表达式,而非编译期;
  2. 跨场景使用:支持XML配置、注解(如@Value)、编程式调用;
  3. 丰富的语法:涵盖字面量、运算符、类型转换、集合操作、Bean引用等;
  4. 与Spring无缝集成:可直接访问Spring容器中的Bean、环境变量、系统属性等。

二、基本语法与常用场景

1. 字面量表达式

支持字符串、数字、布尔、null等基础类型的直接表达:

// 编程式调用示例(核心类:ExpressionParser、SpelExpressionParser、EvaluationContext)ExpressionParserparser=newSpelExpressionParser();// 字符串(单引号包裹)Expressionexp1=parser.parseExpression("'Hello SpEL'");Stringstr=(String)exp1.getValue();// 结果:Hello SpEL// 数字Expressionexp2=parser.parseExpression("100 + 200 * 2");intnum=(Integer)exp2.getValue();// 结果:500// 布尔Expressionexp3=parser.parseExpression("true && false");booleanbool=(Boolean)exp3.getValue();// 结果:false// nullExpressionexp4=parser.parseExpression("null");ObjectnullObj=exp4.getValue();// 结果:null

2. 属性与方法调用

通过.访问对象属性/方法,支持嵌套访问:

// 定义测试对象classUser{privateStringname;privateList<String>hobbies;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicList<String>getHobbies(){returnhobbies;}publicvoidsetHobbies(List<String>hobbies){this.hobbies=hobbies;}publicStringsayHello(Stringmsg){return"Hello: "+msg;}}// 初始化上下文Useruser=newUser();user.setName("张三");user.setHobbies(Arrays.asList("篮球","读书"));EvaluationContextcontext=newStandardEvaluationContext(user);// 访问属性Stringname=(String)parser.parseExpression("name").getValue(context);// 张三// 调用方法(带参数)Stringhello=(String)parser.parseExpression("sayHello('SpEL')").getValue(context);// Hello: SpEL// 嵌套访问(集合属性)Stringhobby=(String)parser.parseExpression("hobbies[0]").getValue(context);// 篮球

3. 运算符

支持算术、逻辑、关系、赋值、三元运算符等:

类型运算符示例说明
算术10 + 23 * 410 % 3加减乘除、取模
逻辑`true
关系5 > 3'abc' == 'abc'大于、等于、不等于等
赋值name = '李四'为属性赋值
三元运算name == '张三' ? '是' : '否'条件判断
Elvis运算符name ?: '默认值'简化空判断(name为空则返回默认值)

示例:

// 三元运算Stringresult=(String)parser.parseExpression("name == '张三' ? '管理员' : '普通用户'").getValue(context);// 管理员// Elvis运算符(空保护)parser.parseExpression("name = null").getValue(context);StringdefaultName=(String)parser.parseExpression("name ?: '未知用户'").getValue(context);// 未知用户

4. 集合操作

支持访问集合元素、筛选、投影等:

// 1. 访问List/MapList<Integer>nums=Arrays.asList(1,2,3,4);EvaluationContextlistContext=newStandardEvaluationContext(nums);intfirst=(Integer)parser.parseExpression("[0]").getValue(listContext);// 1Map<String,Integer>map=newHashMap<>();map.put("a",10);map.put("b",20);EvaluationContextmapContext=newStandardEvaluationContext(map);intval=(Integer)parser.parseExpression("['b']").getValue(mapContext);// 20// 2. 集合筛选(.?[表达式])List<Integer>evenNums=(List<Integer>)parser.parseExpression(".?[#this % 2 == 0]").getValue(listContext);// [2,4]// 3. 集合投影(.![表达式])List<String>strNums=(List<String>)parser.parseExpression(".![#this + '号']").getValue(listContext);// [1号,2号,3号,4号]

5. Spring容器集成

(1)引用Spring Bean(@符号)

在Spring环境中,可直接引用容器中的Bean:

// 假设容器中有一个名为"userService"的Bean@Value("#{userService}")privateUserServiceuserService;// 调用Bean的方法@Value("#{userService.getUserName(1)}")privateStringuserName;
(2)访问环境变量/系统属性
// 系统属性(systemProperties)@Value("#{systemProperties['os.name']}")privateStringosName;// 例如:Windows 10// 环境变量(environment)@Value("#{environment['JAVA_HOME']}")privateStringjavaHome;// Spring配置属性(application.properties)@Value("#{my.properties['app.name']}")privateStringappName;

6. 注解中的常用场景

(1)@Value注解(区别:${}是占位符,#{}是SpEL)
// 基础值@Value("#{100 * 2}")privateintnum;// 200// 空判断@Value("#{user.name ?: '默认名称'}")privateStringuserName;// 集合@Value("#{T(java.util.Arrays).asList('a','b','c')}")privateList<String>letters;
(2)@PreAuthorize(Spring Security权限控制)
// 权限表达式(判断用户是否有指定角色)@PreAuthorize("#userId == authentication.principal.id or hasRole('ADMIN')")publicvoiddeleteUser(LonguserId){// 业务逻辑}

三、编程式使用SpEL的完整示例

importorg.springframework.expression.Expression;importorg.springframework.expression.ExpressionParser;importorg.springframework.expression.spel.standard.SpelExpressionParser;importorg.springframework.expression.spel.support.StandardEvaluationContext;publicclassSpELDemo{publicstaticvoidmain(String[]args){// 1. 创建表达式解析器ExpressionParserparser=newSpelExpressionParser();// 2. 定义上下文(绑定对象)Useruser=newUser();user.setName("李四");user.setAge(25);StandardEvaluationContextcontext=newStandardEvaluationContext(user);// 3. 解析表达式// 访问属性Stringname=(String)parser.parseExpression("name").getValue(context);System.out.println("姓名:"+name);// 李四// 运算 + 赋值parser.parseExpression("age = age + 1").getValue(context);intage=(Integer)parser.parseExpression("age").getValue(context);System.out.println("年龄:"+age);// 26// 方法调用Stringgreet=(String)parser.parseExpression("sayHello('SpEL')").getValue(context);System.out.println(greet);// Hello: SpEL}staticclassUser{privateStringname;privateintage;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicStringsayHello(Stringmsg){return"Hello: "+msg;}}}

四、注意事项

  1. 性能:SpEL运行时解析,高频调用场景需缓存解析后的Expression对象;
  2. 安全:避免解析用户输入的表达式(防止注入攻击);
  3. 区别${}#{}
    • ${}:Spring占位符,仅做字符串替换(先解析);
    • #{}:SpEL表达式,支持动态求值(后解析);
    • 混合使用:@Value("${app.name:#{systemProperties['user.name']}}")(占位符默认值用SpEL);
  4. 类型转换:SpEL内置类型转换器,可自定义TypeConverter扩展。

五、核心API总结

类/接口作用
ExpressionParser表达式解析器(核心接口)
SpelExpressionParserExpressionParser的默认实现
EvaluationContext表达式求值上下文(绑定变量、Bean等)
StandardEvaluationContextEvaluationContext的默认实现
Expression解析后的表达式对象(可多次求值)

SpEL是Spring生态中灵活的动态表达式工具,核心场景包括配置注入、权限控制、动态规则判断等,掌握其语法可大幅提升Spring开发的灵活性。

http://www.cnnetsun.cn/news/88578.html

相关文章:

  • Qwen-Image微调实战:让模型认识新车
  • 路由策略与策略路由
  • 软件测试面试题及答案,2026春招必看版
  • 基于飞桨实现图像分类:从LeNet到ResNet
  • 基于单片机的智能窗帘控制系统设计(光照+遥控)【附代码】
  • LobeChat插件系统开发指南:拓展你的AI应用边界
  • 基于单片机的智能燃气泄漏报警与关闭系统设计【附代码】
  • 基于单片机的智能水位控制系统设计(水箱+自动补水)【附代码】
  • LobeChat本地安装详细步骤指南
  • 《12个月服务期!黑龙江炉渣外运处置项目公开招标》
  • 2025年国产电脑操作系统推荐:银河麒麟为何成为党政机关首选?
  • Flutter 2025 国际化与本地化工程:从多语言到文化适配,打造真正全球化的应用
  • 事务拦截器TransactionInterceptor
  • Qwen3-VL-30B 4bit量化版发布:单卡部署突破
  • FLUX.1-ControlNet自定义控制模式全解
  • Windows server 2019 离线安装docker容器
  • springboot基于uniapp的有机农产品商城电商平台_4747f8w7-小程序
  • 用Dify构建文生视频工作流:从输入到输出
  • 基于Android的高校教室预约管理平台系统(源码+lw+部署文档+讲解等)
  • 开源不输商用!LobeChat媲美ChatGPT的用户体验实测
  • 十三、Kafka基础环境实战
  • EmotiVoice 安装与环境配置指南
  • LobeChat能否实现AI专利检索?技术创新辅助工具开发
  • vue基于spring boot的乡村民宿预订周边旅游管理系统
  • 网安零基础必冲!upload-labs 文件上传漏洞保姆级通关教程
  • vue基于Springboot框架 新能源充电桩报修管理系统
  • v3基于SpringBoot的酒店管理系统
  • Git安装Windows版本并配置清华镜像用于TensorFlow贡献开发
  • Langchain-Chatchat 0.3.1 Windows本地部署指南
  • 私有云ACK:企业智能化转型的安全基座与算力引擎