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中,用户只需要将精力聚焦业务逻辑的实现上,不需要关心底层代码的实现,这极大的提高开发效率。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值