当前位置: 首页 > backend >正文

springboot AOP中,通过解析SpEL 表达式动态获取参数值

切面注解

import com.bn.document.constants.FmDeptCatalogueConstants;import java.lang.annotation.*;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FmDeptCatalogueAopAnnotation {/*** 权限类型*/FmDeptCatalogueConstants value();/*** 目录id*/String catalogueId() ;
}

切面类 (整个类) 重点代码在下面

package com.bn.document.aop;import com.bn.document.constants.FmDeptCatalogueConstants;
import com.bn.document.po.FmDeptCataloguePo;
import com.bn.document.po.LoginUser;
import com.bn.document.service.FmDeptCatalogueService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.util.List;@Aspect
@Component
public class MyAspect {private final ExpressionParser parser = new SpelExpressionParser();private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();@Autowiredprivate FmDeptCatalogueService fmDeptCatalogueService;/*** 定义切入点:拦截带有 @MyCustomAnnotation 的方法*/@Pointcut("@annotation(com.bn.document.aop.FmDeptCatalogueAopAnnotation)")public void cataloguePointcut() {}/*** 环绕增强:获取注解中的权限类型,检查用户权限*/@Around("cataloguePointcut()")public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {// 获取方法上的注解FmDeptCatalogueAopAnnotation annotation = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(FmDeptCatalogueAopAnnotation.class);if (annotation == null) {return joinPoint.proceed(); // 没有注解直接放行}// 获取权限类型FmDeptCatalogueConstants permissionType = annotation.value();// 获取方法参数值Object[] args = joinPoint.getArgs();LoginUser loginUser = null;// 遍历参数列表,提取 LoginUser 和 catalogueIdfor (Object arg : args) {if (arg instanceof LoginUser) {loginUser = (LoginUser) arg;}}// 开始解析  SpEL 表达式MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();// 获取方法参数名 + 参数值,用于构建 SpEL 上下文String[] paramNames = parameterNameDiscoverer.getParameterNames(method);// 构建 EvaluationContext,并绑定参数EvaluationContext context = new StandardEvaluationContext();if (paramNames != null && args.length > 0) {for (int i = 0; i < paramNames.length; i++) {context.setVariable(paramNames[i], args[i]); // 绑定参数}}// 解析表达式中的目录IDString catalogueIdExpr = annotation.catalogueId();Long catalogueId = parser.parseExpression(catalogueIdExpr).getValue(context, Long.class);// 判断参数是否为空if (loginUser == null || loginUser.getDeptId() == null) {throw new SecurityException("登录信息错误");}if (catalogueId == null || catalogueId <= 0) {throw new SecurityException("目录ID不能为空");}// 调用服务层查询权限List<FmDeptCataloguePo> result = fmDeptCatalogueService.getFmDeptCataloguePoWithDeptId(loginUser.getDeptId(),catalogueId,permissionType);// 如果权限不存在if (result == null || result.isEmpty()) {throw new SecurityException("您没有【" + permissionType.getDes() + "】权限");}// 否则放行return joinPoint.proceed();}}

重点【开始解析 SpEL 表达式】

// 开始解析  SpEL 表达式MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();// 获取方法参数名 + 参数值,用于构建 SpEL 上下文String[] paramNames = parameterNameDiscoverer.getParameterNames(method);// 构建 EvaluationContext,并绑定参数EvaluationContext context = new StandardEvaluationContext();if (paramNames != null && args.length > 0) {for (int i = 0; i < paramNames.length; i++) {context.setVariable(paramNames[i], args[i]); // 绑定参数}}// 解析表达式中的目录IDString catalogueIdExpr = annotation.catalogueId();Long catalogueId = parser.parseExpression(catalogueIdExpr).getValue(context, Long.class);

使用

1.获取对象中的属性值

 @Override@Transactional(rollbackFor = Exception.class)@FmDeptCatalogueAopAnnotation(value = FmDeptCatalogueConstants.MODIFY_PERMISSION, catalogueId = "#sysFileCataloguePo.parentId")public CommonResponse insertSub(SysFileCataloguePo sysFileCataloguePo,LoginUser loginUser) {
}

1.1 结果

在这里插入图片描述

2.直接取值

 @Override@FmDeptCatalogueAopAnnotation(value = FmDeptCatalogueConstants.DETAILS_PERMISSION, catalogueId = "#id")public CommonResponse getSub(Long id,  LoginUser loginUser) {}

2.1 结果

在这里插入图片描述

完结!!!

http://www.xdnf.cn/news/6519.html

相关文章:

  • 第二十五天打卡
  • GUI图形化演示
  • 【测试】用例篇
  • 免疫浸润分析
  • 哲学物理:太极图和莫比乌斯环有什么关系?
  • 【QT 项目部署指南】使用 Inno Setup 打包 QT 程序为安装包(超详细图文教程)
  • Vue3的基础知识
  • 【skywalking】index“:“skywalking_metrics-all“},“status“:404}
  • Ansys Zemax | 在 MATLAB 或 Python 中使用 ZOS-API 进行光线追迹的批次处理
  • TASK02【Datawhale 组队学习】使用 LLM API 开发应用
  • javascript —— ! 和 !! 的区别与作用
  • 傻子学编程之——数据库如何性能优化
  • 西瓜书【机器学习(周志华)】目录
  • [网络升级指南] 服务器网卡/带宽如何选?1GbE vs 10GbE vs 25GbE+ 性能与成本深度解析 (2025)
  • 香山新篇:海淀低密奢居的典范之作
  • 今日行情明日机会——20250515
  • OpenShift AI - 用 ModelCar 构建容器化模型,提升模型弹性扩展速度
  • 冲刺软考:做减法,走出备考迷茫,高效提分!
  • 学习C++的好书:C++编程之禅
  • Spring类
  • 基于WinCC flexible 2008、STEP_7和博途之间的项目移植
  • rsync入门笔记
  • 【Redis】压缩列表
  • 打破传统束缚:Captiks 无线惯性动捕与步态分析系统如何重新定义运动测量?
  • 【内含文档PPT】基于SSM框架的智能交通信息管理系统
  • day21-线性表(链表III)
  • 网络爬虫学习之httpx的使用
  • 函数专题1
  • 【大模型面试每日一题】Day 19:如何设计自动化评估框架验证大模型的多步推理能力(如数学解题)?
  • 使用Python与正则表达式高效提取Excel中的票号数据