SpringBoot uses @ControllerAdvice annotation

@ControllerAdvice is a new annotation provided by Spring 3.2. It is a Controller enhancer that can add some logic to the method annotated by @RequestMapping in the controller. There are three main functions

  • The global configuration of the controller can be placed in the same place through the @ControllerAdvice annotation.
  • The methods of the class annotated with @ControllerAdvice can be annotated with @ExceptionHandler, @InitBinder, and @ModelAttribute.
    • @ExceptionHandler: used to handle exceptions in the controller globally and perform global exception handling
    • @InitBinder: Used to set up WebDataBinder, used to automatically bind foreground request parameters to the Model, and preprocess global data.
    • @ModelAttribute: The original function is to bind key-value pairs to the Model. Here, global @RequestMapping can get the key-value pairs set here, and global data binding.
  • The @ControllerAdvice annotation will be applied to all controller methods annotated with @RequestMapping.

Global exception handling:

Need to cooperate with @ExceptionHandler.
When throwing an exception to the controller, the exception can be handled uniformly, specifying the returned json format or jumping to an error page

/**
 * @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;
    }

Custom exception

/**
 * @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;
    }
}

Test 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");
    }

Test Results:

{"msg":"缺少必需参数:name","code":400}
{"msg":"这是自定义异常","code":400}

Global data binding

The global data binding function can be used to do some initial data operations. We can define some public data in the class annotated with @ControllerAdvice, so that in the interface of each Controller, you can access the data. . To use the steps, first define the global data as follows:

/**
 * @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;
    }

Use the @ModelAttribute annotation to mark the return data of the method as a global data. By default, the key of this global data is the returned variable name, and the value is the return value of the method. Of course, developers can re-specify through the name attribute of the @ModelAttribute annotation key. After the definition is completed, the data defined here can be obtained in any Controller interface:

    @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";
    }

operation result

{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] 

Global data preprocessing

Consider that I have two entity classes, Book and Author, defined as follows:

@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;
}

If I define a data adding interface, as follows:

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

At this time, the adding operation will be problematic, because both entity classes have a name attribute, which cannot be distinguished when passed from the front end. At this point, the global data preprocessing of @ControllerAdvice can solve this problem

The solution steps are as follows:
1. Alias ​​the variables in the interface:

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

2. Perform request data preprocessing
Add the following code to the class marked by @ControllerAdvice:

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

The @InitBinder("b") annotation indicates that the method is used to process Book and related parameters. In the method, add a b prefix to the parameters, that is, the request parameters must have the b prefix.

3. Send the request

When the request is sent, the parameters can be distinguished by adding different prefixes to the parameters of different objects.
Insert picture description here

This is my WeChat official account: Program Yuanwei Magazine For more articles, please follow WeChat official account
Insert picture description here

Guess you like

Origin blog.csdn.net/CharlesYooSky/article/details/106332283