動態

詳情 返回 返回

【Spring開發】SpringCloud交友項目實戰第6篇:3. 統一token處理【附代碼文檔】 - 動態 詳情

🏆🏆🏆教程全知識點簡介:1、Dubbo的前世今生 1、項目介紹 1.1、項目背景 1.2、市場分析 1.3、目標用户羣體 1.4、使用場景 1.5、競爭對手分析 1.7、技術方案 2、前後端分離開發思想 3、開發工具與環境搭建 3.1、開發工具 3.2、環境搭建 4、sms_code驗證瑪 4.1 阿里雲短信 4.2 自動裝配 1. 完善用户信息 1.2 百度人臉識別 1.2.1 概述 1.2.2 賬號申請 1.2.4 抽取模板工具 2.2 更新用户資料 2.2.1 接口文檔 2.2.2 代碼實現 3. 統一token處理 3.1.需求分析 3.2 解決方案 攔截器(Interceptor) ThreadLocal MongoDB入門 數據庫以及表的操作 新增數據 更新數據 刪除數據 查詢數據 1.3 設置陌生人問題 1.4 通知設置 1.5 黑名單管理 4. SpringData-Mongo 4.2 完成基本操作 5. 今日佳人 5.1 表結構設計 5.2 服務提供者 5.2.0 導入依賴 5.2.2 RecommendUserApi接口 分片集羣 原理介紹 集羣搭建 2、圈子功能 2.1、功能説明 3、圈子實現 3.2、發佈動態 1. 動態查詢 1.1 查詢好友動態 2. 圈子互動 2.3 動態點贊 2.4.3 喜歡標識 安裝 準備 使用 1. 即時通信 2. 環信 2.1 開發簡介 2.2 環信Console 2.3 環信API介紹 初始化 基礎API 3. 抽取環信組件 3.1 編寫Properties對象 3.2 編寫HuanXinTemplate 3.3 編寫自動配置類 2. MongoDB地理位置檢索 2.1 地理位置索引 Point LineString Polygon 2.2 案例 3. 上報地理位置 4. 搜附近 1. 我的訪客 1.2 記錄訪客數據 tanhua-model tanhua-app-server tanhua-dubbo-interface 1.3 首頁誰看過我 需求分析 3. FastDFS 3.2. 工作原理 3.2.1. 文件的上傳 分佈式文件系統FDFS配置 4. 發佈小視頻 1、用户凍結解凍 1.1 用户凍結 1.3 查詢數據列表 1.4 明日系統修改 2.2 定時任務 3、內容審核 1、瞭解推薦系統 1.1、什麼是推薦系統? 1.3、推薦系統業務流程 1.4、協同過濾推薦算法 1.5、ALS算法 2、好友推薦 2.1、流程 2.2、部署好友推薦服務

<!-- start:bj1 -->

📚📚👉👉👉git倉庫code.zip 直接get:   https://gitlab.com/yiqing112/backend/-/blob/main/Spring/Sprin...    🍅🍅

<!-- end:bj1 -->

✨ 本教程項目亮點

🧠 知識體系完整:覆蓋從基礎原理、核心方法到高階應用的全流程內容
💻 全技術鏈覆蓋:完整前後端技術棧,涵蓋開發必備技能
🚀 從零到實戰:適合 0 基礎入門到提升,循序漸進掌握核心能力
📚 豐富文檔與代碼示例:涵蓋多種場景,可運行、可複用
🛠 工作與學習雙參考:不僅適合系統化學習,更可作為日常開發中的查閲手冊
🧩 模塊化知識結構:按知識點分章節,便於快速定位和複習
📈 長期可用的技術積累:不止一次學習,而是能伴隨工作與項目長期參考

🎯🎯🎯全教程總章節


🚀🚀🚀本篇主要內容

3. 統一token處理

3.1.需求分析

代碼存在如下問題:

  • 重複性的登錄驗證

    ​ 通過SpringMVC攔截器進行登錄校驗

  • 繁瑣的token獲取及解析

    ​ 通過SpringMVC攔截器解析token

    ​ 將解析對象存入ThreadLocal

3.2 解決方案

基於ThreadLocal + 攔截器的形式統一處理

攔截器(Interceptor)

  • 是一種動態攔截方法調用的機制;
  • 類似於Servlet 開發中的過濾器Filter,用於對處理器進行前置處理和後置處理。

ThreadLocal

  • 線程內部的存儲類,賦予了線程存儲數據的能力。
  • 線程內調用的方法都可以從ThreadLocal中獲取同一個對象。
  • 多個線程中ThreadLocal數據相互隔離

3.3 代碼實現

3.3.1 ThreadLocal工具類

定義ThreadLocal工具類,僅需要調用set方法即可將數據存入ThreadLocal中

Spring Boot API 文檔

package com.tanhua.server.interceptor;

import com.tanhua.model.domain.User;

/**
 * @author Administrator
 */
public class UserHolder {

    private static ThreadLocal<User> tl = new ThreadLocal<User>();

    /**
     * 保存數據到線程
     */
    public static void set(User user) {
        tl.set(user);
    }

    /**
     * 獲取線程中的用户信息
     */
    public static User get() {
        return tl.get();
    }


    /**
     * 從當前線程,獲取用户對象的id
     */
    public static Long getUserId() {
        if (tl.get() == null) {
            return null;
        }
        return tl.get().getId();
    }

    /**
     * 從當前線程,獲取用户對象的手機號碼
     */
    public static String getMobile() {
        if (tl.get() == null) {
            return null;
        }
        return tl.get().getMobile();
    }

