Filter基础知识

一、简介

作用:对Servlet容器调用Servlet的过程进行拦截,从而在Servlet进行响应处理的前后实现一些特殊的功能。

过滤器 API:Filter,FilterChain,FilterConfig。

Filter 程序:实现了 Filter 接口的 Java 类,由Servlet容器进行调用和执行,需要在 web.xml 中进行注册和设置它所能拦截的资源。

原理:Filter可以对Servlet容器发送给Servlet程序的请求和Servlet程序回送给Servlet容器的响应进行拦截。可以决定是否将请求继续传递给Servlet程序,以及对请求和响应信息是否进行修改。

二、使用方法

1)void init(FilterConfig filterConfig)

作用:类似于 Servlet 的 init 方法。在创建 Filter 对象(Filter 对象在 Servlet 容器加载当前 WEB 应用时即被创建)后,立即被调用, 且只被调用一次。该方法用于对当前的 Filter 进行初始化操作。Filter 实例是单例的。

  • FilterConfig 类似于 ServletConfig
  • 可以在 web.xml 文件中配置当前 Filter 的初始化参数. 配置方式也和 Servlet 类似。

2)void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

作用:真正 Filter 的逻辑代码需要编写在该方法中。每次拦截都会调用该方法。

参数:FilterChain:Filter 链。多个 Filter 可以构成一个 Filter 链。

  • chain.doFilter(ServletRequest request, ServletResponse response):把请求传给 Filter 链的下一个 Filter,若当前 Filter 是 Filter 链的最后一个 Filter,将把请求给到目标 Serlvet(或 JSP)。
  • 多个 Filter 拦截的顺序和 <filter-mapping> 配置的顺序有关,靠前的先被调用。

3)public void destroy()

释放当前 Filter 所占用的资源的方法。在 Filter 被销毁之前被调用,且只被调用一次。

public class HelloFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) 
throws IOException, ServletException {//放行 chain.doFilter(request, response); } @Override public void destroy() { } }

web.xml

url-pattern:指定该 Filter 可以拦截哪些资源,即可以通过哪些 url 访问到该 Filter。

<dispatcher>:指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。可以设置多个<dispatcher> 子元素用来指定 Filter 对资源的多种调用方式进行拦截

  • REQUEST:当用户直接访问页面时,Web 容器将会调用过滤器。如果目标资源是通过 RequestDispatcher 的 include() 或 forward() 方法访问时,那么该过滤器就不会被调用。通过 GET 或 POST 请求直接访问。
  • FORWARD:如果目标资源是通过 RequestDispatcher 的 forward() 方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。或 <jsp:forward page="/..." /> 或 通过 page 指令的 errorPage 转发页面. <%@ page errorPage="test.jsp" %>
  • INCLUDE:如果目标资源是通过 RequestDispatcher 的 include() 方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。或 <jsp:include file="/..." />
  • ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。在 web.xml 文件中通过 error-page 节点进行声明:
    <error-page>
        <exception-type>java.lang.ArithmeticException</exception-type>
        <location>/test.jsp</location>
    </error-page>
<!-- 注册 Filter -->
<filter>
    <filter-name>helloFilter</filter-name> 
    <filter-class>com.atguigu.javaweb.HelloFilter</filter-class>
</filter>

<!-- 映射 Filter -->
<filter-mapping>
    <filter-name>helloFilter</filter-name>
    <url-pattern>/test.jsp</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

三、应用

1. 使浏览器不缓存页面的过滤器

有3个HTTP响应头字段都可以禁止浏览器缓存当前页面

  • HttpServletResponse.setDataHeader("Expires", -1);
  • HttpServletResponse.setHeader("Cache-Control", "no-cache");
  • HttpServletResponse.setHeader("Pragma", "no-cache");
//HttpFilter的实现与HttpServlet相似
public
class NoCacheFilter extends HttpFilter { @Override public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { response.setDateHeader("Expires",-1); response.setHeader("Cache-Control","no-cache"); response.setHeader("Pragma","no-cache"); filterChain.doFilter(request, response); } }

2. 字符编码的过滤器

目标:让所有的页面都不会出现字符编码问题,为此需要添加一个过滤器

EncodingFilter.java

public class EncodingFilter extends HttpFilter{

    private String encoding;
    
    @Override
    protected void init() {
        encoding = getFilterConfig().getServletContext().getInitParameter("encoding");
    }
    
    @Override
    public void doFilter(HttpServletRequest request,
            HttpServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {
        System.out.println(encoding); 
        request.setCharacterEncoding(encoding);
        filterChain.doFilter(request, response);
    }
}

web.xml

 <context-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
 </context-param>
 <filter>
      <filter-name>encodingFilter</filter-name>
      <filter-class>com.atguigu.javaweb.encoding.EncodingFilter</filter-class>
 </filter>
  
 <filter-mapping>
      <filter-name>encodingFilter</filter-name>
      <url-pattern>/*</url-pattern>
 </filter-mapping>
原文地址:https://www.cnblogs.com/CComma/p/7203330.html