`
Dapple
  • 浏览: 101703 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

职责链模式(Chain of responsibility)以及servlet中filter的原理

阅读更多
先看经典职责链代码,

(代码来自维基)

package pattern;

import java.io.*;

abstract class PurchasePower {

	protected final double base = 500;
	protected PurchasePower successor;

	public void setSuccessor(PurchasePower successor) {
		this.successor = successor;
	}

	abstract public void processRequest(PurchaseRequest request);
}

class ManagerPPower extends PurchasePower {
	private final double ALLOWABLE = 10 * base;

	public void processRequest(PurchaseRequest request) {
		if (request.getAmount() < ALLOWABLE)
			System.out.println("Manager will approve $" + request.getAmount());
		else if (successor != null)
			successor.processRequest(request);
	}
}

class DirectorPPower extends PurchasePower {
	private final double ALLOWABLE = 20 * base;

	public void processRequest(PurchaseRequest request) {
		if (request.getAmount() < ALLOWABLE)
			System.out.println("Director will approve $" + request.getAmount());
		else if (successor != null)
			successor.processRequest(request);
	}
}

class VicePresidentPPower extends PurchasePower {
	private final double ALLOWABLE = 40 * base;

	public void processRequest(PurchaseRequest request) {
		if (request.getAmount() < ALLOWABLE)
			System.out.println("Vice President will approve $"
					+ request.getAmount());
		else if (successor != null)
			successor.processRequest(request);
	}
}

class PresidentPPower extends PurchasePower {
	private final double ALLOWABLE = 60 * base;

	public void processRequest(PurchaseRequest request) {
		if (request.getAmount() < ALLOWABLE)
			System.out
					.println("President will approve $" + request.getAmount());
		else
			System.out.println("Your request for $" + request.getAmount()
					+ " needs a board meeting!");
	}
}

class PurchaseRequest {

	private int number;
	private double amount;
	private String purpose;

	public PurchaseRequest(int number, double amount, String purpose) {
		this.number = number;
		this.amount = amount;
		this.purpose = purpose;
	}

	public double getAmount() {
		return amount;
	}

	public void setAmount(double amt) {
		amount = amt;
	}

	public String getPurpose() {
		return purpose;
	}

	public void setPurpose(String reason) {
		purpose = reason;
	}

	public int getNumber() {
		return number;
	}

	public void setNumber(int num) {
		number = num;
	}
}

public class CheckAuthority {
	public static void main(String[] args) {
		ManagerPPower manager = new ManagerPPower();
		DirectorPPower director = new DirectorPPower();
		VicePresidentPPower vp = new VicePresidentPPower();
		PresidentPPower president = new PresidentPPower();
		manager.setSuccessor(director);
		director.setSuccessor(vp);
		vp.setSuccessor(president);

		// enter ctrl+c to kill.
		try {
			while (true) {
				System.out
						.println("Enter the amount to check who should approve your expenditure.");
				System.out.print(">");
				double d = Double.parseDouble(new BufferedReader(
						new InputStreamReader(System.in)).readLine());
				manager.processRequest(new PurchaseRequest(0, d, "General"));
			}
		} catch (Exception e) {
			System.exit(1);
		}
	}
}


这段代码实现了不同审批限额由不同级别的人去审批的功能。

该模式有如下特点:

1. 几个对象组成链表结构,用来向后传递请求;
2. 请求被处理,则返回;否则继续向后传递;(有的实现则是不论请求是否被处理,都向后传递)。
3. 对象都继承自同一个父类或实现了共同的用来处理请求的接口。

优点:

1. 发起者(调用者)与接收者分离。
2. 可动态插入职责链。

缺点:

1. 遍历链表有性能损耗。

职责链模式的经典应用是Servlet中的的Filter技术。略过Filter的很简单的使用
方法,我们来看看它在tomcat中的实现。为了说明方便,这里只是它的实现的一
个简化演示代码。

用户自定义的filter都需实现了如下的Filter接口,

doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throws java.io.IOException,ServletException

用户在这个接口里写的代码可以截获请求。对截获的请求处理后,可以把处理权
传递给下一个filter。传递给下一个filter的方法是调用如下一行代码,

chain.doFilter(request,response);

这行代码是Servlet里的Filter技术的核心,所以接下来我们主要就是分析、模拟
这行代码做了什么,它是如何把请求传递给下一个filter的,下一个filter是何
时被创建的。

下面是对整个过程的简单模拟。很简单,就是读配置文件,生成多个
ApplicationFilterConfig对象(称呼它为配置对象),该配置对象负责生成
filter对象。
final class ApplicationFilterChain implements FilterChain {
	private List filterConfigs = new ArrayList();
	private Iterator iterator = null;

	public void doFilter(ServletRequest request, ServletResponse response) {
		if (this.iterator == null)
			this.iterator = filters.iterator();

		if (this.iterator.hasNext()) {
			ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) iterator
					.next();// 在这里取得下一个filter的配置对象
			Filter filter = filterConfig.getFilter();// 注意:在这里取得了下一个filter,这个filter就是你实现了filter接口的filter.
			filter.doFilter(request, response, this);// 把请求传递个下一个filter处理
		}
	}

	public void startFilter() {
		ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) iterator
				.next();
		Filter filter = filterConfig.getFilter();
		filter.doFilter(request, response, this);
	}

	public void addFilterConfig(ApplicationFilterConfig filterConfig) {
		filterConfigs.add(filterConfig);
	}
}

final class ApplicationFilterConfig implements FilterConfig {
	private Filter filter = null;
	private String filterClass;

	public Filter getFilter() {
		if (this.filter != null)
			return (this.filter);

		Class clazz = classLoader.loadClass(filterClass);
		this.filter = (Filter) clazz.newInstance();
		return this.filter;
	}
}

public class MainTest {
	public FilterChain create() {
		ApplicationFilterChain a = new ApplicationFilterChain();
		List filters = readConfigFile();// 读取配置文件,获取filter信息,实现过程略
		for (int i = 0; i < filters.size(); i++) {
			ApplicationFilterConfig afc = (ApplicationFilterConfig) filters
					.get(i);
			a.addFilterConfig(afc);
		}
		return a;
	}

	public static void main(String args[]) {
		(new MainTest()).create().startFilter();
	}
}


tomcat的chain实现有3个要点,

1. 不是一下子全部初始化所有的filter对象,而是只初始化所有的配置对象。配
置对象的生成比filter对象的生成节省资源,生成配置对象只是存储了一些配置
信息。filter对象的生成需要反射,相对消耗资源。

2. 在第一次调用filter的时候,由配置对象生成filter对象。下一次再次调用则
直接使用已经生成的filter对象。缓存思路。

3. 由FilterChain维护一个链表,链表中存放着配置对象的链条,每次用户调用
一次chain.doFilter(req, res),链表就去取下一个配置对象,再通过配置对象
得到下一个filter,然后调用该filter,接着你在filter里写的逻辑就被执行了。

1
0
分享到:
评论

相关推荐

    Chain Of Responsibility模式

    Chain of Responsibility(责任链)模式是一种行为设计模式,它允许将请求沿着处理者对象的链进行发送,每个对象都可以处理请求或将其传递给链中的下一个对象。这种模式常用于事件处理或者命令的执行流程,使得多个...

    Servlet Filter 的单元测试

    这包括对HttpServletRequest、HttpServletResponse对象的检查,以及对Chain of Responsibility模式的模拟。通常,我们需要创建一个MockFilterChain对象,然后调用`doFilter`方法并检查其行为。 4. **异常处理**:...

    责任链模式demo

    责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许将请求沿着处理者对象的链进行传递,直到某个对象处理这个请求。在Java Web开发中,Filter接口就是责任链模式的一个典型应用,用于实现...

    实用j2EE设计模式编程指南J2EE.rar

    10. **职责链(Chain of Responsibility)模式**:在过滤器链中,多个Filter按顺序处理请求,每个Filter决定是否处理或传递给下一个。 11. **状态(State)模式**:对于具有多种状态的对象,根据其状态改变行为,...

    JAVA过滤器及原理

    doFilter方法通常会调用Chain of Responsibility设计模式,通过调用Chain参数的doFilter方法将请求传递给下一个过滤器或目标Servlet。 二、过滤器的生命周期 1. **初始化(init)**:当过滤器被加载到Servlet容器...

    23种JAVA设计模式和15种J2EE设计模式

    行为型模式则关注对象之间的交互和职责分配,包括模板方法(Template Method)、策略(Strategy)、观察者(Observer)、迭代器(Iterator)、访问者(Visitor)、命令(Command)、责任链(Chain of Responsibility...

    J2EE Web层设计模式实例演练

    7. **职责链(Chain of Responsibility)模式**:用于处理请求的分发,多个处理者形成一个链,请求沿着链传递,直到被某个处理者处理。这在权限管理和日志记录等场景中很常见。 8. **适配器(Adapter)模式**:允许...

    J2EE设计模式API

    14. **职责链模式(Chain of Responsibility)**: 通过将请求沿着处理者链传递,使得多个对象都有机会处理该请求。例如,`Exception Handling`的层次结构。 15. **命令模式(Command)**: 将请求封装为一个对象,...

    设计模式

    责任链模式(Chain of Responsibility)是一种行为设计模式,它的主要目的是将请求的发送者和接收者解耦,使得多个对象都有机会处理这个请求。在这个模式中,请求沿着一条链传递,直到某个对象处理它为止。这样做的...

    123种JAVA设计模式和15种J2EE设计模式.pdf

    13. 责任链(Chain of Responsibility)模式为请求创建了一个接收者对象的链。 14. 命令(Command)模式将请求封装为对象,从而使你可用不同的请求对客户进行参数化。 15. 解释器(Interpreter)模式为特定问题定义...

    J2EE相关设计模式23种Java设计模式

    13. **责任链模式(Chain of Responsibility)**:避免将处理请求的逻辑硬编码到单一的对象中,而是让多个对象组成链式结构,请求沿着链传递,直到被处理。在J2EE中,异常处理机制可以看作责任链模式的实例。 14. **...

    java的设计模式之过滤器模式.docx

    过滤器模式,也称为 Chain of Responsibility 模式,是一种行为设计模式,主要用于处理请求的过滤逻辑。在 Java 中,过滤器模式通常应用于网络请求、数据预处理或权限控制等场景。这种模式允许我们通过一系列相互...

    JAVA设计模式

    Java Servlet的Filter Chain机制就是责任链模式的应用。 13. **命令模式(Command)**:将请求封装为一个对象,以便使用不同的请求、队列请求、或者支持可撤销的操作。Java Swing的ActionListener接口就是命令模式...

    轻松掌握java责任链模式

    责任链模式(Chain of Responsibility Pattern)是设计模式中的一种行为模式,它的主要目的是为了实现请求的发送者与接收者之间的解耦。在Java中,这种模式常用于处理一系列连续的操作,比如Spring框架中的拦截器...

Global site tag (gtag.js) - Google Analytics