前言:自定义注解,通过aop切面前置通知,对请求接口进行权限控制

1,创建枚举类

package org.springblade.sample.annotationCommon;import lombok.AllArgsConstructor;
import lombok.Getter;import java.util.Arrays;
import java.util.Optional;/*** @Title: PermissionAnnotationEnum* @Author it—xtm* @Package AnnotationCommon* @Date 2025/8/5 21:21* @description: 权限枚举类,定义系统中常用的权限控制类型*/
@Getter
@AllArgsConstructor
public enum PermissionAnnotationEnum {/*** 全部权限:可以查看所有数据*/ALL(1, "全部数据可见"),/*** 仅本人可见:只能查看自己创建的数据*/OWN(2, "仅本人可见"),/*** 本部门可见:只能查看本部门数据*/OWN_DEPT(3, "所在机构可见"),/*** 本部门及子部门可见*/OWN_DEPT_CHILD(4, "所在机构及子级机构可见"),/*** 自定义权限:根据自定义条件过滤数据*/CUSTOM(5, "自定义权限范围"),/*** 无权限:不能查看任何数据*/NONE(6, "无权限访问");/*** 权限类型编码*/private final Integer type;/*** 权限描述*/private final String description;/*** 根据类型编码获取枚举实例** @param type 权限类型编码* @return 对应的枚举实例,若不存在则返回空*/public static PermissionAnnotationEnum getByType(Integer type) {if (type == null) {return null;}return Arrays.stream(values()).filter(enumItem -> enumItem.getType().equals(type)).findFirst().orElse(null);}}

2,创建注解

