org.jboss.netty.channel
接口 ChannelPipeline

所有已知实现类:
DefaultChannelPipeline, StaticChannelPipeline

public interface ChannelPipeline

处理或拦截一个ChannelChannelEventChannelHandler列表. ChannelPipeline实现了拦截过滤器模式的高级形式让用户在一个事件如何被处理以及管道里ChannelHandler之间如何交互上提供了了全方位控制.

管道的创建

对于每一个通道,一个新的管道必须被创建及附加到通道上.一旦附加,通道与管道的连接是永久的;通道不能附加另一个管道或从当前管道里分离.

创建管道的推荐方式是使用Channels里的帮助方法而不是调用独立实现的构造方法:

 import static org.jboss.netty.channel.Channels.*;
 ChannelPipeline pipeline = pipeline(); // 与 Channels.pipeline()相同
 

管道里的事件如何流动

下图典型的描述了ChannelPipeline里的ChannelHandler如何处理 ChannelEvent.一个ChannelEvent要么被ChannelUpstreamHandler 处理要么被ChannelDownstreamHandler处理以及通过调用 ChannelHandlerContext.sendUpstream(ChannelEvent)ChannelHandlerContext.sendDownstream(ChannelEvent) 被转发到最接近的处理器.意味着事件被解析有多少不同依赖于它是上游事件还是下游事件.请参考ChannelEvent了解更多信息.
                                       I/O Request
                                     via Channel or
                                 ChannelHandlerContext
                                           |
  +----------------------------------------+---------------+
  |                  ChannelPipeline       |               |
  |                                       \|/              |
  |  +----------------------+  +-----------+------------+  |
  |  | Upstream Handler  N  |  | Downstream Handler  1  |  |
  |  +----------+-----------+  +-----------+------------+  |
  |            /|\                         |               |
  |             |                         \|/              |
  |  +----------+-----------+  +-----------+------------+  |
  |  | Upstream Handler N-1 |  | Downstream Handler  2  |  |
  |  +----------+-----------+  +-----------+------------+  |
  |            /|\                         .               |
  |             .                          .               |
  |     [ sendUpstream() ]        [ sendDownstream() ]     |
  |     [ + INBOUND data ]        [ + OUTBOUND data  ]     |
  |             .                          .               |
  |             .                         \|/              |
  |  +----------+-----------+  +-----------+------------+  |
  |  | Upstream Handler  2  |  | Downstream Handler M-1 |  |
  |  +----------+-----------+  +-----------+------------+  |
  |            /|\                         |               |
  |             |                         \|/              |
  |  +----------+-----------+  +-----------+------------+  |
  |  | Upstream Handler  1  |  | Downstream Handler  M  |  |
  |  +----------+-----------+  +-----------+------------+  |
  |            /|\                         |               |
  +-------------+--------------------------+---------------+
                |                         \|/
  +-------------+--------------------------+---------------+
  |             |                          |               |
  |     [ Socket.read() ]          [ Socket.write() ]      |
  |                                                        |
  |  Netty Internal I/O Threads (Transport Implementation) |
  +--------------------------------------------------------+
 
从图的左边可以知道一个上游事件处理是由下往上方向的.一个上游处理器通常处理由图下方的I/O线程产生的入站数据. 入站数据通常是读取远程端通过实际输入操作的数据如InputStream.read(byte[]) .如果一个上游事件超过了顶部上游处理器,则会被悄悄的丢弃.

从图的右边可以知道一个下游事件处理是由上往下方向的.一个下游处理器通常是产生或转换出站流量如写请求.如果一个下游事件超过了底部下游处理器,它会被关联 Channel的I/O线程处理.这个I/O线程通常执行实际的输出操作如OutputStream.write(byte[]).

例如,我们假设我们创建了以下管道:

 ChannelPipeline p = Channels.pipeline();
 p.addLast("1", new UpstreamHandlerA());
 p.addLast("2", new UpstreamHandlerB());
 p.addLast("3", new DownstreamHandlerA());
 p.addLast("4", new DownstreamHandlerB());
 p.addLast("5", new UpstreamHandlerX());
 
在上面的例子,名字以Upstream开头的类是一个上游处理器.名字以Downstream开头的类是一个下游处理器.

