文章目录
一:过滤器拦截原理
Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法。web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法。调用filterChian对象的doFilter方法,web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。相反,如果不调用该方法,web资源不会被访问。
二:Servlet里面的过滤器作用
- 动态地拦截请求和响应,变换或使用包含在请求或响应中的信息
- 在客户端的请求访问后端资源之前,拦截这些请求。
- 在服务器的响应发送回客户端之前,处理这些响应。
三:Filter的生命周期
- init(FilterConfig filterConfig) //只容器初始化的时候调用一次,即应用启动的时候加载一次
- doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 只要命中过滤规则就触发,可以在filter中根据条件决定是否调用chain.doFilter(request, response)方法, 即是否让目标资源执行
- destroy() //只容器销毁的时候调用一次,即应用停止的时候调用一次
四:元注解: @WebFilter
//该Filter是否支持异步操作模式
asyncSupported
//指定Filter对那种dispatcher模式进行过滤 该属性支持 Async,Error Forward,include,request
dispatcherType
//Filter 显示的名称
displayName
//Filter的名称
filterName
//Filter的配置参数
initParams
//过滤的Servlet可以指定多个,表示对这几个特定的的servlet 进行过滤
servletNames
//指定 Filter拦截的 URL,和上面的servletNames配置一样,用*可以表示通配符,但是不用字母后加*,应该按照模块划分,比如/user/*
urlPatterns/value
五:过滤器拦截实战
package net.xdclass.web.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
//@WebFilter(filterName = "xxx", servletNames = {"cookieServlet"},urlPatterns = {"/user/*","/order/*"})
@WebFilter(filterName = "xxx", servletNames = {"cookieServlet"},urlPatterns = {"/get_cookie_test"})
//@WebFilter(filterName = "xxx",urlPatterns = {"/*"})
public class CustomFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CustomFilter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("CustomFilter doFilter");
servletRequest.setCharacterEncoding("UTF-8");
servletResponse.setCharacterEncoding("UTF-8");
servletResponse.setContentType("text/html:charset=utf-8");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("CustomFilter destroy");
}
}
代码讲解:命中/get_cookie_test路径时,会走doFilter里面的逻辑,打印CustomFilter doFilter,命中其他路径时候,均不走doFilter里面的逻辑,不打印CustomFilter doFilter。
六:FilterConfig类
过滤器配置类,可以通过这个获取过滤器基本信息
6.1 dispatcherTypes 参数
- 指定Filter对那种dispatcher模式进行过滤,不符合的则不进行过滤
- REQUEST:默认值,浏览器直接请求的资源会被过滤器拦截
- FORWARD:转发访问资源会被过滤器拦截
- INCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC:异步访问资源
七:实操
DispatchServlet类实现的功能是转发或者重定向,对下述代码中
转发:req.getRequestDispatcher(“/index.jsp”).forward(req,response);
重定向:response.sendRedirect(“/index.jsp”);这两行代码分别注释,查看CustomFilter类实现的效果,主要查看CustomFilter类中的dispatcherTypes参数的作用
package net.xdclass.web.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("/forward")
public class DispatchServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
System.out.println("DispatchServlet doGet");
//req.setAttribute("name","xdclass");
User user = new User();
user.setHost("https://xdclass.net");
user.setId(1);
user.setName("老王");
//req.setAttribute("user",user);
req.setAttribute("name","jack");
req.getRequestDispatcher("/index.jsp").forward(req,response);
// response.sendRedirect("/index.jsp");
//response.sendRedirect("https://xdclass.net");
//req.getRequestDispatcher("request").forward(req,resp);
}
}
CustomFilter类
package net.xdclass.web.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
//@WebFilter(filterName = "xxx", servletNames = {"cookieServlet"},urlPatterns = {"/user/*","/order/*"})
//@WebFilter(filterName = "xxx", servletNames = {"cookieServlet"},urlPatterns = {"/get_cookie_test"})
@WebFilter(filterName = "xxx",urlPatterns = {"/*"},initParams = {
@WebInitParam(name="encoding",value = "UTF-8"),
@WebInitParam(name="loginPage",value = "/login.jsp"),
},dispatcherTypes = {DispatcherType.FORWARD})
public class CustomFilter implements Filter {
private FilterConfig filterConfig;
private String encoding;
private String loginPage;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CustomFilter init");
this.filterConfig = filterConfig;
String filterName = filterConfig.getFilterName();
System.out.println("filterName" + filterName);
this.encoding = filterConfig.getInitParameter("encoding");
this.loginPage = filterConfig.getInitParameter("loginPage");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("CustomFilter doFilter");
servletRequest.setCharacterEncoding(encoding);
servletResponse.setCharacterEncoding(encoding);
servletResponse.setContentType("text/html:charset=utf-8");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("CustomFilter destroy");
}
}
代码概述:
- 当DispatchServlet类中req.getRequestDispatcher(“/index.jsp”).forward(req,response);生效时,访问/forward路径,CustomFilter中的doFilter会被触发打印CustomFilter doFilter,因为CustomFilter类中因为dispatcherTypes参数的影响,只有转发的路径才会走doFilter逻辑
- 当DispatchServlet类中response.sendRedirect(“/index.jsp”);生效时,访问/forward路径,CustomFilter中的doFilter不会被触发不打印CustomFilter doFilter,因为CustomFilter类中因为dispatcherTypes参数的影响,只有转发的路径才会走doFilter逻辑,而现在DispatchServlet类是重定向类。