spring的EL表达式

spring的EL表达式

        起初觉得这一章并没有什么好讲的,因为我在工作中也只是运用了其中很基础的一些功能,直到今天去深入学习这一块才发现,其实spring的EL(expressing language)表达式是多么强大.

        Spring的EL表达式简称为SpEL,让他OGNL表达式等表达式相似,他与spring直接是互相独立的,比如负责解析字符串的接口(ExpressionParse).可以先看下官方的例子:

ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'");
String message = (String) exp.getValue();

  官方宣称SpEL表达式支持以下几个功能:

        1.    文字表达
        2.    算术运算符
        3.    正则表达式
        4.    类
        5.    访问属性,数组,集合和Map
        6.    方法调用
        7.    关系运算符
        8.    任务
        9.    调用构造方法
        10.   关联bean对象
        11.   构造数组
        12.    内联集合
        13.    内联Map
        14.    三元云算符
        15.    变量
        16.    用户定义方法
        17.     集合投影
        18.    集合选择

        19.    模板表达式

      当然,这不是我们需要重点关注的方式.下面来看下如何在注解中使用SpEl表达式.

        1.    简单字符串注入

@Value("spring boot")
private String spring;

这种方法简单粗暴,但是感觉没有什么使用的实际意义.(个人见解,勿喷)

        2.    从系统属性中获取并注入

@Value("#{systemProperties['os.name']}")
private String osName;

输出是PC的操作系统,例如Windows 10,他能获取系统的属性值

        3.    调用类的方法

@Value("#{T(java.lang.Math).random() * 100}")
private double randomNumber;

输出的是随机的一个0~100的double值,T()中填写的是调用的java中类.他可以直接使用算术运算符计算值

        4.    获取类的属性

首先写一个简单的Person类

package com.yczuoxin.demo.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Person {

    @Value("zhangsan")
    private String pName;

    public String getpName() {
        return pName;
    }

    public void setpName(String pName) {
        this.pName = pName;
    }
}

然后去获取其pName:

@Value("#{person.pName}")
private String pName;

输出的结果就是我们注入进去的"zhangsan",所以SpEL可以直接获取类中的属性.

注意:这里Person类的pName属性是私有的,所以必须提供get方法.不然会报错.但是如果pName是共有方法,则不需要提供get方法也可以获取值.

        5.    链式调用方法

还是以Person类来测试

@Value("#{person.getpName().toUpperCase()}")
private String pName;

此时我们输出的结果是"ZHANGSAN",可见成功的调用了String的toUpperCase方法.此时,思维严谨的朋友肯定会问了,如果获取出来的值是null的话,不就空指针了?说的没错,如果是null会抛出org.springframework.beans.factory.UnsatisfiedDependencyException的异常,那么要怎么避免呢?只需要如下地方加一个"?"号就可以解决了.

@Value("#{person.getpName()?.toUpperCase()}")
private String pName;

?号的作用就是在调用方法之前,先判断结果是不是null值,如果是则直接返回null,如果不是,才会继续调用后面的方法.

        6.    算术运算

@Value("#{(1+2)>3}")
public boolean count;

输出结果是false,说明SpEL支持算术运算.

        7.    三元运算符

@Value("#{(1+2)>3 ? 'yes' : 'no'}")
public String count;

输出结果为no,说明SpEL支持三元运算

        8.    elvis 运算符(如果有值则输出值,为null则输出默认值),依然用Person类,删掉注解@Value

@Value("#{person.getpName()?:'zhangsan'}")
private String pName;

输出结果为zhangsan,说明SpEL支持elvis 运算符.

        9.    集合类型的运用

       先改写Person类,在其中加入了age属性,重新toString方法,无参构造和有参构造.

package com.yczuoxin.demo.config;

import org.springframework.stereotype.Component;

@Component
public class Person {

    public Person() {
    }

    public Person(String pName, int age) {
        this.pName = pName;
        this.age = age;
    }

    private String pName;
    private int age;

    public void setpName(String pName) {
        this.pName = pName;
    }

    public String getpName() {
        return pName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

然后加入测试bean

package com.yczuoxin.demo.config;

import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class TestBean {

    public List list = Arrays.asList(new Person("zhangsan",19),new Person("lisi",19), new Person("wangwu",20));
    public Map map;

    public TestBean(){

        map = new HashMap<>();
        map.put("key1","value1");
        map.put("key2","value2");
        map.put("key3","value3");
    }
}

                   a.    查询集合下标为2的元素

@Value("#{testBean.list[2]}")
private Person person;
Person{pName='wangwu', age=20}

                     可见SpEL取出了list中下标为2的对象.

@Value("#{testBean.map[key1]}")
private String value;
value1
                        在Map中,取出的Map对应key的值.

                b.    查询集合中值对应的对象

@Value("#{testBean.list.?[age==19]}")
private List person;
[Person{pName='zhangsan', age=19}, Person{pName='lisi', age=19}]

                    SpEL取出了age为19的对象.注意要拿list去接收,不然会报错.其中.?[]是查询所有,而.^[]是查询第一个,满足条件的,.$[]

                查询最后一个满足条件的.

                c.    集合投影

@Value("#{testBean.list.![pName]}")
private List pNames;
[zhangsan, lisi, wangwu]

                     SpEL使用.![]进行集合投影,将Person集合中的pName属性都拿了出来,并且塞到了一个新的集合之中,

 

       忘记了最常用的获取配置文件的内容的方法了,在此补上

配置文件

book.name = spring boot
@Value("${book.name}")
private String normal;
spring boot

什么,你的结果不对?,因为你需要在配置类上加上一个注解如下,这个很简单也很常用,就不仔细说了.

package com.yczuoxin.demo.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

@Configuration
@PropertySource("classpath:test.properties")
public class Beans {

    @Value("${book.name}")
    public String name;

    public void print(){
        System.out.println(name);
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){
        return new PropertySourcesPlaceholderConfigurer();
    }
}

       先记录到这里,是不是感觉SpEL功能特别强大,只是我们工作中没有想到去使用他.所以在这里,我做成一个笔记,到时候说不定项目中可以用到,看起来还会比较高大上.


你可能感兴趣的:(spring)