如给的例子配置,当一个事件上游的处理顺序是1, 2, 3, 4, 5.当一个事件下游,顺序是5, 4, 3, 2, 1.在上面的原则上, ChannelPipeline会跳过某些处理器的计算以缩短栈的深度:

组建一个管道

一个用户被假定在一个管道里有一个或多个ChannelHandler用来接收I/O事件(如. read)和请求I/O操作(如. write and close).例如,一个典型的服务器在每个通道的管道里有以下处理器,但你的里程可能是多变的,这依赖于复杂性和协议的特性及业务逻辑:

  1. 协议解码器 - 转化二进制数据(如.ChannelBuffer)为一个Java对象.
  2. 协议编码器 - 转化一个Java对象为二进制数据.
  3. ExecutionHandler - 应用一个线程模型.
  4. 业务逻辑处理器- 执行实际的业务逻辑(如.数据库访问).
它会如下例子所示:
 ChannelPipeline pipeline = Channels.pipeline();
 pipeline.addLast("decoder", new MyProtocolDecoder());
 pipeline.addLast("encoder", new MyProtocolEncoder());
 pipeline.addLast("executor", new ExecutionHandler(new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576)));
 pipeline.addLast("handler", new MyBusinessLogicHandler());
 

线程安全

一个ChannelHandler可以在任何时候被添加或删除,因为ChannelPipeline 是线程安全的.例如,当敏感信息被交换和交换后移除时你可以插入一个SslHandler.

缺陷

因为当前默认ChannelPipeline的内部详细实现,如果以下代码管道里的FirstHandler 是最后一个处理器,那么代码不能如愿工作:

 public class FirstHandler extends SimpleChannelUpstreamHandler {
 
     @Override
     public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
         // 从管道里移除处理器,
         ctx.getPipeline().remove(this);
         // 并让SecondHandler处理当前事件.
         ctx.getPipeline().addLast("2nd", new SecondHandler());
         ctx.sendUpstream(e);
     }
 }
 
要如愿实现行为,你必须在移除之前添加SecondHandler或确保在FirstHandlerSecondHandler之间至少有一个处理器.


方法摘要
 void addAfter(java.lang.String baseName, java.lang.String name, ChannelHandler handler)
          在管道里已存在处理器之后插入ChannelHandler.
 void addBefore(java.lang.String baseName, java.lang.String name, ChannelHandler handler)
          在管道已存在处理器前插入ChannelHandler.
 void addFirst(java.lang.String name, ChannelHandler handler)
          在管道第一个位置插入ChannelHandler.
 void addLast(java.lang.String name, ChannelHandler handler)
          在管道最后位置插入ChannelHandler.
 void attach(Channel channel, ChannelSink sink)
          附加该管道到一个指定的ChannelChannelSink.一旦一个管道被附加,就不能分离或重新附加.
<T extends ChannelHandler>
T
get(java.lang.Class<T> handlerType)
          返回管道里指定类型的ChannelHandler.
 ChannelHandler get(java.lang.String name)
          返回管道里指定名称的ChannelHandler.
 Channel getChannel()
          返回该管道被附加的Channel.
 ChannelHandlerContext getContext(ChannelHandler handler)
          返回管道里指定ChannelHandler的上下文对象.
 ChannelHandlerContext getContext(java.lang.Class<? extends ChannelHandler> handlerType)
          返回在该管道里指定类型的ChannelHandler的上下文对象.
 ChannelHandlerContext getContext(java.lang.String name)
          返回在该管道里指定名字的ChannelHandler的上下文对象.
 ChannelHandler getFirst()
          返回该管道的第一个ChannelHandler.
 ChannelHandler getLast()
          返回管道里最后一个ChannelHandler.
 ChannelSink getSink()
          返回该管道被附加的ChannelSink.
 boolean isAttached()
          只有当该管道被附加到一个Channel才返回true.
 void remove(ChannelHandler handler)
          移除管道里指定的ChannelHandler.
<T extends ChannelHandler>
T
remove(java.lang.Class<T> handlerType)
          移除该管道里指定类型的ChannelHandler
 ChannelHandler remove(java.lang.String name)
          移除该管道里指定名称的ChannelHandler
 ChannelHandler removeFirst()
          移除管道第一个ChannelHandler.
 ChannelHandler removeLast()
          移除管道最后一个ChannelHandler.
 void replace(ChannelHandler oldHandler, java.lang.String newName, ChannelHandler newHandler)
          使用指定处理器替换管道里指定的ChannelHandler.
