为自己网站建设,设计公司推广渠道,2023百度秒收录技术,免费网站优化怎么做文章目录 序列化是什么#xff1f;常见的序列化协议使用序列化反序列化序列化List反序列化List 查看源码#xff0c;分析不足进行改善 序列化是什么#xff1f;
如果我们需要持久化 Java 对象比如将 Java 对象保存在文件中#xff0c;或者在网络传输 Java 对象#xff0c… 文章目录 序列化是什么常见的序列化协议使用序列化反序列化序列化List反序列化List 查看源码分析不足进行改善 序列化是什么
如果我们需要持久化 Java 对象比如将 Java 对象保存在文件中或者在网络传输 Java 对象这些场景都需要用到序列化。
序列化将数据结构或对象转换成可以存储或传输的形式通常是二进制字节流也可以是 JSON, XML 等文本格式反序列化将在序列化过程中所生成的数据转换为原始数据结构或者对象的过程
对于 Java 这种面向对象编程语言来说我们序列化的都是对象Object也就是实例化后的类(Class) 下面是序列化和反序列化常见应用场景 对象在进行网络传输比如远程方法调用 RPC 的时候之前需要先被序列化接收到序列化的对象之后需要再进行反序列化将对象存储到文件之前需要进行序列化将对象从文件中读取出来需要进行反序列化将对象存储到数据库如 Redis之前需要用到序列化将对象从缓存数据库中读取出来需要反序列化将对象存储到内存之前需要进行序列化从内存中读取出来之后需要进行反序列化。
序列化的主要目的是通过网络传输对象或者说是将对象存储到文件系统、数据库、内存中。
常见的序列化协议
JDK 自带的序列化方式一般不会用 因为序列化效率低并且存在安全问题。比较常用的序列化协议有 fastjson、jackson、protobufPB、、、 在我的项目中使用jackson
使用
我们所有的jackson序列化以及反序列化都是基于ObjecMapper来操作的 我们先定义一个错误的异常类。后续所有的序列化反序列化操作都是针对这个错误类实例出的对象而完成的。
Data
public class CommonResultT implements Serializable {private Integer code;private T data;private String msg;public static T CommonResultT success(T data) {CommonResultT result new CommonResultT();result.code GlobalErrorCodeConstants.SUCCESS.getCode();result.data data;result.msg ;return result;}public static T CommonResultT error(Integer code, String msg) {Assert.isTrue(!GlobalErrorCodeConstants.SUCCESS.getCode().equals(code),code 不是错误的异常);CommonResultT result new CommonResultT();result.code code;result.msg msg;return result;}public static T CommonResultT error(ErrorCode errorCode){return error(errorCode.getCode(), errorCode.getMsg());}
}序列化 void TestJackson(){ObjectMapper objectMapper new ObjectMapper();CommonResultString commonResult1 CommonResult.error(500,系统错误);//序列化String str;try {str objectMapper.writeValueAsString(commonResult1);System.out.println(str);} catch (JsonProcessingException e) {throw new RuntimeException(e);}}
反序列化 //反序列化try {CommonResultString commonResult objectMapper.readValue(str, CommonResult.class);System.out.println(commonResult.getCode()commonResult.getMsg());} catch (JsonProcessingException e) {throw new RuntimeException(e);}序列化List
//序列化listListCommonResultString list Arrays.asList(CommonResult.success(success111),CommonResult.success(success222));try {str objectMapper.writeValueAsString(list);System.out.println(str);} catch (JsonProcessingException e) {throw new RuntimeException(e);}反序列化List
这里反序列化有一个注意事项 objecMapper.readValue里面的第二个参数 valueType不能直接放里不能直接放 listCommonResultString.class要使用 JavaType的方法 将list 和 list里面的元素 整合成一个类型 //反序列化listJavaType listType objectMapper.getTypeFactory().constructParametricType(List.class,CommonResult.class);try {list objectMapper.readValue(str,listType);System.out.println(list);} catch (JsonProcessingException e) {throw new RuntimeException(e);} 运行结果如下
查看源码分析不足 在我上述给出的代码中我们可以看到每一次进行序列化反序列化操作时都需要进行try-catch操作那么我们观察springboot的源码可以来借鉴改善我们的代码 点开SpringBoot源码找到反序列化List的方法。 public ListObject parseList(String json) {return (List)this.tryParse(() - {return (List)this.getObjectMapper().readValue(json, LIST_TYPE);}, Exception.class);}我们观察到里面调用到了tryParse这个方法我们点开这个方法 protected final T T tryParse(CallableT parser, Class? extends Exception check) {try {return parser.call();} catch (Exception var4) {Exception ex var4;if (check.isAssignableFrom(ex.getClass())) {throw new JsonParseException(ex);} else {ReflectionUtils.rethrowRuntimeException(ex);throw new IllegalStateException(ex);}}}我们可以看到parseList中通过lambda表达式的方式将异常全部在tryParse中进行try-catch。
解析tryParse
参数列表 CallableT parser, Class? extends Exception check 第一个参数是一个Callable第二个参数是一个Exception的class返回值 泛型Tparser.call() 相当于是将parseList中的lambda表达式进行调用。(List)this.tryParse(() - { return (List)this.getObjectMapper().readValue(json, LIST_TYPE);catch (Exception var4) { Exception ex var4; if (check.isAssignableFrom(ex.getClass())) { throw new JsonParseException(ex); } 检查捕获的这个var4异常是否是我们传入的check异常的实例或者是其子类的一个实例如果是就抛出JsonParseException(ex)
5.else { ReflectionUtils.rethrowRuntimeException(ex); throw new IllegalStateException(ex); } 不是预期的异常就抛出IllegalStateException(ex)
进行改善
对ObjecMappper使用一个单例的构造方法使用tryParse来对try-catch进行优化
public class JacksonUtil {public JacksonUtil() {}//单例模式 创建objecMapperprivate final static ObjectMapper OBJECT_MAPPER;static {OBJECT_MAPPER new ObjectMapper();}private static ObjectMapper getObjectMapper() {return OBJECT_MAPPER;}// 以后就可以直接调用这个方法 而不用再传一个异常private static T T tryParse(CallableT parser) {return tryParse(parser, JacksonException.class);}/*/参考的是 springboot源码 */private static T T tryParse(CallableT parser,Class? extends Exception check) {try {return parser.call();} catch (Exception ex) {if (check.isAssignableFrom(ex.getClass())) {throw new JsonParseException(ex);}throw new IllegalStateException(ex);}}/*** 序列化方法* param object* return*/public static String writeValueAsString(Object object){return JacksonUtil.tryParse(()-{return JacksonUtil.getObjectMapper().writeValueAsString(object);});}/*** 反序列化* param content* param valueType* return* param T*/public staticT T readValue(String content, ClassT valueType) {return JacksonUtil.tryParse(()-{return JacksonUtil.getObjectMapper().readValue(content, valueType);});}/*** 反序列化list* param content* param paramClasses* return* param T*/public static T T readListValue(String content, Class? paramClasses) {JavaType javaType JacksonUtil.getObjectMapper().getTypeFactory().constructParametricType(List.class, paramClasses);return JacksonUtil.tryParse(()-{return JacksonUtil.getObjectMapper().readValue(content, javaType);});}}