SpringBoot中使用@ControllerAdvice注解详解

 更新时间:2023年10月12日 10:23:17   作者:CharlesYao  
这篇文章主要介绍了SpringBoot中使用@ControllerAdvice注解详解,@ControllerAdvice,是Spring3.2提供的新注解,它是一个Controller增强器,可对controller中被 @RequestMapping注解的方法加一些逻辑处理,需要的朋友可以参考下

@ControllerAdvice注解

@ControllerAdvice,是Spring3.2提供的新注解,它是一个Controller增强器,可对controller中被 @RequestMapping注解的方法加一些逻辑处理。主要作用有一下三种

  • 通过@ControllerAdvice注解可以将对于控制器的全局配置放在同一个位置。
  • 注解了@ControllerAdvice的类的方法可以使用@ExceptionHandler、@InitBinder、@ModelAttribute注解到方法上。
    • @ExceptionHandler:用于全局处理控制器里的异常,进行全局异常处理
    • @InitBinder:用来设置WebDataBinder,用于自动绑定前台请求参数到Model中,全局数据预处理。
    • @ModelAttribute:本来作用是绑定键值对到Model中,此处让全局的@RequestMapping都能获得在此处设置的键值对 ,全局数据绑定。
  • @ControllerAdvice注解将作用在所有注解了@RequestMapping的控制器的方法上。

全局异常处理

需要配合@ExceptionHandler使用。 当将异常抛到controller时,可以对异常进行统一处理,规定返回的json格式或是跳转到一个错误页面

/**
 * @ClassName:CustomExceptionHandler
 * @Description: 全局异常捕获
 * @Author: 
 * @Date: 2020/5/25、13:38
 */
@Slf4j
@ControllerAdvice(annotations = {Controller.class, RestController.class})
public class WebControllerAdvice {
    @ResponseBody
    @ExceptionHandler
    public Map errorHandler(Exception ex) {
        Map errorMap = new HashMap();
        errorMap.put("code", 400);
        //判断异常的类型,返回不一样的返回值
        if (ex instanceof MissingServletRequestParameterException) {
            errorMap.put("msg", "缺少必需参数:" + ((MissingServletRequestParameterException) ex).getParameterName());
        } else if (ex instanceof MyException) {
            errorMap.put("msg", "这是自定义异常");
        }
        return errorMap;
    }

自定义异常

/**
 * @ClassName:MyException
 * @Description: 定义异常
 * @Author: 
 * @Date: 2020/5/25、13:44
 */
public class MyException extends RuntimeException {
    private long code;
    private String msg;
    public MyException(Long code, String msg) {
        super(msg);
        this.code = code;
        this.msg = msg;
    }
    public MyException(String msg) {
        super(msg);
        this.msg = msg;
    }
}

测试Controller

@RestController
public class TestController {
    @RequestMapping("testException")
    public String testException() throws Exception{
        throw new MissingServletRequestParameterException("name","String");
    }
    @RequestMapping("testMyException")
    public String testMyException() throws MyException{
        throw new MyException("i am a myException");
    }

测试结果:

{"msg":"缺少必需参数:name","code":400}

{"msg":"这是自定义异常","code":400}

全局数据绑定

全局数据绑定功能可以用来做一些初始化的数据操作,我们可以将一些公共的数据定义在添加了 @ControllerAdvice 注解的类中,这样,在每一个 Controller 的接口中,就都能够访问导致这些数据。使用步骤,首先定义全局数据,如下:

/**
 * @ClassName:MyGlobalDataHandler
 * @Description: 全局数据
 * @Author: 
 * @Date: 2020/5/25、14:01
 */
@ControllerAdvice
public class MyGlobalDataHandler {
    @ModelAttribute(name = "md")
    public Map<String,Object> getGlobalData(){
        HashMap<String, Object> map = new HashMap<>();
        map.put("age", 99);
        map.put("gender", "男");
        return map;
    }

使用 @ModelAttribute 注解标记该方法的返回数据是一个全局数据,默认情况下,这个全局数据的 key 就是返回的变量名,value 就是方法返回值,当然开发者可以通过 @ModelAttribute 注解的 name 属性去重新指定 key。定义完成后,在任何一个Controller 的接口中,都可以获取到这里定义的数据:

