前言
github: https://github.com/vergilyn/SpringBootDemo
代码位置:(注意测试方法在,test下的SpelValueApplicationTest.class)
一、什么是SpEL
SpEL:spring表达式语言,Spring Expression Language。从spring3开始引入。
可以通过xml或注解的施行映射properties中的属性到JavaBean,并通过Spring注入。
二、Spring boot中常见的应用
@Value("${base.name}") private String baseName; @Value("#{'string'}") // 或 @Value('#{"string"}') public String spelString;
(个人理解) 以$开头的只是普通模式,而以#开头的才是SpEL。
针对这两种,它们默认值的写法也是不一样的。
${ property : default_value } #{ obj.property ?: default_value }
三、以$取值
## value-base.properties
base.name=vergil base.song=Safe&Sound base.nest.song=base.song
package com.vergilyn.demo.spring.value.property; import java.util.Calendar; import java.util.Date; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; @PropertySource("classpath:config/value/value-base.properties") @Component("base") public class BaseProperty { @Value("${base.name}") private String baseName; @Value("${base.song}") private String baseSong; /* 嵌套(内往外) * 解析:先取内部${base.nest.song}=base.song -> ${base.song} = Safe&Sound */ @Value(value = "${${base.nest.song}}") private String nestSong; @Override public String toString() { return this.getClass().getSimpleName() +":{baseName: "+this.baseName+", baseSong: "+this.baseSong+"}"; } public String getBaseName() { return baseName; } public void setBaseName(String baseName) { this.baseName = baseName; } public String getBaseSong() { return baseSong; } public void setBaseSong(String baseSong) { this.baseSong = baseSong; } public String getNestSong() { return nestSong; } public void setNestSong(String nestSong) { this.nestSong = nestSong; } public Date nowDate(){ return Calendar.getInstance().getTime(); } }
结果:
BaseProperty: {"baseName":"vergil","baseSong":"Safe&Sound","nestSong":"Safe&Sound"}
四、以#取值 一般形式
## value-spel.properties
spel.name=dante spel.mix=baseSong
package com.vergilyn.demo.spring.value.property; import java.util.Date; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; @PropertySource("classpath:config/value/value-spel.properties") @Component public class SpelProperty { @Value("${spel.name}") //注意这里是 $ private String spelName; /* base:指BaseProperty.class(默认为baseProperty),因为定义了@Component("base") * baseSong:并不是*.properties中的key,而是此key对应的class变量 */ @Value("#{base.baseSong}") private String spelSong; /* // @Value("${ '#{base.baseSong}' }") //这个不支持。因为#开头的才是spel。 * 解析:由内往外,${spel.mix} = baseSong。然后在spel表达式中,('')表示定义字符串。 * 所以 #{'baseSong'} = baseSong */ @Value("#{ '${spel.mix}' }") private String mixSong; @Value("#{base. ${spel.mix} }") //组合,特别.后面跟的是对象属性。所以要是class中的属性,而不是properties中的key private String mixSong2; public String getMixSong2() { return mixSong2; } public void setMixSong2(String mixSong2) { this.mixSong2 = mixSong2; } public String getSpelName() { return spelName; } public void setSpelName(String spelName) { this.spelName = spelName; } public String getSpelSong() { return spelSong; } public void setSpelSong(String spelSong) { this.spelSong = spelSong; } public String getMixSong() { return mixSong; } public void setMixSong(String mixSong) { this.mixSong = mixSong; } }
结果:
SpelProperty: {"mixSong":"baseSong","mixSong2":"Safe&Sound","spelName":"dante","spelSong":"Safe&Sound"}
四、以#取值 各种复杂形式
package com.vergilyn.demo.spring.value.property; import java.util.Date; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class SpelBasisProperty { @Value("#{124}") public int spelInt; @Value("#{124.24}") public float spelFloat; @Value("#{1e4}") public double spelSpec; @Value("#{true}") public boolean spelBoolean = false; @Value("#{'string'}") // 或 @Value('#{"string"}') public String spelString; /* 调用方法。 * 在SpEL中避免抛出空指针异常(NullPointException)的方法是使用null-safe存取器: * ?. 运算符代替点(.) #{object?.method()},如果object=null,则不会调用method() */ @Value("#{base.getNestSong()}") public String spelNestSong; @Value("#{base.nowDate()}") //返回值可以是任何类型 public Date spelNowDate; @Value("#{null?.toString()}") //当?.左边为null时,不再执行右边的方法。(避免NPE) public String spelNull; /** * 在SpEL中,使用T()运算符会调用类作用域的方法和常量。 */ @Value("#{T(java.lang.Math).PI}") public double T_PI; @Value("#{T(java.lang.Math).random()}") public double T_andom; /** * SpEL运算>>>> * 四则运算:+ - * / * 比较:eq(==),lt(<),le(<=),gt(>),ge(>=)。 * 逻辑表达式:and,or,not或!。 * 三元表达式: * i. #{base.name == 'vergilyn' ? true : false} * ii. #{base.name == 'vergilyn' ? base.name : 'dante'} * spel可以简化为:#{base.name ?: 'dante'} 当base.name !=null则取base.name,否则取'dante'。 * (?:)通常被称为elvis运算符。 * 正则:#{base.song matches '[a-zA-Z0-9._%+_]+@[a-zA-Z0-9.-]+\.com'} 。 (不光有matches,还有很多别的,可详细baidu/google) */ @Value("#{100 / 20}") //四则运算: + - * / public int spelArithmetic; }
结果:
SpelBasisProperty: {"T_PI":3.141592653589793,"T_andom":0.49286684542729553,"spelArithmetic":5,"spelBoolean":true,"spelFloat":124.24,"spelInt":124,"spelNestSong":"Safe&Sound","spelNowDate":1489169611736,"spelSpec":10000.0,"spelString":"string"}