🎉🎉《Spring Boot实战案例合集》目前已更新188个案例,我们将持续不断的更新。文末有电子书目录。
💪💪永久更新承诺
我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务。
💌💌如何获取
订阅我们的合集《点我订阅》,并通过私信联系我们,我们将第一时间将电子书发送给您。
环境:SpringBoot3.4.2
1. 简介
在Spring Boot项目中,@RestControllerAdvice是一个非常实用的注解,它用于全局处理应用程序中的异常,并将异常信息以RESTful的方式返回给客户端,使得代码更加整洁和易于维护。
@RestControllerAdvice简介
@RestControllerAdvice是SpringMVC框架提供的一个组合注解,它结合了@ControllerAdvice和@ResponseBody的功能。@ControllerAdvice用于定义全局控制器层面的增强逻辑,比如全局异常处理、全局数据绑定等;而@ResponseBody则用于将方法的返回值作为HTTP响应体返回。
全局数据绑定,请查看下面这篇文章:
使用场景
当你希望统一处理应用程序中所有控制器的异常,并将异常信息以JSON格式返回给客户端时,可以使用@RestControllerAdvice。这将以友好的错误提示给前端开发者或用户。
基本用法
这里由于不是专门来讲@ControllerAdvice,所以仅仅给出简单使用示例
public class GlobalExceptionHandler {// 处理特定异常的方法public ResponseEntity<ErrorResponse> handleException(Exception e) {ErrorMessage error = new ErrorMessage(e.getMessage()) ;returnnew ResponseEntity<>(error, HttpStatus.BAD_REQUEST) ;}}
查看更多关于全局异常处理,请查看下面这篇文章:
Spring MVC异常处理:这几种方式让你轻松应对,你都使用了那些方式?
以上对SpringBoot项目中关于异常处理做了简单的介绍,并且这应该也是绝大多数项目的基操。而接下来将给大家介绍Spring针对REST服务提供的一个异常处理类,该类的原理基本上与上面介绍的相同,只是Spring针对各种不同的异常做了定制化的处理,这个类是:ResponseEntityExceptionHandler
2. 实战案例
ResponseEntityExceptionHandler是个抽象类,它可以处理 Spring MVC 引发的异常,并提供钩子来自定义响应体。我们只需要创建 ResponseEntityExceptionHandler 的子类,使用 @ControllerAdvice 对其进行注解,覆盖必要的方法,并将其声明为 Spring Bean即可。
该类的核心方法如下:
public abstract class ResponseEntityExceptionHandler {HttpRequestMethodNotSupportedException.class,HttpMediaTypeNotSupportedException.class,HttpMediaTypeNotAcceptableException.class,MissingPathVariableException.class,MissingServletRequestParameterException.class,ServletRequestBindingException.class,ConversionNotSupportedException.class,TypeMismatchException.class,HttpMessageNotReadableException.class,HttpMessageNotWritableException.class,MethodArgumentNotValidException.class,MissingServletRequestPartException.class,BindException.class,NoHandlerFoundException.class,AsyncRequestTimeoutException.class})public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) throws Exception {HttpHeaders headers = new HttpHeaders();if (ex instanceof HttpRequestMethodNotSupportedException) {HttpStatus status = HttpStatus.METHOD_NOT_ALLOWED;return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, headers, status, request);}// ...其它if else判断else {throw ex;}}protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {pageNotFoundLogger.warn(ex.getMessage());Set<HttpMethod> supportedMethods = ex.getSupportedHttpMethods();if (!CollectionUtils.isEmpty(supportedMethods)) {headers.setAllow(supportedMethods);}return handleExceptionInternal(ex, null, headers, status, request);}// 其它异常处理方法}
该类中的处理异常类的方法都是protected,这写方法我们都可以在子类中进行重写,定制自己的处理逻辑。在这些具体异常处理的方法中都会调用同一个方法 handleExceptionInternal,所以这里我们既可以重写具体异常处理的方法,也可以重新改方法进行统一的处理。
自定义实现
在该子类中我只针对一个异常处理(以参数转换异常为例)及handleExceptionInternal进行重写。
有如下接口:
("/{id}")public Object ex(("id")Long id) {return String.format("接收到参数:%d", id) ;}
当请求的URL是:/demos/666a时程序将抛出异常,类型无法转换为Number类型。如下异常:
接下来进行异常处理
public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {protected ResponseEntity<Object> handleTypeMismatch(TypeMismatchException ex,HttpHeaders headers,HttpStatus status,WebRequest request) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body(String.format("参数解析错误: %s", ex.getMessage())) ;}}
输出结果
重写统一结果返回
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,HttpStatus status, WebRequest request) {Rresult = R.failure(ex.getMessage()) ;return ResponseEntity.ok(result) ;}
输出结果
扩展异常处理
在实际开发中都会定义自己的异常或者是发生其它异常,在这些情况下上面的类就没法满足需求了,我们可以在上面的子类中在定义自己的异常处理。
public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {({Exception.class})public ResponseEntity<Object> systemExceptionHandle(Exception ex) {if (ex instanceof BusinessException) {return ResponseEntity.ok(R.failure(String.format("业务处理异常: %s", ex.getMessage()))) ;} else if (ex instanceof DataErrorException) {return ResponseEntity.ok(R.failure(String.format("数据错误异常: %s", ex.getMessage()))) ;} else {return ResponseEntity.ok(R.failure(ex.getMessage())) ;}}}
在创建ResponseEntityExceptionHandler子类的同时,我们还可以根据自己实际业务情况定义其它的异常处理句柄。
以上是本篇文章的全部内容,如对你有帮助就请作者吃个棒棒糖🍭。
推荐文章
面试官:说说@Configuration与@Component有什么区别?
全新升级:SpringBoot Admin可视化监控工具全面解析
Spring Boot全局异常处理:3种方案,第三种性能40%的提升
高级开发!Spring Boot自定义@Download实现任意文件下载(支持异步流式)
性能优化!Spring Boot 优化JPA插入操作,性能提升N倍,尤其批量操作
解锁Spring资源Resource的强大功能,提升开发效率
SpringBoot一个注解轻松实现多版本Rest API接口控制
【高效开发】使用Spring Data JPA的QBE功能,轻松构建查询条件
你以为只有Controller一种接口定义方式?详解Web函数式接口


