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 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 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属性文件,用${}来引用属性
test.properties,只包含一个属性对
itemName=phone
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,于是有了这篇文章,学无止境...