职责链模式
将对象连成一条链,使得请求可以在链中进行传递,直到有一个对象处理他为止。
责任链中的角色
抽象处理者角色(Handler):定义出一个处理请求的接口。如果需要,接口可以定义出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。
具体处理者角色(ConcreteHandler):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
抽象处理者角色
public abstract class Handler {
/**
* 持有后继的责任对象
*/
protected Handler successor;
/**
* 示意处理请求的方法,虽然这个示意方法是没有传入参数的
* 但实际是可以传入参数的,根据具体需要来选择是否传递参数
*/
public abstract void handleRequest();
/**
* 取值方法
*/
public Handler getSuccessor() {
return successor;
}
/**
* 赋值方法,设置后继的责任对象
*/
public void setSuccessor(Handler successor) {
this.successor = successor;
}
}
具体处理者角色
public class ConcreteHandler extendsHandler {
/**
* 处理方法,调用此方法处理请求
*/
@Override
public void handleRequest() {
/**
* 判断是否有后继的责任对象
* 如果有,就转发请求给后继的责任对象
* 如果没有,则处理请求
*/
if(getSuccessor() != null)
{
System.out.println("放过请求");
getSuccessor().handleRequest();
}else
{
System.out.println("处理请求");
}
}
}
客户端类
public class Client {
public static void main(String[] args) {
//组装责任链
Handler handler1 = new ConcreteHandler();
Handler handler2 = new ConcreteHandler();
handler1.setSuccessor(handler2);
//提交请求
handler1.handleRequest();
}
}
例子中的责任链处理逻辑很简单:当有下一个处理者的时候,则直接传递给下一个处理者,当没有的时候,则自己处理。
以上就是一般的责任链模式的处理逻辑。和我们在web开发中经常使用到的filter非常相似。下面看看在netty中是如何使用责任链模式的。
Netty中的责任链模式使用
在netty中,将Channel的数据管道抽象为ChannelPipeline,消息在ChannelPipeline中流动和传递。ChannelPipeline是ChannelHandler的容器,持有I/O事件拦截器ChannelHandler的链表,负责对ChannelHandler的管理和调度。由ChannelHandler对I/O事件进行拦截和处理,并可以通过接口方便地新增和删除ChannelHandler来实现不同业务逻辑的处理。
ChannelPipeline的责任链事件处理过程
图中展示了一个消息被ChannelPipeline链拦截和处理的过程。
(1) 底层的SocketChannel read方法读取ByteBuf,触发ChannelRead事件,由I/O线程NioEventLoop调用ChannelPipeline的fireChannelRead方法,将消息传输到ChannelPipeline中。
(2) 消息依次被HeadHandler、ChannelHandler1、ChannelHandler2……TailHandler拦截和处理,在这个过程中,任何ChannelHandler都可以中断当前的流程,结束消息的传递。
(3) 当调用ChannelHandlerContext的write方法发送消息,消息从TailHandler开始,经ChannelHandlerN……ChannelHandler1、HeadHandler,最终被添加到消息发送缓冲区中等待刷新和发送,在此过程中也可以被中断