首页 > 其他分享 >过滤器Filter

过滤器Filter

时间:2024-08-19 16:51:48浏览次数:7  
标签:请求 void Filter doFilter 过滤器 public

目录

一、概述

二、Filter接口

1.源码

2.API

三、使用

1.步骤

2.需求

3.代码

 四、过滤器的生命周期

五、过滤器链的使用

六、注解方式配置过滤器


一、概述

Filter,即过滤器,是JAVAEE技术规范之一,作用目标资源的请求进行过滤的一套技术规范,是Java Web项目中最为实用的技术之一

  • Filter接口定义了过滤器的开发规范,所有的过滤器都要实现该接口

  • Filter的工作位置是项目中所有目标资源之前,容器在创建HttpServletRequest和HttpServletResponse对象后,会先调用Filter的doFilter方法

  • Filter的doFilter方法可以控制请求是否继续,如果放行,则请求继续,如果拒绝,则请求到此为止,由过滤器本身做出响应

  • Filter不仅可以对请求做出过滤,也可以在目标资源做出响应前,对响应再次进行处理

  • Filter是GOF中责任链模式的典型案例

  • Filter的常用应用包括但不限于: 登录权限检查,解决网站乱码,过滤敏感字符,日志记录,性能分析... ...

过滤器开发中应用的场景

  • 日志的记录

  • 性能的分析

  • 乱码的处理

  • 事务的控制

  • 登录的控制

  • 跨域的处理

工作图解 

二、Filter接口

1.源码

package jakarta.servlet;
import java.io.IOException;

public interface Filter {
    default public void init(FilterConfig filterConfig) throws ServletException {
    }
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException;
    default public void destroy() {
    }
}

2.API

API目标
default public void init(FilterConfig filterConfig)初始化方法,由容器调用并传入初始配置信息filterConfig对象
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)过滤方法,核心方法,过滤请求,决定是否放行,响应之前的其他处理等都在该方法中
default public void destroy()销毁方法,容器在回收过滤器对象之前调用的方法

三、使用

1.步骤

A.定义一个过滤器类实现Filter接口并重写doFilter方法 

B.随便定义两个测试Servlet为目标资源

C.在web.xml文件里面配置过滤器要过滤的目标资源uri(也可以在过滤器类上面添加@WebFilter("目标资源uri")注解)

2.需求

开发一个日志记录过滤器

  • 用户请求到达目标资源之前,记录用户的请求资源路径

  • 响应之前记录本次请求目标资源运算的耗时

  • 可以选择将日志记录进入文件,为了方便测试,这里将日志直接在控制台打印

3.代码

定义一个过滤器类,编写功能代码  

public class LoggingFilter  implements Filter {

    private SimpleDateFormat dateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 参数父转子
        HttpServletRequest request =(HttpServletRequest)  servletRequest;
        HttpServletResponse  response =(HttpServletResponse)  servletResponse;
        // 拼接日志文本
        String requestURI = request.getRequestURI();
        String time = dateFormat.format(new Date());
        String beforeLogging =requestURI+"在"+time+"被请求了";
        // 打印日志
        System.out.println(beforeLogging);
        // 获取系统时间
        long t1 = System.currentTimeMillis();
        // 放行请求
        filterChain.doFilter(request,response);
        // 获取系统时间
        long t2 = System.currentTimeMillis();
        //  拼接日志文本
        String afterLogging =requestURI+"在"+time+"的请求耗时:"+(t2-t1)+"毫秒";
        // 打印日志
        System.out.println(afterLogging);

    }
}

说明:

  • doFilter方法中的请求和响应对象是以父接口的形式声明的,实际传入的实参就是HttpServletRequest和HttpServletResponse子接口级别的,可以安全强转

  • filterChain.doFilter(request,response); 这行代码的功能是放行请求,如果没有这一行代码,则请求到此为止

  • filterChain.doFilter(request,response);在放行时需要传入request和response,意味着请求和响应对象要继续传递给后续的资源,这里没有产生新的request和response对象

