一:拦截器
拦截全局请求HandlerInterceptor

public interface HandlerInterceptor {

   /**
     * 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
     * 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
   */
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

   /**
     * 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
   */
    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;

   /**
    * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
   */
    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;

}

用途:
拦截非法请求,日志记录等。

用法:
1.直接实现HandlerInterceptor接口,实现三个方法

/**
 * HandlerInterceptor  拦截请求,过滤掉非法请求
*/
public class CheckTokenGetHandler implements HandlerInterceptor {
    @Autowired
    private CheckTokenRequest checkTokenRequest;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        String token = httpServletRequest.getParameter("cookieid");
        //根据token,校验token是否存在合法
        if (checkTokenRequest.tokenIsExist(token)){
            return true;
        }else {
        //返回false之前,设置response相应前台
         checkTokenRequest.returnJson(httpServletResponse);
         return false;
        }
        //return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}

2.继承HandlerInterceptorAdapter适配器
有时候我们的业务需求只需要实现三个回调函数之间的一个,所以不需要实现所有的方法,Spring提供了一个HandlerInterceptor的适配器HandlerInterceptorAdapter,继承这个类,重写需要用到的回调方法即可。

public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
    public HandlerInterceptorAdapter() {
    }

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
	//这个方法是AsyncHandlerInterceptor独有的方法
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    }
}

拦截器HandlerInterceptor的装载
写一个配置类,继承WebMvcConfigurerAdapter,重写addInterceptors添加拦截器(可同时加载多个拦截器)

/**
 * web MVC配置类,加载拦截器
 */
@Configuration
public class DeveloperWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {


    @Bean
    public CheckTokenGetHandler getCheckTokenGetHandler(){
        return new CheckTokenGetHandler();
    }

    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getCheckTokenGetHandler()).addPathPatterns("/**");
    }
}

有一点需要注意!spring在启动时,@Configuration注解的类生产出让Spring IoC容器管理的Bean实例的工厂。@Bean注解的方法产生一个对象,注册到容器中,这里联合使用@Bean和@Configuration注解使得在实体类中使用的@Autowired注解能够顺利将实体类注入,如果不提前声明Bean,拦截器将在SpringContext(加载Bean)之前注册,从而导致拦截器中的@Autowired注解的变量将为null。顺便提一下@PostConstruct这个注解在@Autowired注解修饰的变量或者方法之后执行,可以用来做一些初始化方法的加载。

二:请求的过滤及处理
RequestBodyAdvice
仅支持post请求,数据以body的形式发送
实现RequestBodyAdvice类或者继承RequestBodyAdviceAdapter(RequestBodyAdvice适配器)
在实现类上加注解@ControllerAdvice

import java.io.IOException;
import java.lang.reflect.Type;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;

public interface RequestBodyAdvice {
	//这里是一个前置拦截匹配操作,其实就是告诉你满足为true的才会执行下面的beforeBodyRead方法,这里可以定义自己业务相关的拦截匹配
    boolean supports(MethodParameter var1, Type var2, Class<? extends HttpMessageConverter<?>> var3);
	//当请求体为空时调用(可拦截body为空的请求)
    Object handleEmptyBody(Object var1, HttpInputMessage var2, MethodParameter var3, Type var4, Class<? extends HttpMessageConverter<?>> var5);
	//在请求体未读取(转换)时调用(可对数据进行处理,解密数据,过滤非法数据,重新序列化等)
    HttpInputMessage beforeBodyRead(HttpInputMessage var1, MethodParameter var2, Type var3, Class<? extends HttpMessageConverter<?>> var4) throws IOException;
    //在请求体完成读取后调用(可针对读取后的对象做转换,此处不做处理)
    Object afterBodyRead(Object var1, HttpInputMessage var2, MethodParameter var3, Type var4, Class<? extends HttpMessageConverter<?>> var5);
}

ResponseBodyAdvice
ResponseBodyAdvice 的用途在于对返回内容做拦截处理:

public interface ResponseBodyAdvice<T> {
    // 返回true,启动拦截,false,不启动拦截
    boolean supports(MethodParameter var1, Class<? extends HttpMessageConverter<?>> var2);
	//在返回数据之前启动拦截,比如做数据的加密处理等
    T beforeBodyWrite(T var1, MethodParameter var2, MediaType var3, Class<? extends HttpMessageConverter<?>> var4, ServerHttpRequest var5, ServerHttpResponse var6);
}