责任链模式以及责任链模式在netty中的使用

职责链模式

将对象连成一条链,使得请求可以在链中进行传递,直到有一个对象处理他为止。

 

责任链中的角色

抽象处理者角色(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,最终被添加到消息发送缓冲区中等待刷新和发送,在此过程中也可以被中断

 

在Netty中将事件根据源头的不同分为InBound事件和OutBound事件。InBound事件通常由I/O线程触发,例如TCP链路建立和关闭、读事件等等,分别会触发相应的事件方法。而OutBound事件则一般由用户主动发起的网络I/O操作,例如用户发起的连接操作,绑定操作和消息发送操作等,也会分别触发相应的事件方法。由于netty中提供了一个抽象类ChannelHandlerAdapter,它默认不处理拦截的事件。所以,在实际编程过程中,我们只需要继承ChannelHandlerAdapter,在我们的自定义Handler中覆盖业务关心的事件方法即可。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值