大数跨境
0
0

强大!Spring非常实用的内置类专门处理Rest API异常

强大!Spring非常实用的内置类专门处理Rest API异常 Spring全家桶实战案例
2025-11-11
0
导读:强大!Spring非常实用的内置类专门处理Rest API异常
Spring Boot 3实战案例锦集PDF电子书已更新至130篇!
图片

🎉🎉《Spring Boot实战案例合集》目前已更新188个案例,我们将持续不断的更新。文末有电子书目录。

💪💪永久更新承诺

我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务

💌💌如何获取
订阅我们的合集点我订阅,并通过私信联系我们,我们将第一时间将电子书发送给您。

→ 现在就订阅合集

环境:SpringBoot3.4.2



1. 简介

在Spring Boot项目中,@RestControllerAdvice是一个非常实用的注解,它用于全局处理应用程序中的异常,并将异常信息以RESTful的方式返回给客户端,使得代码更加整洁和易于维护。

@RestControllerAdvice简介

@RestControllerAdvice是SpringMVC框架提供的一个组合注解,它结合了@ControllerAdvice@ResponseBody的功能。@ControllerAdvice用于定义全局控制器层面的增强逻辑,比如全局异常处理、全局数据绑定等;而@ResponseBody则用于将方法的返回值作为HTTP响应体返回。

全局数据绑定,请查看下面这篇文章:

@InitBinder注解会用吗?该如何使用?

使用场景

当你希望统一处理应用程序中所有控制器的异常,并将异常信息以JSON格式返回给客户端时,可以使用@RestControllerAdvice。这将以友好的错误提示给前端开发者或用户。

基本用法

这里由于不是专门来讲@ControllerAdvice,所以仅仅给出简单使用示例

@RestControllerAdvicepublic class GlobalExceptionHandler {// 处理特定异常的方法  @ExceptionHandler(Exception.class)    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 {  @ExceptionHandler({      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    })  @Nullable  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进行重写。

有如下接口:

@GetMapping("/{id}")public Object ex(@PathVariable("id")Long id) {  return String.format("接收到参数:%d", id) ;}

当请求的URL是:/demos/666a时程序将抛出异常,类型无法转换为Number类型。如下异常:

接下来进行异常处理

@ControllerAdvicepublic class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
  @Override  protected ResponseEntity<ObjecthandleTypeMismatch(      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<ObjecthandleExceptionInternal(  Exception ex, Object body, HttpHeaders headers,   HttpStatus status, WebRequest request) {  Rresult = R.failure(ex.getMessage()) ;  return  ResponseEntity.ok(result) ;}

输出结果

扩展异常处理

在实际开发中都会定义自己的异常或者是发生其它异常,在这些情况下上面的类就没法满足需求了,我们可以在上面的子类中在定义自己的异常处理。

@ControllerAdvicepublic class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {  @ExceptionHandler({Exception.class})  public ResponseEntity<ObjectsystemExceptionHandle(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一个很少使用但是非常强大的功能

解锁Spring资源Resource的强大功能,提升开发效率

SpringBoot一个注解轻松实现多版本Rest API接口控制

【高效开发】使用Spring Data JPA的QBE功能,轻松构建查询条件

SpringCloud项目开发中实用技巧总结

SpringWeb开发中实用技巧

SpringBoot这些条件注解助你高效开发

你以为只有Controller一种接口定义方式?详解Web函数式接口

一个很有意思的Spring注入问题,你遇到过吗?

图片
图片
图片
图片
图片
图片
图片

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读285
粉丝0
内容832