Filter体现职责链模式
1. 前言
Filter—Filter 技术是servlet2.3 新增加的功能。完成的流程:对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
Filter体现了一种职责琏模式。那么他是如何体现的呢?
2. 职责链模式
在具体的解释这个之前先看看职责链模式的定义:使多个对象都有机会处理请求 ,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一个链,并沿着这条链传递请求,直到有一个对象处理它为止。
对于Filter而言就是,请求传给具体的web资源(比如jsp/servlet)之前要经过Filter的预处理,在web资源处理完成返回给客户端之前也要被Filter处理一遍。就好比下面的这种图
当创建了多个Filter之后,客户端传来一个Request请求,它就面对着这一个Filter链,职责琏模式就体现在这里。这个请求会在这个
Filter链上一个一个被传递下去对它进行预处理,处理完成之后就传给下一个Filter直到最后一个,然后才交给web进行相应的访问和处理。它的
uml图(并不是完成的结构图,只是体现职责琏模式的结构图)如下:
一个Filter接口定义了三个方法:init()(初始化方法);destroy()(销毁方法);doFilter()(核心的职责方法);两个具体类实现了Filter接口:ConcreteFilter1和ConcreteFilter2;
一个FilterChain接口定义了一个方法:doFilter();一个具体的实现类ConcreteFilterChain;
其中FilterChain主要的作用是完成找到下一个Filter。
3. 具体的实现
下面是对于上面结构图的一个简单实现,帮助我们理解一下Filter体现的职责琏模式。
ConcreteFilter1类
- package com.test.filter;
- import java.io.IOException;
- import javax.servlet.Filter;
- import javax.servlet.FilterChain;
- import javax.servlet.FilterConfig;
- import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- /**
- * ConcreteFilter1类
- * @author pf
- *
- */
- public class ConcreteFilter1 implements Filter {
- // private String encoding;
- @Override
- public void destroy() {
- System.out.println("ConcreteFilter1()的destroy()执行");
- }
- @Override
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- System.out.println("----ConcreteFilter1()的chain.doFilter()调用之前:对用户请求(request)进行预处理");
- //继续执行
- //后面有filter继续调用,没有的话就进入到了jsp,一直调用最后
- chain.doFilter(request, response);
- System.out.println("ConcreteFilter1()的chain.doFilter()调用之后:对服务器响应(response)进行后处理");
- }
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- // System.out.println("init开始");
- // this.encoding = filterConfig.getInitParameter("encoding");
- // System.out.println("init得到encoding:" + encoding);
- System.out.println("ConcreteFilter1()的init()方法调用");
- }
- }
ConcreteFilter2类
- package com.test.filter;
- import java.io.IOException;
- import javax.servlet.Filter;
- import javax.servlet.FilterChain;
- import javax.servlet.FilterConfig;
- import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- /**
- * 采用Filter统一处理字符集
- * @author pf
- *
- */
- public class ConcreteFilter2 implements Filter {
- // private String encoding;
- @Override
- public void destroy() {
- System.out.println("ConcreteFilter2()的destroy()执行");
- }
- @Override
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- System.out.println("ConcreteFilter2()的chain.doFilter()调用之前");
- // request.setCharacterEncoding(encoding);
- //后面有filter继续调用,没有的话就进入到了jsp,一直调用最后
- chain.doFilter(request, response);
- System.out.println("ConcreteFilter2()的chain.doFilter()调用完成");
- }
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- // System.out.println("init开始");
- // this.encoding = filterConfig.getInitParameter("encoding");
- // System.out.println("init得到encoding:" + encoding);
- System.out.println("ConcreteFilter2()的init()方法调用");
- }
- }
web.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.4"
- xmlns="http://java.sun.com/xml/ns/j2ee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
- http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
- <filter>
- <filter-name>ConcreteFilter1</filter-name>
- <filter-class>com.test.filter.ConcreteFilter1</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>ConcreteFilter1</filter-name>
- <url-pattern>*.jsp</url-pattern>
- </filter-mapping>
- <filter>
- <filter-name>ConcreteFilter2</filter-name>
- <filter-class>com.test.filter.ConcreteFilter2</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>ConcreteFilter2</filter-name>
- <url-pattern>*.jsp</url-pattern>
- </filter-mapping>
- </web-app>
完成之后启动服务器,我这里是tomcat,会显示如下信息:
说明在启动服务器的时候就会创建我们的Filter对象
随便访问一个页面再次查看console
关闭服务器:说明在关闭服务器的时候销毁创建的Filter对象
从上面的执行结果再来看一下Filter。我们设置了两个Filter,分别是ConcreteFilter1和ConcreteFilter2.按照
我们在web.xml中配置的顺序来执行,先执行了ConcreteFilter1,在执行ConcreteFilter2.
但是注意观察,他们在真正调用chain的doFilter方法之后的调用顺序正好相反了。所以我们从这个结果可以看到Filter的执行顺序是遵循”后
进先出”的原则。现将传来的url按照配置中的顺序进行预处理,但是确实先按照相反的filter顺序执行处理好的请求。
下面是讲他的调用过程画了一个时序图:
3. 总结:
通过上面代码执行的结果来看,Filter很好的实现了职责链模式,对于任何一个请求来讲都有一条Filter链可以处理它,具体是哪一个处理了我们其实并不知道但是在到达servlet之前就是已经给我们处理好了,这样子就很好的做到了对象之间的解耦和。
原文:Filter体现职责链模式
Filter体现职责链模式的更多相关文章
- Filter技术+职责链模式
Filter是一个过滤器,存在Webclient与请求的资源之间.这里的资源能够说是jsp或servlet.它的作用就是在请求达到资源之前,先对请求进行预处理.而且也能够对servlet处理后的res ...
- 职责链模式(chain of responsibility)
一. 写在前面的 这么多的设计模式,我觉得职责链是我第一次看上去最简单,可是回想起来却又最复杂的一个模式. 因此,这个文章我酝酿了很久,一直也没有胆量发出来,例子也是改了又改,可是仍然觉得不够合理.所 ...
- 重温设计模式(三)——职责链模式(chain of responsibility)
一. 写在前面的 这么多的设计模式,我觉得职责链是我第一次看上去最简单,可是回想起来却又最复杂的一个模式. 因此,这个文章我酝酿了很久,一直也没有胆量发出来,例子也是改了又改,可是仍然觉得不够合理.所 ...
- javascript设计模式学习之十三——职责链模式
一.职责链的定义和使用场景 职责链模式的定义是,职责链模式将一系列可能会处理请求的对象连接成一条链,请求在这些对象之间一次传递,直到遇到一个可以处理它的对象.从而避免请求的发送者和接收者之间的耦合关系 ...
- js设计模式(12)---职责链模式
0.前言 老实讲,看设计模式真得很痛苦,一则阅读过的代码太少:二则从来或者从没意识到使用过这些东西.所以我采用了看书(<js设计模式>)和阅读博客(大叔.alloyteam.聂微东)相结合 ...
- CSharp设计模式读书笔记(14):职责链模式(学习难度:★★★☆☆,使用频率:★★☆☆☆)
职责链模式(Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象 ...
- Java设计模式之《职责链模式》及应用场景
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6530089.html 职责链模式(称责任链模式)将请求的处理对象像一条长链一般组合起来,形 ...
- C#设计模式之二十一职责链模式(Chain of Responsibility Pattern)【行为型】
一.引言 今天我们开始讲"行为型"设计模式的第八个模式,该模式是[职责链模式],英文名称是:Chain of Responsibility Pattern.让我们看看现实生活中 ...
- LindDotNetCore~职责链模式的应用
回到目录 职责链模式 它是一种设计模块,主要将操作流程与具体操作解耦,让每个操作都可以设置自己的操作流程,这对于工作流应用是一个不错的选择! 下面是官方标准的定义:责任链模式是一种设计模式.在责任链模 ...
随机推荐
- Centos 6.5 Zookeeper 安装
tar -xvf zookeeper-3.4.8.tar.gz 修改配置文件 测试 上传启动脚本,内容如下: #!/bin/bash #chkconfig:2345 20 90 #descriptio ...
- ipv4理论知识3-分类编址之两级编址
两级编制 分类编址时,同一网络中的所有地址都属于统一个地址块,而每个地址块包含两部分:网络标识和主机标识.网络标识指明了网络,主机标识则指明了连接到该网络的一台特定的主机.如下图描绘了分类编址中一个I ...
- Laravel 数据库读写分离
config/database.php ... 'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', 'localho ...
- Linux服务器磁盘扩展和oracle表空间文件迁移操作记录
1.环境介绍 服务器硬件:Dell R710 服务器OS:红帽子Linux RHEL4.8 数据库:Oracle 10g 2.出现的问题 因为数据表每天有上百万的数据写入表,加上建立索引,导致表空 ...
- C# Regex实例
regex1 @"w*(?<Rawsize>\d*x\d*x\d*)\D*(?<RawResolution>(\d*p\d*x*){0,3})_\w*" 测 ...
- <a>链接的四个伪类顺序
<a>元素的作用是可以创建一个链接,链接对应4个状态:未访问,已访问,鼠标悬停,鼠标点击瞬间. 为了给链接的4个状态应用样式,引入伪类的概念. 什么是伪类呢?简单点说,就是你没定义这个类, ...
- 基于Azure构建PredictionIO和Spark的推荐引擎服务
基于Azure构建PredictionIO和Spark的推荐引擎服务 1. 在Azure构建Ubuntu 16.04虚拟机 假设前提条件您已有 Azure 帐号,登陆 Azure https://po ...
- NOIP2013火柴排队[逆序对]
题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2 其中 ai 表示 ...
- HTML5中支持新的媒体元素有这些
HTML5对媒体的支持性很强,支持以下媒体元素: · audio 定义音频 · video 定义视频 · embed 作为外部应用的容器 · source 多种媒体源的支持 · track ...
- c语言中的scanf在java中应该怎么表达,Scanner类。
1 java是面向对象的语言 它没有像C语言中的scanf()函数,但是它的类库中有含有scanf功能的函数 2 java.util包下有Scanner类 Scanner类的功能与scanf类似 3 ...