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

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 结果

在这里插入图片描述

完结!!!

相关文章:

  • 使用WebSocket实现跨多个服务器传输音频及实时语音识别
  • spark和hadoop之间的区别和联系
  • 以项目的方式学QT开发(一)
  • VisionPro斑点寻找工具Blob
  • MyBatis:从入门到深度理解
  • 深度解析 IDEA 集成 Continue 插件:提升开发效率的全流程指南
  • 【python基础知识】Day26 函数
  • Yeoman实战指南:从零打造自定义项目生成器
  • 人工智能100问☞第23问:卷积神经网络(CNN)为何擅长图像处理?
  • 最新网盘资源搜索系统,电视直播,Alist聚合播放
  • QMK固件OLED显示屏配置教程:从零开始实现个性化键盘显示(实操部分)
  • DevExpressWinForms-TreeList-数据绑定
  • 如何在Edge浏览器里-安装梦精灵AI提示词管理工具
  • OrangePi Zero 3学习笔记(Android篇)10 - SPI和从设备
  • 二程运输的干散货船路径优化
  • 2025年山东省数学建模F题思路
  • 精益数据分析(61/126):移情阶段评分体系构建与实战案例解析
  • MySQL 用户权限管理:从入门到精通
  • 2025年5月-信息系统项目管理师高级-软考高项-成本计算题
  • WebSocket:实时通信(如聊天应用)从零到一的深度解析
  • 武大校长:人工智能不存在“过度使用”,武大不会缩减文科
  • 新片|《碟中谍8:最终清算》定档5月30日
  • 人民网三评“网络烂梗”:莫让低级趣味围猎青少年
  • 佩斯科夫:俄方代表团15日将在伊斯坦布尔等候乌克兰代表团
  • 白玉兰奖征片综述丨动画的IP生命力
  • 中国巴西民间推动建立经第三方验证的“森林友好型”牛肉供应链