JAVA序列化 结合 Netty

来源:互联网 发布:怎样才能加入淘宝商城 编辑:程序博客网 时间:2024/05/20 00:38

序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。

序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例


序列化的作用

  • 把对象的字节序列永久地保存到硬盘上(通常存放在一个文件中);
  • 在网络上传送对象的字节序列。
    当你想把的内存中的对象保存到一个文件中或者数据库中时候;
    当你想用套接字在网络上传送对象的时候;
    当你想通过RMI传输对象的时候;

Serializable接口

public class Message implements Serializable{    private static final long serialVersionUID = 1L;    private long   id;          //id    private long   receiveId;   //接受者    private long   sendId;      //发送者    private String content;     //内容    private int    type;        //类型    private int    state;       //状态    private Date   createTime;  //创建时间    /**     * @return the id     */    public long getId() {        return id;    }    /**     * @param id the id to set     */    public void setId(long id) {        this.id = id;    }    /**     * @return the receive     */    public long getReceiveId() {        return receiveId;    }    /**     * @param receive the receive to set     */    public void setReceiveId(long receiveId) {        this.receiveId = receiveId;    }    /**     * @return the send     */    public long getSendId() {        return sendId;    }    /**     * @param send the send to set     */    public void setSendId(long sendId) {        this.sendId = sendId;    }    /**     * @return the content     */    public String getContent() {        return content;    }    /**     * @param content the content to set     */    public void setContent(String content) {        this.content = content;    }    /**     * @return the type     */    public int getType() {        return type;    }    /**     * @param type the type to set     */    public void setType(int type) {        this.type = type;    }    /**     * @return the state     */    public int getState() {        return state;    }    /**     * @param state the state to set     */    public void setState(int state) {        this.state = state;    }    /**     * @return the createTime     */    public Date getCreateTime() {        return createTime;    }    /**     * @param createTime the createTime to set     */    public void setCreateTime(Date createTime) {        this.createTime = createTime;    }    public String toString() {        return "message [id=" + id + ", receiveId=" + receiveId + ", sendId=" + sendId + ", content="+ content                 + ", type=" + type + ", state=" + state + ", createTime=" + createTime + "]";    }}

Protobuf

简述

Protocol Buffers (ProtocolBuffer/ protobuf )是Google公司开发的一种数据描述语言,类似于XML能够将结构化数据序列化,可用于数据存储、通信协议等方面。现阶段支持C++、JAVA、Python等三种编程语言。

