说责任链之前,先引入一个场景,假如规定学生请假小于或等于 2 天,班主任可以批准;小于或等于 7 天,系主任可以批准;小于或等于 10 天,院长可以批准;其他情况不予批准;以此为需求,写一个程序,你会怎么做?按着过程思维方式,最快最直白的就是,if else嘛,配合java,无非多追加学生类和各个角色的类。下面介绍的设计模式或许会给我们一些启发。

1|1责任链模式

责任链又叫做职责链,是属于行为型设计模式,它的初衷是为了解决一个事件需要经过多个对象处理是很常见的场景。责任链的运作流程是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递。所以责任链将请求的发送者和请求的处理者解耦了。

1|2责任链的实现

责任链的设计源于数据结构中的链表,从模式的定义中就能看出,它需要一串走下去,而每一个处理请求的对象,都需要记录下一个处理请求的对象,即标准的数据链表方式。

职责链模式的实现主要包含以下角色。

抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。

具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。

客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与被处理;理解责任链模式应当理解其模式,而不是其具体实现。责任链模式的独到之处是将其节点处理者组合成了链式结构,并允许节点自身决定是否进行请求处理或转发,相当于让请求流动起来。

UML类图如下:

1|3模式的实现例子:

参照以上的思想,我们针对一开始的场景编写请假的程序:

public class LeaveApprovalTest {

public static void main(String[] args) {

//组装责任链

Leader teacher1 = new ClassAdviser();

Leader teacher2 = new DepartmentHead();

Leader teacher3 = new Dean();

//Leader teacher4=new DeanOfStudies();

teacher1.setNext(teacher2);

teacher2.setNext(teacher3);

//teacher3.setNext(teacher4);

//提交请求

teacher1.handleRequest(8);

}

}

//抽象处理者:领导类

abstract class Leader {

private Leader next;

public void setNext(Leader next) {

this.next = next;

}

public Leader getNext() {

return next;

}

//处理请求的方法

public abstract void handleRequest(int LeaveDays);

}

//具体处理者1:班主任类

class ClassAdviser extends Leader {

public void handleRequest(int LeaveDays) {

if (LeaveDays <= 2) {

System.out.println("班主任批准您请假" + LeaveDays + "天。");

} else {

if (getNext() != null) {

getNext().handleRequest(LeaveDays);

} else {

System.out.println("请假天数太多,没有人批准该假条!");

}

}

}

}

//具体处理者2:系主任类

class DepartmentHead extends Leader {

public void handleRequest(int LeaveDays) {

if (LeaveDays <= 7) {

System.out.println("系主任批准您请假" + LeaveDays + "天。");

} else {

if (getNext() != null) {

getNext().handleRequest(LeaveDays);

} else {

System.out.println("请假天数太多,没有人批准该假条!");

}

}

}

}

//具体处理者3:院长类

class Dean extends Leader {

public void handleRequest(int LeaveDays) {

if (LeaveDays <= 10) {

System.out.println("院长批准您请假" + LeaveDays + "天。");

} else {

if (getNext() != null) {

getNext().handleRequest(LeaveDays);

} else {

System.out.println("请假天数太多,没有人批准该假条!");

}

}

}

}

//具体处理者4:教务处长类

class DeanOfStudies extends Leader {

public void handleRequest(int LeaveDays) {

if (LeaveDays <= 20) {

System.out.println("教务处长批准您请假" + LeaveDays + "天。");

} else {

if (getNext() != null) {

getNext().handleRequest(LeaveDays);

} else {

System.out.println("请假天数太多,没有人批准该假条!");

}

}

}

}

2|0Tomcat中Filter的执行过程

前边已经讲述了关于责任链模式的结构与特点,下面介绍其应用场景,责任链模式通常在以下几种情况使用。

多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。

可动态指定一组对象处理请求,或添加新的处理者。

需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。

说完了责任链的灵活应用,下面结合tomcat中Filter的例子,进行一个标准责任链的解析,先来看以下Tomcat的过滤器机制:

这是一个tomcat处理请求的过程,即它会有多个过滤器,这里的过滤器串联起来,形成一条过滤链,前端或者浏览器发来了request,会经过这条链,顺着链依次经过每个过滤器,最终由servlet处理后,再逐一返回。这有点像栈结构,但是这其中逐一处理,构成一条链,又符合责任链的设计规则。

查看一下Tomcat中Filter接口的源码:

