博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
7 -- Spring的基本用法 -- 12... Spring 3.0 提供的表达式语言(SpEL)
阅读量:6510 次
发布时间:2019-06-24

本文共 10699 字,大约阅读时间需要 35 分钟。

  7.12 Spring 3.0 提供的表达式语言(SpEL)

    Spring表达式语言(简称SpEL)是一种与JSP 2 的EL功能类似的表达式语言,它可以在运行时查询和操作对象图。支持方法调用和基本字符串模板函数。

    SpEL 可以独立于Spring容器使用------只是当成简单的表达式语言来使用;也可以在Annotation或XML配置中使用SpEL,这样可以充分利用SpEL简化Spring的Bean配置。

      7.12.1 使用Expression接口进行表达式求值。

        Spring的SpEL 可以单独使用,可以使用SpEL对表达式计算、求值。

        SpEL主要提供了如下三个接口:

          ⊙ ExpressionParser : 该接口的实例负责解析一个SpEL表达式,返回一个Expression对象。

          ⊙ Expression : 该接口的实例代表一个表达式。

          ⊙ EvaluationContext : 代表计算表达式值的上下文。当SpEL表达式中含有变量时,程序将需要使用该API来计算表达式的值。

        Expression实例代表一个表达式,它包含了如下方法用于计算,得到表达式的值。

          ⊙ Object getValue() : 计算表达式的值。

          ⊙ <T> T getValue(Class<T> desiredResultType) : 计算表达式的值,而且尝试将该表达式的值当成desiredResultType类型处理。

          ⊙ Object getValue(EvaluationContext context) : 使用指定的EvaluationContext来计算表达式的值。

          ⊙ <T> T getValue(EvaluationContext context,Class<T> desiredResultType) : 使用指定的EvaluationContext来计算表达式的值,而且尝试将该表达式的值当成desiredResultType类型处理。

          ⊙ Object getValue(Object rootObject) : 以rootObject作为表达式的root对象来计算表达式的值。

          ⊙ <T> T getValue(Object rootObject , Class<T> desiredResultType) : 以rootObject 作为表达式的root对象来计算表达式的值,而且尝试将该表达式的值当场desiredResultType类型来处理。

        Class : SpELTest

package edu.pri.lime._7_12_1.main;import java.util.ArrayList;import java.util.Date;import java.util.List;import org.springframework.expression.EvaluationContext;import org.springframework.expression.Expression;import org.springframework.expression.ExpressionParser;import org.springframework.expression.spel.standard.SpelExpressionParser;import org.springframework.expression.spel.support.StandardEvaluationContext;import edu.pri.lime._7_12_1.bean.Person;public class SpELTest {    public static void main(String[] args){//        创建一个ExpressionParser对象,用于接卸表达式        ExpressionParser parser = new SpelExpressionParser();//        最简单的字符串表达式        Expression exp = parser.parseExpression("'HelloWorld'");        System.out.println("'HelloWorld' 的结果 : " + exp.getValue());//        调用方法的表达式        exp = parser.parseExpression("'HelloWorld'.concat('!')");        System.out.println("'HelloWorld'.concat('!') 的结果 : " + exp.getValue());//        调用对象的getter方法        exp = parser.parseExpression("'HelloWorld'.bytes");        System.out.println("'HelloWorld'.bytes 的结果 : " + exp.getValue());//        访问对象的属性(相当于HelloWorld.getBytes().length)        exp = parser.parseExpression("'HelloWorld'.bytes.length");        System.out.println("'HelloWorld'.bytes.length 的结果 : " + exp.getValue());//        使用构造器来创建对象        exp = parser.parseExpression("new String('HelloWorld')" + ".toUpperCase()");        System.out.println("new String('HelloWorld')" + ".toUpperCase() 的结果是 : " + exp.getValue());        Person person = new Person(1,"孙悟空", new Date());        exp = parser.parseExpression("name");        System.out.println("以Person为root,name表达式的值是 : " + exp.getValue(person, String.class));        exp = parser.parseExpression("name == '孙悟空'");        StandardEvaluationContext ctx = new StandardEvaluationContext();//        将person设为Context的root对象        ctx.setRootObject(person);//        以指定Context来计算表达式的值        System.out.println(exp.getValue(ctx,Boolean.class));        List
list = new ArrayList
(); list.add(true); EvaluationContext ctx_ = new StandardEvaluationContext();// 将list设置成EvaluationContext的一个变量 ctx_.setVariable("list", list);// 修改list变量的第一个元素的值 parser.parseExpression("#list[0]").setValue(ctx_, "false");// list集合的第一个元素被改变 System.out.println("list集合的第一个元素为 : " + parser.parseExpression("#list[0]").getValue(ctx_)); }}

        EvaluationContext代表SpEL计算表达式值的“上下文”,这个Context对象可以包含多个对象,但只能有一个root(根)对象。当表达式中包含变量是,SpEL机会根据EvaluationContext中的变量的值对表达式进行计算。

        为了往EvaluationContext里放入对象(SpEL称之为变量),可以调用该对象的如下方法:

          ⊙ setVariable(String name,Object value) : 向EvaluationContext中放入value对象,该对象名为name。为了在SpEL访问EvaluationContext中指定对象,应采用与OGNL类是的格式:#name

        StandardEvaluationContext提供了如下方法来设置root对象。

          ⊙ setRootObject(Object rootObject)

        在SpEL中访问root对象的属性时,可以省略root对象的前缀:foo.bar 访问rootObject的foo属性的bar属性。、

        使用Expression对象计算表达式的值时,可以直接指定root对象:exp.getValue(person,String.class) 以person对象为root对象计算表达式的值。

      7.12.2 Bean定义中的表达式语言支持

        Spring允许在Bean定义中使用SpEL。在XML配置文件和Annotation中都可以使用SpEL。在XML配置文件和Annotation中使用SpEL时,在表达式外面增加#{}包围即可。

        Class : Author

package edu.pri.lime._7_12_2.bean.impl;import java.util.List;import edu.pri.lime._7_12_2.bean.Axe;import edu.pri.lime._7_12_2.bean.Person;public class Author implements Person {    private Integer id;    private String name;    private List
books; private Axe axe; public void useAxe(){ System.out.println("我是" + name + ",正在砍柴\n" + axe.chop()); System.out.println("稍后我会看两本名字:" + books + "的书"); } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List
getBooks() { return books; } public void setBooks(List
books) { this.books = books; } public Axe getAxe() { return axe; } public void setAxe(Axe axe) { this.axe = axe; } }

        XML :

        Class : SpringTest

package edu.pri.lime._7_12_2.main;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import edu.pri.lime._7_12_2.bean.Person;import edu.pri.lime._7_12_2.bean.impl.Author;public class SpringTest {    public static void main(String[] args){        ApplicationContext ctx = new ClassPathXmlApplicationContext("app_7_12_2.xml");        Person author = ctx.getBean("author",Author.class);        author.useAxe();    }}

        Console :

我是0.04521700994046529,正在砍柴用钢斧砍材真快稍后我会看两本名字:[你好, 哈哈]的书

      7.12.3 SpEL语法详述

        1.直接量表达式

          直接量表达式是SpEL中最简单的表达式,直接量表达式就是在表达式中使用Java语言支持的直接量,包括字符串、日期、数值、boolean值和null。

          

//        使用直接量表达式        ExpressionParser parser = new SpelExpressionParser();        Expression exp = null;        exp = parser.parseExpression("'Hello World!'");        System.out.println(exp.getValue());        exp = parser.parseExpression("new java.util.Date()");        System.out.println(exp.getValue());        exp = parser.parseExpression("1");        System.out.println(exp.getValue());        exp = parser.parseExpression("true");        System.out.println(exp.getValue());        exp = parser.parseExpression("null");        System.out.println(exp.getValue());

        2.在表达式中创建数组

          SpEL表达式直接支持使用静态初始化、动态初始化两种语法来创建数组。

//            创建一个数组            exp = parser.parseExpression("new String[]{'java','Struts','Spring'}");            System.out.println(exp.getValue());//            创建二维数组            exp = parser.parseExpression("new int[2][4]");            System.out.println(exp.getValue());

        3.在表达式中创建List集合

          SpEL直接使用如下语法来创建List集合:{ele1,ele2,ele3...}

//            创建一个集合            exp = parser.parseExpression("{'java','Struts','Spring'}");            System.out.println(exp.getValue());//            创建二维集合            exp = parser.parseExpression("{
{'lime','oracle'},{'java','Spring'}}"); System.out.println(exp.getValue());

        4.在表达式中访问List、Map等集合元素

          在SpEL中访问List集合的元素:#list[index]

          在SpEL中访问Map集合的元素:#map[key]

List
list = new ArrayList
(); list.add("Java"); list.add("Struts"); list.add("Spring"); Map
map = new HashMap
(); map.put("Java", 80.0); map.put("Spring", 89.0);// 创建一个EvaluationContext对象,作为SpEL解析变量的上下文 EvaluationContext ctx = new StandardEvaluationContext();// 设置两个变量 ctx.setVariable("myList", list); ctx.setVariable("myMap",map);// 访问List集合的第二个元素 System.out.println(parser.parseExpression("#myList[1]").getValue(ctx));// 访问Map集合的指定元素 System.out.println(parser.parseExpression("#myMap['Java']").getValue(ctx));

        5.调用方法

//            调用String对象的substring()方法            System.out.println(parser.parseExpression("'Hello World'.substring(2,5)").getValue());            List
list = new ArrayList
(); list.add("java"); list.add("springMVC"); list.add("spring"); list.add("myBatis");// 创建一个EvaluationContext对象,作为SpEL解析变量的上下文 EvaluationContext ctx = new StandardEvaluationContext();// 设置一个变量 ctx.setVariable("myList", list);// 调用指定变量所代表对象的subList()方法 System.out.println(parser.parseExpression("#myList.subList(1,3)").getValue(ctx));

        6.算术、比较、逻辑、赋值、三目等运算符

          在SpEL中使用赋值运算符可以直接改变表达式所引用的实际对象。

List
list = new ArrayList
(); list.add("Java"); list.add("SpringMVC"); list.add("Spring"); list.add("MyBatis"); EvaluationContext ctx = new StandardEvaluationContext(); ctx.setVariable("myList", list);// 对集合的第一个元素进行赋值 parser.parseExpression("#myList[0]='JavaLime'").getValue(ctx); System.out.println(list.get(0));// 使用三目运算符 System.out.println(parser.parseExpression("#myList.size() > 3 ? " + "'myList长度大于3' : 'myList长度不大于3'").getValue(ctx));

        7.类型运算符

          T():这个运算符用于告诉SpEL将该运算符内的字符串当成“类”处理,避免Spring对其进行其他解析。尤其是调用某个类的静态方法时。

//            调用Math的静态方法            System.out.println(parser.parseExpression("T(java.lang.Math).random()").getValue());//            调用System的静态方法            System.out.println(parser.parseExpression("T(System).getProperty('os.name')").getValue());

          在表达式中使用某个类时,推荐使用该类的全限定类名。但如果只写类名,不写包名,SpEL也可以尝试处理,SpEL使用StandardTypeLocator去定位这些类,它默认会在java.lang包下找这些类。

        8.调用构造器

          SpEL允许在表达式中直接使用new来调用构造器,这种调用可以创建一个Java对象。

//            创建对象            System.out.println(parser.parseExpression("new String('HelloWorld').substring(2,4)").getValue());            System.out.println(parser.parseExpression("new javax.swing.JFrame('测试')" + ".setVisible('true')").getValue());

        9.变量

          SpEL允许通过EvaluationContext来使用变量,该对象包含了一个setVariable(String name,Object value)方法,该方法用于设置一个变量。在SpEL中通过#name来访问该变量。

          SpEL中有如下两个特殊的变量:

            ⊙ #this : 引用SpEL当前正在计算的对象。

            ⊙ #root :引用SpEL的EvaluationContext的root对象。

        10.自定义函数

啦啦啦

啦啦啦

啦啦啦

啦啦啦

转载地址:http://yfbfo.baihongyu.com/

你可能感兴趣的文章
如何在C#项目中使用NHibernate
查看>>
使用vigil 监控微服务系统包含可视化界面
查看>>
安装python包到指定虚拟环境
查看>>
力扣(LeetCode)21
查看>>
网页视频流m3u8/ts视频下载
查看>>
聊聊flink的TableFactory
查看>>
Python 基础起步 (十) 什么叫函数?
查看>>
每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
查看>>
8年软件测试工程师感悟——写给还在迷茫中的朋友
查看>>
5G一周热闻:华为夺联通5G大单,首张5G电话卡发放
查看>>
“迁移策略+新容器运行时”应对有状态应用的冷热迁移挑战
查看>>
使用Swoole加速Laravel(正式环境中)
查看>>
mockjs让前端开发独立于后端
查看>>
延迟脚本的方式
查看>>
vue中实现单选
查看>>
1.4linux单用户模式下修改root密码和救援模式修改root密码
查看>>
微服务架构优缺点
查看>>
解读userenv的日志
查看>>
跨进程通信之Messenger
查看>>
ext3与ext4区别
查看>>