motan的序列化支持两种协议,一种是json,另一种是hessian2。主要涉及到的类和接口是是:FastJsonSerialization、Hessian2Serialization、Serialization、Codec、AbstractCodec、NettyDecoder、NettyEncoder、DefaultRpcCodec和CompressRpcCodec等。

1.FastJsonSerialization使用json作为数据交换协议,Hessian2Serialization使用hessian2作为数据交换协议

@SpiMeta(name = "hessian2")
public class Hessian2Serialization implements Serialization { @Override
public byte[] serialize(Object data) throws IOException {//使用hessan2进行序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Hessian2Output out = new Hessian2Output(bos);
out.writeObject(data);
out.flush();
return bos.toByteArray();
} @SuppressWarnings("unchecked")
@Override
public <T> T deserialize(byte[] data, Class<T> clz) throws IOException {//使用hessan2进行反序列化
Hessian2Input input = new Hessian2Input(new ByteArrayInputStream(data));
return (T) input.readObject(clz);
}
}

2.motan支持压缩和非压缩两种方式

    public byte[] encode(Channel channel, Object message) throws IOException {
if (needEncodeV1(message)) {//判断使用哪个版本的encode,decode同样
return v1Codec.encode(channel, message);
} else {
// 使用v2压缩版本
return encodeV2(channel, message);//使用压缩版本的encode
} } public byte[] encodeV2(Channel channel, Object message) throws IOException {
try {
if (message instanceof Request) {
return encodeRequest(channel, (Request) message);//序列化并压缩request对象 } else if (message instanceof Response) {
return encodeResponse(channel, (Response) message);//序列化并压缩response对象 }
} catch (Exception e) {
if (ExceptionUtil.isMotanException(e)) {
throw (RuntimeException) e;
} else {
throw new MotanFrameworkException("encode error: isResponse=" + (message instanceof Response), e,
MotanErrorMsgConstant.FRAMEWORK_ENCODE_ERROR);
}
} throw new MotanFrameworkException("encode error: message type not support, " + message.getClass(),
MotanErrorMsgConstant.FRAMEWORK_ENCODE_ERROR);
} private byte[] encodeRequest(Channel channel, Request request) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput output = createOutput(outputStream);
addMethodInfo(output, request); //拿到hessian2或fasjson处理对象
Serialization serialization =
ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(
channel.getUrl().getParameter(URLParamType.serialize.getName(), URLParamType.serialize.getValue())); if (request.getArguments() != null && request.getArguments().length > 0) {
for (Object obj : request.getArguments()) {
serialize(output, obj, serialization);//序列化
}
} if (request.getAttachments() == null || request.getAttachments().isEmpty()) {
// empty attachments
output.writeShort(0);
} else {
// 需要copy一份attachment进行签名替换,这样在失败重试时原始的request信息不会变更
Map<String, String> attachments = copyMap(request.getAttachments());
replaceAttachmentParamsBySign(channel, attachments); addAttachment(output, attachments);
} output.flush();
byte[] body = outputStream.toByteArray(); byte flag = MotanConstants.FLAG_REQUEST; output.close();
Boolean usegz = channel.getUrl().getBooleanParameter(URLParamType.usegz.getName(), URLParamType.usegz.getBooleanValue());
int minGzSize = channel.getUrl().getIntParameter(URLParamType.mingzSize.getName(), URLParamType.mingzSize.getIntValue());
return encode(compress(body, usegz, minGzSize), flag, request.getRequestId());//压缩处理
}

3.通过NettyDecoder和NettyEncoder与netty框架进行结合

	protected Object encode(ChannelHandlerContext ctx, Channel nettyChannel, Object message) throws Exception {

		long requestId = getRequestId(message);//获取requestId
byte[] data = null; if (message instanceof Response) {
try {
data = codec.encode(client, message);
} catch (Exception e) {
LoggerUtil.error("NettyEncoder encode error, identity=" + client.getUrl().getIdentity(), e);
Response response = buildExceptionResponse(requestId, e);
data = codec.encode(client, response);
}
} else {
data = codec.encode(client, message);//调用DefaultRpcCodec或压缩的codec来编码
} byte[] transportHeader = new byte[MotanConstants.NETTY_HEADER];
ByteUtil.short2bytes(MotanConstants.NETTY_MAGIC_TYPE, transportHeader, 0);
transportHeader[3] = getType(message);
ByteUtil.long2bytes(getRequestId(message), transportHeader, 4);
ByteUtil.int2bytes(data.length, transportHeader, 12); return ChannelBuffers.wrappedBuffer(transportHeader, data);
}

  

