写在SpEL之前

EL表达式是JSP中一个十分重要的概念。它允许我们从model中读取数据以及条件性的渲染JSP页面。Spring在3.0的版本中也引入了Spring Expression Language从而使得spring具有更好的可扩展性和跨平台性。
虽然SpEL引擎作为Spring 组合里的表达式解析的基础 ,但它不直接依赖于Spring,可独立使用。这也是SpEL的最大优点。

这一章内容将包括SpEL的使用,并且会举一个例子从配置文件中读取相应的属性。因为最终的项目是为了实现thymeleaf+springboot+mysql, 而很多地方都无形中使用了SpEL,比如Thymeleaf获取model数据,比如项目从config文件中获取常量配置。让我们赶紧来感受一下这个功能的强大吧。

SpEL Operators

SpEL支持在表达式中使用多种类型的运算符,具体情况如上图所示。SpEL默认的格式为#{expression}。当然,它也支持嵌套一般的属性获取符${properties},如#{${someProperty} + 2}。这些值可以使用@Value("")注释注入到相应的属性上。
下面我们将举一些例子来说明这些运算符的使用

算数运算符

@Value("#{19 + 1}") // add的值为20
private double add; @Value("#{'String1 ' + 'string2'}") //addString的值为"String1 string2"
private String addString; @Value("#{20 - 1}") // subtract值为19
private double subtract;@Value("#{10 * 2}") // multiply值为20
private double multiply;@Value("#{36 / 2}") // divide值为19
private double divide;@Value("#{36 div 2}") // div操作等价与/
private double divideAlphabetic; @Value("#{37 % 10}") // modulo值为7
private double modulo;@Value("#{37 mod 10}") // mod操作等价于%
private double moduloAlphabetic; @Value("#{2 ^ 9}") // powerOf的值为512
private double powerOf;@Value("#{(2 + 2) * 2 + 9}") // brackets值为17
private double brackets;

这里之所以给/赋予等价符号div是为了让XML配置形式兼容,无需进行转义。

关联和逻辑运算符

@Value("#{1 == 1}") // equal值为true
private boolean equal;@Value("#{1 eq 1}") // eq等价于==
private boolean equalAlphabetic;@Value("#{1 != 1}") // notEqual值为false
private boolean notEqual;@Value("#{1 ne 1}") // ne等价于!=
private boolean notEqualAlphabetic;@Value("#{1 < 1}") // lessThan的值为false
private boolean lessThan;@Value("#{1 lt 1}") // lt等价于<
private boolean lessThanAlphabetic;@Value("#{1 <= 1}") // lessThanOrEqual的值为true
private boolean lessThanOrEqual;@Value("#{1 le 1}") // le等价于<=
private boolean lessThanOrEqualAlphabetic;@Value("#{1 > 1}") // greaterThan的值为false
private boolean greaterThan;@Value("#{1 gt 1}") // gt等价于>
private boolean greaterThanAlphabetic;@Value("#{1 >= 1}") // greaterThanOrEqual的值为true
private boolean greaterThanOrEqual;@Value("#{1 ge 1}") // ge等价于>=
private boolean greaterThanOrEqualAlphabetic;@Value("#{250 > 200 && 200 < 4000}") // and值为true
private boolean and; @Value("#{250 > 200 and 200 < 4000}") // and等价于&&
private boolean andAlphabetic;@Value("#{400 > 300 || 150 < 100}") // or的值为true
private boolean or;@Value("#{400 > 300 or 150 < 100}") // or等价于||
private boolean orAlphabetic;@Value("#{!true}") // not值为false
private boolean not;@Value("#{not true}") // not等价于!
private boolean notAlphabetic;

条件运算符

condition ? a : b是指condition成立时值为a,否则为b
这种条件运算符可以用于实现if-else语句,也可以用于判断属性是否为空,并且在属性为空时提供默认值。

@Value("#{2 > 1 ? 'a' : 'b'}") // ternary的值为b
private String ternary;@Value("#{someBean.someProperty != null ? someBean.someProperty : 'default'}")
private String ternary;@Value("#{someBean.someProperty ?: 'default'}") // 等价于上式的执行结果
private String elvis;

正则表达式

使用matches语句来判断当前的字符串是否满足特定的正则表达式

