ProtobufSerializer.java 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package com.sdyc.ndmp.protobuf.serializer;
  2. import com.google.protobuf.GeneratedMessage;
  3. import io.netty.buffer.ByteBuf;
  4. import io.netty.buffer.Unpooled;
  5. import java.lang.reflect.InvocationTargetException;
  6. import java.lang.reflect.Method;
  7. import java.nio.charset.Charset;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10. /**
  11. * <pre>
  12. *
  13. * Created by IntelliJ IDEA.
  14. * User: zhenqin
  15. * Date: 14-7-28
  16. * Time: 下午3:36
  17. * To change this template use File | Settings | File Templates.
  18. *
  19. * </pre>
  20. *
  21. * @author zhenqin
  22. */
  23. public class ProtobufSerializer implements Serializer<GeneratedMessage> {
  24. private static final long serialVersionUID = 1L;
  25. /**
  26. * 字符编码
  27. */
  28. protected String charset = "UTF-8";
  29. /**
  30. * 内部缓存
  31. */
  32. protected final static Map<Class<?>, Method>
  33. CLASS_METHOD_MAP = new HashMap<Class<?>, Method>(3);
  34. public ProtobufSerializer() {
  35. }
  36. public ProtobufSerializer(String charset) {
  37. this.charset = charset;
  38. }
  39. @Override
  40. public byte[] serialize(GeneratedMessage o) {
  41. if (o == null) {
  42. return null;
  43. }
  44. byte[] bytes = o.toByteArray();
  45. String clazz = o.getClass().getName();
  46. byte[] bytes1 = clazz.getBytes(Charset.forName(charset));
  47. ByteBuf channelBuffer = Unpooled.buffer(4 + bytes.length + bytes1.length);
  48. channelBuffer.writeInt(bytes1.length);
  49. channelBuffer.writeBytes(bytes1);
  50. channelBuffer.writeBytes(bytes);
  51. return channelBuffer.array();
  52. }
  53. @Override
  54. public GeneratedMessage deserialize(byte[] bytes) {
  55. if (bytes == null || bytes.length == 0) {
  56. return null;
  57. }
  58. ByteBuf channelBuffer = Unpooled.wrappedBuffer(bytes);
  59. channelBuffer.resetReaderIndex();
  60. int classNameLength = channelBuffer.readInt();
  61. ByteBuf classBuf = channelBuffer.readBytes(classNameLength);
  62. String clazzName = classBuf.toString(Charset.forName(charset));
  63. ByteBuf objectBuf = channelBuffer.readBytes(channelBuffer.readableBytes());
  64. // 检查一下Netty Protobuf解码器是怎么写的
  65. try {
  66. return reflact(clazzName, objectBuf.array());
  67. } catch (ClassNotFoundException e) {
  68. throw new IllegalStateException("class: " + clazzName + " not found!", e);
  69. } catch (NoSuchMethodException e) {
  70. throw new IllegalStateException("class: " + clazzName + " has not method: parseFrom(byte[]).", e);
  71. } catch (Exception e) {
  72. throw new IllegalStateException("reflection error!", e);
  73. }
  74. }
  75. protected static GeneratedMessage reflact(String clazz, byte[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
  76. Class<?> aClass = Class.forName(clazz);
  77. Method method = CLASS_METHOD_MAP.get(aClass);
  78. if (method == null) {
  79. method = aClass.getMethod("parseFrom", byte[].class);
  80. CLASS_METHOD_MAP.put(aClass, method);
  81. }
  82. return (GeneratedMessage) method.invoke(null, args);
  83. }
  84. public String getCharset() {
  85. return charset;
  86. }
  87. public void setCharset(String charset) {
  88. this.charset = charset;
  89. }
  90. }