首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring MVC vs JAX-RS (JSR 311) 深度對比:RESTful 服務開發兩大框架選型指南

     編輯:Java 相關知識

Spring 3 引入全面 REST 支援,與 JAX-RS (Jersey 參考實現) 形成兩大主流選擇。本文從引導程序、資源/控制器模型、請求映射、參數綁定、內容協商、異常處理六大維度系統對比,助你根據場景選型。

架構定位差異

維度JAX-RS (Jersey)Spring MVC
核心目標Web Services (API)Web Applications + Web Services
編程模型Resource (根/子資源鏈)Controller (扁平映射)
Spring 整合SpringServlet 代理DispatcherServlet 原生
部署單元WAR (Servlet 容器)WAR (Servlet 容器)

引導與依賴注入 (共同基礎)

兩者均使用 `ContextLoaderListener` 載入業務/持久層 Spring 容器:


<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:META-INF/spring/module-config.xml</param-value>
</context-param>
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

JAX-RS 資源模型


@Path("/accounts/")
@Component @Scope("prototype")  // 每請求實例
public class AccountResource {
  @Context UriInfo uriInfo;
  @Autowired AccountRepository repo;
  
  @GET @Path("{username}")
  public Account getAccount(@PathParam("username") String username) { ... }
  
  @Path("{username}/portfolios/")
  public PortfolioResource getPortfolioResource(@PathParam("username") String username) {
    return new PortfolioResource(repo, username, uriInfo); // 子資源手動實例化
  }
}
  • 根資源由 JAX-RS 運行時 (Spring) 管理,支援 `@Context` 注入請求上下文
  • 子資源由應用代碼 `new` 建立,依賴透過建構子傳遞
  • 形成處理鏈:`AccountResource` → `PortfolioResource`

架構圖 資源鏈

Spring MVC 控制器模型


@Controller @RequestMapping("/accounts")
public class AccountController {
  @Autowired AccountRepository repo;
  
  @RequestMapping(value="/{username}", method=GET)
  public @ResponseBody Account getAccount(@PathVariable String username) { ... }
}

@Controller @RequestMapping("/accounts/{username}/portfolios")
public class PortfolioController {  // 獨立控制器,無鏈式關係
  @Autowired AccountRepository repo;
  ...
}
  • 控制器皆為 Spring 單例 Bean,請求數據通過方法參數注入
  • 無子資源概念,路徑直接映射到獨立控制器
  • 可選擇在單一控制器處理所有子路徑

請求映射能力對比

特性JAX-RS @PathSpring MVC @RequestMapping
路徑變量`{username}``{username}`
正則約束`{username:.*}``{username:.*}`
查詢參數存在性不支援`params="foo"` / `params="!foo"`
查詢參數值不支援`params="foo=123"`
Header 存在性不支援`headers="Foo-Header"`
Header 值匹配不支援`headers="content-type=text/*"`
媒體類型消費/產生`@Consumes`/`@Produces``consumes`/`produces` 屬性

Spring MVC 請求匹配條件更豐富,適合複雜 Web 應用路由。

參數綁定與類型轉換

來源JAX-RSSpring MVC
查詢參數`@QueryParam``@RequestParam`
表單參數`@FormParam``@RequestParam` (統一)
Cookie`@CookieParam``@CookieValue`
Header`@HeaderParam``@RequestHeader`
矩陣參數`@MatrixParam` (獨有)不支援
路徑變量`@PathParam``@PathVariable`

Spring MVC 亮點:參數名與註解值同名時可省略註解值 (`@RequestParam String q`),需編譯時保留參數名 (`-parameters` / debug symbols)。

類型轉換機制

  • JAX-RS:尋找 `valueOf(String)` 靜態方法、單參構造函數、基本類型、集合泛型
  • Spring 3:繼承 JAX-RS 規則,新增 `Formatter` / `Converter` 註解驅動格式化體系 (`@DateTimeFormat`、`@NumberFormat` 等)

請求體與響應體處理

操作JAX-RSSpring MVC
讀取請求體 (JSON/XML)參數直接綁定,`MessageBodyReader` (JAXB/Jackson)`@RequestBody` 參數,`HttpMessageConverter` (JAXB/Jackson/XMLBeans/Castor/JiBX/XStream)
寫入響應體返回值自動序列化,`MessageBodyWriter``@ResponseBody` 返回值,同樣 `HttpMessageConverter`
配置簡化需手動註冊 Provider`` 自動掃描 classpath 註冊 Jackson/JAXB

HttpMessageConverter 配置

狀態碼、Header 與異常處理

場景JAX-RSSpring MVC
設定狀態碼`Response.status(204).build()` 鏈式 API`@ResponseStatus(HttpStatus.NO_CONTENT)` 方法級
Location Header`Response.created(uri).build()` + `UriBuilder`注入 `HttpServletResponse` 手動 `setHeader`
異常處理拋 `WebApplicationException` / 子類 (如 `NotFoundException`),每方法需 try-catch`@ExceptionHandler` + `@ResponseStatus` 類級集中處理

選型建議決策樹

  1. 純 API 微服務、團隊熟悉 JAX-RS、需標準化可移植 → JAX-RS (Jersey/RESTEasy)
  2. 既有 Spring 應用、需同時服務 HTML 頁面與 API、偏好集中式異常處理、豐富請求匹配 → Spring MVC
  3. Spring Boot 專案 → 兩者皆支援,`spring-boot-starter-web` (MVC) / `spring-boot-starter-jersey` (JAX-RS) 一鍵啟用
  4. 混合部署 → 同一應用掛載不同 Servlet 路徑 (`/api/*` Jersey, `/web/*` MVC) 共存

Spring 3 額外 REST 增強 (Web 應用面向)

  • JSP 標籤:`` 模板生成連結
  • HiddenHttpMethodFilter:表單模擬 PUT/DELETE
  • ContentNegotiatingViewResolver:Accept Header 自動選擇視圖
  • 新視圖實現:`MappingJackson2JsonView`、XML 視圖等

無絕對優劣,只有場景契合度。理解兩種模型本質差異,才能在架構演進中做正確決策。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved