最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot基于攔截器與ThreadLocal實現(xiàn)用戶登錄校驗

 更新時間:2025年12月10日 08:34:12   作者:ShaneD771  
本文介紹了一種在SpringBoot中實現(xiàn)統(tǒng)一登錄校驗和上下文共享的解決方案,通過使用攔截器、ThreadLocal和自定義工具類,實現(xiàn)了在請求處理過程中優(yōu)雅地獲取當(dāng)前登錄用戶信息,并且避免了在每個Controller方法中重復(fù)編寫校驗代碼,需要的朋友可以參考下

1. 背景與問題

在無狀態(tài)的 HTTP 協(xié)議下,Web 應(yīng)用通常使用 SessionToken 機制來維持用戶的登錄狀態(tài)。在 Spring Boot 后端開發(fā)中,面臨兩個核心問題:

  1. 統(tǒng)一校驗:如何在請求到達(dá)業(yè)務(wù)邏輯之前,統(tǒng)一攔截未登錄請求,避免在每個 Controller 方法中重復(fù)編寫校驗代碼?
  2. 上下文共享:在 Controller、Service 甚至 Dao 層中,如何優(yōu)雅地獲取當(dāng)前登錄用戶的信息,而不需要層層傳遞 User 對象參數(shù)?

這里介紹登錄 + 攔截器 (Interceptor) + 線程本地變量 (ThreadLocal)”

2. 架構(gòu)設(shè)計

該方案的流程如下:

  1. 登錄接口:負(fù)責(zé)認(rèn)證身份,并將用戶信息存入 HttpSession。
  2. 攔截器 (preHandle):在請求進(jìn)入 Controller 之前攔截。校驗 Session 中是否存在用戶信息。
    • 若存在:將用戶信息讀取并存入當(dāng)前線程的 ThreadLocal 中,放行。
    • 若不存在:攔截請求,返回 401 狀態(tài)碼。
  3. 業(yè)務(wù)層 (Controller/Service):需要用戶信息時,直接從 ThreadLocal 中獲取,無需依賴 Session API。
  4. 攔截器 (afterCompletion):請求結(jié)束,響應(yīng)返回前,移除 ThreadLocal 中的用戶信息,防止內(nèi)存泄漏。

3. 代碼實現(xiàn)步驟

3.1 封裝 ThreadLocal 工具類 (UserHolder)

為了在同一線程內(nèi)共享數(shù)據(jù),我們需要封裝一個基于 ThreadLocal 的工具類。它充當(dāng)了線程內(nèi)全局容器的角色。

public class UserHolder {
    // 使用 ThreadLocal 保存用戶信息,UserDTO 為脫敏后的用戶對象
    private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>();

    // 保存用戶
    public static void saveUser(UserDTO user){
        tl.set(user);
    }

    // 獲取用戶
    public static UserDTO getUser(){
        return tl.get();
    }

    // 移除用戶(防止內(nèi)存泄漏的關(guān)鍵)
    public static void removeUser(){
        tl.remove();
    }
}

3.2 自定義登錄攔截器 (LoginInterceptor)

攔截器實現(xiàn) HandlerInterceptor 接口,負(fù)責(zé)“校驗”和“上下文傳遞”。

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 1. 獲取 Session
        HttpSession session = request.getSession();
        
        // 2. 獲取 Session 中的用戶
        Object user = session.getAttribute("user");
        
        // 3. 校驗用戶是否存在
        if (user == null) {
            // 4. 不存在,攔截,設(shè)置狀態(tài)碼 401 (未授權(quán))
            response.setStatus(401);
            return false;
        }
        
        // 5. 存在,將用戶信息保存到 ThreadLocal
        // 這一步實現(xiàn)了從 Web 層 (Session) 到 業(yè)務(wù)層 (ThreadLocal) 的狀態(tài)轉(zhuǎn)移
        UserHolder.saveUser((UserDTO) user);
        
        // 6. 放行
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 7. 必須移除用戶,避免線程池復(fù)用導(dǎo)致的“數(shù)據(jù)串號”和內(nèi)存泄漏
        UserHolder.removeUser();
    }
}

3.3 注冊攔截器 (MvcConfig)

通過實現(xiàn) WebMvcConfigurer 接口,將自定義攔截器注冊到 Spring MVC 的攔截鏈中,并配置攔截路徑。

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .excludePathPatterns(
                        "/user/code",   // 發(fā)送驗證碼
                        "/user/login",  // 登錄接口
                        "/blog/hot",    // 熱門博客
                        "/shop/**",     // 店鋪詳情
                        "/shop-type/**" // 店鋪類型
                ).order(1);
    }
}

3.4 業(yè)務(wù)層獲取用戶信息 (/user/me)

在 Controller 中,我們不再需要操作 HttpSessionHttpServletRequest,直接調(diào)用 UserHolder 即可。

@GetMapping("/me")
public Result me(){
    // 直接從 ThreadLocal 獲取當(dāng)前請求關(guān)聯(lián)的用戶信息
    UserDTO user = UserHolder.getUser();
    return Result.ok(user);
}

4. 組件關(guān)系

這套機制中,各組件的職責(zé)與關(guān)系如下:

4.1 攔截器 (Interceptor) 與 Session 的關(guān)系

  • 關(guān)系讀取者與存儲者。
  • 解析:Session 是由 Tomcat 容器管理的服務(wù)器內(nèi)存存儲。攔截器作為請求處理的第一道關(guān)卡,負(fù)責(zé)從 Session 中讀取狀態(tài)。攔截器并不產(chǎn)生用戶數(shù)據(jù),它只是校驗 Session 中是否已由登錄接口寫入了數(shù)據(jù)。

4.2 攔截器 (Interceptor) 與 ThreadLocal 的關(guān)系

  • 關(guān)系生產(chǎn)者與容器。
  • 解析:這是本架構(gòu)最精妙的地方。攔截器在 preHandle 階段充當(dāng)“搬運工”,將 Session 中的數(shù)據(jù)(Web 作用域)復(fù)制到 ThreadLocal(線程作用域)。這使得后續(xù)的 Service 層代碼可以完全脫離 javax.servlet API,實現(xiàn)了業(yè)務(wù)邏輯與 Web 容器的解耦。

4.3 Controller/Service 與 ThreadLocal 的關(guān)系

  • 關(guān)系消費者與容器。
  • 解析:Controller 或 Service 層完全不需要知道攔截器的存在,也不需要知道數(shù)據(jù)是從 Session 來的還是 Token 來的。它們只需要信任 UserHolder,認(rèn)為“只要代碼執(zhí)行到這里,UserHolder 里一定有當(dāng)前用戶”,從而簡化了代碼邏輯。

5. 總結(jié)

實現(xiàn)這套登錄校驗攔截機制,本質(zhì)上是為了解決兩個工程化問題:

  1. 安全性(Secur11ity):通過攔截器實現(xiàn)統(tǒng)一的權(quán)限控制,防止未登錄用戶訪問受保護(hù)資源。
  2. 代碼解耦(Decoupling):利用 ThreadLocal 替代參數(shù)傳遞,使得用戶信息可以在同一請求線程的任意位置被訪問,極大地提高了代碼的可維護(hù)性。

在后續(xù)的分布式演進(jìn)中(如引入 Redis),我們只需要修改 登錄接口(存 Redis)攔截器(查 Redis) 的邏輯,而業(yè)務(wù)層獲取用戶信息的代碼(UserHolder.getUser())完全不需要改動,這體現(xiàn)了良好的架構(gòu)擴(kuò)展性。

以上就是SpringBoot基于攔截器與ThreadLocal實現(xiàn)用戶登錄校驗的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot用戶登錄校驗的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于@ComponentScan注解及其XML配置方式

    基于@ComponentScan注解及其XML配置方式

    這篇文章主要介紹了基于@ComponentScan注解及其XML配置方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 一個簡單的Java文件讀取的進(jìn)度條

    一個簡單的Java文件讀取的進(jìn)度條

    這篇文章主要介紹了一個簡單的Java文件讀取的進(jìn)度條,寫一個可以使用的?demo,涉及到了文件的相對路徑問題,需要的朋友可以參考下
    2023-04-04
  • 一文綜合對比分析JDK?8、JDK?17和JDK?19

    一文綜合對比分析JDK?8、JDK?17和JDK?19

    Java是一門非常流行的編程語言,由于其跨平臺性、可移植性以及強大的面向?qū)ο筇匦远鴤涫芮嗖A,這篇文章主要介紹了JDK?8、JDK?17和JDK?19綜合對比分析的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考下
    2026-01-01
  • SpringBoot自定義bean綁定實現(xiàn)

    SpringBoot自定義bean綁定實現(xiàn)

    這篇文章主要介紹了SpringBoot自定義bean綁定,最常見的配置綁定的場景,是在自定義的bean中通過@Value注解將某個屬性和對應(yīng)的配置綁定
    2022-10-10
  • 關(guān)于Struts2文件上傳與自定義攔截器

    關(guān)于Struts2文件上傳與自定義攔截器

    本篇文章,小編將為大家介紹關(guān)于Struts2文件上傳與自定義攔截器,有需要的朋友可以參考一下
    2013-04-04
  • java 生成二維碼實例

    java 生成二維碼實例

    這篇文章主要介紹了java 生成二維碼的實例,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • java創(chuàng)建txt文件并寫入內(nèi)容的方法代碼示例

    java創(chuàng)建txt文件并寫入內(nèi)容的方法代碼示例

    這篇文章主要介紹了java創(chuàng)建txt文件并寫入內(nèi)容的兩種方法,分別是使用java.io.FileWriter和BufferedWriter,以及使用Java7的java.nio.file包中的Files和Path類,需要的朋友可以參考下
    2025-01-01
  • java中的equals()和toString()方法實例詳解

    java中的equals()和toString()方法實例詳解

    這篇文章主要介紹了java中的equals()和toString()方法實例詳解的相關(guān)資料,這里舉例說明,并附實例代碼,和實現(xiàn)效果圖,需要的朋友可以參考下
    2016-11-11
  • Java中的幾種讀取properties配置文件的方式

    Java中的幾種讀取properties配置文件的方式

    這篇文章主要介紹了Java中的幾種讀取properties配置文件的方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • mybatis 根據(jù)id批量刪除的實現(xiàn)操作

    mybatis 根據(jù)id批量刪除的實現(xiàn)操作

    這篇文章主要介紹了mybatis 根據(jù)id批量刪除的實現(xiàn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08

最新評論

锦屏县| 内黄县| 兰西县| 云南省| 托克逊县| 上高县| 天全县| 封开县| 社旗县| 蕉岭县| 来安县| 万荣县| 辽阳县| 巴里| 新民市| 任丘市| 汽车| 宁陕县| 万源市| 白山市| 北辰区| 米易县| 内黄县| 囊谦县| 金川县| 上饶县| 繁峙县| 北海市| 准格尔旗| 顺平县| 孝昌县| 敦化市| 兰州市| 应城市| 梁河县| 大城县| 富宁县| 丽水市| 临沭县| 册亨县| 甘肃省|