spring之SpEL表示式
1.什麼是SpEL表示式
SpEL表示式語言是一種表示式語言,是一種可以與一個基於spring的應用程式中的執行時物件互動的東西。有點類似於ognl表示式。總得來說SpEL表示式是一種簡化開發的表示式,通過使用表示式來簡化開發,減少一些邏輯、配置的編寫。
2.SpEL表示式語言入門程式
(1)xml配置的方式:
配置環境:pom.xml
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.0.5.RELEASE</version> </dependency> </dependencies>
applicationContext.xml檔案:
<bean id="MyMessage" class="cn.spy.spel.injection.MyMessage">
<property name="message" value="#{systemProperties['user.language']}"></property>
</bean>
MyMessage.java檔案:
public class MyMessage { private String message; public String getMessage() {return message; } public void setMessage(String message) { this.message = message; } }
測試程式:
public class Test { public static void main(String[] args) { ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml"); MyMessage myMessage=context.getBean(MyMessage.class); System.out.println(myMessage.getMessage()); } }
結果:
解釋:這裡使用了表示式#{systemProperties['user.language']}來設定值,用來檢索使用者語言系統的屬性。
(2)採用註解的方式
applicationContext.xml檔案:
<context:component-scan base-package="cn.spy.spel"></context:component-scan>
MyMessage2.java檔案:
@Component public class MyMessage2 { @Value("#{systemProperties['user.language']}") private String message; public String getMessage() { return message; } }
解釋:這裡使用了@Value註解的方式,當例項化MyMessage2這個bean的時候,將使用該註解設定預設值。此處還是使用了之前的SpEL表示式,來設定使用者語言系統的屬性。(在這裡@Value註解既可以在類的欄位屬性上面,也可以在建構函式和方法上面使用)。
測試:
public static void main(String[] args) { ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml"); MyMessage2 myMessage =context.getBean(MyMessage2.class); System.out.println(myMessage.getMessage()); }
結果:
3.分析器(瞭解)
SpEL上下文中所定義的每一個表示式都應該首先被解析,然後在被評估。解析的過程採用了ExpressionParser介面的分析器進行處理的。SpelExpressionParser主要負責將字串表示式解析到已編譯的Expression物件中。(建立的分析器例項是執行緒安全)
程式碼形式:
ExpressionParser parser =new SpelExpressionParser();
注意:
在SpEL表示式中,預設情況下,表示式字首為 ' # ' ,而後綴為 ' } ' 。如果表示式中沒有字首和字尾,那麼表示式字串就被當作純文字。
分析器解析Spel中純文字表示式HelloWorld:
public class HelloWorldTest { ExpressionParser parser; @Before public void setup(){ //初始化建立SpEL表示式解析器 parser =new SpelExpressionParser(); } @Test public void test(){ //使用解析器解析出表示式exp Expression exp=parser.parseExpression("'Hello World'"); //在表示式中獲取指定型別的值 String value =exp.getValue(String.class); assertThat(value ,is("Hello World")); } }
junit測試結果:
4.使用SpEL表示式呼叫方法
(1)使用SpEL呼叫普通方法
就是SpEL也支援在表示式中採用方法呼叫的形式
範例:
User.java:
public class User { private String username; private String password; public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public String getUsername() { return "李四"; } public String getPassword() { return "lisi123"; } public void printUser(){ System.out.println("當前使用者的使用者名稱:"+username+" ,密碼:"+password); } }
applicationContext.xml配置檔案:
<bean id="user1" class="cn.spy.spel.method.User"> <property name="username" value="張三"></property> <property name="password" value="zhangsan123"></property> </bean> <bean id="user2" class="cn.spy.spel.method.User"> <property name="username" value="#{user2.getUsername()}"></property> <property name="password" value="#{user2.getPassword()}"></property> </bean>
測試:
public class TestMethod { public static void main(String[] args) { ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml"); User user1 =(User) context.getBean("user1"); user1.printUser(); User user2 =(User) context.getBean("user2"); user2.printUser(); } }
結果:
(2)使用SpEL呼叫構造方法
@Test public void test(){ ExpressionParser parser =new SpelExpressionParser(); Expression exp=parser.parseExpression("new Double(3.1415926)"); Double value =exp.getValue(Double.class); assertThat(value ,is(3.1415926)); }
結果:
(3)使用SpEL呼叫靜態方法
@Test public void test(){ ExpressionParser parser =new SpelExpressionParser(); Expression exp=parser.parseExpression("T(java.lang.Math).abs(-1)"); Integer value =exp.getValue(Integer.class); assertThat(value ,is(1)); }
結果:
6.使用SpEL表示式呼叫變數和函式
(1)#變數的表示式使用
SpEL使用上下文StandardEvaluationContext查詢表示式中存在的變數。在表示式中使用變數名稱前新增一個標籤字首#,使用已註冊的變數。
public class TestSpEL { @Test public void test(){ ExpressionParser parser =new SpelExpressionParser(); StandardEvaluationContext context =new StandardEvaluationContext(); context.setVariable("message", "Hello World"); String value =parser.parseExpression("#message").getValue(context, String.class); assertThat(value, is("Hello World")); } }
結果:
(2)#root表示式的使用
可以在上下文中設定一個物件評估,可以使用#root訪問該物件。
public class TestSpEL { @Test public void test(){ ExpressionParser parser =new SpelExpressionParser(); StandardEvaluationContext context =new StandardEvaluationContext(); context.setRootObject(new Var()); Assert.assertTrue(parser.parseExpression("#root").getValue(context) instanceof Var); } }
結果:
(3)訪問系統的屬性和環境
SpEL預定義變數:systemProperties和systemEnvironment
parser.parseExpression("@systemProperties['java.version']").getValue(context);
parser.parseExpression("@systemProperties[JAVA_HOME]").getValue(context);
7.使用SpEL表示式中的運算子
SpEL提供了多種運算子。
注意:如果解析表示式時,在完全限定的類名中包含一個運算子的文字表示形式,則會產生異常。
正則表示式運算子matches
@Test public void test(){ ExpressionParser parser =new SpelExpressionParser(); assertThat(parser.parseExpression("35 matches '[0-9]+'").getValue(Boolean.class), is(true)); }
結果:
邏輯運算子between
@Test public void test(){ ExpressionParser parser =new SpelExpressionParser(); assertThat(parser.parseExpression("3 between {2,5}").getValue(Boolean.class), is(true)); }
結果: