@ControllerAdvice
这个注解乍一看,咋这么有点熟悉,和 @Controller
咋这么像啊?没错,@ControllerAdvice
这个注解就是一个增强版的 @Controller
。那么我们今天要了解的这个注解有什么用呢?功能如下:
- 1、全局异常处理
- 2、全局数据绑定
- 3、全局数据预处理
注意:
这个注解并不是 Spring Boot 中特有的,这个注解是 SpringMVC 中提供的,所以在 Spring Boot 中可以直接使用。
全局异常处理
对于全局异常的处理还是非常简单的,我们只需要自己定义个类,添加该注解 @ControllerAdvice
即可,代码如下:
@ControllerAdvice
public class CustomException {
@ExceptionHandler
public ModelAndView customException(Exception e) {
ModelAndView mv = new ModelAndView();
mv.addObject("message", e.getMessage());
mv.setViewName("yexiaomo");
return mv;
}
}
在 resources 目录下的 templates 目录下自定义自己的错误页面,这里小编引入了 Thymeleaf ,代码如下:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div th:text="${message}"></div>
</body>
</html>
小编在其它的 Controller 代码中定义了一个除数不能为零的异常,启动项目访问:http://localhost:8080/hello
@ExceptionHandler
注解用来指明异常的处理类型,如果想处理具体的异常,我们指定具体的异常类即可。例如,如果该注解里指定的为 NullpointerException ,那么我们程序中的 空指针异常才会被我们自定义的异常处理。
在该类中,我们可以定义很多个方法,不同的方法可以处理不同的异常,例如专门处理空指针异常、数组越界异常的等等方法,我们也可以直接写一个如同小编的上面的案例一样,一个方法处理所有的异常信息。
全局数据绑定
全局数据绑定功能可以用来做一些初始化的数据操作,我们可以将一些公共的数据定义在添加了 ControllerAdvice
注解的类中,这样,在每个 Controller 的接口中,就都能狗访问导致这些数据了。
首先我们要先定义放置全局数据的类,如下:
@ControllerAdvice
public class CustomException {
@ModelAttribute
public Map<String, Object> myData() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("username", "yexiaomo");
map.put("password", "111");
return map;
}
}
其中使用
@ModelAttribute
这个注解标记该方法的返回数据是一个全局数据,默认情况下,这个全局数据的 key 就是返回的变量名, value 就是方法返回值,我们也可以使用@ModelAttribut
注解的 name 属性重新定义 key。
然后我们在任意一个 Controller 中,都可以获取到这里定义的数据:
@RestController
public class HelloController {
@GetMapping("/data")
public void getData(Model model) {
Map<String, Object> map = model.asMap();
Set<String> keySet = map.keySet();
for (String key:
keySet) {
Object o = map.get(key);
System.out.println(key + " : " + o);
}
}
@RequestMapping("/hello")
public String hello() {
int a = 10/0;
return "hello";
}
}
启动项目,访问:http://localhost:8080/data
全局数据预处理
假如我们的一个项目中在定义的时候,有两个类,其中相同的属性:
//书类
public class Book {
private String name;
private double price;
//此处省略toString方法,以及 get 和 set 方法
}
//作者类
public class Author {
private String name;
private Integer age;
//此处省略toString方法,以及 get 和 set 方法
}
我们有个数据添加接口,如下:
@RestController
public class BookController {
@PostMapping("/book")
public void book(Book book, Author author) {
System.out.println(book);
System.out.println(author);
}
}
这时我们启动项目,使用 Postman 工具测试:
然后我们看后台数据的打印如下:
完全不符合我的需求,如果我们在项目设计的时候我们可以通过定义不同的属性名即可避免,但是项目已经开发了这么就修改起来肯定是不可能的,那么我们要怎么做呢?
这就是小编要讲的 @ControllerAdvice
注解的第三个功能全局数据预处理:
- 1、我们首先要在我们的接口传入的变量取别名:
@RestController
public class BookController {
@PostMapping("/book")
public void book(@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")
:该注解中的参数要和我们自定义的请求数据的别名一致,然后我们需要在方法中给b 参数添加一个 b 前缀(可自定义), a 参数添加一个 a 前缀(可自定义)。
- 3、发送请求
我们在在发请求时要给每个对象中的属性添加我们自定义的前缀,如下:
这时我们在看后台返回的数据:
介绍完毕,本是 SpringMVC 中的注解,那么我们可以在 SSM 项目中使用,同样也能在 Spring Boot 中使用。