【深入浅出Spring原理及实战】「原理分析专题」从零开始教你SpringEL表达式使用和功能分析讲解指南(上篇)

news2024/10/5 20:43:32
  • Spring EL表达式语言,这种语言jsp中学到的el,但是在整个spring之中其表达式语言要更加的复杂,而且支持度更加的广泛,最重要的是他可以进行方法的调用,对象的实例化,集合操作等等,但是唯一的难点就是:代码太复杂了,表达式太复杂了。
  • 深刻领会,spring中针对于字符串的改进,程序员使用字符串开发,绝对要比使用那些类简单,所以在spring里面无时无刻提供的就是字符串的加强。

使用案例

字符串的截取

public class TestStringSub{
     public static void main(String [] args){
		String str = "hello world".subString(5,6);
		System.out.println(str);
	 }
}

整个spring表达式操作之中可以将一个完全的字符串变为了一个可以用于程序执行的语句,这系系列的执行语句需要有一系列的支持类完成,但是至少我可以发现字符串的功能又一次被加强了。

字符串的截取(SpringEL表达式)

public class TestStringSubExpression{
     public static void main(String [] args){
		String expression = "\"hello world\".subString(5,6)";
	    ExpressionParser expressionParser = new SpelExpressionParser();// 指定spelExpressionParser解析器实现类
		Expression expression = parser.parseExpression(expression);//解析表达式 
		EvaluationContext context = new StandardEvaluationContext(expression);//设置对象模型基础。
		System.out.println(expression.getValue(evaluationContext);
	 }
}

封装一个工具方法:

专门解析传入对象的指定属性数值,这里做了下处理,如果获取失败,则直接返回当前传入的属性名称,方便大家做静态解析和动态解析,比如你传入一个8,因为8的这个属性肯定会不对,所以最后会返回一个8。

private static ExpressionParser expressionParser = new SpelExpressionParser();
public static Object getValueByExpression(Object targetObject,String propertyName){
        try {
            EvaluationContext evaluationContext = new StandardEvaluationContext();
            evaluationContext.setVariable("model",targetObject);
            Expression expression =expressionParser.parseExpression(String.format("#{#model.%s}",propertyName),new TemplateParserContext());
            return expression.getValue(evaluationContext,Object.class);
        } catch (ParseException e) {
            log.warn("ParseException analysis the parameter is {}",propertyName);
        } catch (EvaluationException e) {
            log.warn("EvaluationException analysis the parameter is {}",propertyName);
        }
        return propertyName;
    }

表达式解析器

org.springframework.expression.expressionparser

主要负责根据给定的表达式字符串内容对解析器进行处理.

解析器处理类

org.springframework.expression.spel.standard.spelexpressionparsr

Expressionparser本身只是一个操作的标准,但是它对应的处理类必须单独设置,本次使用的是spel的标准处理

表达式

org.springframework.expression.Expression

将字符串根据指定的解析器进行解析,而后使用这个生成表达式:

设置表达式的一些属性信息:

org.springframework.expression.evaluationcontext

因为表达式操作之中可能会存在有某些占位符需要进行处理

参数动态化传入+解析操作
public class TestStringSubExpression{
     public static void main(String [] args){
		String expression = "\"hello world\".subString(#start,#end)";
	    ExpressionParser expressionParser = new SpelExpressionParser();// 指定spelExpressionParser解析器实现类
		Expression expression = parser.parseExpression(expression);//解析表达式 
		EvaluationContext context = new StandardEvaluationContext(expression);//设置对象模型基础。
	    context.setVariable("start",1);
	    context.setVariable("end",2);
		System.out.println(expression.getValue(evaluationContext);
	 }
}

套用模板方法解析器

import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

public class Test {
    public static void main(String[] args) {
        //测试SpringEL解析器
        String template = "#{#name},早上好";//设置文字模板,其中#{}表示表达式的起止,#user是表达式字符串,表示引用一个变量。
        ExpressionParser paser = new SpelExpressionParser();//创建表达式解析器

        //通过evaluationContext.setVariable可以在上下文中设定变量。
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("name","Alex");

        //解析表达式,如果表达式是一个模板表达式,需要为解析传入模板解析器上下文。
        Expression expression = paser.parseExpression(template,new TemplateParserContext());

        //使用Expression.getValue()获取表达式的值,这里传入了Evalution上下文,第二个参数是类型参数,表示返回值的类型。
        System.out.println(expression.getValue(context,String.class));
    }
}

表达式的处理原理

除了编写字符串之外还可以编写数字.甚至各种字符串的数据.
一定要首先对其一个判断,判断表达式应该由那些组成,而后要拆分组成的内容,最后要进行字符串的相关数据类型的转换,从而得出最终的计算结果.

