
举个例子
假设在Web资源中,A资源要写5行代码,而B资源也要写一模一样的5行代码,这时就把这些代码都提取出来,
在过滤器里写这些代码,因为访问任何资源都要经过过滤器,在过滤器走一遍就可以,而不用访问资源一个接一个。
应用:权限控制,用户登录之后才能查看后台信息,而Web资源中都要判断一下是否登录,而这个操作就可以放在Filter中,通用操作。
1. Filter 快速入门

 
创建
FilterDemo,配置@WebFilter("/*")表示拦截所有,拦截记得要放行,要不然不能访问到对应的资源

@WebFilter("/*")
public class FilterDemo implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //1. 放行前,对 request数据进行处理
        System.out.println("1.FilterDemo...");
        //放行
        chain.doFilter(request,response);
        //2. 放行后,对Response 数据进行处理
        System.out.println("5.FilterDemo...");
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException	{
    }
    @Override
    public void destroy() {
    }
}
 
2. Filter 执行流程

JSP的代码,验证执行的流程
<body>
    <h1>hello JSP~</h1>
    <%
        System.out.println("2.hello jsp");
    %>
</body>
 
过滤器代码
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //1. 放行前,对 request数据进行处理
        System.out.println("1.FilterDemo...");
        //放行
        chain.doFilter(request,response);
        //2. 放行后,对Response 数据进行处理
        System.out.println("3.FilterDemo...");
    }
 
控制台输出

3. Filter 使用细节
3.1 拦截路径配置

3.2 过滤器链
这里创建过滤器2

@WebFilter("/*")
public class FilterDemo2 implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //1. 放行前,对 request数据进行处理
        System.out.println("2.FilterDemo...");
        //放行
        chain.doFilter(request,response);
        //2. 放行后,对Response 数据进行处理
        System.out.println("4.FilterDemo...");
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void destroy() {
    }
}
 
控制台打印顺序

当有很多过滤器时,确定执行顺序

4. 对登录案例进行改进
当没有进行登录时,还是通过改变URL路径来直接访问,这就存在不安全性;为了改进权限,设置过滤器,当用户已经登录过了,直接放行,未登录,返回登录页面显示未登录信息

创建LoginFilter
@WebFilter("/*")
public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest)servletRequest;
        // 判断访问资源路径是否和登录注册相关
        String[] urls = {"/login.jsp", "/imgs/", "/css/", "/loginServlet", "/register.jsp", "/registerServlet", "/checkCodeServlet"};
        // 获取当前访问资源的资源路径
        String url = req.getRequestURL().toString();
        // 循环判断
        for (String u: urls
             ) {
            if(url.contains(u)){
                // 找到了
                // 放行
                filterChain.doFilter(req, servletResponse);
                return;
            }
        }
        //1. 如果访问的资源不是登录注册的,则判断session中是否有user
        HttpSession session = req.getSession();
        Object user = session.getAttribute("user");
        //2. 判断user是否为null
        if(user != null){
            // 登陆过了
            //放行
            filterChain.doFilter(servletRequest, servletResponse);
        }else {
            // 跳转到登录页面,且提示信息
            req.setAttribute("login_msg", "用户未登录");
            req.getRequestDispatcher("/Login.jsp").forward(req, servletResponse);
        }
    }
    @Override
    public void destroy() {
    }
}
                

















