spring之SpEL表达式详解

 更新时间:2022年02月17日 10:25:13   作者:sunpy 孙培煜  
这篇文章主要介绍了spring之SpEL表达式详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

1.什么是SpEL表达式

SpEL表达式语言是一种表达式语言,是一种可以与一个基于spring的应用程序中的运行时对象交互的东西。有点类似于ognl表达式。总得来说SpEL表达式是一种简化开发的表达式,通过使用表达式来简化开发,减少一些逻辑、配置的编写。

2.SpEL表达式语言入门程序

(1)xml配置的方式

配置环境:pom.xml

<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>4.0.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-expression</artifactId>
			<version>4.0.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.0.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>4.0.5.RELEASE</version>
		</dependency>
</dependencies>

applicationContext.xml文件:

<bean id="MyMessage" class="cn.spy.spel.injection.MyMessage">
        <property name="message" value="#{systemProperties['user.language']}"></property>
</bean>

MyMessage.java文件: 

public class MyMessage {
 
	private String message;
 
	public String getMessage() {
		return message;
	}
 
	public void setMessage(String message) {
		this.message = message;
	}
	
}

测试程序:

public class Test {
	public static void main(String[] args) {
		ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml");
		MyMessage myMessage =context.getBean(MyMessage.class);
		System.out.println(myMessage.getMessage());
	}
}

结果:

解释:这里使用了表达式#{systemProperties['user.language']}来设置值,用来检索用户语言系统的属性。

(2)采用注解的方式

applicationContext.xml文件:

<context:component-scan base-package="cn.spy.spel"></context:component-scan>

MyMessage2.java文件:

@Component
public class MyMessage2 {
	
	@Value("#{systemProperties['user.language']}")
	private String message;
 
	public String getMessage() {
		return message;
	}
}

解释:这里使用了@Value注解的方式,当实例化MyMessage2这个bean的时候,将使用该注解设置默认值。此处还是使用了之前的SpEL表达式,来设置用户语言系统的属性。(在这里@Value注解既可以在类的字段属性上面,也可以在构造函数和方法上面使用)。

测试:

public static void main(String[] args) {
		ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml");
		MyMessage2 myMessage =context.getBean(MyMessage2.class);
		System.out.println(myMessage.getMessage());
	}

结果:

3.分析器

SpEL上下文中所定义的每一个表达式都应该首先被解析,然后在被评估。解析的过程采用了ExpressionParser接口的分析器进行处理的。SpelExpressionParser主要负责将字符串表达式解析到已编译的Expression对象中。(创建的分析器实例是线程安全)

代码形式:

ExpressionParser parser =new SpelExpressionParser();

注意:

在SpEL表达式中,默认情况下,表达式前缀为 ' # ' ,而后缀为 ' } ' 。如果表达式中没有前缀和后缀,那么表达式字符串就被当作纯文本。

分析器解析Spel中纯文本表达式HelloWorld:

public class HelloWorldTest {
	ExpressionParser parser;
	
	@Before
	public void setup(){
		//初始化创建SpEL表达式解析器
		parser =new SpelExpressionParser();
	}
	
	@Test
	public void test(){
		//使用解析器解析出表达式exp
		Expression exp=parser.parseExpression("'Hello World'");
		//在表达式中获取指定类型的值
		String value =exp.getValue(String.class);
		assertThat(value ,is("Hello World"));
	}
}

junit测试结果:

4.使用SpEL表达式调用方法

(1)使用SpEL调用普通方法

就是SpEL也支持在表达式中采用方法调用的形式

范例:

User.java:

public class User {
	
	private String username;
	private String password;
	public void setUsername(String username) {
		this.username = username;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getUsername() {
		return "李四";
	}
	public String getPassword() {
		return "lisi123";
	}
	public void printUser(){
		System.out.println("当前用户的用户名:"+username+" ,密码:"+password);
	}
}

applicationContext.xml配置文件:

        <bean id="user1" class="cn.spy.spel.method.User">
			<property name="username" value="张三"></property>
			<property name="password" value="zhangsan123"></property>
		</bean>		
				
