SpringBoot中的过滤器和拦截器的应用

SpringBoot中的过滤器和拦截器的应用

Scroll Down

1. 过滤器第一种配置方法(有一定局限性)

  • 这种配置方法比较简单,用自定义类去实现Filter接口并使用@Component注解将自定义类加入到IOC容器,再复写其中的init和doFilter和destroy方法。
@Component
public class TimeFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("time filter init ");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("time filter start");
        long start = new Date().getTime();
        /**
         * 注意这里的request和response并不是HttpRequest和HttpResponse,需要强转
         * 一定要调用chain.doFilter()方法放行这次的请求和响应
         */
        chain.doFilter(request,response);
        System.out.println("time filter:" + (new Date().getTime() - start));
        System.out.println("time filter finish");
    }

    @Override
    public void destroy() {
        System.out.println("time filter destroy");
    }
}

  • init方法是在controller方法执行之前最先执行的。
  • doFilter方法时真正执行过滤器逻辑的地方。
  • destroy方法是过滤器销毁时执行的方法
  • 这种过滤器的实现局限性在于不能很好地基于不同url拦截请求并且不能设置过滤器之间的优先级

2. 过滤器第二种实现方法(推荐使用)

  • 这种方法是将自定义类配置成spring的配置类,在自定义过滤器类上就不需要使用@Component注解了
@Configuration
public class WebConfig {  
    @Bean
    public FilterRegistrationBean timeFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        TimeFilter timeFilter = new TimeFilter();
        registrationBean.setFilter(timeFilter);//注册自定义过滤器
        registrationBean.setOrder(1);//定义过滤器优先级
        ArrayList<String> urls = new ArrayList<>();
        /**
         * 可以添加更多的路径拦截请求
         */
        urls.add("/*");
        registrationBean.setUrlPatterns(urls);
        return registrationBean;
    }
}

3. 拦截器

  • 首先需要自定义一个拦截器实现HandlerInterceptor接口并使用@Component注解将当前类注入到IOC容器,HandlerInterceptor接口中有三个方法。
@Component
public class TimeInterceptor implements HandlerInterceptor {
    /**
     * 访问controller里面方法之前被调用
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("preHandle");
        System.out.println("调用controller中的类名为"+((HandlerMethod)o).getBean().getClass().getName());
        System.out.println("调用controller中的方法名为"+((HandlerMethod)o).getMethod().getName());
        httpServletRequest.setAttribute("startTime",new Date().getTime());
        //返回false则controller中的方法不会被调用
        return true;
    }

    /**
     * 当controller方法执行完毕紧接着调用这个方法,如果controller中的方法抛出了异常那么这个方法就不会被调用
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
        Long start = (Long)httpServletRequest.getAttribute("startTime");
        System.out.println("time interceptor:" + (new Date().getTime() - start));

    }

    /**
     * 这个方法时不管是否有异常等等,都会被调用
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param e
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("afterCompletion");
        Long start = (Long)httpServletRequest.getAttribute("startTime");
        System.out.println("time interceptor:" + (new Date().getTime() - start));
        System.out.println("exception = "+e);

    }
}

  • 然后将自定义拦截器配置到spring中
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
    @Autowired
    private TimeInterceptor timeInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(timeInterceptor);
    }
}