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

Spring中@Controller與@RestController核心解析實戰(zhàn)指南

 更新時間:2025年11月05日 09:19:17   作者:Kay_Liang  
本文系統(tǒng)解析了Spring MVC中@Controller、@RestController和@RequestMapping的核心功能與最佳實踐,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

在 Spring 生態(tài)中,@Controller@RestController 往往被視為“孿生”組件,而 @RequestMapping 及其派生注解則承擔(dān)了路由樞紐的角色。本文依托 Spring Framework 官方文檔與社區(qū)實踐,系統(tǒng)梳理三者背后的設(shè)計動機(jī)、運(yùn)行機(jī)理、協(xié)作流程與常見誤區(qū),并給出可落地的編碼建議。全文約 6000 字,力求在學(xué)術(shù)嚴(yán)謹(jǐn)性與博客可讀性之間取得平衡,與各位 Java 學(xué)習(xí)者一起進(jìn)階學(xué)習(xí)。

1 引言

Spring MVC 自 2.5 引入注解驅(qū)動編程模型以來,Java Web 開發(fā)逐步擺脫厚重的 XML 配置。@Controller 作為模式層與前端控制器 DispatcherServlet 之間的橋梁,率先被開發(fā)者熟知;隨后 Spring 4.0 推出 @RestController,以“組合注解”形態(tài)將 @ResponseBody 的能力固化到控制器層,順應(yīng)了前后端分離與云原生浪潮。與此同時,@RequestMapping 及其細(xì)化派生(@GetMapping、@PostMapping 等)構(gòu)成了請求路由的“元語言”,在類與方法兩級提供精確映射。理解它們之間的分工與協(xié)作,是構(gòu)建高可維護(hù)、高測試覆蓋率 Web 應(yīng)用的必要前提。

2@Controller:表現(xiàn)層模式入口

2.1 語義與定位

@Controller 是 Spring stereotype 注解家族的一員,與 @Service、@Repository 并列。該注解僅做“標(biāo)記”用途,本身不依賴 Servlet API,也不直接處理線程并發(fā)邏輯。Spring 容器在刷新階段通過 ClassPathBeanDefinitionScanner 識別 @Controller 類,將其注冊為獨(dú)立的 BeanDefinition,并設(shè)置 singleton 作用域。此后,DispatcherServlet 借助 HandlerMappingHandlerAdapter 完成 URL 到 Bean 的關(guān)聯(lián)。

2.2 返回值類型與視圖解析

在純 MVC 模式下,控制器方法可返回:

  • String——邏輯視圖名,由 ViewResolver 解析為具體 JSP、Thymeleaf、FreeMarker 模板;
  • ModelAndView——同時攜帶模型數(shù)據(jù)與視圖對象;
  • void——直接利用 HttpServletResponse 寫流,常用于文件下載;
  • 其他類型——若未標(biāo)注 @ResponseBody,則會被當(dāng)成模型屬性,默認(rèn)視圖名為“URL 路徑簡化形式”。

由此可見,@Controller 默認(rèn)面向“頁面渲染”場景,其核心擴(kuò)展點(diǎn)在于視圖抽象層。

2.3 與@Component的層級關(guān)系

@Controller 元注解標(biāo)注了 @Component,因而被 <context:component-scan>@ComponentScan 掃描時同樣享受依賴注入、AOP 代理、生命周期回調(diào)等能力。區(qū)別僅在于語義層面:Spring MVC 會在運(yùn)行時利用注解元數(shù)據(jù)區(qū)分 Web 層組件,與業(yè)務(wù)層、持久層隔離,方便做全局異常處理、權(quán)限切面等。

3@RestController:面向 REST 的組合式革新

3.1 源碼級別的“語法糖”

Spring 4.0 新增的 @RestController 實現(xiàn)極為簡潔,其源碼僅由兩個元注解構(gòu)成:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController { 
    String value() default "";
}

這意味著被 @RestController 標(biāo)注的類首先依舊是 @Controller,因而能被 DispatcherServlet 識別;其次,類中所有方法默認(rèn)攜帶 @ResponseBody 語義,即返回值直接由 HttpMessageConverter 序列化,不再走視圖解析鏈。

3.2 消息轉(zhuǎn)換器鏈路