		<bean id="user2" class="cn.spy.spel.method.User">
			<property name="username" value="#{user2.getUsername()}"></property>
			<property name="password" value="#{user2.getPassword()}"></property>
		</bean>	

测试:

public class TestMethod {
	public static void main(String[] args) {
		ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml");
		User user1 =(User) context.getBean("user1");
		user1.printUser();
		User user2 =(User) context.getBean("user2");
		user2.printUser();
	}
}

结果:

(2)使用SpEL调用构造方法

@Test
public void test(){
	ExpressionParser parser =new SpelExpressionParser();
	Expression exp=parser.parseExpression("new Double(3.1415926)");
	Double value =exp.getValue(Double.class);
	assertThat(value ,is(3.1415926));
}

结果:

(3)使用SpEL调用静态方法

@Test
public void test(){
	ExpressionParser parser =new SpelExpressionParser();
	Expression exp=parser.parseExpression("T(java.lang.Math).abs(-1)");
	Integer value =exp.getValue(Integer.class);
	assertThat(value ,is(1));
}

结果:

6.使用SpEL表达式调用变量和函数

(1)#变量的表达式使用

SpEL使用上下文StandardEvaluationContext查找表达式中存在的变量。在表达式中使用变量名称前添加一个标签前缀#,使用已注册的变量。

public class TestSpEL {
	@Test
	public void test(){
		ExpressionParser parser =new SpelExpressionParser();
		StandardEvaluationContext context =new StandardEvaluationContext();
		context.setVariable("message", "Hello World");
		String value =parser.parseExpression("#message").getValue(context, String.class);
		assertThat(value, is("Hello World"));
	}
}

结果:

(2)#root表达式的使用

可以在上下文中设置一个对象评估,可以使用#root访问该对象。

public class TestSpEL {
	@Test
	public void test(){
		ExpressionParser parser =new SpelExpressionParser();
		StandardEvaluationContext context =new StandardEvaluationContext();
		context.setRootObject(new Var());
		Assert.assertTrue(parser.parseExpression("#root").getValue(context) instanceof Var);
	}
}

结果:

(3)访问系统的属性和环境

SpEL预定义变量:systemProperties和systemEnvironment

parser.parseExpression("@systemProperties['java.version']").getValue(context);
parser.parseExpression("@systemProperties[JAVA_HOME]").getValue(context);

7.使用SpEL表达式中的运算符

SpEL提供了多种运算符。

类型

运算符

关系

<,>,<=,>=,==,!=,lt,gt,le,ge,eq,ne

算术

+,- ,* ,/,%,^

逻辑

&&,||,!,and,or,not,between,instanceof

条件

?: (ternary),?: (elvis)

正则表达式

matches

其他类型

?.,?[…],![…],^[…],$[…]

注意:如果解析表达式时,在完全限定的类名中包含一个运算符的文本表示形式,则会产生异常。

正则表达式运算符matches

@Test
	public void test(){
		ExpressionParser parser =new SpelExpressionParser();
		assertThat(parser.parseExpression("35 matches '[0-9]+'").getValue(Boolean.class), is(true));
	}

结果:

逻辑运算符between

@Test
public void test(){
	ExpressionParser parser =new SpelExpressionParser();
	assertThat(parser.parseExpression("3 between {2,5}").getValue(Boolean.class), is(true));
}

结果:

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java在Word中插入上标和下标的实现方法

    Java在Word中插入上标和下标的实现方法

    在某些情况下,你可能需要在Microsoft Word中插入上标和下标。例如,当你正在创建一个涉及科学公式的学术文件时,在这篇文章中,你将学习如何使用Spire.Doc for Java库在Word文档中插入上标和下标,需要的朋友可以参考下
    2022-10-10
  • SpringBoot构建Restful service完成Get和Post请求

    SpringBoot构建Restful service完成Get和Post请求

    这篇文章主要介绍了SpringBoot构建Restful service完成Get和Post请求的示例代码,感兴趣的朋友一起看看吧
    2017-08-08
  • SpringBoot集成canal实现示例解析

    SpringBoot集成canal实现示例解析

    这篇文章主要为大家介绍了springboot整合canal的示例实现解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多多进步,早日升职加薪
    2022-02-02
  • Spring Boot 各种回滚操作实战教程(自动回滚、手动回滚、部分回滚)

    Spring Boot 各种回滚操作实战教程(自动回滚、手动回滚、部分回滚)

    这篇文章主要介绍了Spring Boot 各种回滚操作实战教程(自动回滚、手动回滚、部分回滚),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • SpringBoot+devtools实现热部署的示例代码

    SpringBoot+devtools实现热部署的示例代码

    在软件项目的开发过程中,不可避免的会经常修改代码,每次修改代码,都需要手动停止然后再启动服务,最后验证代码的正确性,今天通过这篇文章,我们一起来学习一下如何使用Spring Boot + devtools 轻松搞定热部署,需要的朋友可以参考下
    2024-08-08
  • Java http请求封装工具类代码实例

    Java http请求封装工具类代码实例

    这篇文章主要介绍了Java http请求封装工具类代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • JavaFX实现简单日历效果

    JavaFX实现简单日历效果

    这篇文章主要为大家详细介绍了JavaFX实现简单日历效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • Spring注解之@Lazy注解使用解析

    Spring注解之@Lazy注解使用解析

    这篇文章主要介绍了Spring注解之@Lazy注解使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • MyBatis Plus构建一个简单的项目的实现

    MyBatis Plus构建一个简单的项目的实现

    这篇文章主要介绍了MyBatis Plus构建一个简单的项目的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • Java中字符串截取方法详解及实际应用小结

    Java中字符串截取方法详解及实际应用小结

    java中截取字符串的常用方法是使用String类的substring方法,本文通过实例代码给大家介绍Java中字符串截取方法详解及实际应用小结,感兴趣的朋友跟随小编一起看看吧
    2024-12-12

最新评论