  1. 首先明确的给出表达式,例如1+2
  2. 随后需要准备出spel的表达式解析器,而进行解析的时候要按照如下的步骤.
    • 使用一个专门的断词器,将给定的表达式字符串拆分为spring可以认可的数据格式.
    • 随后要根据断词器的处理生成抽象语法树
  3. 将已经处理后的表达式定义到一个专门的表达式对象之中等待进行最终的结果计算
  4. 考虑到表达式里面可能会存在部分的占位变量的内容,所以在进行表达式计算之前,需要设置一个表达式上下文对象进行占位变量内容的处理.
  5. 最后设置了变量内容,并且利用表达式对象就可以计算出表达式最终所执行的结果

Spring自动的进行了操作的隐藏,用起来很方便

自定义分隔符

任何的表达式其组成之中一定会包含相应的边界形式,例如:在jsp中的el里面使用${表达式},在spring里面,如果用户有需要也可以定义我们的边界.首先观察解析表达式的操作类:Expressionparser

就是用户自己设计边界符的:

是否使用模板
boolean isTemplate();
边界开始
String getExpressionPrefix();
边界结束
String getExpressionSubffix(); 

使用匿名内部类的方式完成.可以在这步定义表达式的边界.定义的表达式在计算的过程中都会自动的忽略掉,大部分我们不会用到自定义边界。

Expression parser = new SpelExpressionParser().parseExpression(str,new ParserContext(){
   		public boolean isTemplate() {
            return true;
        }

        public String getExpressionPrefix() {
            return "[";
        }

        public String getExpressionSuffix() {
            return "]";
        }
});

// 默认的ParserContext

public interface ParserContext {
    ParserContext TEMPLATE_EXPRESSION = new ParserContext() {
        public boolean isTemplate() {
            return true;
        }

        public String getExpressionPrefix() {
            return "#{";
        }

        public String getExpressionSuffix() {
            return "}";
        }
    };

    boolean isTemplate();

    String getExpressionPrefix();

    String getExpressionSuffix();
}

基本表达式

字面表达式

  • 数值型
  • 布尔型
  • 字符串
  • null就是null

数学表达式

  • 四则运算
Expression exp = parser.parseExpression("1+2+4+5/2");
  • 求模
Expression exp = parser.parseExpression("1%2");
Expression exp = parser.parseExpression("1 MOD 2");
  • 幂运算
Expression exp = parser.parseExpression("1 ^ 2");
  • 除法
Expression exp = parser.parseExpression("1 / 2");

关系表达式

  • 等于
Expression exp = parser.parseExpression("1 == 2");
Expression exp = parser.parseExpression("1 EQ 2");
  • 不等于
Expression exp = parser.parseExpression("1 != 2");
Expression exp = parser.parseExpression("1 NE 2");
  • 大于
Expression exp = parser.parseExpression("1 > 2");
Expression exp = parser.parseExpression("1 GT 2");
  • 大于等于
Expression exp = parser.parseExpression("1 >= 2");
Expression exp = parser.parseExpression("1 GE 2");
  • 区间
Expression exp = parser.parseExpression("1  BETWEEN {5,20}");

其他的以此类推就不过多赘述了!

逻辑表达式