public interface Filter {

void init(FilterConfig var1) throws ServletException;

//熟悉的doFilter(), 熟悉的3个参数request, reponse, filterChain.

void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

void destroy();

}

下面是过滤链的接口源码:

public interface FilterChain {

void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;

}

具体的过滤链的实现,都会带有一个容器,来存放该链中的Filter,即过滤链中包含一个个的过滤器。

2|1做一个简化版的过滤机制

下面我们简化模拟一下Tomcat处理Filter的过程,

首先定义简易版的request和response对象

public class Request{

String msg;

public void setMsg(String msg){

this.msg=msg;

}

}

public class Response{

public void deal(){

System.out.println();

}

}

定义Filter接口及两个实现(http校验,消息敏感字符校验)

public interface Filter{

void doFilter(Request req,Response rep,Filter filer);

}

public HttpFilter implements Filter{

void doFilter(Request req,Response rep,Filter filer){

System.out.println("处理了http验证"+req.getMsg());

filter.doFilter(req,rep,filter);

}

}

public SensitiveFilter implements Filter{

void doFilter(Request req,Response rep,Filter filer){

System.out.println("处理了敏感字符替换"+req.getMsg());

filter.doFilter(req,rep,filter);

}

}

定义过滤链:

public class FilterChain implements Filter{

List filterlist = new Arrary<>();

private int index;

public FilterChain addFilter(Filter filter){

filterlist.add(filter);

return this;

}

void doFilter(Request req,Response res,Filter filter){

if(index == filterlist.size()){

return;//这里是逆序处理响应的关键, 当index为容器大小时, 证明对request的处理已经完成, 下面进入对response的处理.

}

Filter f = filterlist.get(index);//过滤器链按index的顺序拿到filter

index++;

f.doFilter(request, response, filter);

}

}

测试代码:

public class DemoBox {

public static void main(String[] args) {

String msg = "大家好 ";//以下三行模拟一个请求

Request request = new Request();

request.setMsg(msg);

Response response = new Response();//响应

FilterChain fc = new FilterChain();//过滤器链

HttpFilter f1 = new HttpFilter();//创建过滤器

SensitiveFilter f2 = new SensitiveFilter();//创建过滤器

fc.add(f1);//把过滤器添加到过滤器链中

fc.add(f2);

fc.doFilter(request, response, fc);//直接调用过滤器链的doFilter()方法进行处理

}

}

下面按着步骤,详细解释一下上面的代码:

首先我们分别创建一个Request和Response对象.Request在传入进后端时需要依次被过滤器进行处理,Response对象在输出时要依次被过滤器处理.

我们定义了一个Filter接口,它包含处理请求的方法doFilter,这里的Filter可以理解为责任链中的抽象处理者

依次实现了两个拦截器,HttpFilter,SensitiveFilter,做具体的过滤处理,可以理解为责任链中具体处理者的角色

实现一个Filter接口,做一个过滤链的类FilterChain,它除了基本的处理功能,还包含了一个过滤器容器FilterList,用它还存放整条链的Filter。

接着我们调用过滤器链的doFilter()方法对request对象进行处理

这时过滤器链中的index值为0, 通过index我们找到第一个过滤器并调用它的doFilter()方法

进入doFilter()方法后, 首先会对request请求进行处理, 然后又调用了过滤器链的doFilter()方法. 这就是整个责任链模式的精妙之处, 它解释了为什么要给doFilter()加上一个过滤器链参数, 就是为了让每个过滤器可以调用过滤器链本身执行下一个过滤器。

为什么要调用过滤器链本身? 因为当调用过滤器本身后, 程序将跳转回到过滤器链的doFilter方法执行, 这时index为1, 也就是拿到第二个过滤器, 然后继续处理。

正是由于这个跳转, 使得过滤器中对response的处理暂时无法执行, 它必须等待上面的对过滤器链的方法返回才能被执行.

作者:糖拌西红柿,来源:博客园

