【Spring EL<一>✈️ 】SL 表达式的应用

目录

🍸前言

🍻一、Spring EL

       1.1 定义

        1.2 常见使用方式

🍺二、项目案例

        2.1 实现一个简单的案例

        2.2 创建注解

        2.3 切面类实现

        2.4 创建测试接口

        2.5 测试

🍹三、章末


🍸前言

        小伙伴们大家好,前段时间在网上无意间听到了一个很耳生的名词 “Spring EL 表达式”,这几天通过文章、视频的方式了解了些,然后再本地实操下

🍻一、Spring EL

       1.1 定义

         首先来看下全称 Spring Expression Language ,正如命名所言,是 Spring 框架中一种表达式语言。类似于其他编程语言中的表达式语言,用于在运行时计算值或执行特定任务,比如在运行时评估复杂的表达式,通过这些表达式可以访问和操作应用程序上下文中的对象

        1.2 常见使用方式

        其实在项目中这种语法应该挺常见的比如下面这些:

        (1)通过 EL 表达式获取 bean 属性

"#{beanName.property}"

        (2)通过 EL 表达式调用某个 bean 方法

"#{bean.myMethod(args)}"

        (3)通过 EL 表达式进行运算

"#{num1 + num2}"

        ...

        使用方式有很多,本地就挑最常用以及最常见的使用方式,结合注解使用,动态的处理注解参数

🍺二、项目案例

        2.1 实现一个简单的案例

        比如自定义一个注解,用于控制方法级别的日志记录,但日志级别是根据运行时条件动态决定的,通过 Spring EL 表达式实现如下

        注:本地环境需要一个可以启动的 SpringBoot 项目,并且引入了 aop 依赖

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
            2.2 创建注解

        创建一个注解,声明作用域为运行时,并且是作用于方法上面的,另外声明了一个方法,默认值为 true,也就是默认打印日志

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author HuangBen */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecution {String condition() default "true"; // 默认总是记录日志
}

        2.3 切面类实现

       实现了在目标方法执行时环绕通知,动态的获取方法上的注解值,解析比对,判断是否需要打印日志

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;/*** @author HuangBen */
@Aspect
@Component
public class LoggingAspect {private final SpelExpressionParser parser = new SpelExpressionParser();private final DefaultParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();@Around("@annotation(logExecution)")public Object logAround(ProceedingJoinPoint joinPoint, LogExecution logExecution) throws Throwable {boolean shouldLog = evaluateCondition(joinPoint, logExecution.condition());if (shouldLog) {System.out.println("Executing: " + joinPoint.getSignature().getName() + ", Log Level determined by SpEL.");}try {Object result = joinPoint.proceed();//到这里,目标方法执行完毕,要返回的内容先暂存,执行 finally 方法体return result;} finally {if (shouldLog) {System.out.println("Completed: " + joinPoint.getSignature().getName());}}}//用于解析 SpringEL 表达式并获取解析结果private boolean evaluateCondition(ProceedingJoinPoint joinPoint, String expression) {MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();Method method = methodSignature.getMethod();MethodBasedEvaluationContext context = new MethodBasedEvaluationContext(null,method,joinPoint.getArgs(),parameterNameDiscoverer);Expression exp = parser.parseExpression(expression);return exp.getValue(context, Boolean.class);}
}

        2.4 创建测试接口

        这里就简单的写个接口,通过传入的参数决定是否打印日志

        注:这里的 "#input.equalsIgnoreCase('important')" 就是一个简单的表达式,input 表示提供的变量值,后面的是字符串方法,会忽略大小比较字符串是否等于目标值

@GetMapping("/springel")@LogExecution(condition = "#input.equalsIgnoreCase('important')")public void performAction(String input) {System.out.println("Performing action with input: " + input);// 实际业务逻辑...}

       

        如果单纯的比较输入的参数,这里也可以在切面类中实现,但是如果每个接口的 SpringEl 比较的内容都不一样的,阁下又该如何应对, if else 大军吗,不如直接换一个表达式,每个接口都可以有自己的 SpringEL 表达式(这样,编码的可用性不就增强了),比如可以判断输入的字符的长度是否大于 5,来决定是否打印日志,结果如下,注解正常工作

        2.5 测试

        2.5.1 输入参数为打印日志:

        2.4.2 输入参数为不需要打印

        2.5 总结

         这个案例只是简单演示了注解中的 SpringEL 表达式使用方式,通过在目标方法上加上注解,在注解里面写好自定义的 SpringEL 表达式,然后在切面类里面通过 SpringEL 解析工具处理表达式,获取结果即可

🍹三、章末

        文章初步的了解了 SpringEL 表达式的使用方式,以及结合具体的案例了解 Spring AOP 注解的常见用法

        文章到这里就结束了~

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

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

相关文章

32. 【Java教程】集合

在前面的小节中&#xff0c;我们学习了数组&#xff0c;本小节学习的集合同样用于存放一组数据&#xff0c;我们将学习什么是集合、集合的应用场景 &#xff0c;在应用场景部分我们将对比 Java 数组与集合的区别&#xff0c;还将系统介绍 Java 集合的架构&#xff0c;也将结合实…

【观察】数字化生存时代已来临,能源转型如何实现“再升级”?

20多年前&#xff0c;尼古拉斯尼葛洛庞帝在《数字化生存》一书中预言&#xff1a;“数字化生存是现代社会中以新技术为基础的新的生存方式。” 随着数字经济的蓬勃发展&#xff0c;尼葛洛庞帝的预言逐渐被验证。今天&#xff0c;新技术带来的数字化和智能化正全方位影响着经济…

【赠书第27期】向AI提问的艺术:提示工程入门与应用

文章目录 前言 1 问题的构建 1.1 明确性与具体性 1.2 结构化与层次性 1.3 相关性与针对性 2 提问的技巧 2.1 简洁明了 2.2 避免歧义 2.3 使用自然语言 3 与AI的互动策略 3.1 耐心与理解 3.2 逐步引导 3.3 反馈与调整 4 总结与展望 5 推荐图书 6 粉丝福利 前言 …

定时器与PWM的LED控制

目录 一、基础概念定时器定时器类型定时器特性 PWM定义占空比原理 二、实验1.LED周期性亮灭定时器TIM2配置GPIO引脚设置工程相关参数配置Keil编写程序 2.LED呼吸灯(PWM)呼吸灯原理Keil编写程序Keil虚拟示波器&#xff0c;观察 PWM输出波形设置点击setup&#xff0c;并设置观察引…

Sapphire开发日志(三)

任务描述 本周实现并封装了模型的运行&#xff0c;需要在前端安装依赖的库&#xff0c;编写对应的处理函数。同时需要能够展示出抠图效果。 依赖与环境配置 尝试在前端接入并运行onnx。 在前端运行onnx依赖于onnxruntime-web这个包&#xff0c;这个包可以在浏览器进行模型推…

antV+vue3 单选框选中加入逻辑运算,再次点击取消选中,不计入逻辑运算

文章目录 antVvue3 单选框选中加入逻辑运算&#xff0c;再次点击取消选中&#xff0c;不计入逻辑运算需求增加点击事件逻辑处理效果 antVvue3 单选框选中加入逻辑运算&#xff0c;再次点击取消选中&#xff0c;不计入逻辑运算 需求 在做项目时&#xff0c;多次遇到单选框需要再…

【2024新版】银系统源码/超市收银系统/智慧新零售/ERP进销存管理/线上商城/商户助手

>>>系统简述&#xff1a;本系统适用于超吃便利店&#xff0c;美妆母婴行业&#xff0c;服装鞋帽行业&#xff0c;食品零售行业&#xff0c;3C数码电子行业&#xff0c;食品生鲜等一切零售行业&#xff0c;产品功能角色介绍如下 合伙人&#xff1a;无限发展代理商和商…

Pod 控制器

前言 Pod 是 Kubernetes 集群中能够被创建和管理的最小部署单元。所以需要有工具去操作和管理它们的生命周期,这里就需要用到控制器了。 Pod 控制器由 master 的 kube-controller-manager 组件提供&#xff0c;常见的此类控制器有 Replication Controller、ReplicaSet、Deploym…

React-生成随机数和日期格式化

生成随机数 uuid文档&#xff1a;https://github.com/uuidjs/uuid npm install uuid import {v4 as uuidV4} from uuid 使用&#xff1a; uuidV4() 日期格式化 dayjs文档&#xff1a;安装 | Day.js中文网 npm install dayjs import dayjs from dayjs

算法-扫描线

目录 什么是扫描线算法&#xff1f; 扫描线简单应用 更多的扫描线 什么是扫描线算法&#xff1f; 在计算几何中&#xff0c;扫描线算法&#xff08;scan line algorithm&#xff09;一般用来解决几何图形的面积交并&#xff0c;周长交并问题&#xff0c;扫描线算法的核心思想…

SAPUI5基础知识3 - 引导过程(Bootstrap)

1. 背景 在上一篇博客中&#xff0c;我们已经建立出了第一个SAPUI5项目&#xff0c;接下来&#xff0c;我们将为这个项目添加引导过程。 在动手练习之前&#xff0c;让我们先解释一下什么引导过程。 1.1 什么是引导过程&#xff1f; 在计算机科学中&#xff0c;引导过程也称…

5、css3 自动动画渐变背景

效果例图&#xff1a;&#xff08;因gif图片太大&#xff0c;而csdn只能上传小于5m图片&#xff0c;所以无法上传&#xff09; 1、首先上传html代码&#xff1a; <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8">&l…

【鸟哥】Linux笔记-硬件搭配

在Linux这个系统当中&#xff0c;几乎所有的硬件设备文件都在/dev这个目录内。打印机与软盘呢&#xff1f;分别是/dev/lp0, /dev/fd0。 几个常见的设备与其在Linux当中的文件名&#xff1a; 如果你的机器使用的是跟网际网络供应商 &#xff08;ISP&#xff09; 申请使用的云端…

二叉树的构建和遍历(oj题)

一、题目链接 https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId60&&tqId29483&rp1&ru/activity/oj&qru/ta/tsing-kaoyan/question-ranking 二、题目思路 利用先序遍历的方法&#xff0c;构建二叉树。为了保证在递归中&#xf…

USB主机模式——Android

理论 摘自&#xff1a;USB 主机和配件概览 | Connectivity | Android Developers (google.cn) Android 通过 USB 配件和 USB 主机两种模式支持各种 USB 外围设备和 Android USB 配件&#xff08;实现 Android 配件协议的硬件&#xff09;。 在 USB 主机模式下&#xff0…

Redis 中的 Zset 数据结构详解

目录 用法 1. 增 2. 删 3. 查 4. 交&#xff0c;并 编码方式 应用场景 Redis 中的 Zset&#xff08;有序集合&#xff09;是一种将元素按照分数进行排序的数据结构。与上篇写的SetRedis 中的 Set 数据结构详解不同&#xff0c;Zset 中的每个元素都关联一个浮点数类型的…

Jmeter的线程组之间传递参数

使用jemter做接口测试&#xff0c;有时候需要会遇到不同线程组之间调用相同变量的情况&#xff0c;最多见的就是token的传递&#xff0c;网上有很多处理方法&#xff0c;这里只记录setProperty的办法&#xff0c;一招鲜走遍天&#xff01; 首先我有两个线程组&#xff1a; 线程…

vm:为虚拟机配置多个虚拟网卡(ubuntu20.04)

前言&#xff1a; 环境&#xff1a;虚拟机 ubuntu 20.04 要求&#xff1a;如标题&#xff0c;但是这里针对的是 ubuntu 20.04&#xff0c;对于其他操作系统&#xff0c;可以找一下其他操作系统对应的配置文件是什么 vm 添加虚拟网卡 首先进入 vm&#xff1a; 点击设置&#xf…

JVM监控-JMX探针的安装和使用

jvm监控的搭建和使用 ​ Java Management Extensions&#xff08;JMX&#xff09;是一种Java标准&#xff0c;用于管理和监控Java应用程序&#xff0c;特别是分布式系统。它提供了一种标准化的方式来管理应用程序的各种方面&#xff0c;包括性能监控、配置更改、事件通知等。目…

nodemcu32s 和 mini D1 组局域网并用 webSocket 通信

实现思路 使用 mini D1 来搭建一个 webSocket 服务&#xff0c;然后使用 nodemcu32 连接&#xff0c;然后就可以进行通信了。 服务端代码&#xff08;mini D1&#xff09; 在代码中主要是需要控制好 loop 函数中的延时&#xff0c;也就是最后一行代码 delay&#xff0c;如果…