Spring Boot 使用 @ControllerAdvice

学习在 Spring Boot 如何使用 @ControllerAdvice 注解。它其实是 Spring MVC 提供的功能,是一个增强的 Controller ,主要可以实现三个方面的功能:全局异常处理、全局数据绑定、全局数据预处理

1 全局异常处理

@ControllerAdvice
public class MyControllerAdvice {
    @ExceptionHandler(ArrayIndexOutOfBoundsException.class)
    public void globalException(ArrayIndexOutOfBoundsException e, HttpServletResponse resp) throws IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.write("出错了:globalException");
        out.flush();
        out.close();
    }

    /*@ExceptionHandler(ArrayIndexOutOfBoundsException.class)
    public ModelAndView globalException2(ArrayIndexOutOfBoundsException e) throws IOException {
        ModelAndView mv = new ModelAndView("myerror");
        mv.addObject("error", "出错了:globalException2");
        return mv;
    }*/
}
  1. 在类上添加 @ControllerAdvice 注解。
  2. 在方法上添加 @ExceptionHandler 注解,用来指明异常的处理类型,比如这里指定为 ArrayIndexOutOfBoundsException ,则空指针异常就不会进到这个方法中来。
  3. 在该类中,可以定义多个方法,不同的方法处理不同的异常,例如专门处理空指针的方法、专门处理数组越界的方法,或者也可以定义一个通用的方法处理所有的异常。

新建测试接口:

@Controller
public class TestController {
    @ResponseBody
    @GetMapping("/globalException")
    public String globalException(Model model){
        String[] arr = {"a","b"};
        System.out.println(arr[2]);
        return "success";
    }
}

启动项目,访问 http://120.0.0.1:8080/globalException 来验证。

2 全局数据绑定

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

@ControllerAdvice
public class MyControllerAdvice {
    @ModelAttribute(value = "dataKey")
    public Map<String,Object> globalData() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "cxy35");
        map.put("address", "https://cxy35.com");
        return map;
    }
}
  1. 在类上添加 @ControllerAdvice 注解。
  2. 在方法上添加 @ModelAttribute 注解,标记该方法的返回数据是一个全局数据,默认情况下,这个全局数据的 key 就是返回的变量名,value 就是方法返回值,当然可以通过 @ModelAttribute 注解的 name 属性去重新指定 key。

新建测试接口:

@Controller
public class TestController {
    @ResponseBody
    @GetMapping("/globalData")
    public String globalData(Model model) {
        String globalData = "";
        Map<String, Object> map = model.asMap();
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            globalData += ("【"+key + ":" + map.get(key)+"】");
        }
        return globalData;
    }
}

启动项目,访问 http://120.0.0.1:8080/globalData 来验证。

3 全局数据预处理

新建 2 个实体类, Book 和 Author :

public class Book {
    private String name;
    private Double price;

    // getter/setter
}
public class Author {
    private String name;
    private Integer age;

    // getter/setter
}

新建测试接口:

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

因为 2 个实体类都有一个 name 属性,从前端传递时,无法区分。可以通过 @ControllerAdvice 的全局数据预处理来解决这个问题。

@ControllerAdvice
public class MyControllerAdvice {
    @InitBinder("a")
    public void initPreParamA(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("a.");
    }

    @InitBinder("b")
    public void initPreParamB(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("b.");
    }
}
  1. 在类上添加 @ControllerAdvice 注解。
  2. 在方法上添加 @InitBinder 注解,比如 @InitBinder(“b”) 注解表示该方法用来处理和 Book 相关的参数,统一给参数添加一个 b 前缀,即请求参数要有 b 前缀。

修改测试接口:

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

启动项目,通过 Postman 的 POST 请求 http://120.0.0.1:8080/initPreParam?b.name=三国演义&b.price=88.8&a.name=罗贯中&a.age=99 来验证。



扫码关注微信公众号 程序员35 ,获取最新技术干货,畅聊 #程序员的35,35的程序员# 。独立站点:https://cxy35.com

好的,很高兴能回答您的问题。 首先,让我们了解一下 @ControllerAdvice 注解。它是 Spring MVC 框架提供的一种全局异常处理机制,可以让我们在一个地方集中处理所有 Controller 抛出的异常。 使用 @ControllerAdvice 注解的类可以包含多个 @ExceptionHandler 注解的方法,每个方法处理不同的异常类型。当 Controller 抛出异常时,Spring 会根据异常类型找到对应的 @ExceptionHandler 方法进行处理。 以下是一个简单的 @ControllerAdvice 示例: ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Something went wrong!"); } @ExceptionHandler(MyCustomException.class) public ResponseEntity<String> handleMyCustomException(MyCustomException e) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage()); } } ``` 在上面的例子中,我们定义了两个 @ExceptionHandler 方法,分别处理 Exception 和 MyCustomException 类型的异常。 如果您想要更细粒度地处理异常,可以在 @ExceptionHandler 注解中指定具体的异常类型,如下所示: ```java @ExceptionHandler({IOException.class, SQLException.class}) public void handleIOExceptionOrSQLException() { // ... } ``` 另外,@ControllerAdvice 还支持自定义返回值类型和异常解析器,具体可以参考 Spring 官方文档。 最后,关于统一处理异常,除了使用 @ControllerAdvice,我们还可以使用 Spring Boot 提供的 ErrorController 接口或实现自己的异常处理器。 希望能对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值