对请求或者响应进行拦截,并做额外的逻辑处理

filter能在一个请求访问目标资源之前对其进行拦截然后做某些逻辑处理,例如权限检查,也可以在一个输出响应到达客户端之前对其进行拦截并做一些额外的操作(例如,设置响应编码格式)。

二、接口定义

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

三、执行原理分析

当客户端发送一个请求访问某个资源时,Servlet容器会根据web.xml中的配置找出该请求所有匹配的过滤器,并保存到一个数组中,从而形成一个过滤器链,链中的每个过滤器都是一个处理节点。然后通过调用Tomcat服务器中的ApplicationFilterChain对象中的doFilter方法,不断迭代执行数组中的过滤器中的doFilter方法对请求和响应进行额外的逻辑处理(因为过滤器中的doFilter方法会重新调用FilterChain中的doFilter方法)。

Filter其实就是基于回调函数实现的责任链模式的应用。

模拟Servlet容器执行过滤器的场景:

import java.util.List;

class Scratch {
public static void main(String[] args) {
new ApplicationFilterChain().doFilter(new ServletRequest(), new ServletResponse());
} public static interface Filter {
void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain);
} /**
* 自定义过滤器
*/
public static class MyFilter1 implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {
System.out.println("即将执行过滤器1");
//回调方法,用于调用链中的下一个过滤器
filterChain.doFilter(request, response);
System.out.println("已经执行过滤器1");
}
} /**
* 自定义过滤器
*/
public static class MyFilter2 implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {
System.out.println("即将执行过滤器2");
//回调方法,用于调用链中的下一个过滤器
filterChain.doFilter(request, response);
System.out.println("已经执行过滤器2");
}
} /**
* 自定义过滤器
*/
public static class MyFilter3 implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {
System.out.println("即将执行过滤器3");
//回调方法,用于调用链中的下一个过滤器
filterChain.doFilter(request, response);
System.out.println("已经执行过滤器3");
}
} /**
* 模拟过滤器链接口
*/
public static interface FilterChain {
void doFilter(ServletRequest request, ServletResponse response);
} /**
* 模拟ApplicationFilterChain
*/
public static class ApplicationFilterChain implements FilterChain {
//模拟注册的过滤器,保存在一个数组中
Filter[] filters = new Filter[]{new MyFilter1(), new MyFilter2(), new MyFilter3()};
//用于保存遍历过滤器数组的下标
private int pos = 0; /**
* 开始执行过滤器逻辑
*/
public void doFilter(ServletRequest request, ServletResponse response) {
//pos小于过滤器数组中的元素说明过滤器还没执行完
if (pos < filters.length) {
//调用过滤器的doFilter方法,并将this这个当前对象传递进去
filters[pos++].doFilter(request, response, this);
}
}
} /**
* 模拟请求对象
*/
public static class ServletRequest { } /*
* 模拟响应对象
* */
public static class ServletResponse { }
}

结果如下:

四、Filter的生命周期

Filter类似于Servlet,其对象的创建和销毁由Servlet容器负责。当Servlet容器启动的时候,将创建Filter实例对象,并调用其init()方法进行一些初始化操作。当Servlet容器关闭或者重启时,将调用Filter对象的destory()方法,以释放相应的资源。init()和destory()方法在Filter对象的整个生命周期中都只仅会执行一次。当客户端有多个并发请求访问某个资源的时候,doFilter方法可能同时在多个线程环境中被执行,因此有可能出现并发安全问题,需要尽量确保doFilter方法中不会出现操作全局变量的情况。

五、配置Filter

1、xml方法配置

  <filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.demo.web.MyFilter</filter-class>
</filter>
<servlet-mapping>
<servlet-name>MyFilter</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

使用xml配置注解时,默认配置在前面的Filter会先执行。

另外,filterMapping中还可以通过<dispatcher>节点配置指示Servlet容器拦截何种方式的资源。

1、REQUEST:只拦截用户直接访问的资源(默认)。

2、INCLUDE:只拦截通过RequestDispatcher的include()方法访问的资源。

3、FORWARD:只拦截通过RequestDispatcher的forward()方法访问的资源。

3、ERROR:只拦截通过声明式异常处理机制调用的资源。

2、使用注解配置

@WebFilter(filterName="MyFilter",urlPatterns={"/*"})

六、示例代码

MyFilter.java

package com.fengjr.demo01;

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; public class MyFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
servletResponse.getWriter().write("<br/>拦截请求,在执行业务逻辑方法之前<br/>");
servletRequest.setAttribute("str", "Filter");
filterChain.doFilter(servletRequest, servletResponse);
servletResponse.getWriter().write("<br/>拦截响应,执行业务逻辑之后追加此段文本。");
} public void destroy() { }
}

web.xml配置

    <filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.fengjr.demo01.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>

