@ControllerAdvice

  • 描述
  • 用法1-全局异常捕获
  • 用法2-全局数据绑定
  • 用法3-数据预处理


描述

@ControllerAdvice注解是Spring3.2中新增的注解,学名是Controller增强器,作用是给Controller控制器添加统一的操作或处理。
对于@ControllerAdvice,我们比较熟知的用法是结合@ExceptionHandler用于全局异常的处理,但其作用不止于此。ControllerAdvice拆开来就是Controller Advice,关于Advice,在Spring的AOP中,是用来封装一个切面所有属性的,包括切入点和需要织入的切面逻辑。这里ControllerAdvice也可以这么理解,其抽象级别应该是用于对Controller进行切面环绕的,而具体的业务织入方式则是通过结合其他的注解来实现的。@ControllerAdvice是在类上声明的注解,其用法主要有三点:
1.结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的。
2.结合方法型注解@InitBinder,用于request中自定义参数解析方式进行注册,从而达到自定义指定格式参数的目的。
3.结合方法型注解@ModelAttribute,表示其注解的方法将会在目标Controller方法执行之前执行。
从上面的讲解可以看出,@ControllerAdvice的用法基本是将其声明在某个bean上,然后在该bean的方法上使用其他的注解来指定不同的织入逻辑。**不过这里@ControllerAdvice并不是使用AOP的方式来织入业务逻辑的,而是Spring内置对其各个逻辑的织入方式进行了内置支持**

用法1-全局异常捕获

结合@ExceptionHandler即可实现全局异常捕获,并处理,@ExceptionHandler可以传入要捕获的异常的Class<? extends Throwable>[]数组

package com.liurq.config.shiro.handle;

import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.NativeWebRequest;

@ControllerAdvice
public class UnauthorizedExceptionHandle {

    /**
     * 可以获取请求的request对象,按需进行操作
     * 可以获取抛出的异常对象,按需进行操作
     * 可对请求进行重定向,将请求重定向到某个页面或控制器
     * 需要返回json串儿的话,在方法上添加@ResponseBody注解即可
     * @param request
     * @param e
     * @return
     */
//    @ResponseBody
    @ExceptionHandler({UnauthorizedException.class})
    public String unauthorizedException(NativeWebRequest request, UnauthorizedException e){
        System.out.println(request.getParameter("param1"));
        e.printStackTrace();
        return "redirect:/403";
    }
}

用法2-全局数据绑定

搭配@ModelAttribute注解可以做数据绑定,在到达控制器前,将属性放入modelMap中,可以通过name属性指定数据在map中的key,如果不指定的话,有相同返回类型会产生覆盖,建议每个都通过name参数指定key

package com.liurq.advice;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;

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

/**
 * @Author:hyz
 * @Date:2021-07-29
 * @Desc:
 **/
@ControllerAdvice
public class Advice2 {


    /**
     * 通过name参数指定返回值在modelMap中的key
     * @return
     */
    @ModelAttribute(name = "str1")
    public String getData(){
        return "i am str1";
    }

    /**
     * 不指定key则为返回类型Map的首字母小写形式map
     * @return
     */
    @ModelAttribute
    public Map<String,String> getData2(){
        HashMap<String, String> map = new HashMap<>();
        map.put("str2","i am str2");
        return map;
    }
    /**
     * 不指定key则为返回类型Map的首字母小写形式hashMap
     * @return
     */
    @ModelAttribute
    public HashMap<String,String> getData3(){
        HashMap<String, String> map = new HashMap<>();
        map.put("str3","i am str3");
        return map;
    }
    /**
     * 在不指定key的情况下,有两个返回类型相同的数据绑定,则会产生覆盖
     * @return
     */
    @ModelAttribute
    public HashMap<String,String> getData4(){
        HashMap<String, String> map = new HashMap<>();
        map.put("str4","i am str4");
        return map;
    }
}