  • 结构化数据存储方式(XML、 JSON)
  • 高效的编解码性能
  • 语言无关、平台无关、扩展性好
  • 官方支持JAVA、C++、Python三种语言

使用过程:

完整示例 : http://download.csdn.net/detail/hq0556/9826665
1. 选择版本下载protobuf : https://github.com/google/protobuf/releases;
2. 项目加入protobuf-java.jar包;
3. 编写xxx.proto;
4. cmd进入protoc.exe文件夹下:protoc.exe –java_out=./ xxx.proto
这里写图片描述

示例

<dependency>    <groupId>com.google.protobuf</groupId>    <artifactId>protobuf-java</artifactId>    <version>2.5.0</version></dependency>

编写message.proto,与上例Message类对应

package com.heqing.netty.bean.protobuf;option java_package = "com.heqing.netty.bean.protobuf"; option java_outer_classname = "ProtobufProto"; message testBuf  {   required int64 id = 1;   required int64 receiveId = 2;   required int64 sendId = 3;  required string content= 4;  required int32 type = 5;  required int32 state = 6;  required int64 createTime = 7;}
public class TestMessage {    private static byte[] encode(ProtobufProto.testBuf msg) {        return msg.toByteArray();    }    private static ProtobufProto.testBuf decode(byte[] body) throws InvalidProtocolBufferException {        return ProtobufProto.testBuf.parseFrom(body);    }    private static ProtobufProto.testBuf createMessage() {        ProtobufProto.testBuf.Builder builder = ProtobufProto.testBuf.newBuilder();        builder.setId(1l);        builder.setReceive(10001l);        builder.setSend(10002l);        builder.setContent("this is test");        builder.setType(0);        builder.setState(0);        builder.setCreateTime(System.currentTimeMillis());        return builder.build();    }    public static void main(String[] args) {        try {            ProtobufProto.testBuf msg1 = createMessage();            System.out.println("11--->"+msg1.toString());            ProtobufProto.testBuf msg2 = decode(encode(msg1));            System.out.println("22--->"+msg1.toString());            System.out.println("33--->"+msg1.equals(msg2));        } catch(Exception e) {            e.printStackTrace();        }    }}

结合Netty示例

public class ProtobufServer {    public void bind(int port) throws Exception {          //EventLoopGroup是用来处理IO操作的多线程事件循环器          //bossGroup 用来接收进来的连接          EventLoopGroup bossGroup = new NioEventLoopGroup();           //workerGroup 用来处理已经被接收的连接          EventLoopGroup workerGroup = new NioEventLoopGroup();          try {              //启动 NIO 服务的辅助启动类              ServerBootstrap b = new ServerBootstrap();               b.group(bossGroup, workerGroup)                  //配置 Channel                  .channel(NioServerSocketChannel.class)                  .option(ChannelOption.SO_BACKLOG, 128)                .handler(new LoggingHandler(LogLevel.INFO))                .childHandler(new ChannelInitializer<SocketChannel>() {                           @Override                          public void initChannel(SocketChannel ch) throws Exception {                              ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());  //处理半包                            ch.pipeline().addLast(new ProtobufDecoder(ProtobufProto.testBuf.getDefaultInstance()));                            ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());                            ch.pipeline().addLast(new ProtobufEncoder());                            // 注册handler                                ch.pipeline().addLast(new ProtobufServerHandler());                          }                      })                  .childOption(ChannelOption.SO_KEEPALIVE, true);               // 绑定端口,开始接收进来的连接              ChannelFuture f = b.bind(port).sync();              // 等待服务器 socket 关闭 。              f.channel().closeFuture().sync();          } finally {              bossGroup.shutdownGracefully();              workerGroup.shutdownGracefully();          }      }      public static void main(String[] args) throws Exception {          int port = 8080;        new ProtobufServer().bind(port);     }  }
public class ProtobufServerHandler extends ChannelHandlerAdapter {    @Override      public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {         ProtobufProto.testBuf message = (ProtobufProto.testBuf)msg;        System.out.println("send---->"+message.toString());        ProtobufProto.testBuf.Builder builder = ProtobufProto.testBuf.newBuilder();        builder.setId(2l);        builder.setReceive(10002l);        builder.setSend(10001l);        builder.setContent("this is server");        builder.setType(0);        builder.setState(0);        builder.setCreateTime(System.currentTimeMillis());        ctx.writeAndFlush(builder.build());          }    @Override      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {          // 当出现异常就关闭连接          cause.printStackTrace();          ctx.close();      }      @Override      public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {          ctx.flush();      }  }
public class ProtobufClient {    public void connect(String host, int port) throws Exception {          EventLoopGroup workerGroup = new NioEventLoopGroup();          try {              Bootstrap b = new Bootstrap();              b.group(workerGroup)             .channel(NioSocketChannel.class)               .option(ChannelOption.TCP_NODELAY, true)              .handler(new ChannelInitializer<SocketChannel>() {                  @Override                  public void initChannel(SocketChannel ch) throws Exception {                      ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());  //处理半包                    ch.pipeline().addLast(new ProtobufDecoder(ProtobufProto.testBuf.getDefaultInstance()));                    ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());                    ch.pipeline().addLast(new ProtobufEncoder());                    // 注册handler                    ch.pipeline().addLast(new ProtobufClientHandler());                  }              });              // Start the client.              ChannelFuture f = b.connect(host, port).sync();              // Wait until the connection is closed.              f.channel().closeFuture().sync();          } finally {              workerGroup.shutdownGracefully();          }      }      public static void main(String[] args) throws Exception {          ProtobufClient client = new ProtobufClient();          client.connect("127.0.0.1", 8080);      }  }
public class ProtobufClientHandler extends ChannelHandlerAdapter{    // 连接成功后,向server发送消息        @Override        public void channelActive(ChannelHandlerContext ctx) throws Exception {            ProtobufProto.testBuf.Builder builder = ProtobufProto.testBuf.newBuilder();        builder.setId(1l);        builder.setReceive(10001l);        builder.setSend(10002l);        builder.setContent("this is send");        builder.setType(0);        builder.setState(0);        builder.setCreateTime(System.currentTimeMillis());        ctx.writeAndFlush(builder.build());          }        @Override      public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {         ProtobufProto.testBuf message = (ProtobufProto.testBuf)msg;        System.out.println("receive---->"+message.toString());    }    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {        ctx.flush();    }    @Override      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {          // 当出现异常就关闭连接          cause.printStackTrace();          ctx.close();      }}

JBoss Marshalling

JBoss Marshalling 是一个Java 对象序列化包,对 JDK 默认的序列化框架进行了优化,但又保持跟 Java.io.Serializable 接口的兼容,同时增加了一些可调的参数和附件的特性, 这些参数和附加的特性, 这些参数和特性可通过工厂类进行配置.

<dependency>    <groupId>org.jboss.marshalling</groupId>    <artifactId>jboss-marshalling</artifactId>    <version>1.4.11.Final</version></dependency><dependency>    <groupId>org.jboss.marshalling</groupId>    <artifactId>jboss-marshalling-serial</artifactId>    <version>1.4.11.Final</version></dependency>
public class MarshallingServer {    public void bind(int port) throws Exception {        // 配置服务端的NIO线程组        EventLoopGroup bossGroup = new NioEventLoopGroup();        EventLoopGroup workerGroup = new NioEventLoopGroup();        try {            ServerBootstrap b = new ServerBootstrap();            b.group(bossGroup, workerGroup)                    .channel(NioServerSocketChannel.class)                    .option(ChannelOption.SO_BACKLOG, 128)                    .handler(new LoggingHandler(LogLevel.INFO))                    .childHandler(new ChannelInitializer<SocketChannel>() {                        @Override                        public void initChannel(SocketChannel ch) {                            ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());                            ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());                            ch.pipeline().addLast(new MarshallingServerHandler());                        }                    });            // 绑定端口,同步等待成功            ChannelFuture f = b.bind(port).sync();            // 等待服务端监听端口关闭            f.channel().closeFuture().sync();        } finally {            // 优雅退出,释放线程池资源            bossGroup.shutdownGracefully();            workerGroup.shutdownGracefully();        }    }    public static void main(String[] args) throws Exception {        int port = 8080;        new MarshallingServer().bind(port);    }}
@Sharablepublic class MarshallingServerHandler extends ChannelHandlerAdapter {    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {        Message req = (Message) msg;        System.out.println("this send msg --> ["+ req.toString() + "]");        if (2 == req.getId()) {            ctx.writeAndFlush(resp(req.getId()));        }    }    private Message resp(long subReqID) {        Message resp = new Message();        resp.setId(subReqID);        resp.setContent("客户端,我收到你的消息了!");        return resp;    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {        cause.printStackTrace();        ctx.close();// 发生异常,关闭链路    }}
public final class MarshallingCodeCFactory {    /**     * 创建Jboss Marshalling解码器MarshallingDecoder     *      * @return     */    public static MarshallingDecoder buildMarshallingDecoder() {        final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");        final MarshallingConfiguration configuration = new MarshallingConfiguration();        configuration.setVersion(5);        UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);        MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024);        return decoder;    }    /**     * 创建Jboss Marshalling编码器MarshallingEncoder     *      * @return     */    public static MarshallingEncoder buildMarshallingEncoder() {        final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");        final MarshallingConfiguration configuration = new MarshallingConfiguration();        configuration.setVersion(5);        MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);        MarshallingEncoder encoder = new MarshallingEncoder(provider);        return encoder;    }}
public class MarshallingClient {    public void connect(int port, String host) throws Exception {        // 配置客户端NIO线程组        EventLoopGroup group = new NioEventLoopGroup();        try {            Bootstrap b = new Bootstrap();            b.group(group).channel(NioSocketChannel.class)                    .option(ChannelOption.TCP_NODELAY, true)                    .handler(new ChannelInitializer<SocketChannel>() {                        @Override                        public void initChannel(SocketChannel ch) throws Exception {                          ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());                            ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());                            ch.pipeline().addLast(new MarshallingClientHandler());                        }                    });            // 发起异步连接操作            ChannelFuture f = b.connect(host, port).sync();            // 当代客户端链路关闭            f.channel().closeFuture().sync();        } finally {            // 优雅退出,释放NIO线程组            group.shutdownGracefully();        }    }    /**     * @param args     * @throws Exception     */    public static void main(String[] args) throws Exception {        int port = 8080;        new MarshallingClient().connect(port, "127.0.0.1");    }}
public class MarshallingClientHandler extends ChannelHandlerAdapter {    @Override    public void channelActive(ChannelHandlerContext ctx) {        for (int i = 0; i < 10; i++) {            ctx.write(subReq(i));        }        ctx.flush();    }    private Message subReq(int i) {        Message req = new Message();        req.setId(i);        req.setContent("服务端,你收到我的消息了吗?");        return req;    }    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {        System.out.println("this server msg --> [" + msg + "]");    }    @Override    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {        ctx.flush();    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {        cause.printStackTrace();        ctx.close();    }}
0 0
原创粉丝点击