1、编码与解码
    通常我们习惯将编码(Encode)称为序列化(serialization),它将对象序列化为字节数组,用于网络传输、数据持久化或者其它用途。反之,解码(Decode)称为反序列化(deserialization),它把从网络、磁盘等读取的字节数组还原成原始对象(通常是原始对象的拷贝),以方便后续的业务逻辑操作。

2、java序列化
        Java默认提供的序列化机制,需要序列化的Java对象只需要实现java.io.Serializable接口并生成序列化ID,这个类就能够通过java.io.ObjectInput和java.io.ObjectOutput序列化和反序列化。可以直接把Java对象作为可存储的字节数组写入文件,也可以传输到网络上。

2.1 java序列化的缺点      
        无法跨语言。

序列化后码流太大。

序列化性能太低。

3、其他编解码框架
        Java默认的序列化机制效率很低、序列化后的码流也较大,所以涌现出了非常多的优秀的Java序列化框架,例如:Protobuf(google)、Thrift(facebook)、JBoss Marshalling(JBoss)等等。  
    3.1 Protobuf(google)
        Protobuf是google开源的项目,全称Google Protocol Buffers.特点:

1.结构化数据存储格式(xml,json等)

2.高性能编解码技术

3.语言和平台无关,扩展性好

4.支持java,C++,Python三种语言。

3.2 JBoss Marshalling(JBoss)
        JBoss Marshalling是一个java对象的序列化API包,修正了java自带的序列化包的很多问题,但又保持跟java.io.Serializable接口的兼容,

同时又增加了一些可调的参数和附加特性,并且这些参数和特性可通过工厂类的配置。特点:

1.可拔插的类解析器,提供更加便捷的类加载定制策略,通过一个接口即可实现定制。

2.可拔插的对象替换技术,不需要通过继承的方式。

3.可拔插的预定义类缓存表,可以减少序列化的字节数组长度,提升常用类型的对象序列化性能。

4.无须实现java.io.Serializable接口

5.通过缓存技术提升对象的序列化性能。

6.使用非常简单

代码实现

类库:jboss-marshalling-1.3.0.CR9.jar jboss-marshalling-serial-1.3.0.CR9.jar

下载地址:https://www.jboss.org/jbossmarshalling/downloads

我所用的jar 包为 https://pan.baidu.com/s/1tm2EgYtDpTS5dejVnHhvPw 密码:vc8b

1、客户端实体类

package com.xyq.netty.serial;

import java.io.Serializable;

public class Request implements Serializable{

private static final long serialVersionUID = 1L;

private int id;
private String name;
private String requestMessage;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRequestMessage() {
return requestMessage;
}
public void setRequestMessage(String requestMessage) {
this.requestMessage = requestMessage;
}

}

2、服务器端实体类
package com.xyq.netty.serial;

import java.io.Serializable;

public class Response implements Serializable{

private static final long serialVersionUID = 1L;

private int id;
private String name;
private String responseMessage;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getResponseMessage() {
return responseMessage;
}
public void setResponseMessage(String responseMessage) {
this.responseMessage = responseMessage;
}

}

3、JBoss marshalling编解码工具类
package com.xyq.netty.serial;

import io.netty.handler.codec.marshalling.DefaultMarshallerProvider;
import io.netty.handler.codec.marshalling.DefaultUnmarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallingDecoder;
import io.netty.handler.codec.marshalling.MarshallingEncoder;
import io.netty.handler.codec.marshalling.UnmarshallerProvider;

import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration;

public class MarshallingCodeCFactory {

public static MarshallingDecoder buliteMarshallingDecoder(){

//1、首先通过编组工具类的精通方法获取编组实例对象参数序列标识创建的是java序列化工厂对象。
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
//2、创建了MarshallingConfiguration对象,配置了版本号为5
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
//3、根据marshallerFactory和配置创建提供商
UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);
//4、构建Netty的MarshallingDecoder对象,两个参数分别为提供商和单个消息序列化后的最大长度
MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024*1024*1);
return decoder;
}

public static MarshallingEncoder buliteMarshallingEncoder(){
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);
//5、构建Netty的MarshallingEncoder对象,MarshallingEncoder用于实现序列化接口的POJO对象序列化为二进制数组
MarshallingEncoder encoder = new MarshallingEncoder(provider);
return encoder;
}

}

