文章目录

  • 1 场景
  • 2 应用
    • 2.1 过程描述
    • 2.2 字节数组、字符串转换
    • 2.2.1 hex转码
    • 2.2.2 base64转码
    • 2.3 对象序列化字节数组
      • 2.3.1 使用commons-lang3包实现对象序列化
      • 2.3.2 编码实现对象序列化
    • 2.4 完整工具类代码
      • 2.4.1 maven依赖
      • 2.4.2 java代码
  • 3 限制
    • 3.1 序列化前置条件
    • 3.2 字节数组转换字符串
    • 3.3 序列化时忽略属性
  • 4 扩展
    • 4.1 hex和base64
    • 4.2 base32

1 场景

java对象某些时候,需要序列化字符串存储在数据库中,需要的时候,再将字符串反序列化为java对象。

如使用shiro缓存分布式session,需要将session对象序列化成字符串存储在redis中,来达到分布式应用共享session的功能。

为什么不序列化成json?

 java对象同样可以转换为`json`,需要的时候,再转换为java对象。这种情况一般只适用转换`自己创建的javaBean对象`,如果类是非自己管理的javaBean,对象内部`存在没有对外开放set/get方法的属性`,转换后将`丢失`。序列化自己javaBean对象的好处是,通过序列化后的json字符串,可以很清楚知道`被序列化的java对象的内容`。

2 应用

2.1 过程描述

序列化过程:

(1)java对象通过对象输出流ObjectOutputStream,写入到内存字节数组输出流ByteArrayOutputStream

(2)通过内存字节数组输出流ByteArrayOutputStream获取字节数组byte[]

(3)字节数组根据自定义算法转换成字符串(hex/base64等)

反序列化过程:

(1)被序列化后字符串,根据字节数组转换字符串的算法,转换为字节数组byte[]

(2)字节数组通过内存字节数组输入流ByteArrayInputStream写入到对象输入流ObjectInputStream

(3)通过对象输入流ObjectInputStream读取java对象

2.2 字节数组、字符串转换

字节数组转码成字符串依赖如下maven包:

<dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.14</version>
</dependency>

2.2.1 hex转码

(1)字节数组hex转码

public static String bytesToString(byte[] bytes) {//转换成hexreturn org.apache.commons.codec.binary.Hex.encodeHexString(bytes);
}

(2)字符串hex反转码成字节数组

public static byte[] stringToByte(String str) throws DecoderException {//转换成hexreturn org.apache.commons.codec.binary.Hex.decodeHex(str);
}

2.2.2 base64转码

建议此种方式

(1) 字节数组base64转码

public static String bytesToString(byte[] bytes) {//转换成base64return org.apache.commons.codec.binary.Base64.encodeBase64String(bytes);
}

(2) 字符串base64反转码成字节数组

public static byte[] stringToByte(String str) throws DecoderException {//转换成base64return org.apache.commons.codec.binary.Base64.decodeBase64(str);
}

2.3 对象序列化字节数组

字节数组、字符串转换使用2.2中定义的转换方法:bytesToString、stringToByte

2.3.1 使用commons-lang3包实现对象序列化

建议此种方式,代码简单

maven依赖如下:

<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.10</version>
</dependency>

代码如下:

(1)java对象序列化成字符串

public static String serialize(Serializable obj) throws Exception{if(obj!=null) {byte[] bytes = SerializationUtils.serialize(obj);return bytesToString(bytes);}return null;
}

(2)字符串反序列化成java对象

public static <T extends Serializable> T deserialize(String str) throws Exception{if(StringUtils.isNotEmpty(str)){return SerializationUtils.deserialize(stringToByte(str));}return null;
}
2.3.2 编码实现对象序列化

代码如下:

(1)java对象序列化成字符串

public static String serialize(Serializable obj) throws Exception{if(obj!=null) {ByteArrayOutputStream bos=null;ObjectOutputStream oos=null;try {bos=new ByteArrayOutputStream();oos=new ObjectOutputStream(bos);oos.writeObject(obj);byte[] bytes = bos.toByteArray();return bytesToString(bytes);} catch (Exception e) {e.printStackTrace();throw new Exception("序列化对象失败:"+String.valueOf(obj));}finally {try {if(bos!=null){bos.close();}if(oos!=null){oos.close();}} catch (IOException e) {e.printStackTrace();}}}return null;
}

(2)字符串反序列化成java对象

public static <T extends Serializable> T deserialize(String str) throws Exception{if(StringUtils.isNotEmpty(str)){ByteArrayInputStream bai=null;ObjectInputStream ois=null;try{bai=new ByteArrayInputStream(stringToByte(str));ois=new ObjectInputStream(bai);return (T)ois.readObject();}catch (Exception e){e.printStackTrace();throw new Exception("字符串反序列化对象失败:"+String.valueOf(str));}finally {try {if(ois!=null){ois.close();}if(bai!=null){bai.close();}} catch (IOException e) {e.printStackTrace();}}}return null;
}

2.4 完整工具类代码

2.4.1 maven依赖
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.10</version>
</dependency>
<dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.14</version>
</dependency>
2.4.2 java代码
package com.demo.cs.template.util;import org.apache.commons.codec.DecoderException;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.*;/*** 序列化工具类*/
public class SerializeUtil {/*** 字节数组转换为字符串*/public static String bytesToString(byte[] bytes) { 字符串、字节数组转换方式很多,可以根据自己的要求,自定义转换方式//转换成hex//return org.apache.commons.codec.binary.Hex.encodeHexString(bytes);//转换成base64return org.apache.commons.codec.binary.Base64.encodeBase64String(bytes);}/*** 字符串转换为字节数组* @param str* @return*/public static byte[] stringToByte(String str) throws DecoderException { 字符串、字节数组转换方式很多,可以根据自己的要求,自定义转换方式//转换成hex//return org.apache.commons.codec.binary.Hex.decodeHex(str);//转换成base64return org.apache.commons.codec.binary.Base64.decodeBase64(str);}/*** 序列化对象(依赖commons-lang3包)* @param obj 序列化对象* @return  对象序列化之后的字符串*/public static String serialize(Serializable obj) throws Exception{if(obj!=null) {byte[] bytes = SerializationUtils.serialize(obj);return bytesToString(bytes);}return null;}/*** 反序列化对象(依赖commons-lang3包)* @param str   反序列化字符串* @return      反序列化之后的对象*/public static <T extends Serializable> T deserialize(String str) throws Exception{if(StringUtils.isNotEmpty(str)){return SerializationUtils.deserialize(stringToByte(str));}return null;}
}

3 限制

3.1 序列化前置条件

java对象可序列化成字节数组的前提是:
java类必须实现序列化接口:Serializable,此接口代表该类的实例化对象,可以进行序列化(对象内的内置属性,也需要实现此接口)。
如不实现此接口,序列化成对象时,将抛出异常:java.io.NotSerializableException

为防止调用工具类的时候,参数未实现此接口,可在工具类指定参数返回值泛型的类型:

 public static String serialize(Serializable obj) throws Exception{...}public static <T extends Serializable> T deserialize(String str) throws Exception{...}

3.2 字节数组转换字符串

对象序列化后,是以字节数组的形式存在,需要将字节数组转码成可读的字符串。上面有hex和base64转码示例。

无论以哪种方式转码和反转码,均需采用一样的算法。

3.3 序列化时忽略属性

如对象属性被关键字transient所修饰,对象序列化时,将会忽略此属性。如下:

private transient String userName;

4 扩展

4.1 hex和base64

(1)含义

java中有可见字符不可见字符的区分,不可见字符在输出字符串的时候无法看到。如将字节数组转换成字符串,需要先根据编码规则将字节数组转换成字符数组,再将字符数组转换成字符串,由于部分转换后的字符是不可见的,此类字符无法转换成可见的字符串,将存在数据的丢失。在将字节数组转换成对应的字节时,hex和base64可以将不可见字符转换成可见字符,实现数据的二进制安全转换

hex和base64都是编码方式和加密无关,将字节数组编码为可见的字符串

hex的意思是16进制,编码后大小变为2倍,一个字符用两个可见字符来表示。

base64如字面意思,64进制来表示数组,编码后大小变成4/3倍,3个字符用4个可见字符来表示。

(2)编码速度

hex编码解码速度比base64快,hex速度更快

(3)编码后大小

base64编码后字符串大小比hex小,base64占用空间更小

(4)转换后格式

hex编码后内容如下:

aced000573720022636f6d2e64656d6f2e63732e74656d706c6174652e6265616e2e54656d7055736572a55d364cf96782ab0200024c00036167657400134c6a6176612f6c616e672f496e74656765723b4c0008757365724e616d657400124c6a6176612f6c616e672f537472696e673b7870737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c7565787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b020000787000000012740006e5bca0e4b889

base64编码后内容如下:

rO0ABXNyACJjb20uZGVtby5jcy50ZW1wbGF0ZS5iZWFuLlRlbXBVc2VypV02TPlngqsCAAJMAANhZ2V0ABNMamF2YS9sYW5nL0ludGVnZXI7TAAIdXNlck5hbWV0ABJMamF2YS9sYW5nL1N0cmluZzt4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAASdAAG5byg5LiJ

4.2 base32

还有种编码方式base32,如字面意思,32进制来转码字符数组。可酌情使用

java对象序列化为字符串相关推荐

  1. c#将对象序列化为字符串和将字符串反序列化为对象

    asp.net开发中,页面间传值最长用到的是url显式传参,session,application和cookie传值等.对于复杂对象页面传值,如果不考虑性能影响的话,通常可以使用session或者ap ...

  2. 将对象序列化为字符串

    本文翻译自:Serialize an object to string I have the following method to save an Object to a file: 我有以下方法将 ...

  3. java字符串序列化_java对象序列化为字符串

    1 场景 java对象某些时候,需要序列化成字符串存储在数据库中,需要的时候,再将字符串反序列化为java对象. 如使用shiro缓存分布式session,需要将session对象序列化成字符串存储在 ...

  4. java 嵌套对象序列化_在javascript中将复杂的,嵌套的,用户定义的对象序列化为字符串...

    是的,所以's kind of like you'重新序列化对象数据,而不是类数据 . 变量仍然存在,但关于类的元数据(即方法)没有被保留 . 一个解决方案可能是serialijse . serial ...

  5. js对象序列化为json字符串

    网上找了找将js对象序列化为json字符串的方法.结果都不近人意,最后自己写了一个. 注意你得自己为Date增加toString()方法. function Serialize(obj){switch ...

  6. Java对象序列化乱码6_对象序列化成字符串乱码解决

    问题描述: 将一个对象序列化成字符串后,字符串是乱码的,并且反序列化报错. 代码如下: import com.alibaba.fastjson.JSONObject; import org.sprin ...

  7. JavaScriptSerializer-枚举的JSON序列化为字符串

    我有一个包含enum属性的类,并在使用JavaScriptSerializer序列化对象后,我的json结果包含枚举的整数值,而不是其string " name". 有没有一种方法 ...

  8. java 序列化成xml文件_将Java对象序列化成JSON和XML格式

    1.先定义一个Java对象Person: public class Person { String name; int age; int number; public String getName() ...

  9. qs—对象序列化为查询参数和URL解析成对象的库

    安装 npm install qs 使用 let qs = require('qs') // 或者 import qs from 'qs' 方法 对象序列化为URL查询参数 let obj = {a: ...

最新文章

  1. mysql 自动化运维工具_MySQL使用工具Inception实现自动化运维
  2. 字符串模糊/精确查询——mysql
  3. Python网络请求urllib和urllib3详解
  4. 计算机网络 | 数据链路层 :ARP协议、以太网协议、MTU
  5. Mysql和Oracle获取自增主键
  6. Linux 命令之 newgrp -- 登入另一个群组
  7. python以20字符宽居中输出,Python 字符串内置方法(一)
  8. 牛客网编程题03--明明的随机数
  9. EMNLP2018 - 语言理解+对话系统的最新进展
  10. 现实世界的Windows Azure: 采访LexisNexis的Marc Slovak 和 Manish Bhargava
  11. 关键词词云怎么做_网友问:做独立站,怎么做关键词排名,怎么做客户流量?...
  12. 在pycharm中使用pyqt5时clicked().后面connect不自动补全问题解决办法
  13. web前端入门到实战:HTML图像标签img和源属性src及Alt属性、宽高、对齐
  14. 遗传算法优化BP神经网络,bp神经网络的优化算法
  15. detecting android sdk, Select Android SDK directory
  16. 阿里巴巴入选的JCP最高执行委员会,何方神圣?
  17. Arcgis 地理坐标系转投影坐标系(WGS84转CGCS2000)
  18. openwrt路由器php-cli,【在openwrt无线路由器上部署freeswitch+fusionpbx (原帖恩山论坛)】-网关论坛-ZOL中关村在线...
  19. element分页组件,搜索过后current-page 绑定的数据变了,但是页面当前页码并没有变的问题
  20. flutter CustomScrollView中使用Swiper做轮播图问题

热门文章

  1. Linux内核:内存从BIOS->e820->memblock->node/zone基本流程
  2. Linux内存管理:内存描述之内存区域zone
  3. linux下基于Posix message queue的同步消息队列的实现
  4. 【转】C++从零实现神经网络
  5. Python:isinstance()和type()
  6. net start mysql 失败_net start mysql出错,显示错误1067
  7. lisp如何批量选中特定图层_图层管理的奥秘
  8. mysql unique和key_MYSQL的primary key和unique key的区别
  9. mysql5.1 utf8_编译安装mysql 5.1使用utf8解决乱码问题
  10. 录入班级学生姓名科目成绩_如何利用钉钉发布考试成绩