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. 读Pyqt4教程,带你入门Pyqt4 _010

    在PyQt4教程的这部分中,我们讨论拖放操作. 拖放(Drag-and-drop)指的是图形用户界面(Graphical user interface)中,在一个虚拟的对象上按着鼠标键将之拖曳到另一个 ...

  2. python基本操作-文件、目录及路径

    目录 1 前言 2 文件夹操作 2.1 查询操作 2.2 创建操作 2.3 删除操作 2.4 修改操作 3 文件操作 3.1 查询操作 3.2 创建操作 3.3 修改操作 3.4 删除 4 路径操作 ...

  3. 使用PRTG和panabit结合定位网络阻塞的来源

    一.背景   在网络管理工作中,有时会出现网络阻塞,需要定位阻塞来源以采取措施解决问题.二.以一个网络阻塞案例说明定位方法   案例:某企业日常使用多条网络线路,某一段时间发现某条线路传输速率下降,对 ...

  4. Chisel3 - Wire & Reg

    https://mp.weixin.qq.com/s/Y26N5P4XOr5e3uyi5XQY-w   不同于Verilog,Chisel中Wire和Reg并不是数据类型,而是数据容器,作为数据的一个 ...

  5. 使用ADMT和PES实现window AD账户跨域迁移-介绍篇

    使用 ADMT 和 pwdmig 实现 window AD 账户跨域迁移系列: 介绍篇 ADMT 安装 PES 的安装 ADMT:迁移组 ADMT:迁移用户 ADMT:计算机迁移 ADMT:报告生成 ...

  6. 快速搭建基于Spring Boot + Spring Security 环境

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.Spring Security 权限管理框架介绍 简介: Spring Security 提供了基于 ...

  7. Java 第十一届 蓝桥杯 省模拟赛 70044与113148的最大公约数

    问题描述 70044与113148的最大公约数是多少? 答案提交 这是一道结果填空的题,你只需要算出结果后提交即可.本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分. pac ...

  8. Java实现 蓝桥杯VIP 算法提高 打水问题

    算法提高 打水问题 时间限制:1.0s 内存限制:512.0MB 问题描述 N个人要打水,有M个水龙头,第i个人打水所需时间为Ti,请安排一个合理的方案使得所有人的等待时间之和尽量小. 输入格式 第一 ...

  9. Java实现填符号凑算式

    匪警请拨110,即使手机欠费也可拨通! 为了保障社会秩序,保护人民群众生命财产安全,警察叔叔需要与罪犯斗智斗勇,因而需要经常性地进行体力训练和智力训练! 某批警察叔叔正在进行智力训练: 1 2 3 4 ...

  10. JS变量小总

    变量分类:1.栈内存(stack)和堆内存(heap)2.基本类型和引用类型 #栈内存(stack) 一般为静态分配内存,其分配的内存系统自动释放. #堆内存(heap) 一般为动态分配内存,其分配的 ...