• CDI features


    什么是SpEL

    Spring 表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。 语法类似于 EL表达式:SpEL 使用 #{…}作为定界符,所有在大框号中的字符都将被认为是 SpEL。SpEL 为 bean 的属性进行动态赋值提供了便利 通过 SpEL 可以实现:
    通过 bean 的 id 对 bean 进行引用 调用方法以及引用对象中的属性计算表达式的值正则表达式的匹配

    SpEL很重要的一个功能就是能够实现 动态赋值


    字面量表达式

    字面量的表示:
    整数:
    小数:
    科学计数法:
    String可以使用单引号或者双引号作为字符串的定界符号: 或 
    Boolean:

    以上的用法其实没有什么意义,并不能体现出SpEL的强大,这里些出来只是简单介绍下用法而已。


    SpEL使用

    举个例子:
    先创建三个类

    Address类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    package com.spring.spel;
     
    public class Address {
     
        private String province;
        private String city;
     
        public String getProvince() {
            return province;
        }
        public void setProvince(String province) {
            this.province = province;
        }
        public String getCity() {
            return city;
        }
        public void setCity(String city) {
            this.city = city;
        }
        @Override
        public String toString() {
            return "Address [province=" + province + ", city=" + city + "]";
        }
     
    }

    Car类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    package com.spring.spel;
     
    public class Car {
     
        private String brand;
     
        private double price;
     
        //轮胎的周长
        private double tyrePerimeter;
     
        public String getBrand() {
            return brand;
        }
     
        public void setBrand(String brand) {
            this.brand = brand;
        }
     
        public double getPrice() {
            return price;
        }
     
        public void setPrice(double price) {
            this.price = price;
        }
     
        public double getTyrePerimeter() {
            return tyrePerimeter;
        }
     
        public void setTyrePerimeter(double tyrePerimeter) {
            this.tyrePerimeter = tyrePerimeter;
        }
     
        @Override
        public String toString() {
            return "Car [brand=" + brand + ", price=" + price + ", tyrePerimeter="
                    + tyrePerimeter + "]";
        }
     
    }

    Person类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    package com.spring.spel;
     
     
    public class Person {
        private String name;
        private Car car;
        private String city;
        private String info;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Car getCar() {
            return car;
        }
        public void setCar(Car car) {
            this.car = car;
        }
        public String getCity() {
            return city;
        }
        public void setCity(String city) {
            this.city = city;
        }
        public String getInfo() {
            return info;
        }
        public void setInfo(String info) {
            this.info = info;
        }
        @Override
        public String toString() {
            return "Person [name=" + name + ", car=" + car + ", city=" + city
                    + ", info=" + info + "]";
        }
     
    }

    bean配置文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <!-- 使用spel赋字面值 -->
    <bean class="com.spring.spel.Address" id="address">
        <property name="province" value="#{'安徽'}"></property>
        <property name="city" value="#{'合肥'}"></property>
    </bean>
     
    <!-- 使用spel引用类的静态属性 -->
    <bean class="com.spring.spel.Car" id="car">
        <property name="brand" value="bmw"></property>
        <property name="price" value="350000"></property>
        <!-- 引用Math类的静态属性PI -->
        <property name="tyrePerimeter" value="#{T(java.lang.Math).PI * 80}"></property>
    </bean>
     
    <bean class="com.spring.spel.Person" id="person">
        <property name="name" value="tom"></property>
        <!-- 使用spel引用其他的bean -->
        <property name="car" value="#{car}"></property>
        <!-- 使用spel引用其他bean的属性 -->
        <property name="city" value="#{address.city}"></property>
        <!-- 使用spel语法判断 -->
        <property name="info" value="#{car.price > 300000 ? '金领' : '白领'}"></property>
    </bean>

    测试类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-spel.xml");
    Address address = (Address) ctx.getBean("address");
    System.out.println(address);
     
    Car car = (Car) ctx.getBean("car");
    System.out.println(car);
     
    Person person = (Person) ctx.getBean("person");
    System.out.println(person);

    这里写图片描述

    总结:

    #{T(java.lang.Math).PI :使用java类的静态属性#{car}: 使用spel引用其他的bean#{address.city}:使用spel引用其他bean的属性#{car.price > 300000 ? '金领' : '白领'}:使用spel条件判断


    SpEL其他用法:

    调用其他bean实例的方法,还可以连缀操作

    1
    <property name="city" value="#{address.getCity().getXxx}"></property>

    算数运算符:+, -, *, /, %, ^:

    这里写图片描述

    加号还可以用作字符串连接:

    这里写图片描述

    比较运算符: eq(==),lt(<),le(<=),gt(>),ge(>=) 括号里面外面的都可以使用逻辑表达式:and,or,not或!。SpEL支持正则表达式匹配

    1
    <property name="validEmail" value="#{admin.email matches '[a-zA-Z0-9._%+_]+@[a-zA-Z0-9.-]+\.com'}"></property>

    注解使用SpEl

    利用@Value注解可以给实体属性赋默认值
    @Value可以使用SpEL表达式,例如:

    1
    2
    3
    4
    5
    @Value("#{'福建'}")
    private String province;
     
    @Value("#{'福州'}")
    private String city;

    使用前需要开启注解扫描器:

    1
    <context:component-scan base-package="com.spring"></context:component-scan>
     
     

    单个装饰器的使用:装饰器的执行原理
    #1.定义两个装饰器(闭包函数,装饰函数都可以称呼),功能是给字体进行加粗和倾斜的标签。
    def makeBold(fn):
    print("BBBBB"*5)
    def wrapped():
    print("bbbbb"*5)
    return "<b>" + fn() + "</b>"
    return wrapped

    def makeItalic(fn):
    print("IIIII"*5)
    def wrapped():
    print("iiiiii" * 5)
    return "<i>" + fn() + "</i>"
    return wrapped

    #2.装饰器的使用,直接@加上函数名的形式,放到需要装饰的函数头上即可。
    @makeBold #效果等同于test_Bold=makeBold(test_Bold),装饰器放在一个函数上,相当于将这个函数当成参数传递给装饰函数
    def test_Bold():
    print("test_Bold"*5)
    return "this is the test_Bold"

    @makeItalic #效果等同于test_Italic=makeItalic(test_Italic),装饰器放在一个函数上,相当于将这个函数当成参数传递给装饰函数
    def test_Italic():
    print("test_Itali" * 5)
    return "this is the test_Italic"

    下面实现对上面的单个装饰器代码的测试: 
    1.1直接上面运行程序,什么不调用,也不操作,发现也有结果。
    '''执行结果如下:
    BBBBBBBBBBBBBBBBBBBBBBBBB
    IIIIIIIIIIIIIIIIIIIIIIIII
    '''
    原因分析:

          直接执行python程序,不调用任何方法,发现makeBold与makeItalic函数里面的第一个print函数也执行了。因为@makeBold其效果等同于test_Bold=makeBold( test_Bold ),所以程序执行时,从上到下加载执行到函数体上方的标识符@makeBold@makeItalic时,相当于执行了test_Bold=makeBold(test_Bold),test_Italic=makeBold(test_Italic),所以相当于调用了makeBold和makeItlic这两个函数,所以依次执行了这两个函数中第一个print语句。因为@makeBold在前,所以结果就是上面的BBBB....和IIIIIII....(其实这两个函数还有返回值,返回值分别是这两个函数内部的闭包,只是这里没有显示出来而已)

     
     
     
    拦截器
    java里的拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Programming)中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。

    原理

    编辑
    大部分时候,拦截器方法都是通过代理的方式来调用的。Struts 2的拦截器实现相对简单。当请求到达Struts 2的ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器。Struts2拦截器是可插拔的,拦截器是AOP的一种实现。Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。

    定义一个拦截器

    编辑
    自定义一个拦截器需要三步:
    1 .自定义一个实现Interceptor接口(或者继承自AbstractInterceptor)的类。
    2 .在struts.xml中注册上一步中定义的拦截器。
    3 .在需要使用的Action中引用上述定义的拦截器,为了方便也可将拦截器定义为默认的拦截器,这样在不加特殊声明的情况下所有的Action都被这个拦截器拦截。

    与过滤器的区别

    编辑
    过滤器可以简单理解为“取你所想取”,忽视掉那些你不想要的东西;拦截器可以简单理解为“拒你所想拒”,关心你想要拒绝掉哪些东西,比如一个BBS论坛上拦截掉敏感词汇。
    1.拦截器是基于java反射机制的,而过滤器是基于函数回调的。
    2.过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。
    3.拦截器只对action起作用,而过滤器几乎可以对所有请求起作用。
    4.拦截器可以访问action上下文、值栈里的对象,而过滤器不能。
    5.在action的生命周期里,拦截器可以多起调用,而过滤器只能在容器初始化时调用一次。
     
  • 相关阅读:
    [C#]App.Config
    [转][JS]修改链接中的参数
    [转][Oracle]常见报错及处理
    [转]截图软件分享
    [转][C#]手写 Socket 服务端
    3.6的pprint写法改变了:pprint.pprint()
    版本优化-test
    python爬取豆瓣小组700+话题加回复啦啦啦python open file with a variable name
    爬豆瓣被封的解决方案
    去除列表中字符串中的空格换行等
  • 原文地址:https://www.cnblogs.com/zyhello/p/10672322.html
Copyright © 2020-2023  润新知