day12_Filter_Listener

Filter

1. Filter【过滤器】简介

1.1 生活中过滤器

  • 空气净化器
  • 净水器
  • 口罩等

1.2 程序中过滤器【Filter】

  • Servlet:处理请求,做出响应
  • Filter:过滤请求&响应【之前】
    • 如:处理请求之前,解决字符集问题,交给过滤器处理

2. Filter使用

Filter服务器端三大组件之一【Servlet\Listener】
服务器端组件共性
1. 都需要实现某个接口
2. 都需要注册【web.xml&注解】

2.1 Filter常用API

  • Filter接口:javax.servlet.Filter
    • init(FilterConfig config):初始化方法
    • doFilter(ServletRequest req,ServletResponse res,FilterChain chain)
      • 过滤请求&响应
    • destroy():销毁方法
  • FilterConfig:封装Filter配置信息,每个Filter对应唯一一个FilterConfig对象。
    • getFilterName():获取Filter名称
    • getServletContext():获取servlet上下文对象
    • getInitParameter():获取初始化参数
  • FilterChain:封装Filter链信息
    • doFilter():方法用于调用Filter链上的下一个过滤器,如果当前过滤器为最后一个过滤器则将请求发送到目标资源。【放行请求】

2.2 Filter之Helloworld

/*
@author Chunsheng Zhang 尚硅谷
@create 2021/8/18 14:28
/
public class Filter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {

  1. }
  2. @Override<br /> public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {<br /> System.out.println("Filter1->放行前,过滤请求!");<br /> // 省略10000代码<br /> //放行请求<br /> chain.doFilter(request,response);<br /> //放行后<br /> System.out.println("Filter1->放行后,过滤响应!");<br /> }
  3. @Override<br /> public void destroy() {
  4. }<br />}<br /><filter><br /> <filter-name>Filter1</filter-name><br /> <filter-class>com.atguigu.filter.Filter1</filter-class><br /> </filter><br /> <filter-mapping><br /> <filter-name>Filter1</filter-name><br /><!-- 对于过滤器,url一般不会设置/FilterName--><br /> <url-pattern>/TestFilterServlet</url-pattern><br /> </filter-mapping><br />

3. Filter工作原理【单个Filter】

  • 请求被Filter过滤URL
  • 执行Filter中doFilter()方法的放行前代码,过滤请求
  • 执行chain.doFilter(request,response);放行请求,执行目标资源【Servlet】,处理请求,做出响应
  • 执行Filter中doFilter()方法的放行后代码,过滤响应
  • 响应

4. Filter生命周期

  • 构造器
    • 执行时机:启动服务器时,创建Filter
    • 执行次数:在整个生命周期中,只执行一次【单例】
  • init()
    • 执行时机:启动服务器时,执行构造器之后,执行
    • 执行次数:在整个生命周期中,只执行一次
  • doFilter()
    • 执行时机:每次触发指定URL时,执行doFilter()【过滤请求,过滤响应】
    • 执行次数:在整个生命周期中,执行多次
  • destroy()
    • 执行时机:关闭服务器时,执行
    • 执行次数:在整个生命周期中,执行一次

服务器创建组件顺序:Filter > Servlet

5. Filter工作原理【多个Filter】

  • 请求被Filter过滤URL
  • 执行Filter1中doFilter()方法的放行前代码,过滤请求,执行chain.doFilter(request,response);放行请求
  • 执行Filter2中doFilter()方法的放行前代码,过滤请求,执行chain.doFilter(request,response);放行请求
  • 执行目标资源【Servlet】,处理请求,做出响应
  • 执行Filter2中doFilter()方法的放行后代码,过滤响应
  • 执行Filter1中doFilter()方法的放行后代码,过滤响应
  • 响应
  • Filter执行顺序由:
    • web.xml注册中的filter-mapping顺序决定
    • 注解中filter-name名称字母顺序决定,如:aFilter>bFilter

6. Filter中URL匹配规则

  • 精确匹配
    • url匹配

    • Filter1
      com.atguigu.filter.Filter1


      Filter1

      /TestFilterServlet
    • 名称匹配

    • Filter2
      com.atguigu.filter.Filter2


      Filter2

      TestFilterServlet
  • 模糊匹配【带有(*)号匹配】
    • 后缀名匹配:【】书写在URL*最前面
      • 如:*.html
    • 目录匹配:【】书写在URL*最后面
      • 如:/pages/*
    • 注意:【*】不能书写在URL的中间位置

7. 最终版Filter【HttpFilter】

7.1 为什么需要HttpFilter

  • 对比Servlet中,javax.servlet.Servlet接口与javax.servlet.http.HttpServlet类,使用HttpServlet优势如下:
    • 提供获取对象方法【getServletConfig()和getServletContext】
    • 将service()方法,抽象化【在子类中只关注service()】
    • 重写service():类型转换
    • 重载service():通过请求方式不同,调用不同处理方法

7.2 手动搭建HttpFilter思路

  • 提供获取对象方法【getFilterConfig()和getServletContext】
  • 将doFilter()方法,抽象化【在子类中只关注doFilter()】
  • 重载doFilter()方法,类型转换
  • 注意:HttpFilter是抽象类,不能实例化,所以不能注册

7.3 手动搭建HttpFilter示例代码

/*
@author Chunsheng Zhang 尚硅谷
@create 2021/8/18 16:19
/
public abstract class HttpFilter implements Filter {

private FilterConfig filterConfig;

/**<br />     * 获取FilterConfig对象方法<br />     * @return<br />     */<br />    public FilterConfig getFilterConfig() {<br />        return filterConfig;<br />    }

/**<br />     * 获取ServletContext对象方法<br />     * @throws ServletException<br />     */<br />    public ServletContext getServletContext(){<br />        return getFilterConfig().getServletContext();<br />    }


@Override<br />    public void init(FilterConfig filterConfig) throws ServletException {<br />        this.filterConfig = filterConfig;<br />    }

@Override<br />    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {<br />        HttpServletRequest req = (HttpServletRequest)request;<br />        HttpServletResponse res = (HttpServletResponse)response;<br />        doFilter(req,res,chain);<br />    }

public abstract void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException;


@Override<br />    public void destroy() {

}<br />}<br />

8. 基于注解方式注册Filter

/*
@author Chunsheng Zhang 尚硅谷
@create 2021/8/18 15:42
/
@WebFilter(filterName = “Filter3”,value = “*.html”)
public class Filter3 implements Filter {
public void destroy() {
}

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {<br />        System.out.println("Filter3.....");<br />        chain.doFilter(req, resp);<br />    }

public void init(FilterConfig config) throws ServletException {

}<br />}<br />

Listener