01 引言

之前写过一篇关于统一相应的参数处理的文章,有路过的朋友指出错误信息为什么还要统一处理。技术储备浅薄的我一脸懵逼,经过交流才知道,大佬使用了ProblemDetail处理异常,于是专门学习了一下,记录下来分享给大家。

02 简介

org.springframework.http.ProblemDetail

ProblemDetailSpring Boot 3.0(Spring Framework 6.0)引入的类,用于标准化 HTTP API 错误响应格式,符合 RFC 7807 标准。

官网地址:https://docs.spring.io/spring-boot/3.5/reference/web/servlet.html#web.servlet.spring-mvc.error-handling

2.1 属性

private URI type: 错误类型标识(URI格式)

private String title:简短错误描述

private int status:HTTP状态码

private String detail:详细错误描述

private URI instance:具体错误实例标识

private Map<String, Object> properties:扩展属性

2.2 异常返回一览

SpringBoot 3.0之前的报错:

SpringBoot 3.0之后的报错:

03 使用

ProblemDetail的使用是有讲究的,不了解其中的道道,可能触发不了ProblemDetail的异常包装。

3.1 启动开关

SpringBoot框架针对ProblemDetail的启用做了开关,默认关闭。

通过配置生效:

spring.mvc.problemdetails.enabled=true

配置类:

3.2 测试方法

@GetMapping("/divide")
public int divide(int a, int b) {
    return a / b; 
}

如果 b=0,会触发 ArithmeticException。但是这个异常并没有触发ProblemDetail异常的封装。

测试请求:http://127.0.0.1:8080/divide?a=10&b=0

3.3 原因追溯

没有成功,难道是因为配置没有生效。我们从官网找一点蛛丝马迹。

大致意思是:要想启用RFC响应,可以扩展ResponseEntityExceptionHandler并声明@ControllerAdvice。处理器通过@ExceptionHandler采集异常,也可以添加其他异常并映射到ProblemDetail

所以我们看看ResponseEntityExceptionHandler的子类有没有类似的实现:

通过查看,我们可以发现ProblemDetailsExceptionHandler子类,似乎是处理ProblemDetail的关键。

@ControllerAdvice注解我们再熟悉不过了,用于参数绑定、异常处理等。而ResponseEntityExceptionHandler默认处理的异常:

显然没有ArithmeticException异常,自然不会被处理。

那我们只需要使用ResponseEntityExceptionHandler中的异常即可。

3.4 重新测试

测试方法中接收的字段类型为int,我们只需要传入非int类型的数据,就会触发MethodArgumentTypeMismatchException异常。而MethodArgumentTypeMismatchException继承TypeMismatchException异常。

测试地址:http://127.0.0.1:8080/divide?a=10&b=a

结果已经触发ProblemDetail的信息了。

04 问题

ProblemDetail异常包装触发了,但是并不是所有的异常都可以兜得住。即便是ResponseEntityExceptionHandler中的异常也有没有包装的。

小编这里不太理解为什么会从中间分开,上半部分异常不会触发ProblemDetail异常包装,而下半部分会触发。

所以我们在需要处理全局异常的时候,还需要我们自己去处理所有的异常,包括自定义异常已达到统一参数。

05 触发源码

ProblemDetailsExceptionHandler的包位于org.springframework.boot.autoconfigure.web.servlet下,又是如何通过配置启动的呢?

当然还是自动配置的类:WebMvcAutoConfiguration

06 小结

我们可以自己通过ProblemDetail封装异常信息,然后统一异常参数,全局统一处理异常,以达到全局统一的目的。可能里面还有小编理解不到位的地方,有问题评论区指出来,小编加以修正。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