关于Filter

**

JavaWeb的三大组件

Servlet:小应用程序,在JavaWeb中主要做为控制器来使用 可以处理用户的请求并且做出响应。
实现接口:javax.servlet.Servlet

Filter:过滤器,对用户发送的请求或响应进行集中处理,实现请求的拦截。
实现接口:javax.servlet.Filter

Listener:监听器,在某些框架中会使用到监听器(比如spring),在Web执行过程中,引发一些事件,对相应事件进行处理
实现接口:javax.servlet.XxxListener 每个事件有一个接口

应用场景

登录验证、统一编码处理、敏感字符过滤等

配置方式,一共两种
Xml配置如下:
① 编写java类,实现filter接口

import javax.servlet.*;
import java.io.IOException;

/*
    Filter编写
    1. 创建一个类实现Filter接口 (不要导错包了)
    2. 配置web.xml 

    解释:
        1. filter的url-pattern : 是要拦截的路径
        2.   filterChain.doFilter(servletRequest, servletResponse);
            允许请求向后传递
* */
public class MyFilter implements Filter {

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

    }
    /*
        filterChain : 过滤器链
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter拦截请求");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("filter拦截响应");
    }

    @Override
    public void destroy() {

    }
}

**
② 配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <filter>
        <filter-name>MyFilter01</filter-name>
        <filter-class>com.jsj.filter.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyFilter01</filter-name>
        <!-- 过滤器要拦截的路径 -->
        <url-pattern>/MyServlet</url-pattern>
    </filter-mapping>
</web-app>

注解配置如下
① 编写java类,实现filter接口

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/*
    Filter编写
    1. 创建一个类实现Filter接口 (不要导错包了)
    2. 配置注解

    解释:
        1. filter的url-pattern : 是要拦截的路径
        2.   filterChain.doFilter(servletRequest, servletResponse);
            允许请求向后传递
* */
//注解配置
@WebFilter("/MyServlet")
public class MyFilter implements Filter {

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

    }
    /*
        filterChain : 过滤器链
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter拦截请求");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("filter拦截响应");
    }

    @Override
    public void destroy() {

    }
}

Filter模板设置
在这里插入图片描述

模板内容

#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
@javax.servlet.annotation.WebFilter(urlPatterns = "/")
public class ${Class_Name} implements javax.servlet.Filter {
   
    public void init(javax.servlet.FilterConfig config) throws javax.servlet.ServletException {
    }
    public void doFilter(javax.servlet.ServletRequest req, javax.servlet.ServletResponse resp, javax.servlet.FilterChain chain) throws javax.servlet.ServletException, java.io.IOException {
        chain.doFilter(req, resp);
    }
    public void destroy() {
    }
}

工作原理:

  1. 用户发送请求,请求Web资源(包括html,jsp,servlet等)
  2. 如果Web资源的地址,是filter要拦截的地址,请求将先经过filter,并执行doFilter()
  3. doFilter()方法中如果调用filterChain.doFilter(),则允许请求访问下一个Web资源。
  4. 访问Web资源,响应回来会再次经过filter,执行过滤器中的代码,到达浏览器端。

生命周期:

// 初始化方法
public void init(FilterConfig config);

// 执行拦截方法
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain);

// 销毁方法
public void destroy();
  • 创建
    服务器启动项目加载,创建filter对象,执行init方法(只执行一次)

  • 运行(过滤拦截)
    用户访问被拦截目标资源时,执行doFilter方法

  • 销毁
    服务器关闭项目卸载时,销毁filter对象,执行destroy方法(只执行一次)

  • 补充:
    过滤器一定是优先于servlet创建的,后于Servlet销毁

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/*
 Filter三个生命周期方法
    1. init
        项目一运行就执行一次,而且早于Servlet的init
    2. doFilter
         每次被访问都会运行一次,先于Servlet的service

         chain.doFilter(req, resp); 相当于请求转发, 请求才能传递下去

    3. destroy
         服务器关闭之前,执行一次,晚于Servlet的destroy

    记住: Filter的生命周期比Servlet长
 */
@WebFilter(urlPatterns = "/LifeServlet")
public class LifeFilter implements Filter {

    public void init(FilterConfig config) throws ServletException {
        System.out.println("filter init");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("filter doFilter before");
        chain.doFilter(req, resp);
        System.out.println("filter doFilter after");
    }

    public void destroy() {
        System.out.println("filter destroy");
    }
}

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;
/*
    Servlet三个生命周期方法
    1. init
         默认第一次被访问,执行一次
         如果设置启动加载,tomcat启动的时候就会运行
    2. service
         每次被访问都会运行一次
    3. destroy
         服务器关闭之前,执行一次
 */
@WebServlet(value = "/LifeServlet",loadOnStartup = 5)
public class LifeServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {
        System.out.println("servlet init");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("servlet service");
    }

    @Override
    public void destroy() {
        System.out.println("servlet destroy");
    }
}

