文章目录

  • 1.设计模式 - 责任链模式
  • 2.实现责任链模式
  • 2.1类似tomcat的filters伪代码
  • 2.2类似Netty的责任链模式伪代码
  • 3.一个简单例子
  • 要素一:处理器抽象类
  • 要素二:具体的处理器实现类
  • 要素三:保存处理器信息的类
  • 要素四:处理执行
  • 4.Netty中的ChannelPipeline责任链
  • 4.1入站事件和出站事件


1.设计模式 - 责任链模式

  • 责任链模式为请求创建了一个处理对象的链。
  • 发起请求和具体处理请求的过程进行解耦:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递。

Java 责任连模式 netty 责任链_网络

2.实现责任链模式

实现责任链的四个要素:

  • 处理器抽象类
  • 具体的处理器实现类
  • 保存处理器信息
  • 处理执行

简单看下伪代码吧!

2.1类似tomcat的filters伪代码

//---集合形式存储---伪代码---类似tomcat中filters
//处理器抽象类
class AbstractHandler{void doHandler(Object arg0)}
//处理器的具体实现类
class Handler1 extends AbstractHandler{assert coutinue;}
class Handler2 extends AbstractHandler{assert coutinue;}
class Handler3 extends AbstractHandler{assert coutinue;}
//创建集合并存储所有处理器实例信息
List handlers = new List();
handlers.add(handler1,handler2,handler3);
//处理请求,调用处理器
void Process(request){
    for(handler in handlers){
        handler.doHandler(request);
    }
}
//发起请求调用,通过责任链处理请求
call.Process(request);

2.2类似Netty的责任链模式伪代码

//---链表形式调用---伪代码---netty就是这种形式
//处理器抽象类
class AbstractHandler{
AbstractHandler next;//下一个节点
void doHanlder(Object arg0);//handler方法
}
//处理器具体实现类
class Handler1 extend AbstractHandler{assert coutinue};
class Handler2 extend AbstractHandler{assert coutinue};
class Handler3 extend AbstractHandler{assert coutinue};
//将处理器串成链表存储
pipeline = 头[handler1->handler2->handler3]尾
//处理请求,调用处理器(从头到尾)
void Process(request){
handler = pipeline.findOne;//查找第一个
while(hander != null){
handler.doHandler(request);
handler=handler.next();
}
}

3.一个简单例子

我们有这么一个需求,需要给一个字符串后面拼接小尾巴(后缀),那我们怎么用责任链模式去实现呢?

要素一:处理器抽象类

// 处理器抽象类
abstract class AbstractHandler {
    /**
     * 处理器,这个处理器就做一件事情,在传入的字符串中增加一个尾巴..
     */
    abstract void doHandler(HandlerChainContext handlerChainContext, Object arg0); // handler方法
}

要素二:具体的处理器实现类

// 处理器具体实现类
class Handler1 extends AbstractHandler {
    @Override
    void doHandler(HandlerChainContext handlerChainContext, Object arg0) {
        arg0 = arg0.toString() + "..handler1的小尾巴.....";
        System.out.println("我是Handler1的实例,我在处理:" + arg0);
        // 继续执行下一个
        handlerChainContext.runNext(arg0);
    }
}

// 处理器具体实现类
class Handler2 extends AbstractHandler {
    @Override
    void doHandler(HandlerChainContext handlerChainContext, Object arg0) {
        arg0 = arg0.toString() + "..handler2的小尾巴.....";
        System.out.println("我是Handler2的实例,我在处理:" + arg0);
        // 继续执行下一个
        handlerChainContext.runNext(arg0);
    }
}

要素三:保存处理器信息的类

/**
 * handler上下文,我主要负责维护链,和链的执行
 */
class HandlerChainContext {
    HandlerChainContext next; // 下一个节点
    AbstractHandler handler;

    public HandlerChainContext(AbstractHandler handler) {
        this.handler = handler;
    }

    void handler(Object arg0) {
        this.handler.doHandler(this, arg0);
    }

    /**
     * 继续执行下一个
     */
    void runNext(Object arg0) {
        if (this.next != null) {
            this.next.handler(arg0);
        }
    }
}

要素四:处理执行

public class PipelineDemo{
    /**
     * 初始化的时候造一个head,但是没有实际的处理,只是作为责任链的开始
     */
    public HandlerChainContext head = new HandlerChainContext(new AbstractHandler() {
        @Override
        void doHandler(HandlerChainContext handlerChainContext, Object arg0) {
            handlerChainContext.runNext(arg0);
        }
    });

    /**
     * 责任链的调用入口
     */
    public void requestProcess(Object arg) {
        this.head.handler(arg);
    }

    /**
     * 往链表的末尾加一个handler
     */
    public void addLast(AbstractHandler handler){
        HandlerChainContext context = head;
        while (context.next!=null){
            context = context.next;
        }
        context.next = new HandlerChainContext(handler);
    }

    public static void main(String[] args) {
        PipelineDemo pipelineChainDemo = new PipelineDemo();
        pipelineChainDemo.addLast(new Handler2());
        pipelineChainDemo.addLast(new Handler1());
        pipelineChainDemo.addLast(new Handler1());
        pipelineChainDemo.addLast(new Handler2());

        // 发起请求
        pipelineChainDemo.requestProcess("火车呜呜呜~~");

    }
}

打印的结果如下:

我是Handler2的实例,我在处理:火车呜呜呜~~..handler2的小尾巴.....
我是Handler1的实例,我在处理:火车呜呜呜~~..handler2的小尾巴.......handler1的小尾巴.....
我是Handler1的实例,我在处理:火车呜呜呜~~..handler2的小尾巴.......handler1的小尾巴.......handler1的小尾巴.....
我是Handler2的实例,我在处理:火车呜呜呜~~..handler2的小尾巴.......handler1的小尾巴.......handler1的小尾巴.......handler2的小尾巴.....

4.Netty中的ChannelPipeline责任链

  • Pipeline管道保存了通道所有处理器信息
  • 创建新channel是自动创建一个专有的pipeline。
  • 入站事件和出站操作会调用pipeline上的处理器。

4.1入站事件和出站事件

  • 入站事件:通常指I/O线程生成了入站数据。通俗地讲,就是从socket底层自己往上冒出来地事件就是入站。不如EventLoop收到selector的OP_READ事件,入站处理器调用socketChannel.read(ByteBuffer)接收到数据后,这将导致通道的ChannelPipeline中包含的下一个中的channelRead方法被调用。
  • 出站事件:经常是指I/O线程执行实际的输出操作。通俗地讲,就是想主动往socket底层操作的事件都是出站。比如bind方法用意是请求server socket绑定到给定的SocketAddress,这将导致通道的ChannelPipeline中包含的下一个出站处理器中的bind方法被调用。

Netty中事件的定义

inbound 入站事件

事件

描述

fireChannelRegistered

channel注册事件

fireChannelUnregistered

channel解除注册事件

fireChannelActive

channel活跃事件

fireChannelInactive

channel非活跃事件

fireExceptionCaught

异常事件

fireUserEventTriggered

用户自定义事件

fireChannelRead

channel读事件

fireChannelReadComplete

channel读完成事件

fireChannelWritabilityChanged

channel写状态变化事件

outbound 出站事件

事件

描述

bind

端口绑定事件

connect

连接事件

disconnect

断开连接事件

close

关闭事件

deregister

解除注册事件

flush

刷新数据到网络事件

read

读事件,用于注册OP_READ到selector

write

写事件

writeAndFlush

写出数据事件

笔者才疏学浅,从来没接触过netty,后续会再来补充的。