Spring->EL表达式

来源:互联网 发布:virtuozo软件制作dem 编辑:程序博客网 时间:2024/06/07 16:28

Spring-EL介绍:

Spring3中提供了功能丰富强大的表达式语言,简称SpEL(Spring Expression Language)。SpEL是类似于OGNL和JSF EL的表达式语言,能够在运行时构建复杂表达式,存取对象属性、对象方法调用等。所有的SpEL都支持XML(配置Bean.xml时使用)和Annotation(在注解@Value的参数中使用。)两种方式,格式:#{ SpEL expression }

本人用的SpringBoot进行环境初始化,如果使用的Spring Maven依赖如下

<dependencies>    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-core</artifactId>        <version>3.2.4.RELEASE</version>    </dependency>    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-context</artifactId>        <version>3.2.4.RELEASE</version>    </dependency>  </dependencies>

SPEL基础语法:

一、字面量表达式: SpEL支持的字面量包括:字符串、数字类型(int、long、float、double)、布尔类型、null类型。

二、算数运算表达式: SpEL支持加(+)、减(-)、乘(*)、除(/)、求余(%)、幂(^)运算。(SpEL还提供求余(MOD)和除(DIV)而外两个运算符,与“%”和“/”等价,不区分大小写。 )

三、关系表达式:等于(==)、不等于(!=)、大于(>)、大于等于(>=)、小于(<)、小于等于(<=),区间(between)运算
( SpEL同样提供了等价的“EQ” 、“NE”、 “GT”、“GE”、 “LT” 、“LE”来表示等于、不等于、大于、大于等于、小于、小于等于,不区分大小写。)