  • 与操作
Expression exp = parser.parseExpression("1 = 1  AND 2 = 2");
  • 或操作
Expression exp = parser.parseExpression("1 = 1  or 2 = 2");
  • 三目运算符
Expression exp = parser.parseExpression("1 > 1? 1:2);

Spring中#{}与${}的区别

#{}是SrpingEl表达式的语法规则.

例如:#{bean.属性?:默认值},注意bean.属性必须是要存在的,当为null时匹配

${}是Spring占位符的语法规则

请注意它是否能用,跟bean的初始化时间有关.

例如:${属性:默认值},如果属性为null或者不存在的话,就是用默认值填充

使用案例大全

  • @Value(" t e s t . u s e r n a m e " ) : 注 意 这 样 是 错 误 的 . {test.username}"):注意这样是错误的. test.username").符号不是El表达式的取值方式.
  • @Value(“#{test.xxx.other}”):注意这样是错误的,"."这个点不能连续使用.不知道怎么转义
  • @Value(“#{test.usernameXX?:‘默认的username’}”):注意这样是错误的,如果想使用默认值你需要确保test这类以及usernameXX这个属性必须存在
   @Value("#{test.username?:'默认的username'}")
   private String userName;
   @Value("#{test.password}")
   private Integer password;
	@Value("${username}") 
	private String userName;
	@Value("${other.undefindValue}") // 直接使用属性名称输入
   @Value("${xxxxx:other.undefindValue}") // 当xxxxx不存在时,使用other.undefindValue进行赋值
	@Value("${xxxxx:123}") // 当xxxxx不存在时,使用123进行赋值
	private Integer password;
	@Value("${other.undefindValue}")
	private String undefindValue;

当然你还可以通过Environment对象进行获取哦!

// 申明bean需要使用的resource
@PropertySource("classpath:config.properties") 
public class ClazzName{
	// 获取resource
    @Autowired private Environment environment; 
    /** 获取config配置文件 */
	public String getStr(String key){
		return environment.getProperty(key);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/83453.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于jsp+mysql+ssm医院出车管理与绩效分配系统-计算机毕业设计

项目介绍 本毕业设计主要实现集人性化、高效率、便捷等优点于一身的出车管理系统与绩效分配系统,完成系统用户管理、车辆信息管理、调度员信息管理、驾驶员信息管理、救护员信息管理、科室人员管理、院领导信息管理、调度信息管理、出车统计等功能模块。系统通过浏…

Spring Cloud微服务之loadbalancer负载平衡

Spring Cloud微服务之loadbalancer负载平衡 小学时候,曾经做过这样的数学题。 说有一个水池子,上面有一个排水管,下面有一个进水管,开一个进水管,6个小时灌满水池,开一个排水管,10个小时放光整…

给博客网站添加loading加载中动画代码

只需添加几行代码,就可以加强浏览者的体验,不在等待页面加载时感到枯燥,从而关闭网页,很多网站都会制作一个“网页正在加载中”的提示效果或显示加载进程,加载完成后提示消失,大部分都应用在网站的首页。当然网上很多教…

02时间复杂度与空间复杂度

开始系统学习算法啦!为后面力扣和蓝桥杯的刷题做准备!这个专栏将记录自己学习算法是的笔记,包括概念,算法运行过程,以及代码实现,希望能给大家带来帮助,感兴趣的小伙伴欢迎评论区留言或者私信博…

如何将多个视频剪辑到一起?如何把两段视频合成一段

如何将多个视频剪辑到一起?那么如何拼接视频?接下来小编就带大家一起了解下有关视频拼接的几款工具推荐。 工具一:TS视频拼合工具 TS视频合并工具是一款轻便简单的视频合并工具,主要是用于合并TS视频文件的工具,当用…

【分享】本地js文件替换源网页js文件的方法

本文所有教程及源码、软件仅为技术研究。不涉及计算机信息系统功能的删除、修改、增加、干扰,更不会影响计算机信息系统的正常运行。不得将代码用于非法用途,如侵立删!本地js文件替换源网页js文件的方法 环境 win10Fiddlerchrome方法一:Fiddler抓包替换js文件 自动回复器–…

HashMap源码分析以及面试题

目录 5、HashMap源码分析 5.1、初始化容量 5.2、负载因子是多少? 5.3、负载因子可以大于或小于0.75吗? 5.4、扩容长度为多少? 5.5、下标是怎么计算的? 5.6、hash冲突,是怎么解决的? 5.7、什么时候…

[附源码]JAVA毕业设计英语课程学习网站(系统+LW)

[附源码]JAVA毕业设计英语课程学习网站(系统LW) 项目运行 环境项配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术…

安装 NVSwitch GPU 服务器的 cuda 驱动版本、nvidia-docker 指南

一,安装 Cuda 驱动 可参考笔者之前写过的文章: 升级 GPU 服务器 cuda 驱动版本指南 如果出现如下报错,则需安装 gcc、kernel-devel,请参考下面第二步安装 gcc、kernel-devel。 二,安装 gcc、kernel-devel 1&#…

基于狮群算法优化的lssvm回归预测-附代码

基于狮群算法优化的lssvm回归预测 - 附代码 文章目录基于狮群算法优化的lssvm回归预测 - 附代码1.数据集2.lssvm模型3.基于狮群算法优化的LSSVM4.测试结果5.Matlab代码摘要:为了提高最小二乘支持向量机(lssvm)的回归预测准确率,对…

[附源码]计算机毕业设计高校车辆管理系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: Springboot mybatis MavenVue等等组成,B/S模式…

地表最强:免费文字转语音工具

0、前言 我们在刷短视频的时候,经常会听到一些AI合成声音,它们有各种音色、语调,甚至不同的情绪,听起来与人声无异,其实这些大都是利用微软Azure的文字转语音技术来实现的。 虽然国内也有很多配音工具,但…

【优化算法】粒子群优化算法

粒子群优化算法粒子群优化算法简介粒子群优化算法原理粒子群优化算法的数学描述粒子群优化算法框架PySwarms:Python中粒子群优化的研究工具包PySwarms快速使用示例:编写自己的优化循环相关资料粒子群优化算法简介 粒子群优化算法(Particle Swarm Optimi…

如何安然度过行业大萧条,听听10年测试老鸟的分析

国内的互联网行业发展较快,所以造成了技术研发类员工工作强度比较大,同时技术的快速更新又需要员工不断的学习新的技术。因此淘汰率也比较高,超过35岁的基层研发类员工,往往因为家庭原因、身体原因,比较难以跟得上工作…

Huawei Compute Architecture for Neural Networks - CANN

Huawei Compute Architecture for Neural Networks - CANN1. Technical support (技术支持) https://support.huawei.com/enterprise/en/index.html https://support.huawei.com/enterprise/zh/index.html Server - Intelligent Computing -> Ascend Computing (昇腾计算)…

ChatGPT简介与Q群机器人部署教程

最近OpenAi推出的ChatGPT火出NLP圈子,看到不少人说强人工智能已经出现,于是赶紧来体验感受一下。 ChatGPT简介 ChatGPT是一个基于GPT-3(通用语言模型)的聊天机器人。它的目的是能够通过自然语言交流与用户进行对话。它能够理解用…

Seq2Seq基本原理

Seq2Seq基本原理 encoder & decoder Seq2Seq结构用于多个输入和多个输出的模型,但是输入和输出的大小可能并不一致,其本质上也是RNN网络的一个扩展,常见的应用场景包括:机器翻译、语音识别、文本摘要等。 常见的seq2seq的输…

Linux源码下载

方法一、Git下载源码 1.1、进入Linux官网 通过任意浏览器访问:https://www.kernel.org/,界面如下 1.2、选择版本 点击某一个版本对应的browse,Linux版本分为:mainline(主线版本)、stable(稳定版…

函数之公式求和

【问题描述】 编写一个按以下公式求和的函数, 其中 a 是一个 2 ~ 8 的数字。 例如,S(3,5)333333333333333。 在主函数中,由键盘输入a和n,输出 S(a-1,n-1)S(a,n)S(a1,n1) 的值。 例如输入:3 5 则输出&#xff1a…

PAI-Diffusion模型来了!阿里云机器学习团队带您徜徉中文艺术海洋

作者:汪诚愚、段忠杰、朱祥茹、黄俊 导读 近年来,随着海量多模态数据在互联网的爆炸性增长和训练深度学习大模型的算力大幅提升,AI生成内容(AI Generated Content,AIGC)的应用呈现出爆发性增长趋势。其中…