前后端分離下,Spring Boot 請求從發起到響應的完整執行流程

以下是前后端分離架構下,Spring Boot 請求從發起到響應的完整執行流程,結合你提出的所有問題,按真實執行順序和職責鏈條重新整理所有核心概念、結構、關鍵類、數據轉換點和典型代碼示例:


一、前端發起請求(步驟1-2)

關鍵組件:React/Vue + Axios + JSON

axios.get('/api/users', { headers: { Authorization: 'Bearer xxx' } });
  • 不會包含 JSON body(因 GET 請求規范所限)

  • 請求參數以 query param 附帶,如 /api/users?active=true


二、后端接收請求與過濾(步驟3)

關鍵組件:Spring Security Filter Chain

public class JwtAuthenticationFilter extends OncePerRequestFilter {protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {String header = request.getHeader("Authorization");String token = header != null && header.startsWith("Bearer ") ? header.substring(7) : null;if (token != null && jwtUtil.validate(token)) {Authentication auth = jwtUtil.getAuthentication(token);SecurityContextHolder.getContext().setAuthentication(auth);}chain.doFilter(request, response);}
}
  • JWT 驗證只發生在 Filter 中,不會進入 Controller 就已判定是否通過

  • 驗證通過后構造 Authentication 對象放入 SecurityContext


三、DispatcherServlet 分發請求(步驟4)

核心作用:統一接收請求,協調執行鏈

  • DispatcherServlet 并不執行具體處理,只負責流程編排


四、HandlerMapping 確定 Handler(步驟5)

RequestMappingHandlerMapping:匹配@Controller + @RequestMapping 控制器方法
  • 負責查找哪個 Controller 的哪個方法應該處理這個請求

  • 構建好 HandlerExecutionChain(包含攔截器)


五、HandlerAdapter 調用處理器(步驟6)

RequestMappingHandlerAdapter:負責調用注解控制器方法
  • supports(Object handler) 方法確認適配器是否支持此處理器

  • 參數解析、類型轉換、方法調用都由它完成


六、Controller 執行業務分發(步驟7)

@RestController
@RequestMapping("/api/users")
public class UserController {@Autowiredprivate UserService userService;@GetMappingpublic ResponseEntity<List<UserDto>> getUsers() {List<UserDto> list = userService.getAllUsers();return ResponseEntity.ok(list);}
}
  • Controller 不應處理認證邏輯,而是專注于業務與 DTO 構造

  • 使用 ResponseEntity 是為了更靈活控制 HTTP 狀態碼與頭部


七、Service 層執行業務邏輯(步驟8)

@Service
public class UserServiceImpl implements UserService {public List<UserDto> getAllUsers() {List<User> entities = userRepository.findAll();return entities.stream().map(this::toDto).toList();}private UserDto toDto(User user) {return new UserDto(user.getId(), user.getName(), user.getEmail());}
}
  • 接收 Entity 對象 → 轉換為 DTO(數據傳輸對象)

  • 不應返回 ResponseEntity,這保持了關注點分離


八、Repository 訪問數據庫(步驟9-11)

@Repository
public interface UserRepository extends JpaRepository<User, Long> {List<User> findByActiveTrue();
}@Entity
@Table(name = "users")
public class User {@Idprivate Long id;private String name;private String email;
}
  • DAO 實質上是 Repository 接口本身(即 Data Access Object)

  • Entity 是 ORM 框架(JPA/Hibernate)使用的 Java → 表 的映射結構

  • 從數據庫返回的是 Entity 實例,非 DTO,非 DAO


九、響應流程(步驟12-17)

數據返回結構:

步驟返回對象類型
12Repository → ServiceEntity 實體類
13Service → ControllerDTO(如 UserDto)
14Controller → HandlerAdapterResponseEntity 或直接 DTO
15HandlerAdapter → DispatcherServlet包裝為 ModelAndView(內部結構)
17DispatcherServlet → 前端JSON 數據(通過 HttpMessageConverter 序列化)

十、常見問題澄清匯總

?JWT是誰生成的?前端能編輯它嗎?

  • ? 前端不能生成 JWT,必須由后端簽名生成

  • ? JWT 中的 claim 字段(sub/iss/exp)由后端控制

?為什么需要 Authentication?不能直接驗證放行?

  • ? 因為權限注解(如 @PreAuthorize)等依賴 SecurityContextHolder 中的 Authentication 對象

?HandlerMapping vs HandlerAdapter 為什么都要有?

組件功能是否必須
HandlerMapping確定哪個 Controller 處理請求?
HandlerAdapter執行該 Controller 的方法?
  • 二者實現了解耦:DispatcherServlet 不直接依賴 Controller 類型

  • 實際開發可以注冊自定義 Mapping/Adapter

?ResponseEntity vs DTO vs ResponseObject 區別?

類型

定義

用途

DTO

純Java對象,字段只為數據交換

Service 返回給 Controller

ResponseEntity

Spring類,用于封裝響應狀態、頭、體

Controller 返回給框架

自定義 ResponseObject

如 ApiResponse,封裝統一格式

可選嵌入于 ResponseEntity 中

? 不是必須使用 ResponseEntity,直接返回 DTO,Spring 也會自動序列化


建議實踐結構總結

前端請求 → Filter鏈認證(JWT) → DispatcherServlet協調 → HandlerMapping確定Controller
→ HandlerAdapter調用Controller方法 → Controller調用Service → Service調用Repository
→ Repository返回Entity → Service轉換為DTO → Controller包裝為ResponseEntity
→ 返回給前端(JSON)


? 先明確三個概念:

注解

用于

描述

@ExceptionHandler

控制器或異常處理類中的方法

聲明某個方法用來處理特定類型異常

@ControllerAdvice

類級別

用于集中定義所有控制器的全局異常處理

@RestControllerAdvice

@ControllerAdvice + @ResponseBody

自動將返回值作為JSON響應


? 情況分類:異常處理的三個層級

異常發生層

誰處理

示例

Controller層內部異常

當前 Controller 類中的 @ExceptionHandler@ControllerAdvice

請求參數缺失、非法訪問

Service層拋出業務異常

交由 Controller 接收并傳播給 @ControllerAdvice

用戶名重復、余額不足

Repository層拋出數據訪問異常

Service 可以選擇 catch/轉義,也可以上拋

JPA拋出 DataIntegrityViolationException

?1. “用了@ExceptionHandler,為什么還需要@ControllerAdvice?”

  • @ExceptionHandler 是方法級,@ControllerAdvice 是全局級的,集中管理多個Controller的異常處理?。所以兩者不是“互相替代”,而是范圍不同:ControllerAdvice 是容器,ExceptionHandler 是容器里的處理器方法


?2. 那為什么還說“Controller處理Service拋出的異常”?“Controller處理Service異常”指的是:“異常發生于Service層,但由Controller層拋出并觸發了統一異常處理機制”。


? 代碼級舉例(完整調用鏈)

? 1. 自定義異常類:

? 2. Service層拋出異常:

? 3. Controller調用Service:

? 4. 全局異常處理器:

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(UserAlreadyExistsException.class)public ResponseEntity<ApiError> handleUserExists(UserAlreadyExistsException ex) {ApiError error = new ApiError(409, ex.getMessage());return ResponseEntity.status(HttpStatus.CONFLICT).body(error);}@ExceptionHandler(Exception.class)public ResponseEntity<ApiError> handleOther(Exception ex) {ApiError error = new ApiError(500, \"Internal server error\");return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);}
}

? 小結(極簡結論):

問題結論
@ExceptionHandler@ControllerAdvice 沖突嗎?? 不沖突,前者方法級,后者類級,全局異常需要配合使用
Controller是否“處理”Service拋出的異常?? 表面上Controller收到異常,實則由 @ControllerAdvice 捕獲
實際開發該怎么用?? 建議所有 Controller 異常集中交由 @RestControllerAdvice 來統一處理

? 一、前后端通信中的數據結構與序列化處理

?1. 前端發送 GET 請求 /api/users,不做 JSON 清洗嗎?后端收到的是什么?直接處理 JSON 嗎?

  • ? GET 請求不會帶有 JSON 請求體(規范禁止),數據清洗體現在構造 Query 參數(如 /api/users?active=true)。

  • ? 后端不會處理 JSON,而是通過 @RequestParam 解析 URL 查詢參數。

  • ? JSON 序列化只發生在 POST/PUT 請求體響應數據 中。


?2. JSON 序列化 / 反序列化發生在哪一步?DispatcherServlet 負責嗎?

  • ? 反序列化(JSON → Java)發生在 HandlerAdapter 調用 Controller 方法前

  • ? 序列化(Java → JSON)發生在 Controller 方法返回后

  • ? DispatcherServlet 不負責 JSON 處理,它只負責請求轉發。

  • ? JSON 的處理由 HttpMessageConverter(默認使用 Jackson)完成。


? 二、DAO / DTO 的職責與流程中的定位

?3. 什么是 DAO 和 DTO?圖中的第 12~14 步分別返回的是什么?

  • ? DAO(Data Access Object)是用于封裝數據庫訪問邏輯的接口,如 UserRepository extends JpaRepository

  • ? DTO(Data Transfer Object)是前后端或多層之間傳遞數據的載體,如 UserDto

  • 圖中:

    • 第12步:DAO 返回的是實體類(Entity);

    • 第13步:Service 轉換為 DTO,返回給 Controller;

    • 第14步:Controller 使用 ResponseEntity<DTO> 作為響應,框架底層封裝為 ModelAndView


?4. ResponseEntity 和 Model 有什么區別?第 15 步為什么是 ModelAndView?

  • ? ResponseEntity 用于前后端分離,返回完整 JSON 響應;

  • ? Model 是傳統 MVC 模式中用于傳數據給視圖模板的結構;

  • ? ModelAndView 是 Spring MVC 底層用于封裝所有結果的統一結構(即使你返回的是 ResponseEntity,框架也封裝為 ModelAndView(null, body))。

  • ? 前后端分離時,開發者只用 ResponseEntity,無需直接接觸 ModelAndView


? 三、Spring Security 中的 JWT 驗證機制

?5. JWT 驗證流程在 Spring Boot 中是怎樣的?在哪一層?

  • ? JWT 驗證發生在 FilterChain 階段,通常在 OncePerRequestFilter 中實現;

  • ? 驗證步驟:

    • 從請求 Header 獲取 Authorization: Bearer <token>

    • 驗證簽名、結構、過期時間;

    • 解析生成 Authentication

    • 設置到 SecurityContextHolder

    • 放行到 DispatcherServlet;

  • ? DispatcherServlet 和 Handler 不參與認證,只接收已驗證請求。


?6. JWT 是由前端編輯生成的嗎?字段如 iss、sub、exp、roles 是前端決定的嗎?

  • ? JWT 不能由前端生成;

  • ? JWT 是后端使用密鑰生成的,包含的字段完全由后端控制;

  • ? 前端只是接收、存儲并在請求中攜帶;

  • JWT 示例字段如 sub: userId, exp: timestamp, roles: ["ADMIN"] 都由后端代碼設置。


?7. 為什么 JWT 驗證完還要構建 Authentication 對象?不能直接轉發請求嗎?

  • ? 構建 Authentication 的目的是讓 Spring Security 安全機制生效:

    • 權限判斷(如 @PreAuthorize)依賴 SecurityContext

    • 日志、審計、日志追蹤、用戶上下文等都依賴它;

  • ? 如果跳過該步驟,系統將視為匿名用戶,請求將不具備認證身份。


? 四、Spring Security 的方法級授權機制

?8. @PreAuthorize 注解用在哪些類?在哪一步執行?為什么叫 Pre?看起來像是在認證前

  • ? @PreAuthorize 用于 Controller 或 Service 方法上,限制某角色、用戶是否能執行該方法;

  • ? 執行時機是 在方法體執行之前,不是在登錄認證之前;

  • ? 所謂“Pre”指的是在方法調用前進行權限判斷

  • ? 注解本質通過 AOP 攔截方法,依賴于 Authentication 已存在(由 Filter 中設置);

  • ? 如果沒有 Authentication@PreAuthorize 判斷失效,默認拒絕訪問。

用法:

@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) { ... }@PreAuthorize("#userId == authentication.name")
public void updateUser(Long userId, UserDto dto) { ... }

? 總結關鍵詞表

關鍵詞解釋
DTO傳輸數據結構體,跨層/跨系統使用
DAO數據訪問接口,用于封裝數據庫操作
ResponseEntity用于返回 JSON 響應體的 Spring 結構
ModelAndViewSpring MVC 內部統一封裝結構
JWTJSON Web Token,認證令牌,由后端生成
AuthenticationSpring Security 中用于表示認證用戶的對象
SecurityContextHolder保存當前請求上下文的認證信息
@PreAuthorize方法級授權注解,執行方法前做權限判斷

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/75729.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/75729.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/75729.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于sklearn實現文本摘要思考

