java过滤器Filter相关知识点汇总

1.Filter概述

Servlet Filter又称Servlet过滤器,它是在Servlet2.3规范中定义的,能够对Servlet容器传给Web资源的request对象和response对象执行检查和修改。

Filter不是Servlet,不能直接访问,其本身也不能生成request对象和response对象,只能为web资源提供以下过滤功能:

(1)在web资源被访问前,检查request对象,修改请求头和请求正文,或对请求执行预处理操作。

(2)将请求传递到下一个过滤器或目标资源。

(3)在web资源被访问后,检查response对象,修改响应头和响应正文。

Filter是Servlet规范中最实用的技术,通过其可对服务器管理的所有web资源(jsp,servlet,html等)拦截,从而实现特殊的功能,例如用户权限控制、过滤敏感词、设置统一编码格式等。

注意:过滤器并不是必须要将请求传递到下一个过滤器或目标资源,可自行对请求处理,并发送响应给客户端,也可以将请求转发或重定向到其他web资源。

2.Filter接口

与开发Servlet需要实现javax.servlet.Servlet接口类似,开发过滤器要实现javax.servlet.Filter接口,并提供一个公开的不带参数的构造方法,在Filter接口中,定义了3个方法,如下所示:

(1)init():该方法用于初始化过滤器。

(2)doFilter():该方法完成实际的过滤操作,当客户端请求的URL与过滤器映射的URL匹配时,容器会先调用该方法对请求进行拦截。

(3)destroy():该方法在销毁Filter对象之前被调用,用于释放被Filter对象占用的资源。

3、Filter的工作流程

(1)客户端请求访问容器内的web资源。

(2)Servlet容器接收请求,并针对本次请求分别创建一个request对象和response对象。

(3)请求到达web资源之前,先调用Filter的doFilter()方法,检查request对象,修改请求头和请求正文,或对请求执行预处理操作。

(4)在Filter的doFilter()方法内,调用FilterChain.doFilter()方法,将请求传递给下一个过滤器或目标资源。

(5)目标资源生成响应信息返回客户端之前,处理控制权会再次回到Filter的foFilte()方法,执行FilterChain.doFilter()后的语句,检查response对象,修改响应头和响应正文。

(6)响应信息返回客户端。

4、Filter生命周期(分为3个阶段)

(1)初始化阶段:

Servlet容器负责加载和实例化Filter。容器启动时,读取web.xml或@WebFilter的配置信息加载和实例化所有过滤器。

加载和实例化完成后,Servlet容器调用init()方法初始化Filter实例。在Filter生命周期内,init()方法只执行一次。

(2)拦截和过滤阶段

这个阶段是Filter生命周期中最重要的阶段。当客户端请求访问web资源时,Servlet容器会根据web.xml或@WebFilter的过滤规则执行检查。当客户端请求的URL与过滤器映射匹配时,容器将该请求的request对象以及FilterChain对象以参数的形式传递给Filter的doFilter()方法,并调用该方法请求/响应拦截和过滤。

(3)销毁阶段

Filter对象创建后会驻留在内存中,直到容器关闭或应用被移除时销毁,销毁Filter对象之前,容器会先调用destory()方法,释放过滤器占用的资源。在Filter生命周期内,destory()只执行一次。

5.注册和映射Filter

(1)通过web.xml配置

元素说明:

<filter>用于注册过滤器

<filter-name>是<filter>元素的子元素,用于指定过滤器的注册名,该元素的内容不能为空。

<filter-class>是<filter>元素的子元素,用于指定过滤器的完整限定名(包名+类名)

<init-param>是<filter>元素中的子元素,用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名称,<param-value>指定参数的值

<filter-mapping>元素用于设置Filter负责拦截的资源。

<filter-name>是<filter-mapping>元素的子元素,用于设置Filter的注册名,该值必须在<filter>元素的子元素<filter-name>中声明过。

<url-pattern>是<filter-mapping>元素的子元素,用于设置Filter拦截的请求路径。

<servlet-name>是<filter-mapping>元素的子元素,用于指定Filter拦截的资源被Servlet容器调用的方式,可以是REQUEST,INCLUDE,FORWAED和ERROR之一。默认情况是REQUEST。用户可以设置多个<dispatcher>子元素指定Filter对资源的多种调用方式进行拦截。

<dispather>元素的取值及意义:

**REQUEST:**当用户直接访问页面时,容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问,则该过滤器就不会被调用。

**INCLUDE:**如果目标资源通过RequestDispatcher的include()方法访问,则该过滤器将被调用,除此之外,该过滤器不会被调用。

**ERROR:**如果目标资源通过声明式异常处理机制访问,则该过滤器将被调用,除此之外,过滤器不会被调用。

(2)通过@WebFilter注解配置

@WebFilter注解也可配置过滤器,容器在部署应用时,会根据具体属性配置将相应类部署为过滤器。

@WebFilter注解具有下标给出的一些常用属性,但是value,urlPatterns,servletNames三者必须至少包含一个,且value和urlPatterns不能共存,如果同时指定,通常忽略value的取值。

6、过滤器链

在web应用中,可部署多个Filter,若这些Filter都拦截同一目标资源,就组成了一个Filter链,过滤器链中的每个过滤器负责特定操作和任务,客户端请求在各个过滤器减传递,直至传递给目标资源。

FilterChain接口:javax.servlet包中提供了一个FilterChain接口,该接口由容器实现。容器将其实例对象作为参数传入Filter对象的doFilter()方法中。Filter对象可以使用FilterChain对象调用链中下一个Filter的doFilter()方法,若该Filter是链中最后一个过滤器,则调用目标资源的service()方法。FilterChain接口中只有一个方法------doFilter,详细信息如下:

7.Filter链的拦截过程

请求资源时,过滤器链中的过滤器一次对请求处理,并将请求传递给下一个过滤器,直到最后将请求传递给目标资源,发送响应信息时。则按照相反的顺序对相应处理,直到将响应返回给客户端。

注意:过滤器链中的任何一个Filter没有调用FilterChain.doFilter()方法,请求都不会达到目标资源。

8、总结Filter代码编写流程

(1)定义类,实现Filter接口,并重写其所有方法

(2)配置Fiter拦截资源的路径:在类上定义@WebFilter注解或者web.xml文件配置。

(3)在doFilter()方法中设置处理的方法。

具体的代码案例:

md-end-block 复制代码
<span style="background-color:#f8f8f8"><span style="color:#333333">package Filter;
​
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
​
​
@WebFilter("/*") //表示拦截所有资源
public class UserSessionFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }
​
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器成功执行!");
        //放行
      filterChain.doFilter(servletRequest,servletResponse);
​
    }
​
    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}</span></span>

运行截图:

相关推荐
xlsw_1 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹2 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭3 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫3 小时前
泛型(2)
java
超爱吃士力架3 小时前
邀请逻辑
java·linux·后端
南宫生3 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石3 小时前
12/21java基础
java
李小白663 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp4 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶4 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb