1. 概述
在本快速教程中,我們將重點關注開發者在向 Spring MVC 暴露 API 時,經常遇到的一個常見錯誤:“請求方法不支持 – 405”。
當然,我們也會討論導致此錯誤的一些常見原因。
2. 請求方法基礎
如果正開始學習 Spring MVC,這裏有一個不錯的入門文章可以參考。
我們還會快速瞭解 Spring 支持的請求方法基礎,以及一些常用的相關類。
以一種高度簡化的方式,MVC HTTP 方法是請求可以觸發在服務器上的基本操作。例如,某些方法可以獲取服務器上的數據,某些方法可以提交數據到服務器,某些方法可能會刪除數據等。
@RequestMapping 註解指定了請求所支持的方法。
Spring 聲明瞭所有支持的請求方法在一個枚舉中,RequestMethod,該枚舉指定了標準的 GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE 動詞。
Spring 的 DispatcherServlet 默認支持所有這些方法,除了 OPTIONS 和 TRACE。@RequestMapping 使用 RequestMethod 枚舉 來指定哪些方法被支持。
3. 簡單 MVC 場景
現在讓我們來看一個代碼示例,它映射了所有 HTTP 方法:
@RestController
@RequestMapping(value="/api")
public class RequestMethodController {
@Autowired
private EmployeeService service;
@RequestMapping(value = "/employees", produces = "application/json")
public List<Employee> findEmployees()
throws InvalidRequestException {
return service.getEmployeeList();
}
}請注意,示例中聲明瞭 findEmployee() 方法。它未指定任何特定的請求方法,這意味着此 URL 支持所有默認方法。
我們可以使用支持的方法(例如 curl)請求 API:
$ curl --request POST http://localhost:8080/api/employees
[{"id":100,"name":"Steve Martin","contactNumber":"333-777-999"},
{"id":200,"name":"Adam Schawn","contactNumber":"444-111-777"}]當然,我們可以通過多種方式發送請求:簡單的 curl 命令、Postman、AJAX 等。
並且,我們當然期望在請求正確映射併成功的情況下獲得 200 OK 響應。
4. 場景分析 – HTTP 405
我們討論的是請求不成功的場景。
‘405 Method Not Allowed’ 是我們在 Spring 請求中經常遇到的錯誤之一。
讓我們看看在 Spring MVC 中明確定義和處理 GET 請求時會發生什麼:
@RequestMapping(
value = "/employees",
produces = "application/json",
method = RequestMethod.GET)
public List<Employee> findEmployees() {
...
}
// send the PUT request using CURL
$ curl --request PUT http://localhost:8080/api/employees
{"timestamp":1539720588712,"status":405,"error":"Method Not Allowed",
"exception":"org.springframework.web.HttpRequestMethodNotSupportedException",
"message":"Request method 'PUT' not supported","path":"/api/employees"}
5. 405 不支持 – 原因、解決方案
我們之前遇到的情況是收到一個 HTTP 響應,狀態碼為 405,這是一種 客户端錯誤,指示服務器不支持請求中發送的方法/動詞。
正如名稱所示,這個錯誤的原因是使用不支持的方法發送請求。
我們可以期望,通過在現有方法映射中定義明確的 PUT 映射來解決這個問題。
@RequestMapping(
value = "/employees",
produces = "application/json",
method = {RequestMethod.GET, RequestMethod.PUT}) ...當然,以下是翻譯後的內容:
或者,我們可以分別定義新的方法/映射:
@RequestMapping(value = "/employees",
produces = "application/json",
method=RequestMethod.PUT)
public List<Employee> postEmployees() ...
6. 結論
請求方法/動詞是 HTTP 通信中一個至關重要的方面。我們需要仔細考慮我們在服務器端定義的操作的精確語義,以及我們發送的精確請求。