和各位小伙伴分享一下使用sklearn進行文本摘要的思考。 第一版本 原理 提取式文本摘要的基本原理是&#xff1a; 將文本分割成句子 計算每個句子的重要性(權重) 選擇權重最高的幾個句子組成摘要 常用的句子權重計算方法&#xff1a; TF-IDF&#xff1a;基于詞頻-逆文檔頻…

OpenHarmony子系統開發 - DFX(三)

OpenHarmony子系統開發 - DFX&#xff08;三&#xff09; 五、HiTraceMeter開發指導 HiTraceMeter概述 簡介 HiTraceMeter在OpenHarmony中&#xff0c;為開發者提供業務流程調用鏈跟蹤的維測接口。通過使用該接口所提供的功能&#xff0c;可以幫助開發者迅速獲取指定業務流…

2025年 能夠有效提升AI的生成質量和邏輯嚴謹性 的通用型系統提示

以下是三個經過精心設計的通用型系統提示&#xff08;System Prompt&#xff09;&#xff0c;能夠有效提升AI的生成質量和邏輯嚴謹性&#xff0c;適用于各類對話、分析和創作場景&#xff1a; Prompt 1 - 專家級分步驗證模式 你是一個具備跨領域知識整合能力的超級AI&#xff…

python爬蟲:小程序逆向實戰教程

根據我之前發表的文章&#xff0c;我們進行延伸實戰https://blog.csdn.net/weixin_64809364/article/details/146981598?spm1001.2014.3001.5501 1. 想要爬取什么小程序&#xff0c;我們進行搜索 2. 找到我們vx小程序的文件地址&#xff0c;我們就可以進行破解 破解步驟強看…

C語言變長數組(VLA)詳解:靈活處理動態數據的利器

引言 在C語言中&#xff0c;傳統的數組大小必須在編譯時確定&#xff0c;這限制了程序處理動態數據的靈活性。C99標準引入的變長數組&#xff08;Variable-Length Array, VLA&#xff09; 打破了這一限制&#xff0c;允許數組長度在運行時動態確定。本文將深入解析VLA的語法、…

串口數據轉換為IP數據

串口數據轉換為IP數據是一種常見的通信技術,用于將傳統的串行設備(如傳感器、控制器等)接入現代的IP網絡。以下是詳細介紹: 1. 轉換原理 串口數據轉換為IP數據的過程涉及硬件和軟件的結合,核心是將串行數據封裝為TCP/IP或UDP/IP數據包,通過網絡傳輸。具體步驟如下: 硬…

client-go如何監聽自定義資源

如何使用 client-go 監聽自定義資源 在 Kubernetes 中使用 client-go 監聽自定義資源&#xff08;Custom Resource&#xff0c;簡稱 CR&#xff09;需要借助 Dynamic Client 或 Custom Informer&#xff0c;因為 client-go 的標準 Clientset 只支持內置資源&#xff08;如 Pod…

C++軟件開發架構

文章目錄 1.全局消息通信MsgHandler.h單元測試(QTest)MsgHandlerUnitTest.hMsgHandlerUnitTest.cpp 2.實例間通信InstMsgHandler.h單元測試InstMsgHandlerUnitTest.hInstMsgHandlerUnitTest.cpp 1.全局消息通信 1. 適用于類與類單個對象實例之間的通信&#xff0c;多個對象需要…

AI Agent設計模式一:Chain

概念 &#xff1a;線性任務流設計 ? 優點&#xff1a;邏輯清晰易調試&#xff0c;適合線性處理流程? 缺點&#xff1a;缺乏動態分支能力 from typing import TypedDictfrom langgraph.graph import StateGraph, END# 定義后續用到的一些變量 class CustomState(TypedDict):p…

Git三劍客:工作區、暫存區、版本庫深度解析

一、引言&#xff1a;為什么需要理解Git的核心區域&#xff1f; 作為開發者&#xff0c;Git是日常必備的版本控制工具。但你是否曾因以下問題感到困惑&#xff1f; 修改了文件&#xff0c;但 git status 顯示一片混亂&#xff1f; git add 和 git commit 到底做了什么&#x…

Python數據類型-list

列表(List)是Python中最常用的數據類型之一&#xff0c;它是一個有序、可變的元素集合。 1. 列表基礎 創建列表 empty_list [] # 空列表 numbers [1, 2, 3, 4, 5] # 數字列表 fruits [apple, banana, orange] # 字符串列表 mixed [1, hello, 3.14, True] # 混合類型…

Keepalive+LVS+Nginx+NFS高可用項目

項目架構 分析 主機規劃 主機系統安裝應用網絡IPclientredhat 9.5無NAT172.25.250.115/24lvs-masterrocky 9.5ipvsadm&#xff0c;keepalivedNAT172.25.250.116/24 VIP 172.25.250.100/32lvs-backuprocky 9.5ipvsadm&#xff0c;keepalivedNAT172.25.250.117/24 VIP 172.25.2…

【視覺與語言模型參數解耦】為什么?方案?

一些無編碼器的MLLMs統一架構如Fuyu&#xff0c;直接在LLM內處理原始像素&#xff0c;消除了對外部視覺模型的依賴。但是面臨視覺與語言模態沖突的挑戰&#xff0c;導致訓練不穩定和災難性遺忘等問題。解決方案則是通過參數解耦方法解決模態沖突。 在多模態大語言模型&#xf…

AI比人腦更強,因為被植入思維模型【43】蝴蝶效應思維模型

giszz的理解&#xff1a;蝴蝶效應我們都熟知&#xff0c;就是說一個微小的變化&#xff0c;能帶動整個系統甚至系統的空間和時間的遠端&#xff0c;產生巨大的鏈式反應。我學習后的啟迪&#xff0c;簡單的說&#xff0c;就是不要忽視任何微小的問題&#xff0c;更多時候&#x…

AI 數理邏輯基礎之統計學基本原理(上)

目錄 文章目錄 目錄統計學統計學基本概念描述性統計數據可視化圖表工具 匯總統計統計數據的分布情況&#xff1a;中位數、眾數、平均值統計數據的離散程度&#xff1a;極差、方差、標準差、離散系數 相關分析Pearson 線性關系相關系數Spearman 單調關系相關系數 回歸分析回歸模…

無招回歸阿里

這兩天&#xff0c;無招回歸阿里的新聞被刷屏了。無招創業成立的兩氫一氧公司無招的股份也被阿里收購&#xff0c;無招以這種姿態回歸阿里&#xff0c;并且出任釘釘的 CEO。有人說&#xff0c;這是對 5 年前“云釘一體”戰略的糾偏。現在確實從云優先到 AI 優先&#xff0c;但云…

算法題(114):矩陣距離

審題&#xff1a; 本題需要我們找出所有0距離最近的1的曼哈頓距離 思路&#xff1a; 方法一&#xff1a;多源bfs 分析曼哈頓距離&#xff1a; 求法1&#xff1a;公式法&#xff0c;帶入題目公式&#xff0c;利用|x1-x2||y1-y2|求出 求法2&#xff1a;曼哈頓距離就是最短距離 本…

LLM 性能優化有哪些手段?

LLM(大語言模型)性能優化是一個多維度、多層次的系統工程,涉及從提示工程到模型微調,從推理加速到系統架構優化等多個方面。以下是當前主流的優化手段及其技術細節: 一、提示工程(Prompt Engineering) 提示工程是優化LLM性能最直接、成本最低的方法,適用于快速原型開發…

群體智能避障革命:RVO算法在Unity中的深度實踐與優化

引言&#xff1a;游戲群體移動的挑戰與進化 在《全面戰爭》中萬人戰場恢弘列陣&#xff0c;在《刺客信條》鬧市里人群自然涌動&#xff0c;這些令人驚嘆的場景背后&#xff0c;都離不開一個關鍵技術——群體動態避障。傳統路徑規劃算法&#xff08;如A*&#xff09;雖能解決單…

I.MX6ULL 交叉編譯環境配置與使用

一、什么是交叉編譯 我們一般開發程序在自己的電腦上開發&#xff0c;運行的時候將程序燒錄到板子運行。但我們的開發平臺是X86架構&#xff0c;而I.MX6ULL是ARM架構&#xff0c;所以需要一個在 X86 架構的 PC 上運行&#xff0c;可以編譯 ARM 架構代碼的 GCC 編譯器&#xff0…