1. 概述

在使用 Spring MVC 开发 Web 接口时,我们经常会遇到一个常见的错误:405 Method Not Allowed。这个错误通常发生在客户端向服务端发送了一个不被支持的 HTTP 方法请求。

本文将带你快速了解这个错误的成因,并提供几种常见的解决方案。

2. 请求方法基础

如果你刚接触 Spring MVC,可以先看看这篇入门指南

Spring MVC 支持标准的 HTTP 请求方法,这些方法定义在 RequestMethod 枚举中:

  • GET
  • HEAD
  • POST
  • PUT
  • PATCH
  • DELETE
  • OPTIONS
  • TRACE

其中,Spring 的 DispatcherServlet 默认支持除 OPTIONSTRACE 外的所有方法。

我们可以通过 @RequestMapping 注解来指定某个接口支持的请求方法。如果不显式指定,默认会支持所有方法。

3. 简单的 MVC 场景

下面是一个简单的 Controller 示例,它没有指定任何请求方法,因此默认支持所有方法:

@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();
    }
}

此时,你可以使用任何支持的方法(如 GET、POST)访问 /api/employees 接口:

$ 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"}]

只要请求路径和处理逻辑匹配,就能正常返回 200 OK。

4. 问题场景:HTTP 405 错误

现在我们来看一个出问题的场景。假设我们只允许 GET 请求访问某个接口:

@RequestMapping(
  value = "/employees", 
  produces = "application/json", 
  method = RequestMethod.GET)
public List<Employee> findEmployees() {
    ...
}

然后我们尝试用 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"
}

✅ 结果就是 405 错误,Spring 明确告诉你:不支持你用 PUT 方法访问这个接口!

5. 405 错误的原因与解决方案

❌ 原因总结

HTTP 405 错误本质上是一个客户端错误,表示你发送的 HTTP 方法(GET、POST、PUT 等)不被服务端支持。

✅ 解决方案

方案一:扩展支持的方法

你可以在 @RequestMapping 中添加多个方法支持:

@RequestMapping(
  value = "/employees", 
  produces = "application/json", 
  method = {RequestMethod.GET, RequestMethod.PUT})
public List<Employee> findEmployees() {
    ...
}

方案二:为不同方法定义不同的处理方法

你也可以为每个方法单独定义处理逻辑:

@RequestMapping(value = "/employees", 
  produces = "application/json", 
  method = RequestMethod.GET)
public List<Employee> getEmployees() {
    ...
}

@RequestMapping(value = "/employees", 
  produces = "application/json", 
  method = RequestMethod.PUT)
public List<Employee> updateEmployees() {
    ...
}

⚠️ 注意:如果你的 API 需要严格的 RESTful 设计,建议为不同语义的操作定义不同的方法,而不是一股脑支持所有方法。

6. 小结

HTTP 请求方法是 Web 通信中的核心部分,Spring MVC 提供了灵活的方式来控制接口支持的方法类型。

当你遇到 405 错误时,不要慌,先检查你发送的请求方法是否被接口支持。很多时候只是因为忘了加 method 参数或者方法写错了。

示例代码可以在 GitHub 仓库 中找到。


原始标题:Request Method Not Supported (405) in Spring