当前位置: 首页 > 科技观察

Spring6-SpringBoot3新特性:优雅的业务异常处理

时间:2023-03-12 21:34:24 科技观察

当你使用SpringBoot(SpringMVC)进行RESTfulAPI开发时,你会发现HTTP状态码往往不够有效,无法传达错误信息。HTTP中有一个RFC7807规范:https://www.rfc-editor.org/rfc/rfc7807。本规范定义了HTTPAPI的“问题详细信息”内容。本规范定义了一个“问题详情”(ProblemDetails),用于携带HTTP错误返回信息,避免自定义新的错误返回格式。我们通常自己定义错误返回格式。Spring6.0为我们提供了一个org.springframework.http.ProblemDetail来实现这个规范。RFC7807是一个非常简单的规范。它定义了一种JSON格式,并与一种媒体类型相关联。此JSON格式包含五个可选成员来描述问题的详细信息:类型:用于标识问题类型的URI引用。这个URI的路径内容应该用来显示人类可读的信息来描述类型;title:人类可读的问题类型描述;同一类型的问题,应该总是相同的描述;status:HTTP状态码,包含在问题详情中是一种方便的方式;细节:问题实例的人类可读描述,解释为什么当前问题出现在这个特定场景中;instance:用于标识问题实例的URI引用。此URI的内容应该用于描述问题实例,但不是必需的。我们先创建一个演示工程:1.常用的业务异常处理方法定义了一个业务异常类。异常的含义是:找不到Person时抛出的业务异常。publicclassPersonNotFoundExceptionextendsRuntimeException{@GetterprivatefinalHttpStatus状态;publicPersonNotFoundException(Stringmessage,HttpStatusstatus){super(message);this.status=状态;}}将此业务异常注册到全局异常处理中。通过在@RestControllerAdvice中定义全局切面处理。使用@ExceptionHandler处理指定异常的处理。这里返回的格式是我们自定义的ErrorMsg格式。我们通过自定义这个ErroMsg完成接口用户协议,完成业务异常的处理。@RestControllerAdvice公共类GlobalExceptionHandler{@ExceptionHandler(PersonNotFoundException.class)publicResponseEntitypersonNotFoundHandler(PersonNotFoundExceptione){ErrorMsgmsg=newErrorMsg("0000",e.getMessagen(Emsagen())Response;getStatus());}}自定义错误返回@Data@AllArgsConstructor@NoArgsConstructorpublicclassErrorMsg{privateStringcode;privateStringmsg;}TestController@RestControllerpublicclassPersonController{@GetMapping("/getPerson")publicStringgetPerson(){thrownewPersonNotFoundException("你要找的人不存在",HttpStatus.NOT_FOUND);}}启动程序,访问:http://localhost:8080/getPerson2,基于“问题详情”的业务异常处理是基于我们常规的异常处理,其实可以满足我们的业务需求。使用RFC7807规范,我们可以去掉自定义的异常错误格式(ErrorMsg),使用Spring6.0提供的ProblemDetail,这样以后的异常返回格式就不用再自定义了,而且不同项目之间有标准,使客户在使用时具有可预见性。Spring6.0的方法也很简单,我们只需要将自己返回的ErrorMsg修改为ProblemDetail即可。我们来看看示例代码:@RestControllerAdvicepublicclassGlobalExceptionHandler{@ExceptionHandler(PersonNotFoundException.class)publicProblemDetailpersonNotFoundHandler(PersonNotFoundExceptione){ProblemDetailproblemDetail=ProblemDetail.forStatus(UttpproStatus.RIT_emFOUND("https");/www.toutiao.com/c/user/token/MS4wLjABAAAAJxW0bvHKNNwIpcsocIDAjNHHNXg2yaj1upViHO2JVNw/"));problemDetail.setTitle("找不到人");problemDetail.setDetail(String.format("错误信息:'%s'",e.getMessage()));returnproblemDetail;}}值得一提的是,ProblemDetail还支持设置一个Map的属性:privateMapproperties;这也为我们的自定义扩展提供了更多的空间。启动,访问:http://localhost:8080/getPerson,其实错误返回是符合RFC7807规范的,注意返回的header信息,可以看到返回数据的媒体类型为:application/problem+json:感谢支持看我的书:《从企业级开发到云原生微服务:Spring Boot实战》参考:https://docs.spring.io/spring-framework/docs/6.0.0-RC2/javadoc-api/org/springframework/http/ProblemDetail.html文章来自:Wesley热爱科学的人,如需转载本文,请联系今日热爱科学的卫斯理头条号。