• 7 -- Spring的基本用法 -- 12... Spring 3.0 提供的表达式语言(SpEL)


      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<Boolean> list = new ArrayList<Boolean>();
            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<String> books;
        private Axe axe;
        public void useAxe(){
            System.out.println("我是" + name + ",正在砍柴
    " + 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<String> getBooks() {
            return books;
        }
        public void setBooks(List<String> books) {
            this.books = books;
        }
        public Axe getAxe() {
            return axe;
        }
        public void setAxe(Axe axe) {
            this.axe = axe;
        }
        
    }

            XML :

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
        xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    
        <!-- 使用util:properties加载指定的资源文件 -->
        <util:properties id="confTest" location="classpath:test_zh_CN.properties" />
    <!-- 
        配置setName()的参数时,在表达式中调研那个方法,
        配置setAxe()的参数时,在表达式中创建对象
        配置调用setBooks()的参数时,在表达式中访问其他Bean的属性 -->
        <bean id="author" class="edu.pri.lime._7_12_2.bean.impl.Author" 
            p:name="#{T(java.lang.Math).random()}"
            p:axe="#{new edu.pri.lime._7_12_2.bean.impl.SteelAxe()}"
            p:books="#{{confTest.a,confTest.b}}" />
    </beans>

            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<String> list = new ArrayList<String>();
                list.add("Java");
                list.add("Struts");
                list.add("Spring");
                Map<String,Double> map = new HashMap<String, Double>();
                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<String> list = new ArrayList<String>();
                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<String> list = new ArrayList<String>();
                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.自定义函数

    啦啦啦

    啦啦啦

    啦啦啦

    啦啦啦

  • 相关阅读:
    在Java当中如何优雅地处理临时文件
    lombok插件不建议使用的原因
    linux系统下修改tomcat的端口号时,需要修改的地方
    linux系统下报错为:直接在tomcat的bin目录下生成一个错误文件。
    Linux下修改tomcat端口号
    python实现断点续传下载文件
    Python中下划线---完全解读
    linux  指令 备注
    Linux下高并发socket最大连接数所受的各种限制
    python和pywin32实现窗口查找、遍历和点击
  • 原文地址:https://www.cnblogs.com/ClassNotFoundException/p/6287430.html
Copyright © 2020-2023  润新知