四、区间运算(between):between运算符右边操作数必须是列表类型,且只能包含2个元素。第一个元素为开始,第二个元素为结束,区间运算是包含边界值的,即 xxx>=list.get(0) && xxx<=list.get(1)。
五、逻辑表达式:且(and)、或(or)、非(!或NOT)。(注:逻辑运算符不支持 Java中的 && 和 || 。

六、字符串连接及截取表达式,使用“+”进行字符串连接,支持截取字符(暂时只支持截取一个。如果需要截取多个请使用String.substring()方法)
例如:“’Hello ’ + ‘World!’”得到“Hello World!”;而“’Hello World!’[0]”将返回“H”。

七、三目运算及Elivis运算表达式
Elivis运算符“表达式1?:表达式2”从Groovy语言引入用于简化三目运算符的,当表达式1为非null时则返回表达式1,当表达式1为null时则返回表达式2,简化了三目运算符

八、Bean引用:SpEL支持使用“@”符号来引用Bean(在SpringEL解析器中)

注意:要在Annotation中使用SpEL,必须要通过annotation注册组件。如果你在xml中注册了bean和在java class中定义了@Value,@Value在运行时将会出现异常。

代码测试基于SpEL的Annotation(注解)版本。:

@Componentpublic class People {    @Value("1323")    private int id ;    @Value("zjh")    private String name;    @Value("Beijing")    private String addr;    //如果Student的Bean是以.xml的方式配置的而不是通过注解@Component,这里会异常。    @Value("#{student}")    private Student student;    public People() {        super();    }    public People(Integer id, String name, String addr, Student student) {        this.id = id;        this.name = name;        this.addr = addr;        this.student = student;    }    public void setId(Integer id) {        this.id = id;    }    public void setName(String name) {        this.name = name;    }    public void setAddr(String addr) {        this.addr = addr;    }    public Integer getId() {        return id;    }    public String getName() {        return name;    }    public String getAddr() {        return addr;    }    public Student getStudent() {        return student;    }    public void setStudent(Student student) {        this.student = student;    }}
@Componentpublic class Student {    @Value("#{2000-10}")    private int id ;    @Value("student")    private String name;    @Value("#{20-2}")    private int age;    @Value("#{1==1?true:false}")    private boolean sex;    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public boolean getSex() {        return sex;    }    public void setSex(boolean sex) {        this.sex = sex;    }}
@Componentpublic class SpringELTestCollection {    private List<String> list;    private Map<String,String> map;    public SpringELTestCollection() {        map = new HashMap<String, String>();        map.put("key1","value1");        map.put("key2","value2");        list = new ArrayList<String>();        list.add("List0");        list.add("List1");        list.add("List2");    }    public SpringELTestCollection(List<String> list, Map<String, String> map) {        this.list = list;        this.map = map;    }    public List<String> getList() {        return list;    }    public void setList(List<String> list) {        this.list = list;    }    public Map<String, String> getMap() {        return map;    }    public void setMap(Map<String, String> map) {        this.map = map;    }}
@Configurationpublic class ExampleSpringEL {    @Value("#{people}")    private People people;    @Value("#{people.getStudent()}")    private Student student;    @Value("#{people.getName()}")    private String name;    @Value("#{people.getStudent().sex}")    private Boolean sex;    @Value("#{'zjh'.toUpperCase()}")    private String nameUp;    @Value("#{'zjh'.equals('zjhTest')}")    private Boolean result;    @Value("#{10*20-30}")    private Integer mathExpression;    //@Value("#{1==1 and 2==2}")    @Value("#{1==1?true:false}")    private Boolean RelExpression;    @Value("#{people.name.equals('zjh')}")    private Boolean syExpression;    @Value("#{springELTestCollection.list[0]}")    private String testList;    @Value("#{springELTestCollection.map['key1']}")    private String getMap;    public ExampleSpringEL() {    }    public People getPeople() {        return people;    }    public void setPeople(People people) {        this.people = people;    }    public Student getStudent() {        return student;    }    public void setStudent(Student student) {        this.student = student;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Boolean getSex() {        return sex;    }    public void setSex(Boolean sex) {        this.sex = sex;    }    public String getNameUp() {        return nameUp;    }    public void setNameUp(String nameUp) {        this.nameUp = nameUp;    }    public Boolean getResult() {        return result;    }    public void setResult(Boolean result) {        this.result = result;    }    public Integer getMathExpression() {        return mathExpression;    }    public void setMathExpression(Integer mathExpression) {        this.mathExpression = mathExpression;    }    public Boolean getRelExpression() {        return RelExpression;    }    public void setRelExpression(Boolean relExpression) {        RelExpression = relExpression;    }    public Boolean getSyExpression() {        return syExpression;    }    public void setSyExpression(Boolean syExpression) {        this.syExpression = syExpression;    }    public String getGetMap() {        return getMap;    }    public void setGetMap(String getMap) {        this.getMap = getMap;    }    public String getTestList() {        return testList;    }    public void setTestList(String testList) {        this.testList = testList;    }    @Override    public String toString() {        return "ExampleSpringEL{" +                "people=" + people +                ", student=" + student +                ", name='" + name + '\'' +                ", sex=" + sex +                ", nameUp='" + nameUp + '\'' +                ", result=" + result +                ", mathExpression=" + mathExpression +                ", RelExpression=" + RelExpression +                ", syExpression=" + syExpression +                ", testList='" + testList + '\'' +                ", getMap='" + getMap + '\'' +                '}';    }}

测试类:

@RunWith(SpringRunner.class)@SpringBootTestpublic class StudySpringBootApplicationTests {    @Autowired    private ExampleSpringEL  springEL;    @Test    public void contextLoads() {        System.out.println(springEL.toString());    }}

SpringEL在.xml中的使用:

<bean id="firstBean" class="com.xxxxxx">        <property name="xxxx" value="#{'test'..toUpperCase()}" />        <property name="age" value="#{20*5}" /></bean><bean id="secondBean" class="com.xxxxxx">        <property name="firstBean" value="#{firstBean}" />        <property name="age" value="#{firstBean.age}" /></bean>

SpringEL的实现

那么SpringEl是怎么实现的呢?接下来就是见证奇迹的时刻~~~
Spring里有个解析类来解析这些EL表达式,我们的在@Value以及.xml中使用的EL表达式,会在该解析类解析下获取表达式对应的值。EL表达式解析类:ExpressionParser接口下有三个实现类,SpelExpressionParser、InternalSpelExpressionParser、TemplateAwareExpressionParser我们这里以SpelExpressionParser为主,

Spring EL 解析类的相关API

EvaluationContext可以理解为parser 在这个环境里执行parseExpression解析操作,比如说我们现在往ctx(一个EvaluationContext )中放入一个 对象(SpringELTestCollection)。 @springELTestCollection 就可以在该环境下获取对应的Bean。可以EvaluationContext设置成整个Spring容器,这样只要Spring管理的Bean EL表达式就可以通过@BeanId获取(@Value()中的#{BeanId}就是这个原理)

EL解析器代码测试:

@RunWith(SpringRunner.class)@SpringBootTestpublic class StudySpringBootApplicationTests {    @Autowired    private ExampleSpringEL  springEL;    @Autowired    private SpringELTestCollection elTest;    //ApplicationContext    @Autowired    private ApplicationContext  acontext;    @Test    public void contextLoads() {        System.out.println(springEL.toString());    }    //测试SpringEL解析器    @Test    public void testELParse(){        //        StandardEvaluationContext context = new StandardEvaluationContext();        context.setVariable("springELTestCollection",elTest);        ExpressionParser parser = new SpelExpressionParser();        String value = (String) parser.parseExpression("'zjh'.toUpperCase()").getValue();        System.out.println(value);        Boolean bvalue = parser.parseExpression("1==1?true:false").getValue(Boolean.class);        System.out.println(bvalue);        String mapValue = (String) parser.parseExpression("#springELTestCollection.map['key1']").getValue(context);        System.out.println(mapValue);        //集合相关EL表达式 ,但返回的集合是不可修改的。(禁止增删改会抛异常)        List<Integer> result2 = parser.parseExpression("{1,2,3}").getValue(List.class);    }    //模拟SpringEl的解析过程:    //我们在@Value()中的表达式,经过该解析器解析,进而获取结果集    @Test    public void testELParse2(){        ExpressionParser parser = new SpelExpressionParser();        StandardEvaluationContext context = new StandardEvaluationContext();        context.setBeanResolver(new BeanFactoryResolver(acontext));        //Bean引用:SpEL是使用“@”符号来引用Bean的。        //parser.parseExpression("@exampleSpringEL") == @Value("#{exampleSpringEL}")        ExampleSpringEL result1 = parser.parseExpression("@exampleSpringEL").getValue(context, ExampleSpringEL.class);        String result2 = parser.parseExpression("@exampleSpringEL.getName().toUpperCase()").getValue(context, String.class);        System.out.println(result1.toString());        System.out.println(result2);    }}

资料参考:

SpringEL解析器
SpringEl语法

原创粉丝点击