java设计模式三个模式结合_Java设计模式——责任链(结合Tomcat中Filter机制)相关推荐

  1. java设计模式装饰者模式优点_java设计模式之--装饰者模式

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装 ...

  2. 设计模式——行为型模式之责任链模式(简简单单入门责任链,理解I/O流消息怎么逐步传递处理以及服务器框架转发)

    文章目录 前言 一.责任链模式定义 二.责任链模式结构 三.责任链高级应用 四.责任链模式优缺点 设计模式系列文章 结尾 前言 作者更有一系列设计模式文章(还在持续更新),图例丰富,少量代码,适合入门 ...

  3. 责任链模式实践之Zuul责任链模式

    责任链模式实践之Zuul责任链模式 一,什么是责任链模式 责任链(Chain of Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对 ...

  4. 设计模式(三)--工厂模式

    1.1简单工厂模式 1.1.1看一个具体的需求:看一个披萨的项目:要便于披萨种类的扩展,要便于维护 披萨的种类很多(比如 GreekPizz.CheesePizz 等) 披萨的制作有 prepare, ...

  5. 设计模式(一)Chain Of Responsibility责任链模式

    设计模式篇章,源于网课的学习,以及个人的整理 在我们接收用户提交的字符时,常常会使用到过滤,在学习责任链模式前,我们是这样做的 1.定义一个类 public class MsgProcesser {S ...

  6. java责任链模式审批请假_Java使用责任链模式处理学生请假问题详解

    本文实例讲述了Java使用责任链模式处理学生请假问题.分享给大家供大家参考,具体如下: 一. 模式定义 在责任链模式中,很多对象由每一个对象对其下家的引用而连接起来,形成一条链.客户端应用请求在这个链 ...

  7. 设计模式-责任链模式之**动态配置责任链**

    责任链的优势劣势我就不说,百度上很多. 1.怎么:动态配置责任链 通过配置文件yml来指定你的责任链的执行顺序. 地址 配置文件如何配置,怎么读取 为什么:动态配置责任链 为了方便配置这个链条的执行顺 ...

  8. 23种设计模式C++源码与UML实现--责任链模式

    责任链模式 Chain of Responsibility CoR模式,也叫责任链模式或者责任连锁模式,是行为模式之一,该模式构造一系列分别担当不同的职责的类的对象来共同完成一个任务,这些类的对象之间 ...

  9. 责任链模式与lambda重构责任链模式

    一.概念以及背景 责任链模式(Chain of Responsibility Pattern):责任链模式是一种创建处理对象序列(比如操作序列)的通用方案.一个处理对象可能需要在完成一些工作之后,将结 ...

  10. java 打成war_JAVA语言之Springboot打成war包并在tomcat中运行的部署方法

    本文主要向大家介绍了JAVA语言的Springboot打成war包并在tomcat中运行的部署方法,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 把spring-boot项目按照平常 ...

最新文章

  1. 算法设计与分析课程的时间空间复杂度
  2. python读文件缺key_在Python中读取Twitter json文件时出现KeyErrors
  3. 系统设计说明书案例_案例 | 太阳能+热泵枸杞烘干系统设计及经济性分析
  4. 手动整合ssh框架时的各种错误
  5. JSON JsonArray和JsonObject学习资料
  6. git clone 仓库的部分代码
  7. RocketMQ各角色介绍
  8. 按键改变元素背景颜色 链式编程的原理 评分案例 each方法的使用
  9. GitOps:Kubernetes多集群环境下的高效CICD实践
  10. Linux命令大总结(早期学习时的笔记)
  11. 什么是交换机?交换机的工作原理是什么?
  12. OpenCV--常见图片格式转换与深浅拷贝
  13. 同样版本的jstl,都是jstl1.2版本,有个有问题,另一个没有问题
  14. 2022年最新的百度云盘在线倍速播放实践可用
  15. 《资治通鉴》曾参三人成“真”、胡服骑射、吕不韦
  16. android 自动 创建文件夹,android - 如何在SD卡上自动创建目录
  17. excel冻结窗格参与排序_冻结窗格在Excel中消失
  18. 详细讲解电脑怎么录屏 电脑录制视频的方法
  19. mysql 1032_MySQL 报错 Last_SQL_Errno: 1032
  20. C++开发斗地主(QT)第三篇之动画发牌与位置计算

热门文章

  1. GEE|影像可视化|导出分类结果图像
  2. 数据结构与算法之美-问题与思考收集
  3. C语言计算阶乘及阶乘的和
  4. 2021京东618活动脚本App和电脑版最新版(建议使用app版)
  5. cannot open shared object file
  6. 还原数据库SQL语句
  7. Linux桌面版横评:九、Mandriva Linux 2007 Spring One
  8. matlab 默认颜色顺序,MATLAB:设置行的颜色和样式顺序并行应用
  9. SQL19 查找所有员工的last_name和first_name以及对应的
  10. 宁芝84静电容(蓝牙双模)键盘说明书