<T extends ChannelHandler>
T
replace(java.lang.Class<T> oldHandlerType, java.lang.String newName, ChannelHandler newHandler)
          使用指定处理器替换管道里指定类型的ChannelHandler.
 ChannelHandler replace(java.lang.String oldName, java.lang.String newName, ChannelHandler newHandler)
          使用指定处理器替换管道里指定名称的ChannelHandler.
 void sendDownstream(ChannelEvent e)
          发送指定的ChannelEvent到该管道最后一个的ChannelDownstreamHandler.
 void sendUpstream(ChannelEvent e)
          发送指定的ChannelEvent到该管道第一个的ChannelDownstreamHandler.
 java.util.Map<java.lang.String,ChannelHandler> toMap()
          转化该管道为一个key为处理器名、value为处理器的有序Map.
 

方法详细信息

addFirst

void addFirst(java.lang.String name,
              ChannelHandler handler)
在管道第一个位置插入ChannelHandler.

参数:
name - 插入处理器的名字
handler - 要插入的处理器
抛出:
java.lang.IllegalArgumentException - 如果管道里有名字相同的实体存在则抛出异常
java.lang.NullPointerException - 如果指定的名字或处理器是null则抛出异常

addLast

void addLast(java.lang.String name,
             ChannelHandler handler)
在管道最后位置插入ChannelHandler.

参数:
name - 插入处理器的名字
handler - 要插入的处理器
抛出:
java.lang.IllegalArgumentException - 如果管道里有名字相同的实体存在则抛出异常
java.lang.NullPointerException - 如果指定的名字或处理器是null则抛出异常

addBefore

void addBefore(java.lang.String baseName,
               java.lang.String name,
               ChannelHandler handler)
在管道已存在处理器前插入ChannelHandler.

参数:
baseName - 原存在处理器名称
name - 要插入处理器的名称
handler - 要插入的处理
抛出:
java.util.NoSuchElementException - 如果没有指定名称的实体存在则抛出异常
java.lang.IllegalArgumentException - 如果管道里有名字相同的实体存在则抛出异常
java.lang.NullPointerException - 如果指定的basename,name或处理器是null则抛出异常

addAfter

void addAfter(java.lang.String baseName,
              java.lang.String name,
              ChannelHandler handler)
在管道里已存在处理器之后插入ChannelHandler.

参数:
baseName - 存在的处理器名称
name - 插入到该名称的处理器的后面
handler - 要插入的处理器
抛出:
java.util.NoSuchElementException - 如果没有指定名称的实体存在则抛出异常
java.lang.IllegalArgumentException - 如果管道里有名字相同的实体存在则抛出异常
java.lang.NullPointerException - 如果指定的basename,name或处理器是null则抛出异常

remove

void remove(ChannelHandler handler)
移除管道里指定的ChannelHandler.

抛出:
java.util.NoSuchElementException - 如果该管道里没有该处理器则抛出异常
java.lang.NullPointerException - 如果指定的处理器为null则抛出异常

remove

ChannelHandler remove(java.lang.String name)
移除该管道里指定名称的ChannelHandler

返回:
被移除的处理器
抛出:
java.util.NoSuchElementException - 如果管道里没有指定类型的处理器则抛出异常
java.lang.NullPointerException - 如果指定的处理器为null则抛出异常

remove

<T extends ChannelHandler> T remove(java.lang.Class<T> handlerType)
移除该管道里指定类型的ChannelHandler

类型参数:
T - 处理器类型
参数:
handlerType - 处理器类型
返回:
被移除的处理器
抛出:
java.util.NoSuchElementException - 如果管道里没有指定类型的处理器则抛出异常
java.lang.NullPointerException - 如果指定的处理器为null则抛出异常

removeFirst

ChannelHandler removeFirst()
移除管道第一个ChannelHandler.

返回:
被移除的处理器
抛出:
java.util.NoSuchElementException - 如果管道为空则抛出异常

removeLast

ChannelHandler removeLast()
移除管道最后一个ChannelHandler.

返回:
被移除的处理器
抛出:
java.util.NoSuchElementException - 如果管道为空则抛出异常

replace

void replace(ChannelHandler oldHandler,
             java.lang.String newName,
             ChannelHandler newHandler)