@Value("#{'100' matches '\\d+' }") // Will inject true
private boolean validNumericStringResult;@Value("#{'100fghdjf' matches '\\d+' }") // Will inject false
private boolean invalidNumericStringResult;@Value("#{'valid alphabetic string' matches '[a-zA-Z\\s]+' }") // Will inject true
private boolean validAlphabeticStringResult;@Value("#{'invalid alphabetic string #$1' matches '[a-zA-Z\\s]+' }") // Will inject false
private boolean invalidAlphabeticStringResult;@Value("#{someBean.someValue matches '\d+'}") // Will inject true if someValue contains only digits
private boolean validNumericValue;

获取list和map数据类型

假设现在有一个Bean名称为workersHolder,这个组件中有两个fields,一个是workers的链表,这里记录了所有的员工名称,还有一个是salaryByWorkers键值对map,里面存储了员工姓名和其对应的薪水。现在这个bean中初始化了四个员工信息,如何能将这四个员工的信息读取出来?

@Component("workersHolder")
public class WorkersHolder {private List<String> workers = new LinkedList<>();private Map<String, Integer> salaryByWorkers = new HashMap<>();public WorkersHolder() {workers.add("John");workers.add("Susie");workers.add("Alex");workers.add("George");salaryByWorkers.put("John", 35000);salaryByWorkers.put("Susie", 47000);salaryByWorkers.put("Alex", 12000);salaryByWorkers.put("George", 14000);}//Getters and setters
}

map采用componentName.mapName['key']读取key对应的value
list采用componentName.listName[index]读取对应index下标的元素
同样也支持对方法的调用,整体的语法其实和JAVA是相似的。

@Value("#{workersHolder.salaryByWorkers['John']}") // Will inject 35000
private Integer johnSalary;@Value("#{workersHolder.salaryByWorkers['George']}") // Will inject 14000
private Integer georgeSalary;@Value("#{workersHolder.salaryByWorkers['Susie']}") // Will inject 47000
private Integer susieSalary;@Value("#{workersHolder.workers[0]}") // Will inject John
private String firstWorker;@Value("#{workersHolder.workers[3]}") // Will inject George
private String lastWorker;@Value("#{workersHolder.workers.size()}") // Will inject 4
private Integer numberOfWorkers;

从上面这些例子我们可以看出,SpEL不仅可以调用属性,还可以访问一些公开的方法,甚至进行正则表达式的匹配,可以说是非常轻量级而且全能了。

至此我们已经了解了如何通过annotation来使用SpEL。其实SpEL还可以通过XML进行配置,甚至可以脱离Spring环境使用,下面可以简单介绍。

XML配置

这里直接从别的网站上找了一个实例,有兴趣的可以至底下的references中查看,这里就不详细叙述了。

SpEL in Spring 真实场景示例

现在我们的项目有一个需求,结合配置文件,从配置文件中读取我们想要知道的数据,并赋值给类中的变量。这里我们的配置文件采用yaml格式(不熟悉yaml请先参考我的这篇博客)。现在我们先看配置文件的内容。

配置文件名称为application.yml,application-test.yml和application-validate.yml,位于classpath:/resources/config目录底下,其中application.yml是主配置文件,决定选择哪个配置文件作为当前配置。application-test.yml是测试环境的配置文件,application-validate.yml是校验信息的配置文件。内容分别如下所示。

application.yml

#当前活跃的配置文件为application-test和application-validate
spring:profiles:active: test,validate

application-test.yml

#测试环境的配置内容,这里举的例子是映射到服务器端口号为8080
server:port: 8080...

application-validate.yml

#配置了校验信息
login:username:notempty: 用户名不可以为空

下面展示了在代码中使用annotation获得配置文件中的值

@Value("${server.port}")
private int port;@Value("${login.username.notempty}")
private String notEmpty;

当然,为了方便起见,spring还允许我们将所有的配置文件映射到一个专门的JAVA Class中,封装成一bean。这样在需要注入的时候,只需使用@Autowired注释将其引用进来就可以使用。

@Data
@Component
@ConfigurationProperties(prefix = "server")
public class AppConfig{private int port;
}

这里需要注意的是还需要在spring-boot的入口文件上加标签

@SpringBootApplication
@EnableConfigurationProperties({AppConfig.class})
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

在调用的类中注入AppConfig

@Autowired
private AppConfig config;

References

项目地址
SpEL官方文档中文版
快速教程
spring-boot自定义配置文件
spring-boot yaml使用方式


想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~

