【第26章】spring-spel基础版


前言

Spring表达式语言(简称“SpEL”)是一种功能强大的表达式语言,支持在运行时查询和操作对象图。该语言语法类似于Unified EL,但提供了额外的功能,最显著的是方法调用和基本的字符串模板功能。

虽然还有其他几种Java表达式语言可用 — OGNL、MVEL和JBoss EL,仅举几个例子 — 创建Spring表达式语言是为了向Spring社区提供一种受良好支持的表达式语言,该语言可以在Spring产品组合中的所有产品中使用。它的语言特性是由Spring产品组合中项目的需求驱动的,包括Spring Tools for Eclipse中代码完成支持的工具需求。也就是说,SpEL基于一种技术——gnostic API,如果需要,它可以集成其他表达式语言实现。

虽然SpEL是Spring产品组合中表达式求值的基础,但它并不直接与Spring绑定,可以独立使用。为了自圆其说,本章中的许多例子都使用了SpEL,就好像它是一种独立的表达语言一样。这需要创建一些自举基础结构类,例如解析器。大多数Spring用户不需要处理这个基础设施,而是可以只编写用于评估的表达式字符串。这种典型使用的一个示例是将SpEL集成到创建基于XML或注释的bean定义中,如定义bean定义的Expression支持中所示。


4.1 Evaluation

package org.example.validator.evaluation;

import org.example.validator.po.Inventor;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import java.util.GregorianCalendar;

/**
 * Create by zjg on 2024/4/21
 */
public class Main {
    public static void main(String[] args) {
        System.out.println(parse("'Hello Spel'",String.class));//字符串
        System.out.println(parse("'Hello World'.concat('!')",String.class));//字符串连接
        System.out.println(new String(parse("'Hello World'.bytes",byte[].class)));//得到字节数组
        System.out.println(parse("'Hello World'.bytes.length",Integer.class));//得到参数长度
        System.out.println(parse("new String('hello world').toUpperCase()",String.class));//大写转换
        System.out.println(parse("new String('HELLO WORLD').toLowerCase()",String.class));//小写转换
        // 日期
        GregorianCalendar c = new GregorianCalendar();
        c.set(1856, 7, 9);
        // 创建对象及初始化
        Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");
        String name = getValue("name",String.class,tesla);//获取tesla的name属性值
        System.out.println(name);
        boolean result = getValue("name == 'Nikola Tesla'",Boolean.class,tesla);//获取tesla的name属性值和字符串对比
        System.out.println(result);
    }
    public static <T> T parse(String expressionString, Class<T> clazz){
        ExpressionParser parser = new SpelExpressionParser();
        return clazz.cast(parser.parseExpression(expressionString).getValue());
    }
    public static <T> T getValue(String expressionString, Class<T> clazz,Object object){
        ExpressionParser parser = new SpelExpressionParser();
        return clazz.cast(parser.parseExpression(expressionString).getValue(object));
    }
}

4.1.1. Understanding EvaluationContext

package org.example.validator.evaluation;

import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import java.util.ArrayList;
import java.util.List;

/**
 * Create by zjg on 2024/4/21
 */
public class UnderstandingEvaluationContext {
    public static void main(String[] args) {
        Simple simple = new Simple();
        simple.booleanList.add(true);
        simple.booleanList.add(true);
        simple.booleanList.add(false);
        EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
        ExpressionParser parser = new SpelExpressionParser();//spring内置转换服务
        parser.parseExpression("booleanList[0]").setValue(context, simple, "false");//设置列表下表0的值为false
        simple.booleanList.forEach(System.out::println);
    }

}
class Simple {
    public List<Boolean> booleanList = new ArrayList<Boolean>();
}

4.1.2. Parser Configuration

package org.example.validator.evaluation;

import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import java.util.List;

/**
 * Create by zjg on 2024/4/21
 */
public class ParserConfiguration {
    public static void main(String[] args) {
        class Demo {
            public List<String> list;
        }
        //自动null引用,集合自动增长
        SpelParserConfiguration config = new SpelParserConfiguration(true, true);
        ExpressionParser parser = new SpelExpressionParser(config);
        Expression expression = parser.parseExpression("list[3]");
        Demo demo = new Demo();
        Object o = expression.getValue(demo);
        for(int i=0;i<demo.list.size();i++){//有4个空值
            System.out.println(i+""+demo.list.get(i));
        }
    }
}

4.1.3. SpEL Compilation

package org.example.validator.evaluation;

import org.springframework.expression.Expression;
import org.springframework.expression.spel.SpelCompilerMode;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * Create by zjg on 2024/4/21
 */
public class SpelCompliation {
    public static void main(String[] args) {
        class MyMessage {
            public String payload;

            public void setPayload(String payload) {
                this.payload = payload;
            }
        }
        SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,
                SpelCompliation.class.getClassLoader());//指定编译器模式(立即获取)
        SpelExpressionParser parser = new SpelExpressionParser(config);
        Expression expr = parser.parseExpression("payload");
        MyMessage message = new MyMessage();
        message.setPayload("ssr");
        Object payload = expr.getValue(message);
        System.out.println(payload);
    }
}

