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的请求方式一样,先根据路径找到过滤器名字,然后根据过滤器名字找到过滤器的类