  @GetMapping("/hello")
    public String hello(Model model) {
        Map<String, Object> map = model.asMap();
        System.out.println(map);
        int i = 1 / 0;
        return "hello controller advice";
    }

运行结果

{md={gender=男, age=99}}

2020-05-25 14:04:44.388 - [WARN ] - [org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver:logException:197] - Resolved [java.lang.ArithmeticException: / by zero]

全局数据预处理

考虑我有两个实体类,Book 和 Author,分别定义如下:

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Book extends BaseEntity {
    private String name;
    private Long price;
}
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Author  extends BaseEntity {
    private String name;
    private Long price;
}

如果我定义一个数据添加接口,如下:

@PostMapping("/book")
public void addBook(Book book, Author author) {
    System.out.println(book);
    System.out.println(author);
}

这个时候,添加操作就会有问题,因为两个实体类都有一个 name 属性,从前端传递时 ,无法区分。此时,通过 @ControllerAdvice 的全局数据预处理可以解决这个问题

解决步骤如下:

1.给接口中的变量取别名

@PostMapping("/book")
public void addBook(@ModelAttribute("b") Book book, @ModelAttribute("a") Author author) {
    System.out.println(book);
    System.out.println(author);
}

2.进行请求数据预处理

在 @ControllerAdvice 标记的类中添加如下代码:

@InitBinder("b")
public void b(WebDataBinder binder) {
    binder.setFieldDefaultPrefix("b.");
}
@InitBinder("a")
public void a(WebDataBinder binder) {
    binder.setFieldDefaultPrefix("a.");
}

@InitBinder("b") 注解表示该方法用来处理和Book和相关的参数,在方法中,给参数添加一个 b 前缀,即请求参数要有b前缀

3.发送请求

请求发送时,通过给不同对象的参数添加不同的前缀,可以实现参数的区分

到此这篇关于SpringBoot中使用@ControllerAdvice注解详解的文章就介绍到这了,更多相关SpringBoot的@ControllerAdvice注解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MyBatis-Plus通过version机制实现乐观锁的思路

    MyBatis-Plus通过version机制实现乐观锁的思路

    version机制的核心思想就是,假设发生并发冲突的几率很低,只有当更新数据的时候采取检查是否有冲突,而判断是否有冲突的依据就是version的值是否被改变了,这篇文章主要介绍了MyBatis-Plus通过version机制实现乐观锁的思路,需要的朋友可以参考下
    2021-09-09
  • Mybatis使用注解实现复杂动态SQL的方法详解

    Mybatis使用注解实现复杂动态SQL的方法详解

    当使用 MyBatis 注解方式执行复杂 SQL 时,你可以使用 @Select、@Update、@Insert、@Delete 注解直接在接口方法上编写 SQL,本文给大家介绍了Mybatis如何使用注解实现复杂动态SQL,文中有相关的代码示例供大家参考,需要的朋友可以参考下
    2023-12-12
  • Java调用接口如何获取json数据解析后保存到数据库

    Java调用接口如何获取json数据解析后保存到数据库

    这篇文章主要介绍了Java调用接口如何获取json数据解析后保存到数据库问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • springBoot详解集成Swagger流程

    springBoot详解集成Swagger流程

    Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化 Restful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法、参数和模型紧密集成到服务器端的代码,允许API来始终保持同步
    2022-06-06
  • 一步步教你整合SSM框架(Spring MVC+Spring+MyBatis)详细教程

    一步步教你整合SSM框架(Spring MVC+Spring+MyBatis)详细教程

    使用SSM(Spring、SpringMVC和Mybatis)已经有段时间了,项目在技术上已经没有什么难点了,基于现有的技术就可以实现想要的功能,下面这篇文章主要给大家介绍了关于整合SSM框架:Spring MVC + Spring + MyBatis的相关资料,需要的朋友可以参考下。
    2017-07-07
  • 详解Java8中接口的默认方法和静态方法

    详解Java8中接口的默认方法和静态方法

    Java 8是Java语言的一个重要版本,其中引入了许多新特性和改进,其中一个值得关注的特性是接口的默认方法和静态方法,本文就来和大家简单讲讲吧
    2023-05-05
  • SpringBoot工程下Lombok的应用教程详解

    SpringBoot工程下Lombok的应用教程详解

    这篇文章主要给大家介绍了关于SpringBoot工程下Lombok应用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Java使用apache poi操作excel的方式

    Java使用apache poi操作excel的方式

    这篇文章主要介绍了Java使用apache poi进行excel相关操作,本文主要针对Apache POI对excel的操作进行介绍,主要包括如何创建一个excel、录入数据、读取excel数据的方式,需要的朋友可以参考下
    2022-05-05
  • 解决SpringBoot项目在启动后自动关闭的问题

    解决SpringBoot项目在启动后自动关闭的问题

    今天搭建了一个SpringBoot项目,但是在启动之后就自行关闭了,下面通过本文给大家介绍SpringBoot项目在启动后自动关闭问题及解决方法,需要的朋友可以参考下
    2023-08-08
  • springboot返回图片流的实现示例

    springboot返回图片流的实现示例

    本文主要介绍了springboot返回图片流的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08

最新评论