小编一、SpringEL-根本先容什么是SpringEL(SpEL)?Spring3中引入了Spring表达式措辞—SpringEL,SpEL是一种强大,简洁的装置Bean的办法SpringEL可以通过运行期间实行的表达式将值装置到我们的属性或布局函数当中SpringEL可以调用JDK中供应的静态常量,获取外部Properties文件中的的配置为什么要利用SpringEL?平常通过配置文件或Annotaton注入的Bean,实在都可以称为静态性注入如Bean A中有变量A,它的值须要根据Bean B的B变量为参考,在这场景下静态注入就对这样的处理显得非常无力而Spring3增加的SpringEL就可以完备知足这种需求,而且还可以对不同Bean的字段进行打算再进行赋值,功能非常强大如何利用SpringEL?SpringEL从名字来看就能看出和EL是有点关系的,SpringEL的利用和EL表达式的利用非常相似EL表达式在JSP页面更方便地获取后台中的值,而SpringEL便是为了更方便获取Spring容器中的Bean的值EL利用${},而SpringEL利用#{}进行表达式的声明两者紧张差异$是去找外部配置的参数,将值赋过来#是SpEL表达式,去探求对应变量的内容也可以直策应用@value("常量")注入不该用EL,这样写法与直接赋值等价如果是在Spring中利用可以利用@PropertySource("classpath:my.properties")加载对应配置文件二、EL表达式-根本利用

# 配置文件com: codecoord: el: num: 1001 name: el language: - java - spring - mysql - linux # 逗号分隔可以注入列表 language02: java,spring,mysql,linux利用EL注入大略值

/ 注入大略值,直接注入不该用EL,EL不支持直接指定常量 直接在EL中指定的常量会当做配置处理,和直接赋值等价 /@Value("1432516744")private Integer no;注入配置文件属性值

/ 注入整型属性值 /@Value("${com.codecoord.el.num}")private Integer num;/ 注入字符属性值 /@Value("${com.codecoord.el.name}")private String name;

jsp中获得map的keySpringBoot技巧实践SpELu0026EL表达式 Vue.js

注入默认值

/ 注入字符不存在属性值并指定默认值,默认值利用过冒号分隔 : 注入常量实在就可以指定一个不存在的配置然后利用默认值,此处skill的值为java /@Value("${com.codecoord.el.skill:java}")private String skill;注入列表不支持直接配置文件中数组语法格式注入列表可以识别利用逗号,分隔的配置,spring默认以,分隔

// 缺点写法:不支持直接注入yml列表格式语法列表@Value("${com.codecoord.el.language}")private List<String> listLanguage;@Value("${com.codecoord.el.language}")private String[] strLanguage;/ 支持,分隔的注入列表 /@Value("${com.codecoord.el.language02}")private List<String> listLanguage02;@Value("${com.codecoord.el.language02}")private String[] strLanguage02;完全参考如下配置文件

server: port: 8888com: codecoord: el: num: 1001 name: el language: - java - spring - mysql - linux # 逗号分隔可以注入列表 language02: java,spring,mysql,linux属性配置类

