Netty 权威指南之java 序列化
本章相关知识点:
相信大多数的程序员接触到的第一种序列化或者编码技术是Java序列化,需要实现序列化的POJO对象只需要实现java.io.serlizable接口,根据实际情况生成序列ID,这个类就能通过java.io.ObjectInput 和java.io.ObjectOutput序列化和反序列化。
不需要考虑跨语言调用,对序列化性能没有苛刻的要求,Java默认写序列化机制是最好的选择,真因为如此,Java序列化虽然存在很多弊端,但是依然得到广泛的运用。
本章学习要点:
1、Netty java 序列化服务端开发
2、Netty Java序列化客户端开发
3、运行结果
第一节:Netty java 序列化服务端开发
服务端开发情景如下:Netty服务端接受到客户端的用户订购请求信息,消息定义如图下表7-1
服务端接受到请求信息,对客户合法性进行校验。如果合法,则构造订购成功的应答消息返回个客户端。订购应答消息如表7-2
Netty 服务端开发步骤:
1、在服务端ChannelPipline中新增解码器io.netty.handler.codec.serialization.ObjectDecoder
2、在服务端ChannelPipline 中新增解码器io.netty.handler.codec.serialization.ObjectEncoder
3、需要进行java 序列化的POJO对象必须实现java.io.serializable接口。
服务端代码
SubRespServer.java
package com.nio.server;
import com.nio.handler.SubRespServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
/**
* Created by vixuan-008 on 2015/6/23.
*/
public class SubRespServer {
public static void main(String[] args)throws Exception{
int port=15444;
new SubRespServer().bind(port);
}
public void bind(int port)throws Exception{
//配置服务端的NIO线程池
EventLoopGroup bossGroup=new NioEventLoopGroup();
EventLoopGroup workGroup=new NioEventLoopGroup();
try{
ServerBootstrap b=new ServerBootstrap();
b.group(bossGroup, workGroup);
b.channel(NioServerSocketChannel.class);
b.option(ChannelOption.SO_BACKLOG, 100);
b.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new ObjectDecoder(1024*1024, ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader())));
socketChannel.pipeline().addLast(new ObjectEncoder());
socketChannel.pipeline().addLast(new SubRespServerHandler());
}
});
//绑定端口,等待同步成功
ChannelFuture f=b.bind(port).sync();
//等待服务端关闭监听端口
f.channel().closeFuture().sync();
}finally {
//释放线程池资源
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
SubRespServerHandler.java
package com.nio.handler;
import com.nio.serlizable.SubscribeReq;
import com.nio.serlizable.SubscribeResp;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
/**
* Created by vixuan-008 on 2015/6/23.
*/
public class SubRespServerHandler extends ChannelHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
SubscribeReq subscribeReq=(SubscribeReq)msg;
if(subscribeReq.getUserName().equalsIgnoreCase("zhouzhigang")){
System.out.println("server rceiver dats is:" + subscribeReq.toString()+"") ;
ctx.writeAndFlush(resp(subscribeReq.getSubReqId()));
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
private SubscribeResp resp(int subReqId){
SubscribeResp resp=new SubscribeResp();
resp.setDesc("Netty Book order success,3 day later ,send to the designated address");
resp.setRespCode("0");
resp.setSubReqId(subReqId);
return resp;
}
}
第二节:Netty Java序列化客户端开发
SubReqClient.java
package com.nio.client;
import com.nio.handler.SubReqServerHandler;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
/**
* Created by vixuan-008 on 2015/6/23.
*/
public class SubReqClient {
public static void main(String[] args)throws Exception{
int port=15444;
new SubReqClient().bind(port, "127.0.0.1");
}
public void bind(int port,String host)throws Exception{
//配置客户端NIO线程池
EventLoopGroup workGroup=new NioEventLoopGroup();
try{
io.netty.bootstrap.Bootstrap b=new io.netty.bootstrap.Bootstrap();
b.group(workGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.TCP_NODELAY,true);
b.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new ObjectDecoder(1024, ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader())));
socketChannel.pipeline().addLast(new ObjectEncoder());
socketChannel.pipeline().addLast(new SubReqServerHandler());
}
});
//发起异步连接操作
ChannelFuture f=b.connect(host,port).sync();
//等待客户端链路关闭
f.channel().closeFuture().sync();
}finally {
//释放NIO 线程组
workGroup.shutdownGracefully();
}
}
}
SubReqServerHandler.java
package com.nio.handler;
import com.nio.serlizable.SubscribeReq;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
/**
* Created by vixuan-008 on 2015/6/23.
*/
public class SubReqServerHandler extends ChannelHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
for(int i=0;i<10;i++){
ctx.write(subReq(i));
}
ctx.flush();
}
public SubscribeReq subReq(int i){
SubscribeReq req=new SubscribeReq();
req.setAddress("湖南长沙雨花区西子一间");
req.setPhoneNumber("1877498****");
req.setUserName("zhouzhigang");
req.setSubReqId(i);
req.setProductName("java 开发指南");
return req;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("Receiver message is:"+msg);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
}
相关实体类POJO补充:
SubscribeReq.java
package com.nio.serlizable;
/**
* Created by vixuan-008 on 2015/6/23.
*/
public class SubscribeReq implements java.io.Serializable {
private static final long serialVersionUID=1L;
private int subReqId;
private String userName;
private String productName;
private String phoneNumber;
private String address;
public int getSubReqId() {
return subReqId;
}
public void setSubReqId(int subReqId) {
this.subReqId = subReqId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "SubscribeReq:{subReqId:"+subReqId+",userName:"+userName+",productName:"+productName+",phoneNumber:"+phoneNumber+",address:"+address+"}";
}
}
SubscribeResp.java
package com.nio.serlizable;
/**
* Created by vixuan-008 on 2015/6/23.
*/
public class SubscribeResp implements java.io.Serializable {
private static final long serialVersionUID=1L;
private int subReqId;
private String respCode;
private String desc;
public int getSubReqId() {
return subReqId;
}
public void setSubReqId(int subReqId) {
this.subReqId = subReqId;
}
public String getRespCode() {
return respCode;
}
public void setRespCode(String respCode) {
this.respCode = respCode;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "SubscribeResp:{subReqId:"+subReqId+",respCode:"+respCode+",desc:"+desc+"}";
}
}
第三节:运行结果
服务端截图:
客户端截图:
总结:本章节重点介绍如何使用Netty 提供的ObjectEncoed编码器和ObjectDecode 解码器实现对普通POJO的序列化。通过订书Demo,我们学习了服务端和客户端的开发,并且模拟TCP的粘包和拆包场景,对运行结果进行了相关分析。
通过使用Netty的Java序列化编解码handler,用户通过短短的几行代码,就能完成POJO的序列化和反序列化。在业务处理handler中,用户只需要将精力聚焦业务逻辑的实现上,不需要关心底层代码的实现,这极大的提高开发效率。
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。