前言
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"}