在服务器处理请求之前和发送请求时,被注册的Filter会进行工作。Filter的作用就像是一层滤网,将注册的请求进行拦截并处理。

Filter的业务流程

Imgur Filter位于服务器和用户之间,使用的方法类似于责任链模式, 请求会经过每一层的Filter并向下一层传递。

Filter的API

Filter中有三个方法最重要,分别用于初始化,执行过滤逻辑,销毁。

public interface Filter {
    //过滤器的初始化
    default void init(FilterConfig filterConfig) throws ServletException {
    }
    //过滤器的实际业务,其中包含了报文的请求,响应,和通向下一个Filter的环境。
    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
    //过滤器销毁的时候的逻辑。
    default void destroy() {
    }
}

通过注解配置一个Filter

  1. 通过注解配置一个Filter,该Filter将会拦截所有的请求,判断session中是否含有id信息。
  2. 如果含有id信息则传给下一个Filter。
  3. 不含有id信息则会走到login.jsp
    /**
     * 指定拦截器拦截的URI地址以及其执行的顺序。
     */
    @WebFilter(filterName = "LoginFilter", urlPatterns = "/*")
    @Order(1)
    public class LoginFilter implements Filter {
     public void destroy() {
         System.out.println("Destroy of current filter.");
     }
    
     public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
         /**
          * 获取当前请求的信息和响应的信息。
          */
         HttpServletRequest request = (HttpServletRequest) req;
         HttpServletResponse response = (HttpServletResponse) resp;
         /**
          * 如果要进入登录页面则无需拦截。
          * 或是确定失败了则不要拦截,不然会一直递归直到超时。
          */
         String uri = request.getRequestURI();
         if(uri.indexOf("login.jsp") != -1){
             chain.doFilter(request, response);
             return;
         }
         /**
          * 判断session域中是否含有user信息。
          * 如果包含用户信息,则继续向下一个Filter传递。
          */
         String userInfo = (String) request.getSession().getAttribute("userInfo");
         if(userInfo != null){
             chain.doFilter(request, response);
             return;
         }
         /**
          * 此时不符合上述的所有条件,重定向到登录页面。
          */
         response.sendRedirect("login.jsp");
     }
    
     public void init(FilterConfig config) throws ServletException {
         System.out.println("Initialize of current filter.");
     }
    }
    

SpringBoot中配置Filter

通过阅读文档,我发现用@WebFilter并不能将Filter注册到Spring容器中,此时需要用新的方法注册Filter。

/**
 * 实现一个函数式接口并重写其中的onStartup方法。
 * 在其中添加filter。
 */
public class MyIntializer implements ServletContextInitializer {
    @Autowired
    private LoginFilter loginFilter;
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        servletContext.addFilter("login filter", loginFilter);
    }
}

引用

  1. Java过滤器Filter使用详解
  2. Servlet学习——@WebFilter注解方式使用过滤器