package org.springblade.sample.annotationCommon;import java.lang.annotation.*;
/*** @Title: PermissionAnnotationEnum* @Author it—xtm* @Package AnnotationCommon* @Date 2025/8/5 21:21* @description: 权限注解*/@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited // 允许注解被子类继承
@Documented // 生成JavaDoc时会包含该注解说明
public @interface PermissionAnnotation {PermissionAnnotationEnum type() default PermissionAnnotationEnum.ALL; //权限 类型String[] menuValue();// 需要的菜单编号标识String apiValue();// 需要的api标识boolean isIgnoreRole() default false;// 是否忽略String[] ignoreRoleValue() default {"administrator", "admin"}; //管理员直接忽略}

3,创建切面

package org.springblade.sample.annotationCommon;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;import java.util.Arrays;/*** @Title: AnnotationCommon.AnnotationAspect* @Author it-xtm* @Package PACKAGE_NAME* @Date 2025/8/5 21:45* @description: 权限注解切面,包含各种通知类型*/
@Aspect
@Component
@Slf4j
public class AnnotationAspect {/*** 方法执行前执行 - 前置通知* @param joinPoint 切入点对象,提供了关于当前执行方法的信息* @param permissionAnnotation 注解对象,包含了注解的属性值*/@Before("@annotation(permissionAnnotation)")public void before(JoinPoint joinPoint, PermissionAnnotation permissionAnnotation) {log.info("===== 前置通知开始 =====");log.info("目标方法: {}.{}",joinPoint.getTarget().getClass().getName(),joinPoint.getSignature().getName());log.info("方法参数:{}", Arrays.toString(permissionAnnotation.menuValue()));log.info("方法参数:{}", permissionAnnotation.type());log.info("方法参数:{}", permissionAnnotation.apiValue());log.info("方法参数:{}", Arrays.toString(permissionAnnotation.ignoreRoleValue()));log.info("方法参数:{}", permissionAnnotation.isIgnoreRole());log.info("方法参数:{}", permissionAnnotation.type().getType());log.info("方法参数:{}", permissionAnnotation.type().getDescription());log.info("方法参数:{}", PermissionAnnotationEnum.getByType(permissionAnnotation.type().getType()).getDescription());log.info("===== 前置通知结束 =====");}/*** 环绕通知 - 可以控制目标方法的执行* @param proceedingJoinPoint 可执行的切入点对象* @param permissionAnnotation 注解对象* @return 目标方法的返回值* @throws Throwable 可能抛出的异常*/@Around("@annotation(permissionAnnotation)")public Object around(ProceedingJoinPoint proceedingJoinPoint, PermissionAnnotation permissionAnnotation) throws Throwable {log.info("===== 环绕通知开始 =====");log.info("环绕通知 - 执行目标方法前");// 可以在这里进行权限验证等逻辑boolean hasPermission = checkPermission(permissionAnnotation);if (!hasPermission) {log.warn("权限不足,无法执行方法: {}", proceedingJoinPoint.getSignature().getName());throw new SecurityException("没有执行该操作的权限");}// 执行目标方法long startTime = System.currentTimeMillis();Object result = proceedingJoinPoint.proceed(); // 执行目标方法long endTime = System.currentTimeMillis();log.info("环绕通知 - 执行目标方法后");log.info("方法执行耗时: {}ms", (endTime - startTime));log.info("===== 环绕通知结束 =====");return result;}/*** 后置通知 - 无论方法是否正常执行都会执行* @param joinPoint 切入点对象* @param permissionAnnotation 注解对象*/@After("@annotation(permissionAnnotation)")public void after(JoinPoint joinPoint, PermissionAnnotation permissionAnnotation) {log.info("===== 后置通知开始 =====");log.info("目标方法: {}.{} 执行完成",joinPoint.getTarget().getClass().getName(),joinPoint.getSignature().getName());log.info("清理资源或记录日志等操作");log.info("===== 后置通知结束 =====");}/*** 返回后通知 - 方法正常返回后执行* @param joinPoint 切入点对象* @param permissionAnnotation 注解对象* @param result 方法返回值*/@AfterReturning(pointcut = "@annotation(permissionAnnotation)", returning = "result")public void afterReturning(JoinPoint joinPoint, PermissionAnnotation permissionAnnotation, Object result) {log.info("===== 返回后通知开始 =====");log.info("目标方法: {}.{} 正常返回",joinPoint.getTarget().getClass().getName(),joinPoint.getSignature().getName());log.info("方法返回值: {}", result);log.info("可以在这里处理返回结果");log.info("===== 返回后通知结束 =====");}/*** 异常通知 - 方法抛出异常时执行* @param joinPoint 切入点对象* @param permissionAnnotation 注解对象* @param ex 抛出的异常*/@AfterThrowing(pointcut = "@annotation(permissionAnnotation)", throwing = "ex")public void afterThrowing(JoinPoint joinPoint, PermissionAnnotation permissionAnnotation, Exception ex) {log.error("===== 异常通知开始 =====", ex);log.error("目标方法: {}.{} 抛出异常",joinPoint.getTarget().getClass().getName(),joinPoint.getSignature().getName());log.error("异常信息: {}", ex.getMessage());log.error("可以在这里记录异常日志或进行异常处理");log.error("===== 异常通知结束 =====");}/*** 权限检查逻辑* @param permissionAnnotation 权限注解* @return 是否有权限*/private boolean checkPermission(PermissionAnnotation permissionAnnotation) {// 实际应用中这里应该实现真实的权限检查逻辑log.info("执行权限检查: {}", permissionAnnotation.apiValue());// 简单示例:默认有权限return true;}
}

4,实现示例

