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. 几种常见的app推广形式

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  2. 创建HttpFilter与理解多个Filter代码的执行顺序

    1.自定义的HttpFilter,实现Filter接口 HttpFilter package com.aff.filter; import java.io.IOException; import ja ...

  3. 抽象类(abstract class)与抽象方法

    package cm.aff.abst; /* abstract:抽象的,,可以修饰类,方法 1.修饰类: 抽象类: ①不能被实例化 ②有构造器的 ③凡是类都有构造器 ④抽象方法所修饰的类一定是抽象类 ...

  4. nacos 配置

    具体请访问 https://nacos.io/zh-cn/docs/what-is-nacos.html 网站查看文档,现在开始使用Nacos. 1. 下载Nacos源码 Nacos可以通过 http ...

  5. 16 . PythonWeb框架之Django

    Web框架简介 Web开发是Python语言应用领域的重要部分,也是目前最主要的Web开发语言之一,在其二十多年的历史中出现了数十种Web框架,比如Django.Tornado.Flask.Twist ...

  6. 03 . MysSQL权限和备份

    MySQL权限介绍 mysql中存在4个控制权限的表,分别为 user db tables_priv columns_priv 用户和权限内容放在mysql库中,该库中有一张名为user的表,记录了用 ...

  7. “造轮运动”之 ORM框架系列(一)~谈谈我在实际业务中的增删改查

    想想毕业已经快一年了,也就是大约两年以前,怀着满腔的热血正式跨入程序员的世界,那时候的自己想象着所热爱的技术生涯会是多么的丰富多彩,每天可以与大佬们坐在一起讨论解决各种牛逼的技术问题,喝着咖啡,翘着二 ...

  8. js函数中的this关键字

    关于这个this关键字,也是很多项目中常常被用到的,那么,有人也许会问,干嘛要用this呢,在函数被调用时,直接指明是什么对象在调用不就行了?还整那么个模模糊糊的概念出来干嘛?不过嘛,存在即真理,既然 ...

  9. 【Linux】CentOS7中使用mysql,查询结果显示中文乱码的解决办法

    1.登录mysql mysql -u root -p 2.查看mysql字符集 mysql> show variables like 'chara%'; mysql> show varia ...

  10. Java实现 LeetCode 207 课程表

    207. 课程表 现在你总共有 n 门课需要选,记为 0 到 n-1. 在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1] ...