4.2. Expressions in Bean Definitions

4.2.1. XML Configuration

4.2.1.1 实体类

package org.example.validator.expressions.xml.po;

/**
 * Create by zjg on 2024/4/22
 */
public class NumberGuess {
    private double randomNumber;

    public double getRandomNumber() {
        return randomNumber;
    }

    public void setRandomNumber(double randomNumber) {
        this.randomNumber = randomNumber;
    }

    @Override
    public String toString() {
        return "NumberGuess{" +
                "randomNumber=" + randomNumber +
                '}';
    }
}

package org.example.validator.expressions.xml.po;

/**
 * Create by zjg on 2024/4/22
 */
public class ShapeGuess {
    private double initialShapeSeed;

    public double getInitialShapeSeed() {
        return initialShapeSeed;
    }

    public void setInitialShapeSeed(double initialShapeSeed) {
        this.initialShapeSeed = initialShapeSeed;
    }

    @Override
    public String toString() {
        return "ShapeGuess{" +
                "initialShapeSeed=" + initialShapeSeed +
                '}';
    }
}

package org.example.validator.expressions.xml.po;

/**
 * Create by zjg on 2024/4/22
 */
public class TaxCalculator {
    private String defaultLocale;

    public String getDefaultLocale() {
        return defaultLocale;
    }

    public void setDefaultLocale(String defaultLocale) {
        this.defaultLocale = defaultLocale;
    }

    @Override
    public String toString() {
        return "TaxCalculator{" +
                "defaultLocale='" + defaultLocale + '\'' +
                '}';
    }
}

4.2.1.2 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="numberGuess" class="org.example.validator.expressions.xml.po.NumberGuess">
        <property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>
    </bean>
    <bean id="taxCalculator" class="org.example.validator.expressions.xml.po.TaxCalculator">
        <property name="defaultLocale" value="#{ systemProperties['user.region'] }"/>
    </bean>
    <bean id="shapeGuess" class="org.example.validator.expressions.xml.po.ShapeGuess">
        <property name="initialShapeSeed" value="#{ numberGuess.randomNumber }"/>
    </bean>
</beans>

4.2.1.3 测试类

package org.example.validator.expressions.xml;

import org.example.validator.expressions.xml.po.NumberGuess;
import org.example.validator.expressions.xml.po.ShapeGuess;
import org.example.validator.expressions.xml.po.TaxCalculator;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

/**
 * Create by zjg on 2024/4/22
 */
@SpringJUnitConfig(locations = "classpath:spring-spel.xml")
public class SpringTest {
    @Autowired
    NumberGuess numberGuess;
    @Autowired
    TaxCalculator taxCalculator;
    @Autowired
    ShapeGuess shapeGuess;
    @Test
    public void test(){
        System.out.println(numberGuess);
        System.out.println(taxCalculator);
        System.out.println(shapeGuess);
    }
}

NumberGuess{randomNumber=36.044191193759225}
TaxCalculator{defaultLocale=‘null’}
ShapeGuess{initialShapeSeed=36.044191193759225}

4.2.2. Annotation Configuration

4.2.2.1 实体类

package org.example.validator.expressions.annotation;

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

/**
 * Create by zjg on 2024/4/22
 */
@Component
public class FieldValueTestBean {
    @Value("#{ systemProperties['user.region']?: 'CN' }")
    private String defaultLocale;

    public void setDefaultLocale(String defaultLocale) {
        this.defaultLocale = defaultLocale;
    }

    public String getDefaultLocale() {
        return this.defaultLocale;
    }

    @Override
    public String toString() {
        return "FieldValueTestBean{" +
                "defaultLocale='" + defaultLocale + '\'' +
                '}';
    }
}

package org.example.validator.expressions.annotation;

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

/**
 * Create by zjg on 2024/4/22
 */
@Component
public class MovieRecommender {
    private String defaultLocale;

    private CustomerPreferenceDao customerPreferenceDao;

    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao,
                            @Value("#{systemProperties['user.country']}") String defaultLocale) {
        this.customerPreferenceDao = customerPreferenceDao;
        this.defaultLocale = defaultLocale;
    }

    @Override
    public String toString() {
        return "MovieRecommender{" +
                "defaultLocale='" + defaultLocale + '\'' +
                ", customerPreferenceDao=" + customerPreferenceDao +
                '}';
    }
}

package org.example.validator.expressions.annotation;

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

/**
 * Create by zjg on 2024/4/22
 */
@Component
public class PropertyValueTestBean {
    private String defaultLocale;

    @Value("#{ systemProperties['user.region'] }")
    public void setDefaultLocale(String defaultLocale) {
        this.defaultLocale = defaultLocale;
    }

    public String getDefaultLocale() {
        return this.defaultLocale;
    }

    @Override
    public String toString() {
        return "PropertyValueTestBean{" +
                "defaultLocale='" + defaultLocale + '\'' +
                '}';
    }
}

package org.example.validator.expressions.annotation;

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

