|
|||||||||
上一个类 下一个类 | 框架 无框架 | ||||||||
摘要: 嵌套 | 字段 | 构造方法 | 方法 | 详细信息: 字段 | 构造方法 | 方法 |
public interface ChannelHandler
处理或拦截一个ChannelEvent
并发送一个 ChannelEvent
到ChannelPipeline
里的下一个处理器 .
ChannelHandler
自己并不提供任何方法.要处理一个ChannelEvent
,你需要实现它的子接口.它有两个处理收到事件的子接口,一个用于上游事件,另一个用于下游事件:
ChannelUpstreamHandler
处理和拦截一个上游ChannelEvent
.ChannelDownstreamHandler
处理和拦截一个下游ChannelEvent
.
一个ChannelHandler
是通过ChannelHandlerContext
对象提供的.一个
ChannelHandler
应该通过一个上下文和他属于的ChannelPipeline
交互.使用上下文对象,
ChannelHandler
可以传递上游事件或下游事件、动态修改管道,或保存信息(附件)到指定的处理器中.
ChannelHandler
经常需要保存一下有状态的信息.最简单和推荐的方法是使用成员变量:
public class DataServerHandler extends由于处理器实例有一个专用于一个连接的状态变量,所以你需要为每个新的通道创建一个新的处理器实例以避免一个非法客户端获取机密信息的条件竞争:SimpleChannelHandler
{ private boolean loggedIn;@Override
public void messageReceived(ChannelHandlerContext
ctx,MessageEvent
e) {Channel
ch = e.getChannel(); Object o = e.getMessage(); if (o instanceof LoginMessage) { authenticate((LoginMessage) o); loggedIn = true; } else (o instanceof GetDataMessage) { if (loggedIn) { ch.write(fetchSecret((GetDataMessage) o)); } else { fail(); } } } ... }
// 为每个通道创建一个处理器实例. // 查看Bootstrap.setPipelineFactory(ChannelPipelineFactory)
. public class DataServerPipelineFactory implementsChannelPipelineFactory
{ publicChannelPipeline
getPipeline() { returnChannels
.pipeline(new DataServerHandler()); } }
ChannelHandlerContext
提供的附件:
既然使用附件保存处理器的状态,你可以为不同的管道添加相同的处理器实例:@Sharable
public class DataServerHandler extendsSimpleChannelHandler
{@Override
public void messageReceived(ChannelHandlerContext
ctx,MessageEvent
e) {Channel
ch = e.getChannel(); Object o = e.getMessage(); if (o instanceof LoginMessage) { authenticate((LoginMessage) o); ctx.setAttachment(true); } else (o instanceof GetDataMessage) { if (Boolean.TRUE.equals(ctx.getAttachment())) { ch.write(fetchSecret((GetDataMessage) o)); } else { fail(); } } } ... }
public class DataServerPipelineFactory implementsChannelPipelineFactory
{ private static final DataServerHandler SHARED = new DataServerHandler(); publicChannelPipeline
getPipeline() { returnChannels
.pipeline(SHARED); } }
ChannelLocal
ChannelLocal
:
public final class DataServerState { public static finalChannelLocal
<Boolean> loggedIn = newChannelLocal
<Boolean>() { protected Boolean initialValue(Channel channel) { return false; } } ... }@Sharable
public class DataServerHandler extendsSimpleChannelHandler
{@Override
public void messageReceived(ChannelHandlerContext
ctx,MessageEvent
e) { Channel ch = e.getChannel(); Object o = e.getMessage(); if (o instanceof LoginMessage) { authenticate((LoginMessage) o); DataServerState.loggedIn.set(ch, true); } else (o instanceof GetDataMessage) { if (DataServerState.loggedIn.get(ch)) { ctx.getChannel().write(fetchSecret((GetDataMessage) o)); } else { fail(); } } } ... } // 打印合法客户端的远程地址:ChannelGroup
allClientChannels = ...; for (Channel
ch: allClientChannels) { if (DataServerState.loggedIn.get(ch)) { System.out.println(ch.getRemoteAddress()); } }
@Sharable
注解
不管上面例子是使用附件还是ChannelLocal
,你可以注意到@Sharable
注解.
如果一个ChannelHandler
使用@Sharable
注解,这意味着你可以只创建一次处理器实例,并可以多次添加到一个或多个ChannelPipeline
上而不会发生条件竞争.
如果没有指定该注解,你必须每次创建一个新的处理器实例并添加到一个管道上,因为它有不共享的状态,如成员变量.
该注解被作为文档目的提供,就像 JCIP注解.
查阅ChannelEvent
和ChannelPipeline
了解什么是上游事件和下游事件,它们的区别以及如果在管道中流动.
嵌套类摘要 | |
---|---|
static interface |
ChannelHandler.Sharable
表示被注解的相同 ChannelHandler 实例可以被多次添加到一个或多个ChannelPipeline
上而不会发生条件竞争. |
|
|||||||||
上一个类 下一个类 | 框架 无框架 | ||||||||
摘要: 嵌套 | 字段 | 构造方法 | 方法 | 详细信息: 字段 | 构造方法 | 方法 |