當(dāng)方法返回非 void 且未顯式標(biāo)注 @ResponseBody 時,Spring MVC 通過 RequestMappingHandlerAdapter 調(diào)用 ServletInvocableHandlerMethod,進(jìn)而激活 HandlerMethodReturnValueHandler 鏈。@RestController 場景下,首要的處理器為 RequestResponseBodyMethodProcessor,它依據(jù)請求頭 Accept 與生產(chǎn)端 produces 屬性,借助已注冊的 HttpMessageConverter(常見如 MappingJackson2HttpMessageConverterJaxb2RootElementHttpMessageConverter)完成 POJO→JSON/XML 的序列化,并寫入 ServletOutputStream。整個流程不再依賴 JSP 或模板引擎,因此前后端分離項目通常剔除 spring-boot-starter-thymeleaf 等視圖模塊,以降低部署包體積。

3.3 與@Controller的性能差異

就單次 HTTP 請求而言,兩者在 CPU 指令級幾乎等價;差異主要體現(xiàn)在:

  • 視圖解析環(huán)節(jié)被跳過,減少一次 ViewResolver 鏈遍歷;
  • 內(nèi)存占用方面,免去了 ModelAndView 等中間對象的構(gòu)造;
  • 線程安全上,二者皆基于無狀態(tài) Servlet 模型,無額外鎖競爭。

在 QPS 萬級以下場景,差距可忽略;高并發(fā)壓測中,@RestController 的吞吐量略高 2%~4%,可歸因于視圖解析的省略。

3.4 常見誤區(qū)

  • 認(rèn)為 @RestController 必須搭配 @RequestMapping("/api") 使用——其實類級別路徑可選,可放在方法級;
  • @RestController 當(dāng)成 @Service 使用,導(dǎo)致事務(wù)代理失效——事務(wù)應(yīng)置于業(yè)務(wù)層;
  • 誤以為 @RestController 只能返回 JSON——通過 produces = "application/xml" 或自定義 HttpMessageConverter 同樣支持 XML、MessagePack 等;
  • 把全局異常處理類也標(biāo)注 @RestController——正確做法是 @ControllerAdvice 配合 @ResponseBody@RestControllerAdvice。

4@RequestMapping:路由映射的“元注解”

4.1 屬性總覽

@RequestMapping 提供六大核心屬性:

  • value / path:URI 模板,支持 Ant 風(fēng)格通配符與 {pathVariable};
  • method:HTTP 方法數(shù)組,為空時接受任意方法;
  • params:請求參數(shù)斷言,如 params = "version=2";
  • headers:請求頭斷言,如 headers = "Content-Type=application/json";
  • consumes:限定請求的 Content-Type,對應(yīng) Content-Type 頭;
  • produces:限定響應(yīng)的 Content-Type,對應(yīng) Accept 頭。

以上屬性可組合成細(xì)粒度的匹配條件,Spring 在 RequestMappingHandlerMapping 階段利用 RequestCondition 體系進(jìn)行評分排序,得分高者優(yōu)先。

4.2 類級別與方法級別的協(xié)同

@RequestMapping 允許“兩段式”映射:

@RestController
@RequestMapping("/shop")
public class OrderController {
    @GetMapping("/order/{id}")            // 實際映射 /shop/order/{id}
    public Order getOrder(@PathVariable Long id){ … }
}

類級別路徑作為前綴,方法級別作為后綴,二者拼接后去除重復(fù) /。該策略使得同一業(yè)務(wù)單元可共享根路徑,減少重復(fù)編碼。需要強(qiáng)調(diào)的是,類級別屬性(如 produces)會被方法級別同名屬性覆蓋,而非追加。

4.3 RESTful 風(fēng)格設(shè)計要點(diǎn)

  • 資源名詞復(fù)數(shù)化:/users、/orders
  • 利用路徑變量表達(dá)層級:/users/{userId}/orders/{orderId};
  • 用 HTTP 方法表達(dá)動作:GET 查詢、POST 創(chuàng)建、PUT 全量更新、PATCH 部分更新、DELETE 刪除;
  • 版本化:推薦將版本置于 URL 前綴 /v1/users,或利用 Accept: application/vnd.company.api.v2+json 協(xié)商;
  • 無狀態(tài):拒絕將 session 作為業(yè)務(wù)依據(jù),由 JWTOAuth2 令牌承載身份。

5 派生注解:語義化與最佳實踐

Spring 4.3 起引入五個方法級派生注解,分別對應(yīng)標(biāo)準(zhǔn) HTTP 方法:

注解等效寫法常見場景
@GetMapping@RequestMapping(method=GET)查詢、分頁、導(dǎo)出
@PostMapping@RequestMapping(method=POST)新增、復(fù)雜查詢
@PutMapping@RequestMapping(method=PUT)全量更新
@PatchMapping@RequestMapping(method=PATCH)部分字段更新
@DeleteMapping@RequestMapping(method=DELETE)刪除

使用派生注解可顯著降低 method 硬編碼出錯率,并提升代碼自描述能力。需要注意的是,派生注解不支持 consumes/params 等屬性,但可通過組合 @RequestMapping 達(dá)到同樣效果。

6 參數(shù)綁定與注解協(xié)作

6.1 路徑變量@PathVariable

URI 模板變量需與方法形參一一對應(yīng),支持基本類型及自定義類型轉(zhuǎn)換。若名稱為駝峰,可在 {} 中保留短橫線 /users/{user-id},再通過 @PathVariable("user-id") 顯式綁定。

6.2 查詢參數(shù)@RequestParam

默認(rèn)必填,可通過 required=falseOptional<T> 接收空值;多值場景用 List<T> 接收。對于復(fù)雜對象,Spring 會調(diào)用 WebDataBinder 進(jìn)行級聯(lián)綁定,但建議保持扁平,避免多層嵌套。

6.3 請求體@RequestBody

僅支持 POST/PUT/PATCH,Content-Type 需為 application/json 等可序列化格式。默認(rèn)由 Jackson 反序列化,可通過 @Valid 觸發(fā) Bean Validation,校驗失敗將拋出 MethodArgumentNotValidException,由 @ExceptionHandler 統(tǒng)一處理。

6.4 請求頭@RequestHeader

可用于讀取 Authorization、X-Request-ID 等頭信息,支持 Map<String,String> 批量接收。需要注意大小寫不敏感,因 HTTP 頭本身不區(qū)分大小寫。

6.5 矩陣變量@MatrixVariable

URI 路徑中的鍵值對,如 /cars;color=red;year=2020,需開啟 <mvc:annotation-driven enable-matrix-variables="true"/>,并配合 UrlPathHelper 移除 ; 后的分號截斷。

7 異常處理與統(tǒng)一響應(yīng)

7.1@ControllerAdvice全局?jǐn)r截

通過 @ControllerAdvice(basePackages="com.example.web") 限定掃描范圍,配合 @ExceptionHandler(MethodArgumentNotValidException.class) 返回統(tǒng)一 JSON 響應(yīng)體。該機(jī)制對 @RestController@Controller 同時生效,但后者若返回視圖,則需額外配置 ModelAndView resolver。

7.2 響應(yīng)封裝建議

不推薦直接返回實體對象,應(yīng)定義 CommonResponse<T> 統(tǒng)一包裝:

public class CommonResponse<T> {
    private int code;
    private String message;
    private T data;
    private long timestamp;
}

全局封裝可通過 ResponseBodyAdvice<T> 實現(xiàn),在 beforeBodyWrite 處攔截,避免每個接口手動包裝。

8 測試與可維護(hù)性

8.1 單元測試

利用 MockMvc 可快速驗證路由、參數(shù)、響應(yīng)體,無需啟動 Servlet 容器:

@Autowired
private MockMvc mvc;
@Test
public void shouldReturnUser() throws Exception {
    mvc.perform(get("/v1/users/1")
           .accept(MediaType.APPLICATION_JSON))
       .andExpect(status().isOk())
       .andExpect(jsonPath("$.id").value(1));
}

8.2 層間隔離

控制器僅負(fù)責(zé)協(xié)議轉(zhuǎn)換與參數(shù)校驗,業(yè)務(wù)邏輯下沉至 Service Facade,可避免出現(xiàn)“貧血控制器”與“事務(wù)腳本”陷阱。通過 @WebMvcTest 可只加載 MVC 組件,加速 CI 流水線。

9 版本演進(jìn)與未來趨勢

Spring Framework 6 已全面兼容 Jakarta EE 9,包名由 javax.servlet 遷移至 jakarta.servlet,但注解層保持零改動,因此 @Controller、@RestController、@RequestMapping 依舊穩(wěn)定。隨著 Spring Boot 3 原生鏡像(GraalVM Native Image)的成熟,注解解析階段可在編譯期完成,進(jìn)一步縮短冷啟動時間。另一方面,Spring WebFlux 的 @RestController 在語義層面與 Servlet 棧保持一致,僅底層實現(xiàn)由阻塞式改為事件循環(huán),因此本文結(jié)論同樣適用于響應(yīng)式編程模型。

10 結(jié)論

@Controller@RestController 并非簡單的“新舊替換”,而是面向不同交互模式的互補(bǔ)組件:前者聚焦頁面渲染,后者專注數(shù)據(jù)服務(wù);@RequestMapping 及其派生注解則提供靈活而強(qiáng)大的路由能力。開發(fā)者應(yīng)依據(jù)業(yè)務(wù)場景、團(tuán)隊技能與歷史資產(chǎn),合理選用注解組合,并輔以統(tǒng)一的異常、響應(yīng)、日志規(guī)范,才能在快速迭代與長期維護(hù)之間取得平衡。

到此這篇關(guān)于Spring中@Controller與@RestController核心解析實戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Spring @Controller與@RestController內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中配置Redis連接池的完整指南

    SpringBoot中配置Redis連接池的完整指南

    這篇文章主要為大家詳細(xì)介紹了SpringBoot中配置Redis連接池的完整指南,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-04-04
  • jdk中keytool的使用以及如何提取jks文件中的公鑰和私鑰

    jdk中keytool的使用以及如何提取jks文件中的公鑰和私鑰

    JKS文件由公鑰和密鑰構(gòu)成利用Java?Keytool工具生成的文件,它是由公鑰和密鑰構(gòu)成的,下面這篇文章主要給大家介紹了關(guān)于jdk中keytool的使用以及如何提取jks文件中公鑰和私鑰的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • Java中如何調(diào)用cmd壓縮文件

    Java中如何調(diào)用cmd壓縮文件

    以下是對Java調(diào)用cmd壓縮文件的實現(xiàn)方法進(jìn)行了分析介紹,需要的朋友可以參考下
    2013-07-07
  • Java打包Jar包后使用腳本執(zhí)行

    Java打包Jar包后使用腳本執(zhí)行

    本文詳細(xì)講解了Java打包Jar包后使用腳本執(zhí)行的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • springboot3.x版本集成log4j沖突以及解決log4j沖突不生效問題

    springboot3.x版本集成log4j沖突以及解決log4j沖突不生效問題

    由于Spring Boot自帶的Logback與Log4j沖突,去除了Logback的jar包后仍存在,原因是其他包也引入了Logback,解決方法是找到并去除引入Logback的其他包,如actuator包,并更新Maven
    2024-11-11
  • Spring Boot利用@Async如何實現(xiàn)異步調(diào)用:自定義線程池

    Spring Boot利用@Async如何實現(xiàn)異步調(diào)用:自定義線程池

    這篇文章主要給大家介紹了關(guān)于Spring Boot利用@Async如何實現(xiàn)異步調(diào)用:自定義線程池的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2018-05-05
  • Java實現(xiàn)Token工具類進(jìn)行登錄和攔截

    Java實現(xiàn)Token工具類進(jìn)行登錄和攔截

    在應(yīng)用的登錄時需要生成token進(jìn)行驗證,并放入信息,之后的話可以直接使用瀏覽器的session進(jìn)行登錄,本文就來利用java編寫一個token工具類,可以很方便的生成和解析token,感興趣的可以了解下
    2023-12-12
  • 如何使用Spring AOP預(yù)處理Controller的參數(shù)

    如何使用Spring AOP預(yù)處理Controller的參數(shù)

    這篇文章主要介紹了如何使用Spring AOP預(yù)處理Controller的參數(shù)操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • java微信公眾號開發(fā)案例

    java微信公眾號開發(fā)案例

    這篇文章主要為大家詳細(xì)介紹了java微信公眾號開發(fā)案例,如何接入公眾號,訂閱號怎么樣接收消息,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 深入了解Spring的Bean生命周期

    深入了解Spring的Bean生命周期

    這篇文章主要為大家介紹了Spring的Bean生命周期,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)或工作有一定的參考價值,感興趣的可以學(xué)習(xí)一下
    2022-01-01

最新評論

盐源县| 祥云县| 德兴市| 邻水| 晋城| 噶尔县| 屯留县| 密山市| 习水县| 吉木乃县| 桓台县| 新乐市| 如东县| 长沙县| 永平县| 道真| 黑龙江省| 甘孜| 兰州市| 吉林省| 红桥区| 沈阳市| 杭锦后旗| 静海县| 和田市| 沿河| 璧山县| 泰兴市| 洛扎县| 顺义区| 额济纳旗| 洛川县| 郁南县| 喀喇沁旗| 昌都县| 揭东县| 襄城县| 嵊州市| 璧山县| 屏东县| 会理县|