当前位置: 首页 > article >正文

@RestControllerAdvice注解

@RestControllerAdvice 是 Spring 4 引入的一个组合注解,它结合了 @ControllerAdvice@ResponseBody,专门用于处理 @RestController 类型的控制器中的全局异常、全局数据绑定和全局模型属性等问题。在 Spring Boot 中,@RestControllerAdvice 通常用于统一处理应用中的异常,确保系统中的异常处理逻辑集中管理。

1. @RestControllerAdvice 的组成

@RestControllerAdvice 实际上是两个注解的组合:

  • @ControllerAdvice:是一个用于全局处理 Spring MVC 中异常的注解,它的作用范围不仅限于某个单一的控制器,而是全局适用。
  • @ResponseBody:表示返回的对象会自动序列化为 JSON 格式,直接作为 HTTP 响应体返回。

因此,@RestControllerAdvice 结合了这两者的功能,表示该类是一个控制器增强器,可以全局处理异常、模型属性或数据绑定等,而且返回的结果会直接作为 HTTP 响应体(通常是 JSON 格式)返回给客户端。

2. @RestControllerAdvice 的功能

@RestControllerAdvice 主要有以下几个功能:

1. 全局异常处理 (@ExceptionHandler)

@RestControllerAdvice 可以结合 @ExceptionHandler 注解来全局处理异常。应用中抛出的异常会被该类中的方法捕获并处理,然后返回合适的响应结果。

例如:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ResultData handleException(Exception e) {
        log.error("Global exception occurred: ", e);
        return ResultData.fail("500", "Internal Server Error");
    }
}
  • @ExceptionHandler(Exception.class):表示该方法将处理所有类型的 Exception 异常。
  • handleException 方法会捕获到任何未被其他异常处理器捕获的 Exception,然后返回统一的错误响应。
2. 全局模型属性 (@ModelAttribute)

@RestControllerAdvice 可以在控制器方法执行前,通过 @ModelAttribute 注解向所有的控制器方法添加公共模型属性。这样,所有的控制器方法都可以访问到这些公共属性。

例如:

@RestControllerAdvice
public class GlobalModelAttribute {

    @ModelAttribute
    public void addAttributes(Model model) {
        model.addAttribute("globalAttribute", "This is a global attribute");
    }
}
  • @ModelAttribute 注解的方法会在每个控制器方法执行之前执行。这里添加了一个名为 globalAttribute 的属性,这个属性会自动添加到每个控制器方法的 Model 中。
3. 全局数据绑定 (@InitBinder)

@RestControllerAdvice 也可以通过 @InitBinder 注解定义全局的数据绑定方法。@InitBinder 用于初始化数据绑定,通常用于处理请求参数的格式化和转换。

例如:

@RestControllerAdvice
public class GlobalDataBinder {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.setDisallowedFields("password");
    }
}
  • @InitBinder 注解的方法可以用来处理请求参数的绑定和验证。在上面的例子中,所有请求参数中的 password 字段将被排除在外,不能进行绑定。

3. 常见用法

1. 全局异常处理

在 Spring Boot 中,异常处理通常分为两种:

  • 局部异常处理:每个控制器方法使用 try-catch 语句或者 @ExceptionHandler 处理特定的异常。
  • 全局异常处理:通过 @RestControllerAdvice 统一处理整个应用中的异常。

示例:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultData<String> handleException(Exception e) {
        log.error("Unexpected exception occurred: ", e);
        return ResultData.fail("500", "Internal Server Error");
    }

    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ResultData<String> handleResourceNotFound(ResourceNotFoundException e) {
        log.error("Resource not found: ", e);
        return ResultData.fail("404", e.getMessage());
    }
}
  • 通过 @ExceptionHandler 注解,可以指定不同的异常类型来进行处理。例如,Exception 类的异常返回 500 错误,ResourceNotFoundException 返回 404 错误。
  • 使用 @ResponseStatus 注解可以自定义返回的 HTTP 状态码。
2. 返回统一格式的响应

在实际应用中,通常会要求所有的 API 响应都遵循统一的格式。使用 @RestControllerAdvice 可以确保异常处理的响应符合统一的格式。

示例:

public class ResultData<T> {
    private String code;
    private String message;
    private T data;

    // 省略构造方法、getter、setter等
}

GlobalExceptionHandler 中,可以返回 ResultData 类型的对象,确保所有的异常响应都有一致的结构:

@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ResultData<String> handleException(Exception e) {
    return new ResultData<>("500", "Internal Server Error", null);
}
3. 全局模型属性和数据绑定

@RestControllerAdvice 还可以用来定义全局的模型属性和数据绑定逻辑。比如,可以在全局中设置一些公共的参数,或者格式化请求参数。

示例:

@RestControllerAdvice
public class GlobalDataBinder {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
    }
}

在这个例子中,@InitBinder 配置了一个全局的数据绑定,允许所有的控制器方法接收和格式化 Date 类型的参数。