4、服务器端

package com.xyq.netty.serial;

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;

public class Server {

public static void main(String[] args) throws Exception{
//1、定义两个线程组
EventLoopGroup pGroup = new NioEventLoopGroup();//一个是用于处理服务器端接收客户端连接的
EventLoopGroup cGroup = new NioEventLoopGroup();//一个是进行网络通信的(网络读写的)
try {
//2、创建辅助工具类,用于服务器通道的一系列配置
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(pGroup, cGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
.option(ChannelOption.SO_SNDBUF, 32*1024)
.option(ChannelOption.SO_RCVBUF, 32*1024)
.childHandler(new ChannelInitializer<SocketChannel>() {

@Override
protected void initChannel(SocketChannel ch) throws Exception {

//设置marshalling编码
ch.pipeline().addLast(MarshallingCodeCFactory.buliteMarshallingDecoder());
//设置marshalling解码
ch.pipeline().addLast(MarshallingCodeCFactory.buliteMarshallingEncoder());
//处理业务
ch.pipeline().addLast(new ServerHandler());
}
});

//4、进行绑定
ChannelFuture cf = bootstrap.bind(8765).sync();
System.out.println("server start ...");

//5、等待关闭
cf.channel().closeFuture().sync();
} finally{
pGroup.shutdownGracefully();
cGroup.shutdownGracefully();
}

}

}

5、服务器处理类

package com.xyq.netty.serial;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

public class ServerHandler extends ChannelHandlerAdapter{

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception {

//读取客户端发过来的信息
Request request = (Request) msg;
System.out.println("服务器接收到客户端的信息为 " + request.getId() + " " + request.getName());

//给客户端回应信息
Response response = new Response();
response.setId(request.getId());
response.setName(request.getName()+"res");
ctx.writeAndFlush(response);
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {
ctx.close();
}

}

6、客户端

package com.xyq.netty.serial;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class Client {

public static void main(String[] args) throws Exception{
//创建线程组
EventLoopGroup group = new NioEventLoopGroup();
try {
//创建工具类
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {

@Override
protected void initChannel(SocketChannel ch) throws Exception {

//设置marshalling解码
ch.pipeline().addLast(MarshallingCodeCFactory.buliteMarshallingDecoder());
//设置marshalling编码
ch.pipeline().addLast(MarshallingCodeCFactory.buliteMarshallingEncoder());

ch.pipeline().addLast(new ClientHandler());
}
});

//4、建立连接
ChannelFuture cf = bootstrap.connect("127.0.0.1", 8765).sync();
System.out.println("Client connet ....");

//5、发送信息
for(int i=0; i<5; i++){
Request request = new Request();
request.setId(i);
request.setName("request" + i);
cf.channel().writeAndFlush(request);
}

//6、等待关闭
cf.channel().closeFuture().sync();
} finally{
group.shutdownGracefully();
}
}

}

7、客户端处理类

package com.xyq.netty.serial;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;

public class ClientHandler extends ChannelHandlerAdapter {

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception {

try {
//接收服务端的响应信息
Response response = (Response) msg;
System.out.println("客户端接收到服务端的响应消息为 " + response.getId() +" " + response.getName());
} finally{
ReferenceCountUtil.release(msg);
}
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {
ctx.close();
}
}

Netty的Marshalling编解码器的更多相关文章

  1. Netty 框架学习 —— 编解码器框架

    编解码器 每个网络应用程序都必须定义如何解析在两个节点之间来回传输的原始字节,以及如何将其和目标应用程序的数据格式做相互转换.这种转换逻辑由编解码器处理,编解码器由编码器和解码器组成,它们每种都可以将 ...

  2. netty系列之:netty对marshalling的支持

    目录 简介 netty中的marshalling provider Marshalling编码器 Marshalling编码的另外一种实现 总结 简介 在之前的文章中我们讲过了,jboss marsh ...

  3. 编解码-marshalling

    JBoss的Marshalling序列化框架,它是JBoss内部使用的序列化框架,Netty提供了Marshalling编码和解码器,方便用户在Netty中使用Marshalling. JBoss M ...

  4. netty的编解码器理解(转)

