spring表达语言(SpEL)快速掌握

来源:互联网 发布:mac用户文件夹在哪里 编辑:程序博客网 时间:2024/05/22 05:02
在Spring3中就已经支持EL表达式了, spring Expression Language(SpEL)是类似于OGNL和EL的表达式语言, 能够在运行时构建复杂表达式, 存取对象属性、调用对象方法等, 它支持XML和Annotation两种方式, 格式:#{SpEL expression}。我使用的spring4.2.2的版本,SpEL位于spring-expression的jar包中。

下面是一个测试类,包含了基本的例子
package testSpEL;import org.junit.Test;import org.springframework.expression.EvaluationContext;import org.springframework.expression.Expression;import org.springframework.expression.ExpressionParser;import org.springframework.expression.common.TemplateParserContext;import org.springframework.expression.spel.standard.SpelExpressionParser;import org.springframework.expression.spel.support.StandardEvaluationContext;import java.util.*;/** * writer: holien * Time: 2017-08-17 10:27 * Intent: spring el 测试 */public class SpELTest {    @Test    public void testEL() {        // 模拟一个情境        EvaluationContext context = new StandardEvaluationContext();        // 往情境存放变量        context.setVariable("name", "pens");        // 构造解析器        ExpressionParser parser = new SpelExpressionParser();        // 解析表达式        Expression expression = parser.parseExpression("#name");        // 从情境中获取值并打印,注意:取情境中的属性记得加上context        System.out.println(expression.getValue(context));  // pens        // 直接解析各种变量,可以指定类型,比如getValue(String.class)        System.out.println(parser.parseExpression("10").getValue());  // 10        System.out.println(parser.parseExpression("10.1f").getValue());  // 10.1        System.out.println(parser.parseExpression("0xFFFF").getValue());  // 65535        System.out.println(parser.parseExpression("true").getValue());  // true        System.out.println(parser.parseExpression("null").getValue());  // null        // 调用list        ArrayList<String> list = new ArrayList<>();        list.add("a");        list.add("b");        list.add("c");        context.setVariable("list", list);        System.out.println(parser.parseExpression("#list[0]").getValue(context));  // a        // 调用map        HashMap<Integer, String> map = new HashMap<>();        map.put(1, "x");        map.put(2, "y");        map.put(3, "z");        context.setVariable("map", map);        System.out.println(parser.parseExpression("#map[1]").getValue(context));  // x        // 使用T{}引用类,然后调用静态方法        System.out.println(parser.parseExpression("T(Math).abs(-10)").getValue());  // 10        // Attempted to call method toUpperCase() on null context object        // 防止出现上面的空指针异常,在变量名后面加?,返回null        System.out.println(parser.parseExpression("#age?.toUpperCase()").getValue(context, String.class));  // null        // 使用一个模板情景参数进行字符串拼接,用#{}把变量#name包含起来        System.out.println(parser.parseExpression("我的名字叫#{#name}", new TemplateParserContext()).getValue(context)); // 我的名字叫pens        /**         * ?[condition] 选择符合条件的所有元素         * ^[condition] 选择符合条件的第一个元素         * &[condition] 选择符合条件的最后一个元素         * ![condition] 遍历符合条件的元素         * #this 当前对象或属性         */        // #this代表数组{1, 2, 3, 4, 5}        System.out.println(parser.parseExpression("{1, 2, 3, 4, 5}.?[#this > 3]").getValue());  // [4, 5]        /**         * 关系操作符, 包括: eq(==), ne(!=), lt()<, le(<=), gt(>), ge(>=)         * 逻辑运算符, 包括: and(&&), or(||), not(!)         * 数学操作符, 包括: 加(+), 减(-), 乘(*), 除(/), 取模(%), 幂指数(^)         * 其他操作符, 如: 三元操作符, instanceof, 赋值(=), 正则匹配(matches)         */        System.out.println(parser.parseExpression("5 > 3").getValue());  // true        System.out.println(parser.parseExpression("1 < 10 ? '对' : '错'").getValue());  // 对        System.out.println(parser.parseExpression("#name instanceof T(String)").getValue(context));  // true        System.out.println(parser.parseExpression("#name = 'newName'").getValue(context));  // newName        System.out.println(parser.parseExpression("'4.13' matches '^\\d\\.\\d{2}$'").getValue());  // true    }}

下面是实际开发中使用到的情况,先看看配置文件applicationContext.xml文件,里面顺带加载了test.properties属性文件,用${}来引用属性

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:context="http://www.springframework.org/schema/context"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">    <!-- 扫描包中的组件类,注解需要 -->    <context:component-scan base-package="testSpEL" />    <!-- 加载属性文件 -->    <context:property-placeholder location="classpath:test.properties"/>    <!-- spring的属性加载器,加载properties文件中的属性 -->    <!--<bean id="propertyConfigurer"-->          <!--class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">-->        <!--<property name="location">-->            <!--<value>test.properties</value>-->        <!--</property>-->        <!--<property name="fileEncoding" value="utf-8" />-->    <!--</bean>-->    <bean id="itemBean" class="testSpEL.Item">        <property name="itemId" value="#{111}"/>        <property name="price" value="#{5300.0}"/>        <!-- 注意字符串加单引号 -->        <property name="description" value="#{'流畅IOS手机'}"/>        <!-- 注入属性文件test.properties中的itemName -->        <property name="itemName" value="${itemName}"/>    </bean>    <bean id="orderBean" class="testSpEL.Order">        <!-- 注入上面配置的itemBean,与ref="itemBean"一样的效果 -->        <property name="item" value="#{itemBean}"/>    </bean></beans>

test.properties,只包含一个属性对

itemName=phone

xml方式使用SpEL,两个bean已经配置在applicationContext.xml中了,下面是测试方法
package testSpEL;import org.junit.Test;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * writer: holien * Time: 2017-08-18 21:13 * Intent: 测试配置文件中配置的bean */public class XmlBeanTest {    @Test    public void testXmlBean() {        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");        // 测试itemBean        Item item = (Item) context.getBean("itemBean");        System.out.println("商品项的id:" + item.getItemId() + " 价格:" + item.getPrice()                + " 名称:" + item.getItemName() + " 描述:" + item.getDescription());        // 测试orderBean        Order order = (Order) context.getBean("orderBean");        System.out.println(order.getItem().getItemName());    }}

annotation方式使用SpEL

package testSpEL;import org.junit.Test;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.stereotype.Component;/** * writer: holien * Time: 2017-08-17 10:51 * Intent: 通过注解和SpEL的方式注入属性值的商品项类 */@Component("item")public class Item {    @Value("001")    private int itemId;    @Value("5200.0")    private double price;    // 注入字符串,注意注解不用加单引号    @Value("物美价廉")    private String description;    // 注入.properties文件中的属性    @Value("${itemName}")    private String itemName;    @Test    public void testAnnotationBean() {        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");        Item item = (Item) context.getBean("item");        System.out.println("商品项的id:" + item.getItemId() + " 价格:" + item.getPrice()                + " 名称:" + item.getItemName() + " 描述:" + item.getDescription());    }    public int getItemId() {        return itemId;    }    public void setItemId(int id) {        this.itemId = id;    }    public double getPrice() {        return price;    }    public void setPrice(double price) {        this.price = price;    }    public String getItemName() {        return itemName;    }    public void setItemName(String itemName) {        this.itemName = itemName;    }    public String getDescription() {        return description;    }    public void setDescription(String description) {        this.description = description;    }}
运行结果:商品项的id:1 价格:5200.0 名称:phone 描述:物美价廉

package testSpEL;import org.junit.Test;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.stereotype.Component;/** * writer: holien * Time: 2017-08-17 10:51 * Intent: 通过注解和SpEL的方式注入属性值的订单类 */@Component("order")public class Order {    // 注入item    @Value("#{item}")    private Item item;    @Test    public void testAnnotationBean() {        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");        Order order = (Order) context.getBean("order");        System.out.println(order.getItem().getItemName());    }    public Item getItem() {        return item;    }    public void setItem(Item item) {        this.item = item;    }}
运行结果:phone,证明已经把item当作属性注入到order中。


学shiro时发现shiro中用ehcache做缓存,于是学起了ehcache,学ehcache时发现其与spring整合时,注解中使用了SpEL,于是有了这篇文章,学无止境...


原创粉丝点击