4. @RestControllerAdvice 的优势

  • 集中管理异常:通过 @RestControllerAdvice,你可以把全局的异常处理逻辑集中在一个地方,而不需要在每个控制器中重复写异常处理代码。
  • 统一的错误响应:能够保证整个应用中返回的错误响应有统一的结构(例如 ResultData)。
  • 增强可维护性:集中式的异常处理和数据绑定配置使得代码更易维护和扩展。当业务需求发生变化时,只需要修改 @RestControllerAdvice 中的逻辑,而无需修改每个控制器的代码。
  • 减少冗余代码:通过全局处理,可以避免在多个控制器中重复定义相同的异常处理逻辑或数据绑定逻辑。
    是的,@RestControllerAdvice@ControllerAdvice 都可以实现相似的功能,特别是在处理全局模型属性和数据绑定时,使用 @ControllerAdvice 是完全可以的。两者的区别主要体现在以下几个方面:

5.@RestControllerAdvicevs@ControllerAdvice

@RestControllerAdvice vs @ControllerAdvice

  • @ControllerAdvice 是 Spring 的一个用于全局处理控制器异常、数据绑定、模型属性等的注解,适用于所有类型的控制器。它结合了 @Controller@ResponseBody 的功能,用于处理普通的控制器(即返回视图的控制器,通常是 .jsp.html 等)。

  • @RestControllerAdvice@ControllerAdvice@ResponseBody 的组合注解,适用于 RESTful 风格的控制器,即返回 JSON 或 XML 等数据的控制器。它与 @RestController 结合使用,可以自动将返回值转换为 JSON 格式的响应体,而 @ControllerAdvice 适用于传统的基于视图的控制器。

具体区别

  • 返回类型

    • @ControllerAdvice 默认处理的是基于视图的返回类型,也就是说,它通常返回的是页面视图(例如 .jsp.html)而非 JSON 数据。
    • @RestControllerAdvice 用于 RESTful API 服务,它默认会返回 JSON 数据,而不需要额外配置 @ResponseBody
  • 场景选择

    • 使用 @ControllerAdvice:如果你的应用主要是传统的 Spring MVC 控制器(处理视图渲染),那么 @ControllerAdvice 是合适的。
    • 使用 @RestControllerAdvice:如果你的应用是基于 RESTful API 服务,返回 JSON 或 XML 数据,并且你希望所有的异常处理、数据绑定、模型属性等也以 JSON 格式返回,那么 @RestControllerAdvice 更为合适。

实际应用中的选择

  • 如果你在做的是 传统的 Spring MVC 应用,并且通过控制器返回的是 视图(HTML),那么使用 @ControllerAdvice 是合适的。
  • 如果你在做的是 RESTful API 应用,返回的是 JSON 或 XML 数据,并且希望全局异常、全局数据绑定、全局模型属性等都以 JSON 格式返回给客户端,那么 @RestControllerAdvice 更为合适。

总结

@RestControllerAdvice 是 Spring 提供的一个功能强大的注解,允许你为整个应用提供全局的异常处理、全局模型属性和全局数据绑定等功能。它的主要优势是能够集中管理异常处理,并且提供统一的响应结构,使得应用程序更加清晰、易于维护,尤其在处理大规模应用时,能够极大地减少代码冗余,提高开发效率和系统的健壮性。


http://www.kler.cn/a/461202.html

相关文章:

  • 商用车自动驾驶,迎来大规模量产「临界点」?
  • 前端异常处理合集
  • 双目视觉:reprojectImageTo3D函数
  • 国产编辑器EverEdit - 常用资源汇总
  • GAN对抗生成网络(一)——基本原理及数学推导
  • C# 设计模式(结构型模式):代理模式
  • OneOS操作系统入门-驱动-03:I2C总线及驱动
  • java实现excel导入参考资料合集
  • Zookeeper在中间件的应用和在Spring Boot业务系统中实现分布式锁和注册中心的解决方案
  • CT 扫描显示 USB-C 电缆可能隐藏复杂的恶意硬件
  • 强化学习方法分类详解
  • 电脑cxcore.dll文件缺失怎么办?cxcore100.dll缺失问题解决办法
  • svn不能添加.a文件
  • 从零开发一套UWB定位系统需要多长时间?UWB超宽带定位系统源码
  • 计算机网络•自顶向下方法:IP分片与重组
  • Dell服务器升级ubuntu 22.04失败解决
  • 基于Django+python的Python在线自主评测系统设计与实现
  • caddyfile如何托管静态文件,首页默认为index.html
  • 如何在谷歌浏览器中创建安全的密码
  • 深入理解 pytest Fixture 方法及其应用
  • Java子线程无法获取Attributes的解决方法
  • 【Linux】基础IO-----软硬链接与动静态库
  • docker安装Home Assistant正常下载笔记
  • el-pagination 为什么只能展示 10 条数据(element-ui@2.15.13)
  • 怎么在家访问公司服务器?
  • C# 实用工具分享(1)