拦截路径:

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/*

 # 虚拟路径匹配模式

* 精准匹配
		用户访问指定目标资源(/show.jsp)时,过滤器进行拦截

* 目录匹配
		用户访问指定目录下(/user/*)所有资源时,过滤器进行拦截

* 后缀匹配
		用户访问指定后缀名(*.html)的资源时,过滤器进行拦截

* 匹配所有
		用户访问该网站所有资源(/*)时,过滤器进行拦截
* */
//@WebFilter(urlPatterns = "/user/a.jsp")
//@WebFilter(urlPatterns = {"/user/a.jsp","/user/b.jsp"})
//@WebFilter(urlPatterns = "/user/*")
//@WebFilter(urlPatterns = "*.html")
//@WebFilter(urlPatterns = "*.do")
public class UrlFilter implements Filter {

    public void init(FilterConfig config) throws ServletException {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("UrlFilter执行了");
        chain.doFilter(req, resp);
    }

    public void destroy() {
    }
}

拦截方式:
常见的两种:1. request(默认拦截方式)
浏览器直接发送请求时,拦截
2. forward
请求转发的时候,拦截
比如: 资源A转发到资源B时

① xml版本

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/*
*   # 拦截方式
*       1. 默认情况下, 请求直接来源浏览器 -> 过滤器会执行拦截
*       2. 如果请求来源于 请求转发 -> 过滤器不会执行拦截
*
*   # web.xml中的设置
*       0. filter-mapping的子标签dispatcher
*       1. REQUEST (默认) 浏览器的直接请求
*       2. FORWARD 转发的请求
* */
public class MethodFilter implements Filter {

    public void init(FilterConfig config) throws ServletException {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("我专门拦截BServlet");
        chain.doFilter(req, resp);
    }

    public void destroy() {
    }
}

<filter>
        <filter-name>MethodFilter</filter-name>
        <filter-class>com.itheima04.method.MethodFilter</filter-class>
    </filter>
    <!--
             dispatcher : 用来指定拦截方式的
             1. REQUEST(默认) : 浏览器直接发送过来的请求
             2. FORWARD: 请求转发过来的请求
 
             可以同时设置
         -->
    <filter-mapping>
        <filter-name>MethodFilter</filter-name>
        <url-pattern>/BServlet</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

② 注解版本

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/*
    拦截方式:
        1. request(默认拦截方式)
		        浏览器直接发送请求时,拦截

		2. forward
		        请求转发的时候,拦截

    # 配置
    2. 注解
 */
//@WebFilter(urlPatterns = "/BServlet",dispatcherTypes=DispatcherType.FORWARD) //只配置一种
//配置多种
@WebFilter(urlPatterns = "/BServlet",dispatcherTypes={DispatcherType.REQUEST,DispatcherType.FORWARD})
public class DispatcherFilter implements Filter {

    public void init(FilterConfig config) throws ServletException {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("DispatcherFilter执行了");
        chain.doFilter(req, resp);

    }

    public void destroy() {
    }
}

过滤器链:
在一次请求中,若我们请求匹配到了多个filter,通过请求就相当于把这些filter串起来了,形成了过滤器链.

  • 过滤器链执行顺序 (先进后出)
  • 过滤器链中执行的先后问题…
    配置文件
    谁先声明,谁先执行

    注解【不推荐】
    根据过滤器类名进行排序,值小的先执行。

比如: 用户访问目标资源 show.jsp时,经过 FilterA FilterB

1.用户发送请求
2.FilterA拦截,放行
3.FilterB拦截,放行
4.执行目标资源 show.jsp
5.FilterB增强响应
6.FilterA增强响应
7.封装响应消息格式,返回到浏览器

在这里插入图片描述

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("/SourceServlet")
public class SourceServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("SourceServlet被访问了");
    }

}

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

//@WebFilter(urlPatterns = "/SourceServlet")
public class FilterA implements Filter {

    public void init(FilterConfig config) throws ServletException {
    }

    public void doFilter(ServletRequest req, ServletResponse resp,
                         FilterChain chain) throws ServletException, IOException {
        System.out.println("FilterA执行了");
        //允许请求向后传递
        chain.doFilter(req, resp);
    }

    public void destroy() {
    }
}
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

//@WebFilter(urlPatterns = "/SourceServlet")
public class FilterB implements Filter {

    public void init(FilterConfig config) throws ServletException {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("FilterB执行了");
        chain.doFilter(req, resp);
    }

    public void destroy() {
    }
}
<filter>
      <filter-name>FilterB</filter-name>
      <filter-class>com.jsj.chain.FilterB</filter-class>
   </filter>
   <filter-mapping>
      <filter-name>FilterB</filter-name>
      <url-pattern>/SourceServlet</url-pattern>
   </filter-mapping>

   <filter>
      <filter-name>FilterA</filter-name>
      <filter-class>com.jsj.chain.FilterA</filter-class>
   </filter>
   <filter-mapping>
      <filter-name>FilterA</filter-name>
      <url-pattern>/SourceServlet</url-pattern>
   </filter-mapping>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值