spring-boot周边游(二)SpEL相关推荐

  1. spring boot高性能实现二维码扫码登录(中)——Redis版

    前言 本打算用CountDownLatch来实现,但有个问题我没有考虑,就是当用户APP没有扫二维码的时候,线程会阻塞5分钟,这反而造成性能的下降.好吧,现在回归传统方式:前端ajax每隔1秒或2秒发 ...

  2. spring boot高性能实现二维码扫码登录(上)——单服务器版

    前言 目前网页的主流登录方式是通过手机扫码二维码登录.我看了网上很多关于扫码登录博客后,发现基本思路大致是:打开网页,生成uuid,然后长连接请求后端并等待登录认证相应结果,而后端每个几百毫秒会循环查 ...

  3. 学习Spring Boot:(二十五)使用 Redis 实现数据缓存

    前言 由于 Ehcache 存在于单个 java 程序的进程中,无法满足多个程序分布式的情况,需要将多个服务器的缓存集中起来进行管理,需要一个缓存的寄存器,这里使用的是 Redis. 正文 当应用程序 ...

  4. Spring Boot:(二)启动原理解析

    Spring Boot:(二)启动原理解析 前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂SpringBoot内部启动原理,以后难免会吃亏. ...

  5. Java(Spring boot)实现生成二维码

    文章目录 一.引入spring boot依赖: 二.工具类代码: 三.调用工具类生成二维码 1.将链接生成二维码图片并保存到指定路径 2.将链接生成二维码直接显示在页面 3.将以get请求传参链接生成 ...

  6. Spring Boot(十二)集成spring-boot-starter-mail发送邮件

    项目GitHub地址 : https://github.com/FrameReserve/TrainingBoot Spring Boot(十二)集成spring-boot-starter-mail发 ...

  7. 【单服务器版】spring boot高性能实现二维码扫码登录(上)

    作者:刘冬.NET 来源:http://www.cnblogs.com/GoodHelper/p/8641905.html 前言 目前网页的主流登录方式是通过手机扫码二维码登录.我看了网上很多关于扫码 ...

  8. 【Redis版】spring boot高性能实现二维码扫码登录(中)

    作者: 刘冬 来源:http://www.cnblogs.com/GoodHelper/p/8643071.html 前言 本打算用CountDownLatch来实现,但有个问题我没有考虑,就是当用户 ...

  9. 【订阅与发布机制版】spring boot高性能实现二维码扫码登录(下)

    点击上方[JAVA乐园],选择"置顶公众号",有内涵有价值的文章第一时间送达! 作者: 刘冬 来源:https://www.cnblogs.com/GoodHelper/p/865 ...

  10. 国内最全的Spring Boot系列之二

    历史文章 <国内最全的Spring Boot系列之一> 视频&交流平台 SpringBoot视频:http://t.cn/R3QepWG Spring Cloud视频:http:/ ...

最新文章

  1. php的json格式
  2. 由IP和掩码计算广播地址
  3. js - prototype 继承
  4. arthas使用示例:stack输出当前方法被调用的路径
  5. 欢乐暑假-高校俱乐部暑期线上编程竞赛奖励机制
  6. asp.net mvc web api 参数输入多个参数
  7. java中的循环结构_Java中的循环结构进阶
  8. centos8调整分辨率_Hyper-V 设置 CentOS 8 文本模式下分辨率
  9. 计算机服务哪些不能关闭,Win7系统下哪些系统服务不能关闭
  10. 简述计算机的英语作文,初中计算机的英语作文
  11. 同花顺如何切换k线_K线之形态学:浅谈纸白银产品该如何去做好交易?
  12. L2-024. 部落-PAT团体程序设计天梯赛GPLT
  13. PaddlePaddle飞桨OCR文本检测——入门安装GPU版(一)
  14. Long-Short Memory Network(LSTM长短期记忆网络)
  15. 2020计算机保研系列「最终篇」 —— 我所参加过的高校考核(北大信工/清华Open Fiesta/清华-伯克利/港中文深圳/浙大人工智能/浙大软件/上交软件/中科大先研院/复旦计算机)
  16. VMware Workstation 蓝屏
  17. jsGannt Improved 中文教程文档
  18. 隐马尔可夫模型(一)概念
  19. 如何在wps2019演示(ppt)中无需鼠标点击立即播放视频
  20. zTree的使用教程

热门文章

  1. 无线控制器+FIT AP原理
  2. 计算机笔记本英语,笔记本电脑英文怎么说?
  3. ISO计算机网络体系,ISO网络体系结构论文
  4. ROI Pooling(感兴趣区域池化)【笔记】
  5. Petastorm库--在pytorch中使用读取parquet格式
  6. 校园网连接助手 适用于哆点 Python源码
  7. 中国科幻大片开山之作 --- 我看《流浪地球》
  8. java 必应壁纸批量下载
  9. MFC中使用SKIN++
  10. ocp考证简要须知及报名流程