JavaWeb三大组件之Filter的更多相关文章

  1. JavaWeb三大组件(Servlet,Filter,Listener 自己整理,初学者可以借鉴一下)

    JavaWeb三大组件(Servlet,Filter,Listener 自己整理,初学者可以借鉴一下) Reference

  2. JavaWeb三大组件—过滤器filter

    JavaWeb三大组件 1. 都需要在web.xml中进行配置ServletListener(2个感知监听器不需要配置)Filter 2. 过滤器 它会在一组资源(jsp.servlet..css.. ...

  3. JavaWeb三大组件之一Filter知识总结

    [1] Filter简介    > Filter翻译为中文是过滤器的意思.    > Filter是JavaWeb的三大web组件之一Servlet.Filter.Listener    ...

  4. JavaWeb三大组件(Servlet、Filter、Listener)

    JavaWeb三大组件指的是:Servlet.Filter.Listener,这三个组件在JavaWeb开发中分别提供不同的功能,然而很多人可能只用过其中一个或者两个(Servlet.Filter,比 ...

  5. 学习笔记_过滤器概述(过滤器JavaWeb三大组件之一)

    过滤器Filter Filter和Lister是Servlet规范里的两个高级特性.不同于Servlet,它们不用于处理客户端请求,只用于对request.response进行修改或者对context ...

  6. JavaWeb三大组件

    一.JavaWeb三大组件 Servlet,Listener,Filter.它们在JavaWeb开发中分别提供不同的功能. JavaWeb三大组件都必须在Web.xml中配置 二.三大组件 1.Ser ...

  7. 转-JavaWeb三大组件之Listener监听器

    JavaWeb三大组件之Listener监听器一.概述1,它是一个接口,内容由我们来实现 2,它需要注册,例如注册在按钮上 3,监听器中的方法,会在特殊事件发生时被调用 二.JavaWeb中的监听器1 ...

  8. Filter过滤器-JavaWeb三大组件之一

    Servlet.Filter.Listener是JavaWeb的三大组件,给Web开发提供了很大的便利. 什么是Filter? Filter,过滤器.类似与生活中的净水器.空气净化器. JavaWeb ...

  9. Javaweb三大组件-过滤器、监听器

    1. 过滤器 [filter] 作用: 对单个获取多个servlet起到增强[advice]的作用. 用于在所有的servlet执行前,做一些预处理.例如:做编码处理, 访问量统计[servletCo ...

随机推荐

  1. mac 环境搭建

    安装homebrew jdk 也可以官网下载 maven 官网下载tar.gz包 也在homebrew下安装git,java,mysql.

  2. 在类文件中创建 写入Json文件

    由于业务需要 今天写了一个方法能够定时更新Json文件 即定时从数据库中查询数据 然后转化为Json对象 如果有数据的话 删掉之前的Json文件 重新创建一个文件 然后写入Json对象 中间走了很多弯 ...

  3. display:flex布局

    /*背景 居中 自适应 铺满容器*/ background: center / cover; flex布局是什么? flex是Flexibe Box 的缩写,意思为”弹性布局”, 用来为盒子模型提供最 ...

  4. Unix/Linux系统的发展史

    Unix/Linux系统相信是学编程的人都认识这两个系统.我们知道Unix要钱,而Linux免费,而且这两者之间的发展史是什么样的,是不是两者就是同一个东西呢? 我将会以时间的发展过程来一步步的给大家 ...

  5. JAVA企业级服务器应用之Tomcat

    Tomcat简介 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache,Sun和其他一些公司及个人共同开发而 ...

  6. VMware要不要装在固态SSD上,虚拟机系统文件要不要放固态SSD上,虚拟机伤不伤固态SSD

    先说结论:VMware建议装在固态上运行快,系统文件最好放在机械硬盘上(有钱除外),虚拟机会伤固态. 今天在学淘淘商城中的搜索项目,克隆了一个虚拟机,这个虚拟机开机贼慢,令人无法忍受,我觉得我再也受不 ...

  7. Python-cookie,session

    前言: 其实cookie这个词对于我们并不陌生,经常就听见说网页加载慢了,清理一下浏览器的缓存和cookie,cookie就是一个特殊数据验证类型,一般存储在客户端的浏览器上面,比如我们登录某宝后,下 ...

  8. “AS3.0高级动画编程”学习:第一章高级碰撞检测

    AdvancED ActionScript 3.0 Animation 是Keith Peters大师继"Make Things Move"之后的又一力作,网上已经有中文翻译版本了 ...

  9. 计算kdj

    import pandas as pd def KDJ_K(df,n=9):    df['highest'] = df['high'].rolling(n).max()    df['lowest' ...

  10. java第四章接口

    接口(interface) 语法:修饰符 interface 接口名 extends 父接口1,父接口2....{ //常量定义   //方法定义} class 类名 extends 父类名 impl ...