- 概念:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。
- 作用:一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤等。
- Servlet、Filter、Listener 为 Javaweb 三大组件。
- 使用步骤:
- 定义一个类,实现接口 Filter
- 实现方法
- 配置拦截路径(web.xml 和 注解两种方式)
- 过滤器中的路径为所要拦截的路径。
- 过滤器拦截两次,去和回都拦截。
- 被过滤器拦截的路径需要在 doFilter 方法中放行。
- 快速入门:
import javax.servlet.*;
import java.io.IOException;
@WebFilter("/*")//访问所有资源之前,都会执行该过滤器
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo1被执行了....");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
- web.xml 配置过滤器:
<filter>
<filter-name>demo1</filter-name>
<filter-class>cn.itcast.web.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
<filter-name>demo1</filter-name>
<!-- 拦截路径 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
- 过滤器执行流程:
- 执行过滤器
- 执行放行后的资源
- 回来以后执行过滤器放行代码下边的代码
- 过滤器默认的拦截方式是拦截请求,即每次请求都对应一个拦截的来回,即请求的时候进入,请求结束回来。
protected void doPost() {
System.out.println("Servlet");
/*Filter来
Servlet
jsp
Filter回*/
//request.getRequestDispatcher("/index.jsp").forward(request, response);
/*Filter来
Servlet
Filter回
Filter来
jsp
Filter回*/
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
- 过滤器生命周期方法:
- init:在服务器启动后,会创建 Filter 对象,然后调用 init 方法。只执行一次。用于加载资源。
- doFilter:每一次请求被拦截资源时,会执行。执行多次。
- destroy:在服务器关闭后,Filter 对象被销毁。如果服务器是正常关闭,则会执行 destroy 方法。只执行一次。用于释放资源。
- 拦截路径配置:
- 具体资源路径:
/index.jsp
只有访问 index.jsp 资源时,过滤器才会被执行
- 拦截目录:
/user/*
访问 /user
下的所有资源时,过滤器都会被执行,例如配置 Servlet1 的虚拟路径为 /user/servlet1
,配置 Servlet2 的虚拟路径为 /user/servlet2
,则两个 Servlet 会被拦截。
- 后缀名拦截:
*.jsp
访问所有后缀名为 JSP 资源时,过滤器都会被执行。
- 拦截所有资源:
/*
访问所有资源时,过滤器都会被执行。
- 拦截方式的配置:资源被访问的方式,注解需要设置 dispatcherTypes 属性。
- REQUEST:默认值。路径被浏览器请求的时候拦截。
- FORWARD:路径被转发访问的时候拦截。
- INCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC:异步访问资源
- web.xml 配置拦截方式:设置
<dispatcher></dispatcher>
标签即可。
- dispatcherTypes 属性的值是一个数组,若想让路径在请求和转发的时候都能访问,可以配置两个值,
@WebFilter(value = "/*", dispatcherTypes = {DispatcherType.FORWARD, DispatcherType.REQUEST})
。
- 请求中套一个转发,且都设置拦截的时候,转发拦截是被包含在请求拦截里面的。
//拦截器
@WebFilter(value = "/*", dispatcherTypes = {DispatcherType.FORWARD, DispatcherType.REQUEST})
public class TestFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("Filter来");
chain.doFilter(req, resp);
System.out.println("Filter回");
}
}
//Servlet
@WebServlet("/testServlet")
public class TestServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Servlet");
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
}
//jsp
<%
System.out.println("jsp");
%>
//执行结果:
//Filter来
//Servlet
//Filter来
//jsp
//Filter回
//Filter回
- 过滤器先后顺序问题:
- 注解配置:按照类名的字符串比较规则比较,值小的先执行
- 如:AFilter 和 BFilter,AFilter 就先执行了。
- web.xml 配置:谁的
<filter-mapping>
定义在上边,谁就先执行。
- 过滤器执行顺序:如果有两个过滤器,过滤器 1 和过滤器 2,则执行顺序为 过滤器 1 → 过滤器 2 →资源执行 → 过滤器 2 → 过滤器 1