1.8. 使用POJO代替ChannelBuffer
目前为止所有的实例程序都是使用ChannelBuffer做为协议消息的原始数据结构。在这一节,我们将改进时间协议服务的客户/服务端实现,使用POJO 而不是ChannelBuffer做为协议消息的原始数据结构。
在你的ChannelHandler实现中使用POJO的优势是很明显的;从你的ChannelHandler实现中分离从 ChannelBuffer获取数据的代码,将有助于提高你的ChannelHandler实现的可维护性和可重用性。在时间协议服务的客户/服务端代码 中,直接使用ChannelBuffer读取一个32位的整数并不是一个主要的问题。然而,你会发现,当你试图实现一个真实的协议的时候,这种代码上的分 离是很有必要的。
首先,让我们定义一个称之为UnixTime的新类型。
package org.jboss.netty.example.time; import java.util.Date; public class UnixTime { private final int value; public UnixTime(int value) { this.value = value; } public int getValue() { return value; } @Override public String toString() { return new Date(value * 1000L).toString(); } }
现在让我们重新修改TimeDecoder实现,让其返回一个UnixTime,而不是一个ChannelBuffer。
@Override protected Object decode( ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) { if (buffer.readableBytes() < 4) { return null; } return new UnixTime(buffer.readInt()); }
FrameDecoder和ReplayingDecoder允许你返回一个任何类型的对象。如果它们仅允许返回一个ChannelBuffer类 型的对象,我们将不得不插入另一个可以从ChannelBuffer对象转换 为UnixTime对象的ChannelHandler实现。
有了这个修改后的decoder实现,这个TimeClientHandler便不会再依赖ChannelBuffer。
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { UnixTime m = (UnixTime) e.getMessage(); System.out.println(m); e.getChannel().close(); }
更加简单优雅了,不是吗?同样的技巧也可以应用在服务端,让我们现在更新TimeServerHandler的实现:
@Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) { UnixTime time = new UnixTime(System.currentTimeMillis() / 1000); ChannelFuture f = e.getChannel().write(time); f.addListener(ChannelFutureListener.CLOSE); }
现在剩下的唯一需要修改的部分是这个ChannelHandler实现,这个ChannelHandler实现需要把一个UnixTime对象重新 转换为一个ChannelBuffer。但这却已是相当简单了,因为当你对消息进行编码的时候你不再需要处理数据包的拆分及组装。
package org.jboss.netty.example.time; import static org.jboss.netty.buffer.ChannelBuffers.*; @ChannelPipelineCoverage("all") public class TimeEncoder extends SimpleChannelHandler { public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) { UnixTime time = (UnixTime) e.getMessage(); ChannelBuffer buf = buffer(4); buf.writeInt(time.getValue()); Channels.write(ctx, e.getFuture(), buf); } }
代码说明
1) 因为这个encoder是无状态的,所以其使用的ChannelPipelineCoverage注解值是“all”。实际上,大多数encoder实现都是无状态的。
2) 一个encoder通过重写writeRequested方法来实现对写操作请求的拦截。不过请注意虽然这个writeRequested方法使用了和 messageReceived方法一样的MessageEvent参数,但是它们却分别对应了不同的解释。一个ChannelEvent事件可以既是一 个上升流事件(upstream event)也可以是一个下降流事件(downstream event),这取决于事件流的方向。例如:一个MessageEvent消息事件可以作为一个上升流事件(upstream event)被messageReceived方法调用,也可以作为一个下降流事件(downstream event)被writeRequested方法调用。请参考API手册获得上升流事件(upstream event)和下降流事件(downstream event)的更多信息。
3) 一旦完成了POJO和ChannelBuffer转换,你应当确保把这个新的buffer缓冲转发至先前的 ChannelDownstreamHandler处理,这个下降通道的处理器由某个ChannelPipeline管理。Channels提供了多个可 以创建和发送ChannelEvent事件的帮助方法。在这个例子中,Channels.write(...)方法创建了一个新的 MessageEvent事件,并把这个事件发送给了先前的处于某个ChannelPipeline内的 ChannelDownstreamHandler处理器。
另外,一个很不错的方法是使用静态的方式导入Channels类:
import static org.jboss.netty.channel.Channels.*; ... ChannelPipeline pipeline = pipeline(); write(ctx, e.getFuture(), buf); fireChannelDisconnected(ctx);
最后的任务是把这个TimeEncoder插入服务端的ChannelPipeline,这是一个很简单的步骤。
相关推荐
Netty入门教程文档 Netty是Java的网络编程框架,广泛应用于数据采集服务中,本文将对Netty的基本概念和应用进行详细介绍,并将其与ETL技术结合,讲解如何使用Netty进行数据流转和处理。 1. ETL概述 ETL(Extract...
### Netty 入门与实战:仿写微信 IM 即时通讯系统 #### 一、引言 随着移动互联网技术的飞速发展,即时通讯(IM)应用已成为人们日常生活中不可或缺的一部分。微信作为中国最成功的即时通讯软件之一,其背后的架构和...
在本文中,我们将深入探讨Netty框架,并通过实战项目——仿写微信IM即时通讯系统,来深入了解其在高性能网络应用中的应用。Netty是Java领域中一个高效的异步事件驱动的网络应用程序框架,它为快速开发可维护的高性能...
Netty 入门与实战:仿写微信 IM 即时通讯系统,掘金小册子,netty教程。章节齐全无缺失,排版非常不错。 1.仿微信IM系统简介 1 2.Netty是什么? 2 3.服务端启动流程 8 4.客户端启动流程 11 5.实战:客户端与服务端双向...
### Netty入门与实战:仿写微信IM即时通讯系统 #### 一、引言 随着移动互联网技术的飞速发展,即时通讯(IM)系统已成为人们日常生活中不可或缺的一部分。微信作为国内最受欢迎的即时通讯软件之一,其高效稳定的通信...
《Netty 入门与实战:仿写微信 IM 即时通讯系统》是一份专为初学者设计的高质量教程,旨在帮助读者快速掌握Netty框架并应用到实际的即时通讯系统开发中,如仿写微信IM系统。Netty是Java领域内广泛使用的高性能、异步...
根据提供的文件信息“netty入门到精通”,我们可以深入探讨Netty框架的相关知识点,包括其基本概念、核心组件、应用场景以及如何逐步掌握这项技术。 ### Netty框架简介 Netty是一款高性能、异步事件驱动的网络应用...
4. **拆包粘包理论与解决方案** 拆包粘包问题在TCP通信中常见,因为TCP是面向流的协议,不会区分边界。Netty通过LengthFieldBasedFrameDecoder等解码器来解决这个问题,允许开发者根据特定的长度字段来分割消息。 ...
本工程采用maven+netty4.1.0+PrefixedStringDecoder+json技术,包括客户端和服务端。先运行服务端SampleServer,再去等客户端SampleClient。示例中发的是心跳包,其中消息格式定义为msgType + msgNo + content(json...
文件"72-第2章_20-netty入门-jdk-future-480P 清晰-AVC.Cover.jpg"、"73-第2章_21-netty入门-netty-future-480P 清晰-AVC.Cover.jpg"和"74-第2章_22-netty入门-netty-promise-480P 清晰-AVC.Cover.jpg"详细解释了...
这个教程将引导我们入门 Netty 编码,让我们深入理解其核心概念和实际应用。 首先,Netty 的核心是其设计模式,即 Reactor 模式,也称为事件驱动模型。Reactor 模式允许 Netty 高效地处理大量并发连接,通过非阻塞 ...
《Netty+入门与实战:仿写微信+IM+即时通讯系统》是一本专注于使用Netty框架构建即时通讯系统的教程。Netty是一个高性能、异步事件驱动的网络应用框架,适用于开发服务器和客户端的Java应用。它极大地简化了网络编程...
本教程的3-4集是Netty快速入门系列的一部分,旨在帮助初学者快速理解并掌握Netty的基本概念和核心特性。 在"第三课netty客户端"中,我们将学习如何使用Netty构建网络客户端。Netty提供了高度定制化的客户端...
Netty快速入门系列源码, 参考 https://blog.csdn.net/netcobol Netty是一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。 Netty是...
这个“netty入门案例.zip”文件提供了一个简单的 Netty 应用示例,旨在帮助初学者快速理解并掌握 Netty 的基本概念和使用方法。下面将详细介绍这个入门案例中的关键知识点。 首先,Netty 的核心是其 ChannelHandler...
在学习"Netty入门Reactor示例"时,你可以按照以下步骤进行: 1. **创建服务器端:** - 首先,你需要创建一个ServerBootstrap实例,配置BossGroup和WorkerGroup。 - 然后,添加自定义的...