Learning summary about @ControllerAdvice annotation

        Recently, due to the splitting of the project, I took a look at other project codes by the way, and found that there are still some things that I have not used. After research, I found that they are still very useful, such as the @ControllerAdvice annotation.

        Introduction to @ControllerAdvice annotation

        This annotation is first used on the controller, which is a functional enhancement of the controller. It is an implementation of the aop idea. According to the interception rules, this annotation helps you block the controllers that conform to the rules and make some functional enhancements. This annotation usually cooperates with the following three annotations, or these three annotations achieve three @ExceptionHandlerfunctional @InitBinder enhancements  @ModelAttribute.

        First look at the source code of this annotation:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.web.bind.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<?>[] assignableTypes() default {};

    Class<? extends Annotation>[] annotations() default {};
}

        It can be seen from the source code that the controller to be intercepted can be specified through the basePackages attribute. If you don't add any attributes, you will intercept all controllers. There are several ways to write interception rules:

        

@ControllerAdvice//拦截所有controller
@ControllerAdvice("com.lsl.mylsl")//拦截com.lsl.mylsl包及子包下的controller
@ControllerAdvice(basePackages = "com.lsl.mylsl")//同上
@ControllerAdvice(basePackages = {"com.lsl.mylsl","com.lsl.mjx"})//拦截多个不同包下的controller
@ControllerAdvice(annotations={CustomAnnotation.class})//如果自定义一个注解@CustomAnnotation,拦截有这个注解的controoler

     Use of @ControllerAdvice annotation

        Let's go to the code first, this is the interception configuration class for the controller

        

package com.lsl.mylsl.config;

import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@ControllerAdvice//拦截所有controller
public class ControllerHandlerConfig {

    /**
     * 对所有controller中的方法报HttpRequestMethodNotSupportedException异常就行全局处理
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = {HttpRequestMethodNotSupportedException.class})
    public Map exception405(){
        Map exMessage = new HashMap();
        exMessage.put("code",405);
        exMessage.put("message","请求类型错误");
        return exMessage;

    }

    /**
     * 预设全局数据一
     * @param request
     * @return
     */
    @ModelAttribute(name = "userType")
    public String preParam(HttpServletRequest request){
        String name = request.getHeader("type");
        return name;
    }

    /**
     * 预设全局数据二
     * @return
     */
    @ModelAttribute(name = "userMap")
    public Map preParamMap (){
        Map<String , Object> map = new HashMap<>();
        map.put("stuName","lsl");
        map.put("stuAge","21");
        return map;
    }

    /**
     * 请求参数预处理
     * 把string参数左右两边的空格去掉
     * 把日期格式"2022-10-28"转换成date类型输出
     * @param dataBinder
     */
    @InitBinder
    public void processParam(WebDataBinder dataBinder){

        /*
         * 创建一个字符串微调编辑器
         * 参数{boolean emptyAsNull}: 是否把空字符串("")视为 null
         */
        StringTrimmerEditor trimmerEditor = new StringTrimmerEditor(true);

        /*
         * 注册自定义编辑器
         * 接受两个参数{Class<?> requiredType, PropertyEditor propertyEditor}
         * requiredType:所需处理的类型
         * propertyEditor:属性编辑器,StringTrimmerEditor就是 propertyEditor的一个子类
         */
        dataBinder.registerCustomEditor(String.class, trimmerEditor);

        //同上,这里就不再一步一步讲解了
        dataBinder.registerCustomEditor(Date.class,
                new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), false));
    }



}

Here is the code of the controller class

package com.lsl.mylsl.controller;

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/mylsl")
public class MyHandlerController {

    @ResponseBody
    @PostMapping(value = "handler",produces = "application/json;charset=UTF-8")
    public Map handlerTest(@ModelAttribute("userType") String userType1, Model model){
        Map result = new HashMap();

        System.out.println("userType="+userType1);
        result.put("userType",userType1);


        Map<String, Object> asMap = model.asMap();
        Map userMap = (Map) asMap.get("userMap");
        String stuName = userMap.get("stuName").toString();
        String stuAge = userMap.get("stuAge").toString();
        System.out.println("stuName=" + stuName + ",stuAge=" +stuAge);
        result.put("stuName",stuName);
        result.put("stuAge",stuAge);


        return result;
    }

    @ResponseBody
    @GetMapping("prParam")
    public Map<String, Object> test(String str, Date date) throws Exception {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("str", str);
        map.put("data", date);
        return  map;
    }

}

       1. Handle global exceptions and @ControllerAdvice cooperate with  @ExceptionHandler global exception handling

        Through the code of MyHandlerController, we can see that the method handlerTest() is a post request. Now we use postman to send a get request, and it will be processed by exception405() in ControllerHandlerConfig.

        

 

2. Preset global data . @ControllerAdvice Cooperate with  @ModelAttribute preset global data.

        preParam() and preParamMap() in ControllerHandlerConfig provide 2 ways to write the preset global data, which are obtained in handlerTest() of MyHandlerController.

        

3. Request parameter preprocessing. @ControllerAdvice Cooperate  @InitBinder to realize the preprocessing of request parameters

        Through the get request in the figure below, it can be found that there are spaces around dhk in str, and the date format of date is 2022-10-28. The final output removes the spaces, and the date format becomes a date-type output format. 

 

Guess you like

Origin blog.csdn.net/dhklsl/article/details/127570975