通過自定義注解加aop切面實現權限控制

前言:自定義注解,通過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;從而將時間復雜度優化至接近線性。 莫…