    一.简介 在网络应用中需要实现某种编解码器,将原始字节数据与自定义的消息对象进行互相转换.网络中都是以字节码的数据形式来传输数据的,服务器编码数据后发送到客户端,客户端需要对数据进行解码. 编解码器由 ...

  5. 【Netty】(9)---Netty编解码器

    Netty编解码器 在了解Netty编解码之前,先了解Java的编解码: 编码(Encode)称为序列化, 它将对象序列化为字节数组,用于网络传输.数据持久化或者其它用途. 解码(Decode)称为反 ...

  6. Netty实战十之编解码器框架

    编码和解码,或者数据从一种特定协议的格式到另一种格式的转换.这些任务将由通常称为编解码器的组件来处理.Netty提供了多种组件,简化了为了支持广泛的协议而创建自定义的编解码器的过程.例如,如果你正在构 ...

  7. Netty 系列六(编解码器).

    一.概念 网络传输的单位是字节,如何将应用程序的数据转换为字节,以及将字节转换为应用程序的数据,就要说到到我们该篇介绍的编码器和解码器. 将应用程序的数据转换为网络格式,以及将网络格式转换为应用程序的 ...

  8. Netty In Action中文版 - 第七章:编解码器Codec

    http://blog.csdn.net/abc_key/article/details/38041143 本章介绍 Codec,编解码器 Decoder,解码器 Encoder,编码器 Netty提 ...

  9. Netty 中的消息解析和编解码器

    本篇内容主要梳理一下 Netty 中编解码器的逻辑和编解码器在 Netty 整个链路中的位置. 前面我们在分析 ChannelPipeline 的时候说到入站和出站事件的处理都在 pipeline 中 ...

随机推荐

  1. MVC案例之新增与修改Customer

    新增Customer 添加的流程Add New Customer 超链接连接到 newcustomer.jsp新建 newcustomer.jsp: 在 CustomerServlet 的 addCu ...

  2. equals()方法练习

    1: package com.aff.equals; public class TestOrder { public static void main(String[] args) { Order o ...

  3. Rocket - tilelink - Bits vs. UInt

    https://mp.weixin.qq.com/s/lzDmIHkUph3b1Fxgx66ySg   分析移位/取反操作在Intellij中提示错误的问题.   1. 问题   用到移位/取反的地方 ...

  4. Rocket - spec - RISC-V规范整理

    https://mp.weixin.qq.com/s/xP8JRhkmgUQf0QRm3S2mjA   根据RISC-V规范整理的几个文档.   ​​     1. 原文链接 https://risc ...

  5. Java实现 LeetCode 816 模糊坐标(暴力)

    816. 模糊坐标 我们有一些二维坐标,如 "(1, 3)" 或 "(2, 0.5)",然后我们移除所有逗号,小数点和空格,得到一个字符串S.返回所有可能的原始 ...

  6. (Java实现) 洛谷 P1691 有重复元素的排列问题

    题目描述 设R={r1,r2,--,rn}是要进行排列的n个元素.其中元素r1,r2,--,rn可能相同.使设计一个算法,列出R的所有不同排列. 给定n以及待排列的n个元素.计算出这n个元素的所有不同 ...

  7. Java实现派(Pie, NWERC 2006, LA 3635)

    题目 有F+1个人来分N个圆形派,每个人得到的必须是一整块派,而不是几块拼在一起,且面积要相同.求每个人最多能得到多大面积的派(不必是圆形). 输入的第一行为数据组数T.每组数据的第一行为两个整数N和 ...

  8. Java实现 蓝桥杯VIP 算法训练 和为T

    问题描述 从一个大小为n的整数集中选取一些元素,使得它们的和等于给定的值T.每个元素限选一次,不能一个都不选. 输入格式 第一行一个正整数n,表示整数集内元素的个数. 第二行n个整数,用空格隔开. 第 ...

  9. Java实现蓝桥杯模拟空地长草

    问题描述 小明有一块空地,他将这块空地划分为 n 行 m 列的小块,每行和每列的长度都为 1. 小明选了其中的一些小块空地,种上了草,其他小块仍然保持是空地. 这些草长得很快,每个月,草都会向外长出一 ...

  10. Java实现Fibonacci取余

    Description Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1. 当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少. Input 多 ...