定义两个Servlet作为目标资源  

ServletA

@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 处理器请求
        System.out.println("servletA处理请求的方法,耗时10毫秒");
        // 模拟处理请求耗时
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }
}

ServletB

@WebServlet(urlPatterns = "/servletB", name = "servletBName")
public class ServletB extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 处理器请求
        System.out.println("servletB处理请求的方法,耗时15毫秒");
        // 模拟处理请求耗时
        try {
            Thread.sleep(15);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

配置过滤器以及过滤器的过滤范围  

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">

    <!--配置filter,并为filter起别名-->
   <filter>
       <filter-name>loggingFilter</filter-name>
       <filter-class>com.atguigu.filters.LoggingFilter</filter-class>
   </filter>
    <!--为别名对应的filter配置要过滤的目标资源-->
    <filter-mapping>
        <filter-name>loggingFilter</filter-name>
        <!--通过映射路径确定过滤资源-->
        <url-pattern>/servletA</url-pattern>
        <!--通过后缀名确定过滤资源-->
        <url-pattern>*.html</url-pattern>
        <!--通过servlet别名确定过滤资源-->
        <servlet-name>servletBName</servlet-name>

    </filter-mapping>
</web-app>

说明

  • filter-mapping标签中定义了过滤器对那些资源进行过滤

  • 子标签url-pattern通过映射路径确定过滤范围

    • /servletA 精确匹配,表示对servletA资源的请求进行过滤

    • *.html 表示对以.action结尾的路径进行过滤

    • /* 表示对所有资源进行过滤

    • 一个filter-mapping下可以配置多个url-pattern

  • 子标签servlet-name通过servlet别名确定对那些servlet进行过滤

    • 使用该标签确定目标资源的前提是servlet已经起了别名

    • 一个filter-mapping下可以定义多个servlet-name

    • 一个filter-mapping下,servlet-name和url-pattern子标签可以同时存在

 四、过滤器的生命周期

过滤器作为web项目的组件之一,和Servlet的生命周期类似,略有不同,没有servlet的load-on-startup的配置,默认就是系统启动立刻构造

阶段对应方法执行时机执行次数
创建对象构造器web应用启动时1
初始化方法void init(FilterConfig filterConfig)构造完毕1
过滤请求void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)每次请求多次
销毁default void destroy()web应用关闭时1次

测试代码

@WebFilter("/*")
public class LifeCycleFilter implements Filter {
    public LifeCycleFilter(){
        System.out.println("LifeCycleFilter constructor method invoked");
    }
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("LifeCycleFilter init method invoked");
        
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("LifeCycleFilter doFilter method invoked");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
        System.out.println("LifeCycleFilter destory method invoked");
    }
}

五、过滤器链的使用

 一个web项目中,可以同时定义多个过滤器,多个过滤器对同一个资源进行过滤时,工作位置有先后,整体形成一个工作链,称之为过滤器链

工作原理图 

多个过滤器执行的顺序的因素

(1)如果是web.xml文件配置,先配置先执行

(2)是注解@WebFilter配置的话就看过滤器的类名顺序执行,比如Filter1,Filter2.. 

六、注解方式配置过滤器

@WebFilter(
        filterName = "loggingFilter",
        initParams = {@WebInitParam(name="dateTimePattern",value="yyyy-MM-dd HH:mm:ss")},
        urlPatterns = {"/servletA","*.html"},
        servletNames = {"servletBName"}
)
public class LoggingFilter  implements Filter {
    private SimpleDateFormat dateFormat ;

    /*init初始化方法,通过filterConfig获取初始化参数
    * init方法中,可以用于定义一些其他初始化功能代码
    * */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 获取初始参数
        String dateTimePattern = filterConfig.getInitParameter("dateTimePattern");
        // 初始化成员变量
        dateFormat=new SimpleDateFormat(dateTimePattern);
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 参数父转子
        HttpServletRequest request =(HttpServletRequest)  servletRequest;
        HttpServletResponse  response =(HttpServletResponse)  servletResponse;
        // 拼接日志文本
        String requestURI = request.getRequestURI();
        String time = dateFormat.format(new Date());
        String beforeLogging =requestURI+"在"+time+"被请求了";
        // 打印日志
        System.out.println(beforeLogging);
        // 获取系统时间
        long t1 = System.currentTimeMillis();
        // 放行请求
        filterChain.doFilter(request,response);
        // 获取系统时间
        long t2 = System.currentTimeMillis();
        String afterLogging =requestURI+"在"+time+"的请求耗时:"+(t2-t1)+"毫秒";
        // 打印日志
        System.out.println(afterLogging);

    }
}

