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();
}
}
請注意,該示例聲明瞭 findEmployees() 方法。它沒有指定任何特定的請求方法,這意味着此 URL 支持所有默認方法。
我們可以使用不同的支持的方法請求 API,例如 curl:
$ 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 方法不允許’ 是我們在使用 Spring 請求時經常遇到的常見錯誤。
讓我們看看在 Spring MVC 中明確定義和處理 GET 請求時會發生什麼:
@RequestMapping(
value = "/employees",
produces = "application/json",
method = RequestMethod.GET)
public List<Employee> findEmployees() {
...
}
// 使用 CURL 發送 PUT 請求
$ 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 不支持 – 原因、解決方案
我們之前遇到的情況是收到一個帶有 405 狀態碼的 HTTP 響應,這表示 客户端錯誤,表明請求中使用的方法/動詞不受服務器支持。
正如名稱所示,這個錯誤的根源在於使用不受支持的方法發送請求。
正如我們所期望的,我們可以通過在現有方法映射中定義明確的映射來解決這個問題:
@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 通信中一個關鍵方面。我們需要仔細考慮我們在服務器端定義的操作的精確語義,以及我們發送的精確請求。