一、引言
本篇内容是“异常统一处理”系列文章的重要组成部分,主要聚焦于对 HttpRequestMethodNotSupportedException
的原理解析与异常处理机制,并给出测试案例。
- 关于 全局异常统一处理 的原理和完整实现逻辑,请参考文章:
《SpringBoot 全局异常统一处理(AOP):@RestControllerAdvice + @ExceptionHandler + @ResponseStatus》- 本文仅详细解析 HttpRequestMethodNotSupportedException 的异常处理;其他类型异常的原理和处理方法,请参阅本文所在专栏内的其他文章。
二、异常原理
在Spring Boot应用中,HttpRequestMethodNotSupportedException
异常是由Spring MVC框架抛出的,当客户端通过HTTP协议发送请求到服务器端时,所使用的HTTP方法
(如GET、POST、PUT、DELETE等)与控制器方法所期望的方法不匹配
时,就会触发这个异常。
例如,如果你有一个只支持POST请求的RESTful API接口:
@PostMapping("/some-resource")
public ResponseEntity<String> handlePostRequest(...) {
// ...
}
但客户端尝试以GET方法访问该资源:
GET /some-resource
此时,由于服务器端没有为GET方法配置对应的处理方法,Spring MVC在解析请求并试图找到合适的方法进行处理时,无法找到对应HTTP GET方法的处理器,因此会抛出HttpRequestMethodNotSupportedException
异常,并附带信息说明请求的方法不受支持。
解决这个问题的方式是确保客户端使用与服务器端定义的控制器方法相匹配的HTTP方法进行通信。如果需要支持多种HTTP方法,可以使用@RequestMapping
注解配合method
属性指定多个支持的方法,或者分别使用@GetMapping
、@PostMapping
等注解来明确指定每个HTTP方法的处理器方法。
三、异常处理代码
在Spring Boot应用中,我们可以通过使用@ExceptionHandler
注解来捕获并处理HttpRequestMethodNotSupportedException
异常。
3.1 异常处理示意图
3.2 异常处理核心代码
异常处理策略的核心代码如下:
package com.example.core.advice;
import com.example.core.advice.util.ApiUtil;
import com.example.core.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
/**
* 全局异常处理器
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
private final HttpServletRequest request;
public GlobalExceptionHandler(HttpServletRequest request) {
this.request = request;
}
/**
* Http请求方法不支持异常。
* <p>
* 一个接口,是由【请求方法】(GET、POST、PUT、DELETE等)和【接口路径】两个部分来唯一确定的。
* 当一个请求,能找到对应的【接口路径】,但是没有找到对应的【请求方法】时,会报异常 HttpRequestMethodNotSupportedException ,进入此异常处理。
* 当一个请求,找不到对应的【接口路径】时,会直接报错 404 ,不会进入此异常处理。
* <p>
* 测试:一个接口,应该用Post请求,却用了GET请求。
* <p>
* 报错示例:
* DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported]
* <p>
* 注意:此方法不能包含 HandlerMethod 入参,否则会报错;因为进入此异常处理方法,意味着收到的请求是没有对应的控制器方法的。
*/
@ExceptionHandler
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
public Result<String> handle(HttpRequestMethodNotSupportedException e) {
String api = ApiUtil.getApi(request);
String userMessage = "Http请求方法不支持异常!请稍后重试,或联系业务人员处理。";
String errorMessage = String.format("HttpRequestMethodNotSupportedException(Http请求方法不支持异常);当前请求接口:[%s];报错信息:%s", api, e.getMessage());
return Result.fail(userMessage, String.valueOf(HttpStatus.METHOD_NOT_ALLOWED.value()), errorMessage);
}
}
上述代码中,当出现HttpRequestMethodNotSupportedException
异常时,系统将返回一个状态码为405(Method Not Allowed)的结果,并附带具体的错误信息。
3.3 获取当前请求的API
package com.example.core.advice.util;
import javax.servlet.http.HttpServletRequest;
/**
* API工具类
*
* @author songguanxun
* @since 2024-2-18
*/
public class ApiUtil {
/**
* 获取当前请求的API
*/
public static String getApi(HttpServletRequest request) {
String method = request.getMethod();
String uri = request.getRequestURI();
return String.format("%s %s", method, uri);
}
}
四、测试案例
4.1 测试代码
package com.example.web.exception.controller;
import com.example.web.model.param.UserAddParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@Slf4j
@RestController
@RequestMapping("exception")
@Tag(name = "异常统一处理")
public class ExceptionController {
@PostMapping("HttpRequestMethodNotSupportedException")
@Operation(summary = "异常:HttpRequestMethodNotSupportedException")
public void testHttpRequestMethodNotSupportedException(@Valid @RequestBody UserAddParam param) {
log.info("测试:HttpRequestMethodNotSupportedException");
}
}
4.2 正确请求示例
4.3 未处理异常时的报错
请求响应
控制台的错误日志
4.4 已处理异常时的响应
五、触发异常的情景
如下示例中,当请求 删除用户
接口时,前端漏传id参数,导致接口路径变为 [/users];只有新增用户和查询用户列表的接口为 [/users],且请求方法都不是DELETE。最后,就抛出了 HttpRequestMethodNotSupportedException 异常,因为 接口路径[/users]
不支持DELETE
方法。
当出现此种情况时,说明前端调用接口出现了错误,应检查前端请求代码,将id参数补全。
接口示例
请求示例
文章来源:https://www.toymoban.com/news/detail-856229.html
文章来源地址https://www.toymoban.com/news/detail-856229.html
到了这里,关于异常统一处理:HttpRequestMethodNotSupportedException(Http请求方法不支持异常)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!