     /**
     * 移除線程中數據
     */
    public static void remove() {
        tl.remove();
    }
}

3.3.2 定義攔截器

定義攔截器,在前置攔截方法preHandle中解析token並驗證有效性,如果失效返回狀態碼401。如果有效,解析User對象,存入ThreadLocal中

Swagger/OpenAPI

Maven 生命週期

package com.tanhua.server.interceptor;

import com.tanhua.model.domain.User;
import com.tanhua.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwt;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author Administrator
 */
public class TokenInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //1、獲取請求頭
        String token = request.getHeader("Authorization");

        //2、使用工具類,判斷token是否有效
        boolean verifyToken = JwtUtils.verifyToken(token);
        //3、如果token失效,返回狀態碼401,攔截
        if(!verifyToken) {
            response.setStatus(401);
            return false;
        }
        //4、如果token正常可用,放行
        //解析token,獲取id和手機號碼,
        Claims claims = JwtUtils.getClaims(token);
        String mobile = (String) claims.get("mobile");
        Integer id = (Integer) claims.get("id");
        
        //構造User對象,存入Threadlocal
        User user = new User();
        user.setId(Long.valueOf(id));
        user.setMobile(mobile);

        UserHolder.set(user);

        return true;
    }
    
    //清空
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserHolder.re

# 4. 統一異常處理

軟件開發過程中,不可避免的是需要處理各種異常,常見的形式就是逐層向上拋出,web層進行處理。使用try {...} catch {...}很方便就能對異常做到業務處理

1. 冗餘代碼多,影響代碼可讀性
2. 異常處理和業務代碼耦合

## 4.1 概述

前後兩端數據響應的定義:

* 狀態碼:200
  * 正常執行,解析響應數據

* 狀態碼:500
  * 拋出異常或業務錯誤,解析響應數據中的errCode和errMessage

* 狀態碼:401
  * 權限不足,手機端會自動跳轉登錄

SpringMVC提供了一套解決全局異常的處理方案,可以在代碼無侵入的前提下完成異常處理。遵循逐層拋出,異常處理器統一處理的思路

![](/img/bVdmobR)

## 4.2 基礎代碼

項目中可能存在不可預知的各種異常,如:空指針,數組越界等。針對這類異常,可以直接在異常處理器中統一處理;

還有一類是可預知的錯誤,如圖片不合法,錯誤等等。這類錯誤也可以理解為業務異常,可以通過自定義異常類來處理;

### 4.2.1業務異常對象

為了方便操作,將一些常見的業務錯誤封裝到ErrorResult對象中

Gson 文檔

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ErrorResult {

private String errCode;
private String errMessage;

public static ErrorResult error() {
    return ErrorResult.builder().errCode("999999").errMessage("系統異常稍後再試").build();
}

public static ErrorResult fail() {
    return ErrorResult.builder().errCode("000001").errMessage("發送失敗").build();
}

public static ErrorResult loginError() {
    return ErrorResult.builder().errCode("000002").errMessage("失效").build();
}

public static ErrorResult faceError() {
    return ErrorResult.builder().errCode("000003").errMessage("圖片非人像,請重新上傳!").build();
}

public static ErrorResult mobileError() {
    return ErrorResult.builder().errCode("000004").errMessage("手機號碼已註冊").build();
}

public static ErrorResult contentError() {
    return ErrorResult.builder().errCode("000005").errMessage("動態內容為空").build();
}

public static ErrorResult likeError() {
    return ErrorResult.builder().errCode("000006").errMessage("用户已點贊").build();
}

public static ErrorResult disLikeError() {
    return ErrorResult.builder().errCode("000007").errMessage("用户未點贊").build();
}

public static ErrorResult loveError() {
    return ErrorResult.builder().errCode("000008").errMessage("用户已喜歡").build();
}

public static ErrorResult disloveError() {
    return ErrorResult.builder().errCode("000009").errMessage("用户未喜歡").build();
}

}


### 4.2.2 業務異常類

自定義業務異常類,針對業務錯誤之間拋出業務異常即可

/**

  • 自定義異常類
    */

@Data
public class BusinessException extends RuntimeException {

private ErrorResult errorResult;

public BusinessException(ErrorResult errorResult) {
    super(errorResult.getErrMessage());
    this.errorResult = errorResult;
}

}


## 4.3.統一異常處理

軟件開發過程中,不可避免的是需要處理各種異常,對程序員來説,至少有一半以上的時間都是在處理各種異常情況,所以代碼中就會出現大量的`try {...} catch {...} finally {...}` 代碼塊,不僅有大量的冗餘代碼,而且還影響代碼的可讀性。`Spring`在3.2版本增加了一個註解`@ControllerAdvice`,可以與`@ExceptionHandler`註解配套使用,已異常處理器的形式簡化異常配置

在tanhua-server工程定義統一異常處理類ExceptionAdvice

* 定義java類
* 定義方法(和controller中方法一樣)
* 類上配置註解@ControllerAdvice
* 方法上配置註解@ExceptionAdvice(處理的異常類型)

Tomcat JDBC Pool

/**

  • 自定義統一異常處理
  • 1、通過註解,聲明異常處理類
  • 2、編寫方法,在方法內部處理異常,構造響應數據
  • 3、方法上編寫註解,指定此方法可以處理的異常類型
    */

@ControllerAdvice
public class ExceptionAdvice {

//處理業務異常
@Excep

Add a new 評論

Some HTML is okay.