【spring boot】SpringBoot初学(2.2)– SpEL表达式读取properties属性到Java对象

前言

  github: https://github.com/vergilyn/SpringBootDemo

  代码位置:(注意测试方法在,test下的SpelValueApplicationTest.class

    image

一、什么是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"}

原文地址:https://www.cnblogs.com/VergiLyn/p/6533821.html