import lombok.Data;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import java.util.List;@Data@Componentpublic class ElConfig { / 注入大略值,直接注入不该用EL,EL不支持直接指定常量 直接在EL中指定的常量会当做配置处理,和直接赋值等价 / @Value("1432516744") private Integer no; / 注入整型属性值 / @Value("${com.codecoord.el.num}") private Integer num; / 注入字符属性值 / @Value("${com.codecoord.el.name}") private String name; / 注入字符不存在属性值并指定默认值,默认值利用过冒号分隔 : 注入常量实在就可以指定一个不存在的配置然后利用默认值,此处skill的值为java / @Value("${com.codecoord.el.skill:java}") private String skill; /// 不支持直接注入列表 /@Value("${com.codecoord.el.language}") private List<String> listLanguage; @Value("${com.codecoord.el.language}") private String[] strLanguage;/ / 支持,分隔的注入列表 / @Value("${com.codecoord.el.language02}") private List<String> listLanguage02; @Value("${com.codecoord.el.language02}") private String[] strLanguage02;}向controller中注入配置类,然后访问接口测试结果如下

{ "no": 1432516744, "num": 1001, "name": "el", "skill": "java", "listLanguage02": [ "java", "spring", "mysql", "linux" ], "strLanguage02": [ "java", "spring", "mysql", "linux" ]}三、SpringEL-根本利用利用SpEL注入大略值和普通EL注入利用基本同等SpEl注入map配置文件中须要利用双引号括起来,否则将会注入失落败,key为单引号

# SpElspEl: mapInject: "{'name': 'SpEl', 'website': 'http://www.codeocord.com'}"java类中先利用${spEl.mapInject}注入字符串值,#{}会解析字符串的值转为map

@Value("#{${spEl.mapInject}}")private Map<String, String> mapInject;SpEl注入list除了可以通过EL注入listI外,也可以利用#{${}.split('分隔符')}的办法注入List配置文件中例如利用#分隔

spEl: listInject: "44#11#99#100"java类中先利用${spEl.listInject}注入字符串值,内容利用单引号括起来,然后对字符串利用split方法分隔提示:避免为空情形,可以给一个默认值空串

@Value("#{'${spEl.listInject:}'.split('#')}") private List<String> listInject;动态注入上述注入都是静态注入,SpEl支持从Spring容器中注入信息,称为动态注入。
动态注入类如下

import lombok.AllArgsConstructor;import lombok.Data;import org.springframework.stereotype.Component;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;@Component@Datapublic class SpElConstant { private String name = "SpElConstant-name"; private String nickname = "tianxin"; private int num = 100; private List<String> product = new ArrayList<String>() {{ add("huaweiMate30Pro"); add("xiaomi10x5g"); }}; private Map<String, String> productMap = new HashMap<String, String>() {{ put("huaweiMate30Pro", "5999"); put("xiaomi10x5g", "4999"); }}; private List<City> cityList = new ArrayList<City>() {{ add(new City("深圳", 1000L)); add(new City("杭州", 2000L)); add(new City("贵阳", 900L)); }}; public String showProperty() { return "showProperty-无参数"; } public String showProperty(String name) { return "showProperty-" + name; } @Data @AllArgsConstructor static class City { private String name; private long population; }}SpEl支持和不支持操作支持动态注入实例,类似于工具自动注入SPL不支持直接注入配置文件中的配置支持调用静态和实例方法静态方法:@Value("#{T(package.ClassName).ConstFieldName")支持调用静态类或常量支持运算符运算支持操作凑集支持查询筛选凑集和投影注入完全操作如下

import lombok.Data;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import java.util.List;import java.util.Map;@Data@Componentpublic class SpElConfig { /// 不支持直接注入配置文件值 /@Value("#{com.codecoord.el.num}") private Integer num;/ / 工具注入 / @Value("#{spElConstant}") private SpElConstant spElConstant; / 注入ID为spElConstant Bean中的STR常量/变量 / @Value("#{spElConstant.name}") private String name; / 调用无参方法 / @Value("#{spElConstant.showProperty()}") private String method1; / 有参吸收字符串的方法 / @Value("#{spElConstant.showProperty('Hell SpringEL')}") private String method2; / 方法返回的String为大写 / @Value("#{spElConstant.showProperty().toUpperCase()}") private String method3; / 若利用method3这种办法,若果showProperty返回为null 将会抛出NullPointerException,可以利用以下办法避免 利用?.符号代表若然左边的值为null,将不实行右边方法 / @Value("#{spElConstant.showProperty()?.toUpperCase()}") private String method4; / 注入math常量 / @Value("#{T(java.lang.Math).PI}") private double pi; / 用random方法获取返回值 / @Value("#{T(java.lang.Math).random()}") private double random; / 获取文件路径符号 / @Value("#{T(java.io.File).separator}") private String separator; / 拼接字符串 / @Value("#{spElConstant.nickname + ' ' + spElConstant.name}") private String concatString; / 对数字类型进走运算,spElConstant拥有num属性 / @Value("#{3 T(java.lang.Math).PI + spElConstant.num}") private double operation; / 进行逻辑运算 / @Value("#{spElConstant.num > 100 and spElConstant.num <= 200}") private boolean logicOperation; / 进行或非逻辑操作 / @Value("#{not (spElConstant.num == 100) or spElConstant.num <= 200}") private boolean logicOperation2; / 利用三元运算符 / @Value("#{spElConstant.num > 100 ? spElConstant.num : spElConstant.num + 100}") private Integer logicOperation3; / 获取下标为0的元素 / @Value("#{spElConstant.product[0]}") private String str; / 获取下标为0元素的大写形式 / @Value("#{spElConstant.product[0]?.toUpperCase()}") private String upperStr; / 获取map中key为hello的value / @Value("#{spElConstant.productMap['hello']}") private String mapValue; / 根据product下标为0元素作为key获取testMap的value / @Value("#{spElConstant.productMap[spElConstant.product[0]]}") private String mapStrByproduct; / 注入人口大于即是1000人口的城市 / @Value("#{spElConstant.cityList.?[population >= 1000]}") private List<SpElConstant.City> cityList; / 注入人口即是900人口的城市 / @Value("#{spElConstant.cityList.?[population == 900]}") private SpElConstant.City city; / 注入人口大于即是1000人口的城市,且只保留城市名称 / @Value("#{spElConstant.cityList.?[population >= 1000].![name]}") private List<String> cityName;}注入结果

{ "spElConstant": { "name": "SpElConstant-name", "nickname": "tianxin", "num": 100, "product": [ "huaweiMate30Pro", "xiaomi10x5g" ], "productMap": { "xiaomi10x5g": "4999", "huaweiMate30Pro": "5999" }, "cityList": [ { "name": "深圳", "population": 1000 }, { "name": "杭州", "population": 2000 }, { "name": "贵阳", "population": 900 } ] }, "name": "SpElConstant-name", "method1": "showProperty-无参数", "method2": "showProperty-Hell SpringEL", "method3": "SHOWPROPERTY-无参数", "method4": "SHOWPROPERTY-无参数", "pi": 3.141592653589793, "random": 0.19997238292235787, "separator": "\\", "concatString": "tianxin SpElConstant-name", "operation": 109.42477796076938, "logicOperation": false, "logicOperation2": true, "logicOperation3": 200, "str": "huaweiMate30Pro", "upperStr": "HUAWEIMATE30PRO", "mapValue": null, "mapStrByproduct": "5999", "cityList": [ { "name": "深圳", "population": 1000 }, { "name": "杭州", "population": 2000 } ], "city": { "name": "贵阳", "population": 900 }, "cityName": [ "深圳", "杭州" ]}Spring操作外部Properties文件

<!-- 首先通过applicaContext.xml中<util:properties>增加properties文件 --><!-- 把稳须要引入Spring的util schemea命名空间和把稳id属性,id属性将在SpringEL中利用 --><util:properties id="db" location="classpath:application.properties"/>复制代码public class TestSpringEL { // 把稳db为xml文件中声明的id @Value("#{db['jdbc.url']}") private String propertiesValue;}SpringEL在利用时仅仅是一个字符串,不易于排错与测试,也没有IDE检讨我们的语法,当涌现缺点时较难检测,繁芜的表达式不建议通过SpringEL办法注入。
在非必要情形下,不推举利用SpEl的繁芜注入,清晰可读的代码更为主要且有利于排查问题四、属性自动注入上述都是通过指定字段进行注入,可以通过@ConfigurationProperties指定前缀进行自动注入org.springframework.boot.context.properties.ConfigurationProperties配置类

user: id: ${random.uuid} name: autowire address: unknown website: www.codecoord.com age: ${random.int}自动属性注入类通过prefix指定前端为user,然后将会把user.后的类型按照名称进行注入把稳必须要供应setter方法

import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;@Component@ConfigurationProperties(prefix = "user")@Datapublic class UserConfig { private String id; private String name; private String address; private String website; private Integer age;}可以通过@EnableConfigurationProperties(value = UserConfig.class)将UserConfig再次逼迫注入,问题涌如今如果UserConfig为第三方jar包内的配置类,则可能涌现属性没有注入情形,以是可以指定注入