过滤器

1.过滤器的概念

  过滤器时javaweb的三大组件之一(Servlet,Filter,listener)

  他与servlet很相似,不过过滤器是用来拦截请求的,不是处理请求的。当为某个请求设置过滤器时,如果要执行某个请求的servlet,则会先执行filter,然后如果filter"放行",则继续执行servlet,否则的话,就不放行,不执行servlet,filter是在servlet之前被执行的。过滤器是在服务器启动的时候就被创建的,在服务器关闭的时候销毁。举例如下:

创建两个过滤器,然后重启服务器:

package com.zs.servlet;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo implements Filter {
    public void destroy() {
        System.out.println("过滤器销毁");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

    }

    public void init(FilterConfig config) throws ServletException {
        System.out.println("过滤器初始化");
    }

}
package com.zs.servlet;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/login")
public class FilterDemo2 implements Filter {
    public void destroy() {
        System.out.println("过滤器2被销毁");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {
        System.out.println("过滤器2被创建");
    }

}

运行结果如下:

在tomcat启动时,就创建了过滤器对象。关闭服务器时,就会执行销毁方法,销毁所有过滤器。

为什么要使用过滤器呢?

  我们在写登录功能的时候,会有一种需求是,如果用户已经登录的话,就执行请求,如果没有登陆的话,就跳转到登陆界面,这就是通过过滤器实现的,具体代码如下:

package com.zs.servlet;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo implements Filter {
    public void destroy() {
        System.out.println("过滤器销毁");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//        设置编码格式
        req.setCharacterEncoding("utf-8");

//        判断用户是否登录,如果登录跳转主界面,如果没有登陆则返回登录界面
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        System.out.println("本次请求路径为"+request.getRequestURI());

        Object user = request.getSession().getAttribute("user");

        if (user != null) {
            chain.doFilter(req, resp);
        } else {
            String[] args = {"login.jsp", "login"};
//            获取请求的路径,遍历数组,判断是否包含在路径中
            String url = request.getRequestURI();//拿到用户此次请求的相对地址
            boolean tag=false;//判断用户此次请求路径是否需要拦截,true:拦截,false:不拦截
            for (String arg : args) {
                if (url.contains(arg)) {
                    tag = true;
                    break;
                }
            }

            if (tag) {
                chain.doFilter(req, resp);
            } else {
                response.sendRedirect("login.jsp");
            }
        }
    }

    public void init(FilterConfig config) throws ServletException {
        System.out.println("过滤器初始化");
    }

}

然后运行服务器,本来服务器启动后默认展示index界面,但是添加过滤器后,会通过过滤器,响应登录的页面。

这里有一种错误的认识就是,在过滤器放行或者响应界面后,就不会执行后边的代码了,这种认识是错误的,我们在过滤器的响应后加一个输出语句:

运行结果:

可以看到,每一次拦截请求后,都会执行完方法内的所有代码,并不是放行或者响应后就不执行后面的代码了。

下面创建一个servlet来进行测试:

简单的创建一个servelt:

package com.zs.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/login")
public class ServletDemo extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("执行了servlet");
        resp.sendRedirect("login.jsp");
    }
}

然后修改过滤器的内容:

运行服务器,在浏览器请求login,运行结果如下:

可以看出,在过滤器放行后,会执行servlet中的内容,当servelt中的内容执行完后,会返回过滤器,继续执行过滤器内的内容。

过滤器放行就相当于是调用了一个servlet方法,方法内的内容执行完后,会继续执行过滤器剩下的内容。

 

过滤器除了在类名上加注解的方式配置,还可以在web.xml中配置

与servlet的请求方式一样,先根据路径找到过滤器名字,然后根据过滤器名字找到过滤器的类

 

posted @ 2019-06-29 09:59  Zs夏至  阅读(169)  评论(0编辑  收藏  举报