使用指定处理器替换管道里指定的ChannelHandler.

抛出:
java.util.NoSuchElementException - 如果该管道里没有指定的旧的处理器则抛出异常
java.lang.IllegalArgumentException - 如果该管道已经存在指定新名称的处理器,除了要替换的处理器则抛出异常
java.lang.NullPointerException - 如果指定的旧的处理、新名称或新处理器为null则抛出异常

replace

ChannelHandler replace(java.lang.String oldName,
                       java.lang.String newName,
                       ChannelHandler newHandler)
使用指定处理器替换管道里指定名称的ChannelHandler.

返回:
被移除的处理器
抛出:
java.util.NoSuchElementException - 如果该管道里没有指定的旧的处理器名称的处理器则抛出异常
java.lang.IllegalArgumentException - 如果该管道已经存在指定新名称的处理器,除了要替换的处理器则抛出异常
java.lang.NullPointerException - 如果指定的旧的处理、新名称或新处理器为null则抛出异常

replace

<T extends ChannelHandler> T replace(java.lang.Class<T> oldHandlerType,
                                     java.lang.String newName,
                                     ChannelHandler newHandler)
使用指定处理器替换管道里指定类型的ChannelHandler.

返回:
被移除的处理器
抛出:
java.util.NoSuchElementException - 如果该管道里没有指定的旧的处理器类型的处理器则抛出异常
java.lang.IllegalArgumentException - 如果该管道已经存在指定新名称的处理器,除了要替换的处理器则抛出异常
java.lang.NullPointerException - 如果指定的旧的处理、新名称或新处理器为null则抛出异常

getFirst

ChannelHandler getFirst()
返回该管道的第一个ChannelHandler.

返回:
第一个处理器.如果该管道为空则返回null.

getLast

ChannelHandler getLast()
返回管道里最后一个ChannelHandler.

返回:
最后一个处理器.如果该管道为空则返回null.

get

ChannelHandler get(java.lang.String name)
返回管道里指定名称的ChannelHandler.

返回:
指定名称的处理器. 如果在该管道里没有该处理器则返回null.

get

<T extends ChannelHandler> T get(java.lang.Class<T> handlerType)
返回管道里指定类型的ChannelHandler.

返回:
指定处理器类型的处理器. 如果在该管道里没有该处理器则返回null.

getContext

ChannelHandlerContext getContext(ChannelHandler handler)
返回管道里指定ChannelHandler的上下文对象.

返回:
指定处理器的上下文对象. 如果在该管道里没有该处理器则返回null.

getContext

ChannelHandlerContext getContext(java.lang.String name)
返回在该管道里指定名字的ChannelHandler的上下文对象.

返回:
返回指定名字的处理器的上下文对象. 如果在该管道里没有该处理器则返回null.

getContext

ChannelHandlerContext getContext(java.lang.Class<? extends ChannelHandler> handlerType)
返回在该管道里指定类型的ChannelHandler的上下文对象.

返回:
指定类型的ChannelHandler的上下文对象. 如果在该管道里没有该处理器则返回null.

sendUpstream

void sendUpstream(ChannelEvent e)
发送指定的ChannelEvent到该管道第一个的ChannelDownstreamHandler.

抛出:
java.lang.NullPointerException - 如果指定的事件为null则抛出异常

sendDownstream

void sendDownstream(ChannelEvent e)
发送指定的ChannelEvent到该管道最后一个的ChannelDownstreamHandler.

抛出:
java.lang.NullPointerException - 如果指定的事件为null则抛出异常

getChannel

Channel getChannel()
返回该管道被附加的Channel.

返回:
通道.如果该管道还没有被附加则返回 null.

getSink

ChannelSink getSink()
返回该管道被附加的ChannelSink.

返回:
隧道.如果该管道还没有被附加则返回 null.

attach

void attach(Channel channel,
            ChannelSink sink)
附加该管道到一个指定的ChannelChannelSink.一旦一个管道被附加,就不能分离或重新附加.

抛出:
java.lang.IllegalStateException - 如果该管道已经被附加则抛出异常

isAttached

boolean isAttached()
只有当该管道被附加到一个Channel才返回true.


toMap

java.util.Map<java.lang.String,ChannelHandler> toMap()
转化该管道为一个key为处理器名、value为处理器的有序Map.