	@GetMapping("/list")@ApiOperationSupport(order = 2)@ApiOperation(value = "分页", notes = "参数")@PermissionAnnotation(menuValue = {"test","test2"}, apiValue = "annotation_test")public R<IPage<>> list() {return R.data(null);}

注:将注解加入接口处进行调用(当接口被调用时,前置通知进行拦截判断权限)

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

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

相关文章

IDS知识点

在网络安全工程师、系统运维工程师等岗位的面试中&#xff0c;​​IDS&#xff08;Intrusion Detection System&#xff0c;入侵检测系统&#xff09;​​ 是高频考点&#xff0c;尤其是对网络安全防护、安全监控类岗位。以下是IDS的核心考点和必须掌握的知识点&#xff0c;按优…

Adobe Analytics 数据分析平台|全渠道客户行为分析与体验优化

Adobe Analytics 是业界领先的数据分析平台&#xff0c;帮助企业实时追踪客户行为&#xff0c;整合多渠道数据&#xff0c;通过强大的分析与可视化工具深入分析客户旅程&#xff0c;优化数字体验。结合 Adobe Experience Cloud&#xff0c;Adobe Analytics 成为推动数字化增长和…

【轮播图】H5端轮播图、横向滑动、划屏效果实现方案——Vue3+CSS position/CSS scroller

文章目录定位实现滑屏效果前置知识CSS: touch-action属性CSS: transform属性触摸事件forEach回调占位符准备阶段实现移动效果实现跟手效果触摸结束优化完整代码滚动实现滑屏效果前置知识CSS: scroll-snap-type属性准备阶段实现滑动效果实现吸附效果滚动条隐藏存在问题完整代码s…

忘记了WordPress管理员密码的找回方法

WordPress管理员密码找回方法 如果您忘记了WordPress管理员密码&#xff0c;可以通过以下几种方法找回或重置&#xff1a; 方法1&#xff1a;通过电子邮件重置(最简单) 访问您的WordPress登录页面(通常是wodepress.com/wp-admin或wodepress.com/wp-login.php) 点击”忘记密…

RAFT:让语言模型更聪明地用文档答题

RAFT&#xff1a;让语言模型更聪明地用文档答题 作者注&#xff1a; 本文旨在面向零基础读者介绍 UC Berkeley 提出的 RAFT&#xff08;Retrieval-Augmented Fine-Tuning&#xff09;方法。它是一种训练语言模型的新方式&#xff0c;让模型更好地利用“外部知识”——比如文档、…

【紧急预警】NVIDIA Triton推理服务器漏洞链可导致RCE!

2025 年 8 月 4 日消息&#xff0c;NVIDIA 旗下的 Triton 推理服务器&#xff08;一款支持 Windows 和 Linux 系统、用于大规模运行 AI 模型的开源平台&#xff09;被曝出一系列安全漏洞。这些漏洞一旦被利用&#xff0c;攻击者有可能完全接管存在漏洞的服务器。 Wiz 安全公司…

基于深度学习的医学图像分析:使用PixelCNN实现医学图像生成

前言 医学图像分析是计算机视觉领域中的一个重要应用&#xff0c;特别是在医学图像生成任务中&#xff0c;深度学习技术已经取得了显著的进展。医学图像生成是指通过深度学习模型生成医学图像&#xff0c;这对于医学研究、疾病模拟和图像增强等任务具有重要意义。近年来&#x…

React ahooks——副作用类hooks之useDebounceFn

useDebounceFn 是 ahooks 提供的用于函数防抖的 Hook&#xff0c;它可以确保一个函数在连续触发时只执行最后一次。一、基本用法import { useDebounceFn } from ahooks; import { Button } from antd;const Demo () > {const { run } useDebounceFn(() > {console.log(…

【机器学习深度学习】 知识蒸馏

目录 前言 一、什么是知识蒸馏&#xff1f; 二、知识蒸馏的核心意义 2.1 降低算力与成本 2.2 加速推理与边缘部署 2.3 推动行业应用落地 2.4 技术自主可控 三、知识蒸馏的本质&#xff1a;大模型的知识传承 四、知识蒸馏的“四重红利” 五、DeepSeek的知识蒸馏实践 …

Python高级编程与实践:Python高级数据结构与编程技巧

高级数据结构&#xff1a;掌握Python中的高效编程技巧 学习目标 通过本课程&#xff0c;学员将深入了解Python中的高级数据结构&#xff0c;包括列表推导式、字典推导式、集合推导式和生成器表达式。学员将学习如何利用这些结构来编写更简洁、更高效的代码&#xff0c;并了解它…

【C++】Stack and Queue and Functor

本文是小编巩固自身而作&#xff0c;如有错误&#xff0c;欢迎指出&#xff01;本次我们介绍STL中的stack和queue和其相关的一些容器和仿函数一.stack and queue1.适配器stack和queue其实不是真正意义上的容器&#xff0c;而是容器适配器&#xff0c;而容器适配器又是什么呢&am…

Python爬虫实战:研究OpenCV技术构建图像数据处理系统

1. 引言 1.1 研究背景 在当今数字化时代,图像作为一种重要的信息载体,广泛存在于各类网站、社交媒体和在线平台中。这些图像数据涵盖了从自然风光、人物肖像到商品展示、新闻事件等丰富内容,为数据分析和模式识别提供了宝贵的资源。随着计算机视觉技术的快速发展,对大规模…

电感矩阵-信号完整性分析

电感矩阵:正如电容矩阵用于存储许多信号路径和返回路径的所有电容量&#xff0c;我们也需要一个矩阵存储许多导线的回路自感和回路互感值。需要牢记的是&#xff0c;这里的电感元件是回路电感。当信号沿传输线传播时&#xff0c;电流回路沿信号路径传输&#xff0c;然后立即从返…

JUC相关知识点总结

Java JUC&#xff08;java.util.concurrent&#xff09;是Java并发编程的核心工具包&#xff0c;提供了丰富的并发工具类和框架。以下是JUC的主要知识点&#xff0c;按难易程度分类&#xff0c;供你参考&#xff1a; 1. 基础概念与工具类 1.1 并发与并行&#xff08;易&#x…

激光频率梳 3D 测量方案革新:攻克光学扫描遮挡,130mm 深孔测量精度达 2um

一、深孔测量的光学遮挡难题在精密制造领域&#xff0c;130mm 级深孔&#xff08;如航空发动机燃油孔、模具冷却孔&#xff09;的 3D 测量长期受困于光学遮挡。传统激光扫描技术依赖直射光束&#xff0c;当深径比超过 10:1 时&#xff0c;孔壁中下部形成大量扫描盲区&#xff0…

clickhouse 中文数据的正则匹配

中文数据的正则匹配 在ClickHouse中,正则匹配通常用于数据的筛选、格式化等操作。以下是一些常用的正则匹配技巧: 1. 匹配中文字符 要匹配中文字符,可以使用以下正则表达式: SELECT * FROM my_table WHERE my_column REGEXP [\\x{4e00}-\\x{9fa5}];这里的 \\x{4e00}-\\…

[驱动开发篇] Can通信进阶 --- CanFD 的三次采样

驱动开发篇] Can通信进阶 --- Can报文的三次采样一、CAN FD的采样次数1.1. 标准规定1.2. 传统标准CAN采样1.3. CAN FD的采样策略1.3.1. 基础采样策略1.4. 配置位置1.5. 常见步骤二、CAN FD与标准CAN在采样机制上的主要区别三、使用建议四. 芯片厂商实现4.1. 实际市面情况4.2. 例…

分布式文件系统06-分布式中间件弹性扩容与rebalance冲平衡

分布式中间件弹性扩容与rebalance冲平衡176_如果宕机的数据节点事后再次重启会发生什么事情&#xff1f;某个之前某个宕机的数据节点DataNode-A又重启后&#xff0c;肯定会再次注册&#xff0c;并进行全量上报的流程&#xff0c;此时&#xff0c;就会导致DataNode-A上的文件副本…

芯祥科技:工业/车规级BMS芯片厂商 规格选型对比

芯祥科技公司专注于工业和车规级BMS芯片&#xff0c;电源芯片及可编程模拟芯片的研发与销售&#xff0c;客户遍及新能源储能&#xff0c;汽车&#xff0c;电脑&#xff0c;服务器及电动工具等领域。并具有创业公司成功经验&#xff0c;平均具有逾17年以上的芯片研发和市场销售经…

莫队基础(Mo‘s algorithm)

莫队算法简介 莫队算法是一种用于高效处理离线区间查询问题的算法&#xff0c;由莫涛&#xff08;Mo Tao&#xff09;在2009年提出。其核心思想是通过对查询区间进行分块和排序&#xff0c;利用前一次查询的结果来减少计算量&#xff0c;从而将时间复杂度优化至接近线性。 莫…