motan源码分析七:序列化的更多相关文章

  1. motan源码分析六:客户端与服务器的通信层分析

    本章将分析motan的序列化和底层通信相关部分的代码. 1.在上一章中,有一个getrefers的操作,来获取所有服务器的引用,每个服务器的引用都是由DefaultRpcReferer来创建的 pub ...

  2. ABP源码分析七:Setting 以及 Mail

    本文主要说明Setting的实现以及Mail这个功能模块如何使用Setting. 首先区分一下ABP中的Setting和Configuration. Setting一般用于需要通过外部配置文件(或数据 ...

  3. vuex 源码分析(七) module和namespaced 详解

    当项目非常大时,如果所有的状态都集中放到一个对象中,store 对象就有可能变得相当臃肿. 为了解决这个问题,Vuex允许我们将 store 分割成模块(module).每个模块拥有自己的 state ...

  4. Vue.js 源码分析(七) 基础篇 侦听器 watch属性详解

    先来看看官网的介绍: 官网介绍的很好理解了,也就是监听一个数据的变化,当该数据变化时执行我们的watch方法,watch选项是一个对象,键为需要观察的数据名,值为一个表达式(函数),还可以是一个对象, ...

  5. motan源码分析八:涉及到底层的客户端调用

    之前我们分析了客户端调用服务端的源码,但是没有涉及到通讯层和序列化层,本文将之前讲过的内容做一次串联. 1.上层通过动态代理调用refer的call,每个refer又对应一个nettyclient,下 ...

  6. motan源码分析十一:部分特性

    本章将描述motan部分的特性并对源码进行分析. 1.requestid的维护,使用了当前时间左移20位,再和一个自增变量组合 public class RequestIdGenerator { ); ...

  7. motan源码分析十:流量切换

    motan提供了流量切换的功能,可以实现把一个group的流量切换到另一个group(一个或多个服务都可以).大家可以使用tomcat部署motan的管理工具,并设置几个组,例如可以参考demo代码: ...

  8. motan源码分析五:cluster相关

    上一章我们分析了客户端调用服务端相关的源码,但是到了cluster里面的部分我们就没有分析了,本章将深入分析cluster和它的相关支持类. 1.clustersupport的创建过程,上一章的Ref ...

  9. motan源码分析二:使用spi机制进行类加载

    在motan的源码中使用了很多的spi机制进行对象的创建,下面我们来具体分析一下它的实现方法. 1.在实际的jar包的\META-INF\services目录中引入相关的文件,例如下图中,我解压了co ...

随机推荐

  1. JQuery__Tab实践

    刚开始学做网站的时候,是从DIV+CSS开始的,那时候不明白“幻灯片”“二级导航”等,更不明白“动态网站”.后来,需要用到幻灯片banner的时候,老师没有仔细讲解JS,就说:从网站找来,会用就好!于 ...

  2. jquery对同级的td做radio限制

    <html> <head> <title></title> <script src="http://libs.baidu.com/jqu ...

  3. 访问的是A网址,但是跳转B网址的内容,地址栏还是A网址

    最近家里宽带续费,是用小区小广告的宽带,打开http://download.csdn.net/ 或其他一些设计下载.购物商城或威客网址进不去 提示 经过网上大量搜索和请教,都说是以下几点引起的 1.网 ...

  4. eclipse中启动tomcat

    0.以下即使部署好,点小猫启动tomcat,有一个问题,修改jsp文件,本地tomcat中的此jsp并没有修改,如果右键项目启动,则会修改,不知道为什么 1. 首先发布项目,项目右键,run serv ...

  5. Swift - 26 - 函数的基础写法

    //: Playground - noun: a place where people can play import UIKit // 无参无返回 // -> Void可以省略不写, 或者写成 ...

  6. [转]Delphi : keydown与keypress的区别,组合键

    Shift 是一个集合变量. type TShiftState = set of (ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDoubl ...

  7. 初涉JavaScript模式 (10) : 函数 【进阶用法】

    写在前面 不知不觉写到第10篇了.这篇写起来很忐忑,终于和高级搭上边了(呵呵),这篇我们 主要 说一下 JS 方法的部分高级用法(我知道的),笔者水平有限,难免有错.废话不多少,进入正文. 初始化 我 ...

  8. 正则如何匹配div下的所有<li>标签?

    <?php header('Content-Type:text/html;charset=utf-8'); $str = '<div class="c1s"> & ...

  9. IOS制作一个漂亮的登录界面

    上图是Facebook的登录界面,看起来很漂亮,eamil框和passwod框合在一起,那么这种效果是怎么做出来的呢?我们都知道输入框用layer属性是可以做成圆角的形式,那么怎么样才能够仅仅只让上边 ...

  10. how to count uv area

    先放着,空了再整理.... fn getModeUvVolumetric mode chang= ----得到UV使用率( --global facesNumSum = meshop.getnumfa ...