Filter(过滤器)

Filter简介

  1. filter是服务器端组件,它可以截取客户端和web资源之间的请求和响应消息而过滤不同内容。那具体怎么过滤呢,filter在java中的体现其实是一个接口,我们只需要定义这个接口的实现类,然后实现接口中的过滤方法,在方法中写过滤条件即可·。

  2. 当服务器收到特定的请求后,会先将请求交给过滤器,我们则可以实现filter接口,实现接口中的过滤方法,在方法中对请求信息进行读取修改等操作,然后将请求信息再发送给目标资源。目标资源作出响应后,服务器会再次将响应转交给过滤器,在过滤器中同样可以对响应信息做这些操作,然后再将响应发送给浏览器。
    在这里插入图片描述

  3. 在一个WEB应用中可以部署多个过滤器,多个过滤器就组成了一个过滤器链,请求和响应必须在经过多个过滤器后才能到达目标资源。
    在这里插入图片描述

为什么要使用过滤器

前面说了过滤器可以截取客户端和web资源之间的请求和响应消息,然后进行一些过滤(如:敏感词过滤)或对请求响应设置编码等操作。
其实这些也都可以在Servlet中实现,像设置编码与敏感词过滤等。但是在Servlet中操作就有一个问题了,像每请求一个资源都要在对应Servlet中解决编码问题或敏感词过滤,这样就要写很多重复的代码,而使用过滤器就可以解决这个问题了。

Filter的简单使用

web3.0以上版本,使用注解配置filter

  1. 创建一个类实现过滤器接口
  2. 注解配置过滤器拦截的请求路径(urlPatterns = “/*”)
  3. 在doFilter方法中书写过滤任务
  4. FilterChain.doFilter方法放行当前请求
@WebFilter(filterName = "FilterTest",urlPatterns = "/*")
public class FilterTest implements Filter {
    public void init(FilterConfig config) throws ServletException {
        System.out.print("过滤器初始化");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
		System.out.print("每次请求的路径符合 过滤器配置的路径 与 过滤器拦截请求方式 ,都会执行过滤器的doFilter方法");
        //放行当前请求
        chain.doFilter(req, resp);
    }

    public void destroy() {
        System.out.println("执行过滤器的desotory方法(服务器停止的时候销毁过滤器)");
    }
}

web3.0以前版本,使用web.xml配置filter

  1. 创建一个类实现过滤器接口
public class FilterTest implements Filter {
    public void init(FilterConfig config) throws ServletException {
        System.out.print("过滤器初始化");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
		System.out.print("每次请求的路径符合 过滤器配置的路径 与 过滤器拦截请求方式 ,都会执行过滤器的doFilter方法");
        //放行当前请求
        chain.doFilter(req, resp);
    }

    public void destroy() {
        System.out.println("执行过滤器的desotory方法(服务器停止的时候销毁过滤器)");
    }

}
  1. 在web.xml里面配置过滤器,配置方法与servlet基本一样。

基本配置

    <filter>
        <filter-name>FilterTest</filter-name>
        <filter-class>mycode.FilterTest</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>FilterTest</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

更多完整配置:

    <!--配置Demo01的过滤器-->
    <filter>
        <!--过滤器的名称,相当于注解里的filterName属性-->
        <filter-name>FilterTest</filter-name>
        <!--过滤器的全限定类名-->
        <filter-class>mycode.FilterTest</filter-class>
        <!--初始化参数,相当于注解里的initParams属性-->
        <init-param>
            <param-name>aa</param-name>
            <param-value>AA</param-value>
        </init-param>
    </filter>
    <!--配置过滤器的映射信息(拦截信息)-->
    <filter-mapping>
        <!--过滤器名称,要给哪个过滤器配置拦截的信息-->
        <filter-name>FilterTest</filter-name>
        <!--配置过滤器的拦截范围(可配置多个),相当于注解里的urlPatterns属性-->
        <url-pattern>*.jsp</url-pattern>
        <!--配置过滤器的拦截方式(可配置多个),相当于注解里的dispatcherTypes属性-->
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

扩展:Filter的执行顺序

注解配置的过滤器执行:由过滤器类的全限定类名的排序决定的。
web.xml配置的过滤器执行顺序:按照在web.xml文件中servlet-mapping的顺序决定的,如果顺序越靠前越先被调用。

Filter的配置

虽然根据版本不同配置方式也不同,但是这两种配置的方式,参数属性是一样的,这里以注解配置的方法来说明Filter的配置。

@WebFilter(filterName="FilterTest", urlPatterns="/*", initParams={@WebInitParam(name="参数名",value="参数值")}, dispatcherTypes=DispatcherType.REQUEST)
public class FilterTest implements Filter {
    public void init(FilterConfig config) throws ServletException {
        System.out.print("过滤器初始化");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //放行当前请求
        chain.doFilter(req, resp);
    }

    public void destroy() {
        System.out.println("执行过滤器的desotory方法(服务器停止的时候销毁过滤器)");
    }

}

主要配置:

urlPatterns

说明:配置过滤器的拦截范围,只要客户端请求的资源在过滤器的拦截范围里,过滤器就会拦截这次请求
语法:

  1. 完全匹配的方式:
    urlPatterns="/target",表示只拦截对/target的请求,其它任意请求都不拦截
  2. 目录匹配的方式:以/开头, 以*结尾
    urlPatterns="/*":表示拦截对所有资源的请求
    urlPatterns="/admin/*":表示拦截对/admin/下的任意资源的请求
  3. 扩展名匹配的方式:以*开头,以扩展名结尾
    urlPatterns="*.jsp":表示拦截对.jsp资源的请求
dispatcherTypes

说明:配置拦截不同的请求方式。过滤器默认的拦截方式DispatcherType.REQUEST,只能拦截浏览器对服务器的之间访问,这种请求方式可以说是客户端的请求(有直接访问或重定向)。而服务器资源之间使用转发的方式需要拦截的话。要配置DispatcherType.FORWARD,这样请求转发的请求就会拦截了。
分类:
要拦截客户端的请求(直接访问或重定向): DispatcherType.REQUEST
要拦截请求转发的请求:DispatcherType.FORWARD

注: 两种拦截方式可以共存,写法

@WebFilter(dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST},urlPatterns = "/*")

从配置的角度看过滤器会拦截请求的前提条件

过滤器拦截请求前提条件:在过滤器拦截范围里,并且符合过滤器拦截的请求方式。

Filter相关API及Filter的生命周期

@WebFilter(filterName = "FilterTest",urlPatterns = "/*")
public class FilterTest implements Filter {
	/*
	参数FilterConfig:过滤器的配置信息对象
	*/
    public void init(FilterConfig config) throws ServletException {
        System.out.print("过滤器初始化");
    }

	/*
	参数ServletReqeuset:代表http请求的request对象,通常强转成HttpServletRequest再使用
    参数ServletResponse:代表http响应的response对象,通常强转成HttpServletResponse再使用
	参数FilterChain:过滤器链对象,维护了能够拦截本次请求的所有过滤器的队列。作用:放行请求到下一个过滤器;如果下一个过滤器不存在,请求会到达目标资源
	
	*/
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
		System.out.print("每次请求的路径符合 过滤器配置的路径 与 过滤器拦截请求方式 ,都会执行过滤器的doFilter方法");
        
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        
        //放行当前请求
        chain.doFilter(req, resp);
    }

    public void destroy() {
        System.out.println("执行过滤器的desotory方法(服务器停止的时候销毁过滤器)");
    }
}

