Netty学习08--自定义序列化协议之自定义序列化协议

小咪咪 2023-02-18 08:28 148阅读 0赞
  1. Serializer
  2. package core;
  3. import java.nio.charset.Charset;
  4. import java.util.ArrayList;
  5. import java.util.Collection;
  6. import java.util.HashMap;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.Map.Entry;
  10. import org.jboss.netty.buffer.ChannelBuffer;
  11. /**
  12. * 自定义序列化接口
  13. */
  14. public abstract class Serializer {
  15. public static final Charset CHARSET = Charset.forName("UTF-8");
  16. protected ChannelBuffer writeBuffer;
  17. protected ChannelBuffer readBuffer;
  18. /**
  19. * 反序列化具体实现
  20. */
  21. protected abstract void read();
  22. /**
  23. * 序列化具体实现
  24. */
  25. protected abstract void write();
  26. /**
  27. * 从byte数组获取数据
  28. * @param bytes 读取的数组
  29. */
  30. public Serializer readFromBytes(byte[] bytes) {
  31. readBuffer = BufferFactory.getBuffer(bytes);
  32. read();
  33. readBuffer.clear();
  34. return this;
  35. }
  36. /**
  37. * 从buff获取数据
  38. * @param readBuffer
  39. */
  40. public void readFromBuffer(ChannelBuffer readBuffer) {
  41. this.readBuffer = readBuffer;
  42. read();
  43. }
  44. /**
  45. * 写入本地buff
  46. * @return
  47. */
  48. public ChannelBuffer writeToLocalBuff(){
  49. writeBuffer = BufferFactory.getBuffer();
  50. write();
  51. return writeBuffer;
  52. }
  53. /**
  54. * 写入目标buff
  55. * @param buffer
  56. * @return
  57. */
  58. public ChannelBuffer writeToTargetBuff(ChannelBuffer buffer){
  59. writeBuffer = buffer;
  60. write();
  61. return writeBuffer;
  62. }
  63. /**
  64. * 返回buffer数组
  65. *
  66. * @return
  67. */
  68. public byte[] getBytes() {
  69. writeToLocalBuff();
  70. byte[] bytes = null;
  71. if (writeBuffer.writerIndex() == 0) {
  72. bytes = new byte[0];
  73. } else {
  74. bytes = new byte[writeBuffer.writerIndex()];
  75. writeBuffer.readBytes(bytes);
  76. }
  77. writeBuffer.clear();
  78. return bytes;
  79. }
  80. public byte readByte() {
  81. return readBuffer.readByte();
  82. }
  83. public short readShort() {
  84. return readBuffer.readShort();
  85. }
  86. public int readInt() {
  87. return readBuffer.readInt();
  88. }
  89. public long readLong() {
  90. return readBuffer.readLong();
  91. }
  92. public float readFloat() {
  93. return readBuffer.readFloat();
  94. }
  95. public double readDouble() {
  96. return readBuffer.readDouble();
  97. }
  98. public String readString() {
  99. int size = readBuffer.readShort();
  100. if (size <= 0) {
  101. return "";
  102. }
  103. byte[] bytes = new byte[size];
  104. readBuffer.readBytes(bytes);
  105. return new String(bytes, CHARSET);
  106. }
  107. public <T> List<T> readList(Class<T> clz) {
  108. List<T> list = new ArrayList<>();
  109. int size = readBuffer.readShort();
  110. for (int i = 0; i < size; i++) {
  111. list.add(read(clz));
  112. }
  113. return list;
  114. }
  115. public <K,V> Map<K,V> readMap(Class<K> keyClz, Class<V> valueClz) {
  116. Map<K,V> map = new HashMap<>();
  117. int size = readBuffer.readShort();
  118. for (int i = 0; i < size; i++) {
  119. K key = read(keyClz);
  120. V value = read(valueClz);
  121. map.put(key, value);
  122. }
  123. return map;
  124. }
  125. @SuppressWarnings("unchecked")
  126. public <I> I read(Class<I> clz) {
  127. Object t = null;
  128. if ( clz == int.class || clz == Integer.class) {
  129. t = this.readInt();
  130. } else if (clz == byte.class || clz == Byte.class){
  131. t = this.readByte();
  132. } else if (clz == short.class || clz == Short.class){
  133. t = this.readShort();
  134. } else if (clz == long.class || clz == Long.class){
  135. t = this.readLong();
  136. } else if (clz == float.class || clz == Float.class){
  137. t = readFloat();
  138. } else if (clz == double.class || clz == Double.class){
  139. t = readDouble();
  140. } else if (clz == String.class ){
  141. t = readString();
  142. } else if (Serializer.class.isAssignableFrom(clz)){
  143. try {
  144. byte hasObject = this.readBuffer.readByte();
  145. if(hasObject == 1){
  146. Serializer temp = (Serializer)clz.newInstance();
  147. temp.readFromBuffer(this.readBuffer);
  148. t = temp;
  149. }else{
  150. t = null;
  151. }
  152. } catch (Exception e) {
  153. e.printStackTrace();
  154. }
  155. } else {
  156. throw new RuntimeException(String.format("不支持类型:[%s]", clz));
  157. }
  158. return (I) t;
  159. }
  160. public Serializer writeByte(Byte value) {
  161. writeBuffer.writeByte(value);
  162. return this;
  163. }
  164. public Serializer writeShort(Short value) {
  165. writeBuffer.writeShort(value);
  166. return this;
  167. }
  168. public Serializer writeInt(Integer value) {
  169. writeBuffer.writeInt(value);
  170. return this;
  171. }
  172. public Serializer writeLong(Long value) {
  173. writeBuffer.writeLong(value);
  174. return this;
  175. }
  176. public Serializer writeFloat(Float value) {
  177. writeBuffer.writeFloat(value);
  178. return this;
  179. }
  180. public Serializer writeDouble(Double value) {
  181. writeBuffer.writeDouble(value);
  182. return this;
  183. }
  184. public <T> Serializer writeList(List<T> list) {
  185. if (isEmpty(list)) {
  186. writeBuffer.writeShort((short) 0);
  187. return this;
  188. }
  189. writeBuffer.writeShort((short) list.size());
  190. for (T item : list) {
  191. writeObject(item);
  192. }
  193. return this;
  194. }
  195. public <K,V> Serializer writeMap(Map<K, V> map) {
  196. if (isEmpty(map)) {
  197. writeBuffer.writeShort((short) 0);
  198. return this;
  199. }
  200. writeBuffer.writeShort((short) map.size());
  201. for (Entry<K, V> entry : map.entrySet()) {
  202. writeObject(entry.getKey());
  203. writeObject(entry.getValue());
  204. }
  205. return this;
  206. }
  207. public Serializer writeString(String value) {
  208. if (value == null || value.isEmpty()) {
  209. writeShort((short) 0);
  210. return this;
  211. }
  212. byte data[] = value.getBytes(CHARSET);
  213. short len = (short) data.length;
  214. writeBuffer.writeShort(len);
  215. writeBuffer.writeBytes(data);
  216. return this;
  217. }
  218. public Serializer writeObject(Object object) {
  219. if(object == null){
  220. writeByte((byte)0);
  221. }else{
  222. if (object instanceof Integer) {
  223. writeInt((int) object);
  224. return this;
  225. }
  226. if (object instanceof Long) {
  227. writeLong((long) object);
  228. return this;
  229. }
  230. if (object instanceof Short) {
  231. writeShort((short) object);
  232. return this;
  233. }
  234. if (object instanceof Byte) {
  235. writeByte((byte) object);
  236. return this;
  237. }
  238. if (object instanceof String) {
  239. String value = (String) object;
  240. writeString(value);
  241. return this;
  242. }
  243. if (object instanceof Serializer) {
  244. writeByte((byte)1);
  245. Serializer value = (Serializer) object;
  246. value.writeToTargetBuff(writeBuffer);
  247. return this;
  248. }
  249. throw new RuntimeException("不可序列化的类型:" + object.getClass());
  250. }
  251. return this;
  252. }
  253. private <T> boolean isEmpty(Collection<T> c) {
  254. return c == null || c.size() == 0;
  255. }
  256. public <K,V> boolean isEmpty(Map<K,V> c) {
  257. return c == null || c.size() == 0;
  258. }
  259. }
  260. BufferFactory
  261. package core;
  262. import java.nio.ByteOrder;
  263. import org.jboss.netty.buffer.ChannelBuffer;
  264. import org.jboss.netty.buffer.ChannelBuffers;
  265. /**
  266. * buff工厂
  267. */
  268. public class BufferFactory {
  269. public static ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN;
  270. /**
  271. * 获取一个buffer
  272. *
  273. * @return
  274. */
  275. public static ChannelBuffer getBuffer() {
  276. ChannelBuffer dynamicBuffer = ChannelBuffers.dynamicBuffer();
  277. return dynamicBuffer;
  278. }
  279. /**
  280. * 将数据写入buffer
  281. * @param bytes
  282. * @return
  283. */
  284. public static ChannelBuffer getBuffer(byte[] bytes) {
  285. ChannelBuffer copiedBuffer = ChannelBuffers.copiedBuffer(bytes);
  286. return copiedBuffer;
  287. }
  288. }
  289. Test1
  290. import java.io.ByteArrayInputStream;
  291. import java.io.ByteArrayOutputStream;
  292. import java.io.IOException;
  293. import java.util.Arrays;
  294. public class Test1 {
  295. public static void main(String[] args) throws IOException {
  296. int id = 101;
  297. int age = 21;
  298. ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
  299. arrayOutputStream.write(int2bytes(id));
  300. arrayOutputStream.write(int2bytes(age));
  301. byte[] byteArray = arrayOutputStream.toByteArray();
  302. System.out.println(Arrays.toString(byteArray));
  303. //==============================================================
  304. ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(byteArray);
  305. byte[] idBytes = new byte[4];
  306. arrayInputStream.read(idBytes);
  307. System.out.println("id:" + bytes2int(idBytes));
  308. byte[] ageBytes = new byte[4];
  309. arrayInputStream.read(ageBytes);
  310. System.out.println("age:" + bytes2int(ageBytes));
  311. }
  312. /**
  313. * 大端字节序列(先写高位,再写低位)
  314. * 百度下 大小端字节序列
  315. * @param i
  316. * @return
  317. */
  318. public static byte[] int2bytes(int i){
  319. byte[] bytes = new byte[4];
  320. bytes[0] = (byte)(i >> 3*8);
  321. bytes[1] = (byte)(i >> 2*8);
  322. bytes[2] = (byte)(i >> 1*8);
  323. bytes[3] = (byte)(i >> 0*8);
  324. return bytes;
  325. }
  326. /**
  327. * 大端
  328. * @param bytes
  329. * @return
  330. */
  331. public static int bytes2int(byte[] bytes){
  332. return (bytes[0] << 3*8) |
  333. (bytes[1] << 2*8) |
  334. (bytes[2] << 1*8) |
  335. (bytes[3] << 0*8);
  336. }
  337. }
  338. Test1上面的使用不方便,如果bytes2double又要重新写一个新的方法,比较麻烦,使用Test2
  339. Test2
  340. import java.nio.ByteBuffer;
  341. import java.util.Arrays;
  342. public class Test2 {
  343. public static void main(String[] args) {
  344. int id = 101;
  345. int age = 21;
  346. ByteBuffer buffer = ByteBuffer.allocate(8);
  347. buffer.putInt(id);
  348. buffer.putInt(age);
  349. byte[] array = buffer.array();
  350. System.out.println(Arrays.toString(buffer.array()));
  351. //====================================================
  352. ByteBuffer buffer2 = ByteBuffer.wrap(array);
  353. System.out.println("id:"+buffer2.getInt());
  354. System.out.println("age:"+buffer2.getInt());
  355. }
  356. }
  357. Test2这种方式必须先初始化一个大小,不会自动扩容。如果buffer.putLong(11L),会导致程序出错。
  358. Test3
  359. import java.util.Arrays;
  360. import org.jboss.netty.buffer.ChannelBuffer;
  361. import org.jboss.netty.buffer.ChannelBuffers;
  362. public class Test3 {
  363. public static void main(String[] args) {
  364. ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
  365. buffer.writeInt(101);
  366. buffer.writeDouble(80.1);
  367. byte[] bytes = new byte[buffer.writerIndex()];
  368. buffer.readBytes(bytes);
  369. System.out.println(Arrays.toString(bytes));
  370. "abc".getBytes();
  371. //================================================
  372. ChannelBuffer wrappedBuffer = ChannelBuffers.wrappedBuffer(bytes);
  373. System.out.println(wrappedBuffer.readInt());
  374. System.out.println(wrappedBuffer.readDouble());
  375. }
  376. }
  377. Test3就会自动扩容,但是不会写String类型的数据,("abc".getBytes();)使用Test4直接序列化和反序列化对象。
  378. Resource
  379. import core.Serializer;
  380. public class Resource extends Serializer {
  381. private int gold;
  382. public int getGold() {
  383. return gold;
  384. }
  385. public void setGold(int gold) {
  386. this.gold = gold;
  387. }
  388. @Override
  389. protected void read() {
  390. this.gold = readInt();
  391. }
  392. @Override
  393. protected void write() {
  394. writeInt(gold);
  395. }
  396. }
  397. Player
  398. import core.Serializer;
  399. import java.util.ArrayList;
  400. import java.util.List;
  401. public class Player extends Serializer {
  402. private long playerId;
  403. private int age;
  404. private List<Integer> skills = new ArrayList<>();
  405. private Resource resource = new Resource();
  406. public Resource getResource() {
  407. return resource;
  408. }
  409. public void setResource(Resource resource) {
  410. this.resource = resource;
  411. }
  412. public long getPlayerId() {
  413. return playerId;
  414. }
  415. public void setPlayerId(long playerId) {
  416. this.playerId = playerId;
  417. }
  418. public int getAge() {
  419. return age;
  420. }
  421. public void setAge(int age) {
  422. this.age = age;
  423. }
  424. public List<Integer> getSkills() {
  425. return skills;
  426. }
  427. public void setSkills(List<Integer> skills) {
  428. this.skills = skills;
  429. }
  430. @Override
  431. protected void read() {
  432. this.playerId = readLong();
  433. this.age = readInt();
  434. this.skills = readList(Integer.class);
  435. this.resource = read(Resource.class);
  436. }
  437. @Override
  438. protected void write() {
  439. writeLong(playerId);
  440. writeInt(age);
  441. writeList(skills);
  442. writeObject(resource);
  443. }
  444. }
  445. Test4 (使用前面定义的BufferFactorySerializer
  446. import java.util.Arrays;
  447. public class Test4 {
  448. public static void main(String[] args) {
  449. Player player = new Player();
  450. player.setPlayerId(10001);
  451. player.setAge(22);
  452. player.getSkills().add(101);
  453. player.getResource().setGold(99999);
  454. byte[] bytes = player.getBytes();
  455. System.out.println(Arrays.toString(bytes));
  456. //==============================================
  457. Player player2 = new Player();
  458. player2.readFromBytes(bytes);
  459. System.out.println(player2.getPlayerId() + " "+player2.getAge() + " "+ Arrays.toString(player2.getSkills().toArray())+" " +player2.getResource().getGold());
  460. }
  461. }

代码下载​​​​​​​

发表评论

表情:
评论列表 (有 0 条评论,148人围观)

还没有评论,来说两句吧...

相关阅读

    相关 netty定义协议

    《netty权威指南》一书中关于自定义协议开发的源码中有一部分错误导致代码无法运行,加了一点改变可以完美运行了, package nettyAgreement.dec