motan源码分析七:序列化
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); }