/*
Filter的生命周期
 创建:服务器启动时创建,创建时执行init方法,方法执行一次
 销毁:服务器关闭时销毁,销毁时执行destory方法,方法执行一次
 拦截到请求执行的方法:doFilter方法
*/
相关接口

在这里插入图片描述
Filter接口,编写Filter需要实现该接口

  1. init()方法用于初始化Filter
  2. doFilter()作用和service()方法类似,这里是过滤请求和响应的主要方法。
  3. destroy()用于在Filter对象被销毁前做一些收尾工作。如:释放资源等。

在这里插入图片描述

FilterConfig对象在服务器调用init()方法时传递进来,是过滤器的配置信息对象。作用:

  1. getFilterName() 获取Filter的名字
  2. getServletContext() 获取ServletContext对象(掌握)
  3. getInitParameter() 获取Filter的初始化参数
  4. getInitParameterNames() 获取所有初始化参数的名字

在这里插入图片描述
FilterChain对象是在doFilter()方法被调用时作为参数传递进来的。

  1. doFilter()方法用于调用Filter链上的下一个过滤器,如果当前过滤器为最后一个过滤器则将请求发送到目标资源。

Filter的使用场景

  1. Filter的使用场景:敏感词过滤
  2. 统一设置编码
@WebFilter("/*")//该项目下的所有请求和响应都会经过该过滤器统一解决乱码
public class EncodingFilter implements Filter {
    public void destroy() {
    }
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        
        //统一解决乱码问题
        
        //解决响应的中文乱码
        response.setContentType("text/html;charset=utf-8");
        //解决请求的中文乱码:post方式
        if ("POST".equalsIgnoreCase(request.getMethod())) {
            request.setCharacterEncoding("utf-8");
        }
        //放行请求
        chain.doFilter(request, response);
    }

    public void init(FilterConfig config) throws ServletException {

    }
}
  1. 自动登录
  2. 登录权限检查
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thinking in Coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值