过滤器和拦截器

过滤器和拦截器

Filter

  1. SpringBoot启动默认加载的Filter
    • characterEncodingFilter
    • hiddenHttpMethodFilter
    • httpPutFormContentFilter
    • requestContextFilter
  2. Filter 优先级
    • Ordered.HIGHEST_PRECEDENCE
    • Ordered.HIGHEST_PRECEDENCE
      • 低位值意味着更高的优先级 Higher values are interpreted as lower priority
      • 自定义Filter,避免和默认的Filter优先级一样,不然会冲突
  3. 自定义 Filter
    • 新建一个 Filter 类,实现 javax.servlet.Filter 接口
    public class MyFilter  implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("filter init");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            // 可以对 request 和 response 进行强转进行后续处理
            System.out.println("coming in");
            // 放行
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
            System.out.println("filter destroy");
        }
    }
    
    • 两种方式添加 Filter 进 Spring
      1. servlet 3.0 方式
      • 在自定义 Filter 上添加注解 @WebFileter(urlPatterns={"/api/*"})
        • 支持正则
      • 在启动类添加扫描注解 @ServletComponentScan
      1. config 方式
      • 在自定义 Filter 上添加注解 @Component
      • 添加一个配置类
      /**
       * 对原始 filter 进行配置
       */
      @Configuration
      public class WebConfig {
      
          @Bean
          public FilterRegistrationBean<MyFilter> myFilter(){
              FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();
              MyFilter filter = new MyFilter();
              filterRegistrationBean.setFilter(filter);
              // 可以设置不同的 url
              List<String> urls = new LinkedList<>();
              urls.add("/api/*");
              filterRegistrationBean.setUrlPatterns(urls);
              return filterRegistrationBean;
          }
      }
      
      

Servlet

原生

  • 添加 servlet
@WebServlet(name = "userServlet",urlPatterns = "/test/customs")
public class UserServlet extends HttpServlet {

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().print("custom sevlet");
        resp.getWriter().flush();
        resp.getWriter().close();
    }
}
  • 启动类配置 @ServletComponentScan

Listener 监听器

  • 常用的监听器
    • servletContextListener
    • httpSessionListener
    • servletRequestListener
  • 自定义Listener
@WebListener
public class RequestListener implements ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
    	// TODO Auto-generated method stub
    	System.out.println("======requestDestroyed========");
    }
    
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
    	System.out.println("======requestInitialized========");
    	
    }
}
  • 启动类配置 @ServletComponentScan

拦截器

  1. 新建配置类
  • 1.x
    • 继承 WebMvcConfigurationAdapter
  • 2.x
    • 实现 WebMvcConfigurer
        /**
         * 配置拦截器
         */
        @Configuration
        public class WebConfigTwo implements WebMvcConfigurer {
            @Autowired
            private TimeInterceptor timeInterceptor;
        
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor(timeInterceptor)
                    .addPathPatterns("/user/**")
                    .excludePathPatterns("/user/all");
            }
        }
    
  1. 自定义拦截器 HandlerInterceptor
@Component
public class TimeInterceptor implements HandlerInterceptor {
    /**
     * 进入 controller 之前
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println(" preHandle ");
        request.setAttribute("start", LocalDateTime.now().toEpochSecond(ZoneOffset.UTC));

        System.out.println(((HandlerMethod)handler).getBean().getClass().getName());
        System.out.println(((HandlerMethod)handler).getMethod().getName());

        return true;
    }

    /**
     * controller 返回之前, 出现异常则不会执行
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println(" postHandle ");
        long start = (long) request.getAttribute("start");
        System.out.println("花费了: " + (LocalDateTime.now().toEpochSecond(ZoneOffset.UTC)-start));
    }

    /**
     * 不管 controller 是正常返回还是异常,都会进入
     * 会被 @ControllerHandler 中的 @ExceptionHandler 给吃掉
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println(" afterCompletion ");
        System.out.println("ex is : " + ex);
    }
}

  1. 按照注册顺序进行拦截
  • 先注册,先被拦截

拦截器不生效常见问题:

  1. 是否有加 @Configuration
  2. 拦截路径是否有问题 ** 和 *
  3. 拦截器最后路径一定要 "/**", 如果是目录的话则是 "/*/"

Filter 和 Intercepter 区别

Filter Interceptor
基于函数回调 doFilter() 基于 AOP 思想
只在Servlet前后起作用 深入到方法前后、异常抛出前后等
依赖于 Servlet 容器即web应用中 不依赖于Servlet 容器所以可以运行在多种环境。
只能在容器初始化时调用一次 接口调用的生命周期里, 可以被多次调用

执行顺序

过滤前->拦截前->action执行->拦截后->过滤后

posted @ 2019-11-27 14:47  scp-166  阅读(133)  评论(0编辑  收藏  举报