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));
}

結果:

 

Tags: