REST(Representational State Transfer)是一種軟體架構風格,而非嚴格標準。其核心在於:資源導向、統一介面、無狀態、可快取。在 RESTful 設計中,同一 URL 代表同一資源集合,透過 HTTP Method 語義區分操作:
| HTTP Method | 語義 | 對應操作 |
|---|---|---|
| GET | 查詢 | SELECT |
| POST | 新增 | INSERT |
| PUT | 整體更新 | UPDATE |
| PATCH | 部分更新 | UPDATE (局部) |
| DELETE | 刪除 | DELETE |
基礎 URL:https://localhost:8080/User
GET /User?id=1001 → 查詢 ID 1001 使用者POST /User (Body: name=zhangsan) → 新增使用者PUT /User (Body: id=1001&name=lisi) → 整體更新 ID 1001DELETE /User?id=1001 → 刪除 ID 1001@Controller
@RequestMapping("/User")
public class UserController {
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public User getUser(@RequestParam Long id) { ... }
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public String createUser(@RequestBody User user) { ... }
@RequestMapping(method = RequestMethod.PUT)
@ResponseBody
public String updateUser(@RequestBody User user) { ... }
@RequestMapping(method = RequestMethod.DELETE)
@ResponseBody
public String deleteUser(@RequestParam Long id) { ... }
}
// 新增
$.ajax({ url: "/User", type: "POST", data: {name: "zhangsan"}, ... });
// 更新 - 關鍵點:瀏覽器原生 form 不支援 PUT/DELETE
$.ajax({ url: "/User", type: "POST", data: {_method: "PUT", id: 1001, name: "lisi"}, ... });
// 刪除
$.ajax({ url: "/User", type: "POST", data: {_method: "DELETE", id: 1001}, ... });
HTML 標單僅支援 GET/POST;Servlet API 雖定義 doPut/doDelete 但容器預設不路由。Spring MVC 提供 HiddenHttpMethodFilter 解決:攔截含 _method 參數的 POST 請求,轉換為對應的 HTTP Method。
<filter> <filter-name>hiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
注意: 此 Filter 必須在 DispatcherServlet 之前註冊(web.xml 順序靠前)。
<web-app version="3.0" ...>
<!-- 1. HiddenHttpMethodFilter 必須最先 -->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 2. Spring MVC DispatcherServlet -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
...
</web-app>
| 方案 | 支援 PUT | 支援 DELETE | 備註 |
|---|---|---|---|
| HiddenHttpMethodFilter | ✓ | ✓ | 推薦,標準 REST 實作 |
| HttpPutFormContentFilter | ✓ | ✗ | 僅解決 PUT 請求體解析 |
| 手動在 Controller 判斷 _method 參數 | ✓ | ✓ | 侵入式、不優雅 |
配置完成後,前端 AJAX 以 type: "POST" 發送,攜帶 _method: "PUT" 或 "DELETE",Spring MVC 會自動路由至對應 @RequestMapping(method=RequestMethod.PUT/DELETE) 方法,且請求參數正常綁定。
/deleteUser 這類動詞式端點/v1/User) 或 Header 中HiddenHttpMethodFilter 解決瀏覽器限制,保持 Controller 純淨掌握這套機制,即可在 Spring MVC 中建構符合 REST 原則、前後端分離友好的 API 介面。