前言
@ControllerAdvice是一个非常使用的注解,本文主要介绍@Controller注解的三种功能:
1.全局异常处理
2.全局数据绑定
3.全局数据预处理
全局异常处理
使用@ControllerAdvice可以实现全局异常处理
@ControllerAdvice
public class MyGlobalHandler {
@ExceptionHandler(Exception.class)
public ModelAndView allException(Exception e){
ModelAndView mv = new ModelAndView();
mv.addObject("message",e.getMessage());
mv.setViewName("myerror");
return mv;
}
}
@ExceptionHandler()中注明处理的异常类型,可以使用不同的方法处理不同的异常,也可以像上面一样,一个方法处理所有异常。
全局数据绑定
全局数据绑定功能可以用来做一些数据初始化工作,可以将一些公共的数据定义在@ControllerAdvice标记的类中,在所有Controller中都可以读取数据。使用@ModelAttribute注解标记该方法的返回数据是一个全局数据,默认情况下,这个全局数据的 key 就是返回的变量名,value 就是方法返回值,当然开发者可以通过 @ModelAttribute 注解的 name 属性去重新指定 key。
@ControllerAdvice
public class MyGlobalHandler {
@ModelAttribute("md")
public Map<String,Object> myData(){
HashMap<String, Object> map = new HashMap<>();
map.put("age", 100);
map.put("gender", "男");
return map;
}
}
任意定义一个Controller,我们可以访问里面的数据
@RestController
public class HelloController {
@GetMapping
public String hello(Model model){
Map<String,Object> map = model.asMap();
System.out.println(map);
return "hello";
}
}
全局数据预处理
首先定义两个实体类
public class Book {
private String name;
private Double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
public class Student {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
此时,如果定义一个接口
@GetMapping("/print")
public void print(Book book,Student student){
System.out.println(book);
System.out.println(student);
}
这个操作就会有问题,因为两个实体类都有一个 name 属性,从前端传递时 ,无法区分。此时,通过 @ControllerAdvice 的全局数据预处理可以解决这个问题
解决步骤如下:
1.给变量取别名
@GetMapping("/print")
public void print(@ModelAttribute("b") Book book, @ModelAttribute("s") Student student){
System.out.println(book);
System.out.println(student);
}
2.对数据进行预处理
@InitBinder("b")
public void b(WebDataBinder wdb){
wdb.setFieldDefaultPrefix("b.");
}
@InitBinder("s")
public void s(WebDataBinder wdb){
wdb.setFieldDefaultPrefix("s.");
}
@InitBinder(“b”) 注解表示该方法用来处理和Book和相关的参数,在方法中,给参数添加一个 b 前缀,即请求参数要有b前缀.
3.发送请求
请求发送时,通过给不同对象的参数添加不同的前缀,可以实现参数的区分.