/**
 * Create by zjg on 2024/4/22
 */
@Component
public class SimpleMovieLister {
    private MovieFinder movieFinder;
    private String defaultLocale;

    @Autowired
    public void configure(MovieFinder movieFinder,
                          @Value("#{ systemProperties['user.region'] }") String defaultLocale) {
        this.movieFinder = movieFinder;
        this.defaultLocale = defaultLocale;
    }

    @Override
    public String toString() {
        return "SimpleMovieLister{" +
                "movieFinder=" + movieFinder +
                ", defaultLocale='" + defaultLocale + '\'' +
                '}';
    }
}

4.2.2.2 配置类

package org.example.validator.expressions.annotation;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * Create by zjg on 2024/4/22
 */
@ComponentScan("org.example.validator.expressions.annotation")
@Configuration
public class SpringConfig {
    @Bean
    public MovieFinder movieFinder(){
        return new MovieFinder();
    }
    @Bean
    public CustomerPreferenceDao customerPreferenceDao(){
        return new CustomerPreferenceDao();
    }
}
class MovieFinder{}
class CustomerPreferenceDao{}

4.2.2.3 测试类

package org.example.validator.expressions.annotation;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

/**
 * Create by zjg on 2024/4/22
 */
@SpringJUnitConfig(SpringConfig.class)
public class SpringApplication {
    @Autowired
    FieldValueTestBean fieldValueTestBean;
    @Autowired
    PropertyValueTestBean propertyValueTestBean;
    @Autowired
    SimpleMovieLister simpleMovieLister;
    @Autowired
    MovieRecommender movieRecommender;
    @Test
    public void test() {
        System.out.println(fieldValueTestBean);
        System.out.println(propertyValueTestBean);
        System.out.println(simpleMovieLister);
        System.out.println(movieRecommender);
    }
}

FieldValueTestBean{defaultLocale=‘null’}
PropertyValueTestBean{defaultLocale=‘null’}
SimpleMovieLister{movieFinder=org.example.validator.expressions.annotation.MovieFinder@1b1637e1, defaultLocale=‘null’}
MovieRecommender{defaultLocale=‘CN’, customerPreferenceDao=org.example.validator.expressions.annotation.CustomerPreferenceDao@18151a14}

4.2.2.4 常用系统变量和所有系统变量

package org.example.validator.expressions.annotation;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

/**
 * Create by zjg on 2024/4/22
 */
@SpringJUnitConfig(SpringConfig.class)
public class SpringApplication {
    @Value("#{ systemProperties['user.name'] }")
    private String name;
    @Value("#{ systemProperties['user.dir'] }")
    private String dir;
    @Value("#{ systemProperties['user.country'] }")
    private String country;
    @Value("#{ systemProperties['user.language'] }")
    private String language;
    @Value("#{ systemProperties['PID'] }")
    private String pid;
    @Test
    public void systemProperties() {
        System.out.println(name);
        System.out.println(dir);
        System.out.println(country);
        System.out.println(language);
        System.out.println(pid);
        System.getProperties().forEach((k,v)->{
            System.out.println(k+":"+v);
        });
    }
}


总结

回到顶部
操作手册

尽管我已经参考官方案例去编写完整的案例,但是案例数过多导致文章篇幅过长,但是每个案例都有它的用处,为了保证大家阅读起来的体验感,从这里进行拆分,4.3. Language Reference会在下一个章节里介绍,这一章节只介绍基础用法。

不重复造轮子,我们只是代码的搬运工。
建议大家先看我的文档,再看官方案例,然后你就会发现我写的有多差。
ps:开个玩笑,官方能跑的我能跑,官方不能跑的我也能跑,我写的很详细了,好吧。

在这里插入图片描述

相关推荐

  1. 27spring-spel进阶

    2024-05-01 13:20:02       22 阅读
  2. 23spring-async(异步)

    2024-05-01 13:20:02       36 阅读
  3. Spring SpEL在Flink中的应用-SpEL详解

    2024-05-01 13:20:02       52 阅读
  4. Spring实战68 OAuth2 客户端跑不起来

    2024-05-01 13:20:02       67 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-01 13:20:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-01 13:20:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-05-01 13:20:02       87 阅读
  4. Python语言-面向对象

    2024-05-01 13:20:02       96 阅读

热门阅读

  1. FAISS原理和使用总结

    2024-05-01 13:20:02       34 阅读
  2. H.264码流解析

    2024-05-01 13:20:02       30 阅读
  3. Nacos和Eureka有什么区别

    2024-05-01 13:20:02       32 阅读
  4. 指代消解原理

    2024-05-01 13:20:02       28 阅读
  5. Day41 HTTP编程

    2024-05-01 13:20:02       32 阅读
  6. 邦芒面试:面试时,如何展现卓越的口才

    2024-05-01 13:20:02       30 阅读
  7. 程序员商业模式画布

    2024-05-01 13:20:02       26 阅读
  8. 云计算与云服务

    2024-05-01 13:20:02       37 阅读
  9. 云计算知识点-02

    2024-05-01 13:20:02       34 阅读