pipeline机制

前端之家收集整理的这篇文章主要介绍了pipeline机制前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

最近在看netty的源码,准备将一些理解和总结写出来,netty的源码写的很漂亮理解起来也不是那么容易,很值得我们去学习和借鉴。我们知道在设计模式里面提到过一种责任链的模式,据我看一些源码的了解(不管是公司的中间件还是一些开源的项目),责任链的应用非常广泛,包括现在在公司做的东西。其中netty很好的扩展了责任链模式来实现netty的骨架,我们这里称它为pipeline模式。

如果将数据比作是水,那么pipeline就是水管,里面的阀门就是用来处理水的部分。比如一个Request进来,可能经过层层的处理,包括响应也是,所以类似这种服务端的框架很适合使用pipeline模式,实际上tomcat就是这么做的。netty的pipeline机制非常方便用户使用,定制自己的阀门,pipeline的结构如下图:


其中的HandlerContext就是上面讲的阀门,包括拦截器模式,Filter模式它们的实现都是类似的,全部是基于责任链的变体,每个HandlerContext都聚合一个Handler,由Handler负责具体的逻辑处理,netty中抽象出一个头和尾节点,其中从头向尾执行的时候,头部的逻辑不会执行,从尾向头执行的时候,尾部的逻辑不会执行,这两个虚节点也方便双向链表的实现。自己模拟netty的pipeline实现了一个简化版本的pipeline。下面来看一下代码

package s4netty.pipeline;

/**
 * pipeline接口,可以向pipeline中新增handler
 * 
 * @author Administrator
 *
 */
public interface Pipeline {
	
	Pipeline addFirst(String name,Handler handler);

	Pipeline fireProcess();
}
可以向一个Pipeline中增加Handler,同时可以由Pipeline触发整个链的执行,这里只是一个简单的无参方法fireProcess。
package s4netty.pipeline;

/**
 * handler接口
 * 
 * @author Administrator
 *
 */
public interface Handler {
	void process(HandlerContext context);
}
Handler接口定义,对应pipeline提供了process方法用来处理数据,其中需要的数据会存储在HandlerContext中。
package s4netty.pipeline;
/**
 * 抽象handler执行上下文
 * @author Administrator
 *
 */
public interface HandlerContext {
	
	Handler handler();
	
	HandlerContext fireProcess();
}
上下文的定义同样很简单,一个handler方法由子类实现去返回自己的Handler,同时fireProcess方法负责处理业务逻辑和流程的传递。到现在还只是一些简单接口的定义,可能还看不出来pipeline的端倪,不着急继续往下。
package s4netty.pipeline;

/**
 * 抽象的handler上下文,基于责任链模式实现双向链表
 * 
 * @author Administrator
 *
 */
public abstract class AbstractHandlerContext implements HandlerContext {

	// handler-context的前一个结点
	AbstractHandlerContext prev;

	// handler-context的下一个节点
	AbstractHandlerContext next;

	// handlerContext的名字
	private final String name;

	AbstractHandlerContext(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	@Override
	public HandlerContext fireProcess() {
		// 获取下一个上下文,如果子类不复写该方法,则直接传递到下一个处理节点
		AbstractHandlerContext next = this.next;
		next.invokeProcess();
		return this;
	}

	private void invokeProcess() {
		handler().process(this);
	}
}
抽象的Context是一个很关键的实现,因为它实际上是一个双向的链表,有next节点和prev节点,其中前面讲过fireProcess方法负责业务处理和责任链的传递,在这里也体现出来了。
package s4netty.pipeline;

/**
 * 默认实现,关联一个Handler
 * 
 * @author Administrator
 *
 */
public class DefaultHandlerContext extends AbstractHandlerContext {

	private Handler handler;

	DefaultHandlerContext(String name,Handler handler) {
		super(name);
		this.handler = handler;
	}

	@Override
	public Handler handler() {
		return handler;
	}

}
HandlerContext的默认实现,很简单,就是聚合了一个Handler。
package s4netty.pipeline;

import java.util.HashMap;
import java.util.Map;

/**
 * pipeline模式
 * 
 * @author Administrator
 *
 */
public final class DefaultPipeline implements Pipeline {

	final AbstractHandlerContext head;

	final AbstractHandlerContext tail;

	private Map<String,Handler> ctxHandlers = new HashMap<String,Handler>(4);

	public DefaultPipeline() {

		head = new HeadHandlerContext();
		tail = new TailHandlerContext();

		// 双向链表
		head.next = tail;
		tail.prev = head;
	}

	static final class HeadHandlerContext extends AbstractHandlerContext implements Handler {

		private static final String HEADNAME = "HEAD";

		HeadHandlerContext() {
			super(HEADNAME);
		}

		@Override
		public Handler handler() {
			return this;
		}

		@Override
		public void process(HandlerContext context) {
			System.out.println(this.getName());
		}

	}

	static final class TailHandlerContext extends AbstractHandlerContext implements Handler {

		private static final String TAILNAME = "TAIL";

		TailHandlerContext() {
			super(TAILNAME);
		}

		@Override
		public Handler handler() {
			return this;
		}

		@Override
		public void process(HandlerContext context) {
			System.out.println(this.getName());
		}

	}

	/**
	 * 实现pipeline接口中的addFirst方法,将handler置为head
	 */
	@Override
	public Pipeline addFirst(String name,Handler handler) {

		AbstractHandlerContext newCtx = new DefaultHandlerContext(name,handler);
		AbstractHandlerContext nextCtx = head.next;
		newCtx.prev = head;
		newCtx.next = nextCtx;

		head.next = newCtx;
		nextCtx.prev = newCtx;

		ctxHandlers.put(name,handler);
		return this;
	}

	public Map<String,Handler> getCtxHandlers() {
		return ctxHandlers;
	}

	public void setCtxHandlers(Map<String,Handler> ctxHandlers) {
		this.ctxHandlers = ctxHandlers;
	}

	/**
	 * 触发处理流程
	 */
	@Override
	public Pipeline fireProcess() {
		//从头开始触发流程
		head.fireProcess();
		return this;
	}

}
另外一个重要的类是Pipeline的实现,默认构建了一个只有头尾的双向链表,可以通过addFirst方法向其中添加其他的Handler。

以上就是pipeline机制的简单实现,整体上还是比较清晰的。

原文链接:https://www.f2er.com/javaschema/284302.html

猜你在找的设计模式相关文章