标签:请求,void,Filter,doFilter,过滤器,public
From: https://blog.csdn.net/2202_75483664/article/details/141328174

相关文章

  • HBase学习的第六天--Hbase之过滤器
    Hbase之过滤器HBase的基本API,包括增、删、改、查等。增、删都是相对简单的操作,与传统的RDBMS相比,这里的查询操作略显苍白,只能根据特性的行键进行查询(Get)或者根据行键的范围来查询(Scan)。HBase不仅提供了这些简单的查询,而且提供了更加高级的过滤器(Filter)来查询。过滤器可......
  • 过滤器与拦截器
    过滤器与拦截器参考https://www.cnblogs.com/Black-Ice/p/16248535.html过滤器FilterFilter基本介绍过滤器Filter是Sun公司在Servlet2.3规范中添加的新功能,其作用是对客户端发送给Servlet的请求以及对Servlet返回给客户端的响应做一些定制化的处理,例如校验请......
  • 过滤器模式
    过滤器模式(FilterPattern)或标准模式(CriteriaPattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。双龙物流 概要意图用于将对象的筛选过程......
  • 4.StaticWEP+MAC Filter
    sw3560:vlan104namewepmacintvlan104ipadd10.1.104.254255.255.255.0ipdhcppoolwepmacnetwork10.1.104.0255.255.255.0defalt-router10.1.104.254dns-server10.1.3.241创建接口:controller-interfaces-newinterfacename:wepmac104interfaceaddressv......
  • 23:Python的map函数,filter函数,reduce函数
    #map函数#例子1num_1=[1,2,10,5,3,7]ret=[]foriinnum_1:ret.append(i**2)print(ret)#完成一个,#例子2num_1=[1,2,10,5,3,7]defmap_test(array):#array,数组ret=[]foriinnum_1:ret.append(i**2)returnretr......
  • 设计模式 - 过滤器模式
    ......
  • Spring Cloud Gateway 实现简单自定义过滤器
    背景SpringCloudGateway是SpringCloud退出的第二代网关框架,我们可以用它来实现反向代理,路由转发,权限校验等功能,这里介绍一个它的基础功能,通过Filter机制实现一个简单的HTTP接口处理。从总体上来看SpringCloudGateway提供的过滤器可以分为两类,一种是对全局流量都......
  • QSortFilterProxyModel和QTreeView排序功能
    1、需求,创建一个树有多层结构,同一层按照插入顺序逆序排列; ui.treeView->setHeaderHidden(true);//treewidget头标题是否显示,此处隐藏标题//ui.treeWidget->header()->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);ui.treeView->header()->s......
  • gateway通过过滤器修改uri
    背景:有时要根据不同的请求头或者请求参数动态修改路由的uri实现方案:使用全局过滤器(很关键)https://blog.csdn.net/netyeaxi/article/details/115287385packagecom.tl.gateway.filter;importjava.net.URI;importjava.net.URISyntaxException;importorg.springframewo......
  • 过滤器、拦截器、AOP、ControllerAdvcie执行顺序对比
    过滤器、拦截器、AOP、ControllerAdvcie执行顺序对比0.执行顺序过滤器➡拦截器➡AOP➡ControllerAdvice➡Controller没有异常的情况下,执行顺序如下:有异常的情况下,执行顺序如下:tip:当产生异常后,无论是否有ControllerAdvice处理,HandlerInterceptor都不会执行post......