ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

RedisTemplate配置的jackson.ObjectMapper里的一个enableDefaultTyping方法过期解决

2021-08-18 16:32:40  阅读:308  来源: 互联网

标签:NON jackson RedisTemplate DefaultTyping 类型 enableDefaultTyping objectMapper Obje


起因是使用 objectMapper.enableDefaultTyping()方法是发现被弃用。

建议使用 objectMapper.activateDefaultTyping()方法替代它。

 

1、前言

最近升级SpringBoot,从2.1.6版本升级到2.4.1版本,发现enableDefaultTyping方法过期过期了。

该方法是指定序列化输入的类型,就是将数据库里的数据安装一定类型存储到redis缓存中。

2、为什么要指定序列化输入类型

2.1、没有指定序列化输入类型

如果注释掉enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL),那存储到redis里的数据将是没有类型的纯json,我们调用redis API获取到数据后,java解析将是一个LinkHashMap类型的key-value的数据结构,我们需要使用的话就要自行解析,这样增加了编程的复杂度。

[{"id":72,"uuid":"c4d7fc52-4096-4c79-81ef-32cb1b87fd28","type":2}]

2.2、指定序列化输入类型

指定enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL)的话,存储到redis里的数据将是有类型的json数据,例如:

["java.util.ArrayList",[{"@class":"com.model.app","id":72,"uuid":"c4d7fc52-4096-4c79-81ef-32cb1b87fd28","type":2}]]

这样java获取到数据后,将会将数据自动转化为java.util.ArrayList和com.model.app,方便直接使用。

3、enableDefaultTyping过期怎么解决

3.1 查找函数接口

查看enableDefaultTyping内部实现

/** @deprecated */
@Deprecated
public ObjectMapper enableDefaultTyping(ObjectMapper.DefaultTyping dti) {
    return this.enableDefaultTyping(dti, As.WRAPPER_ARRAY);
}

查看enableDefaultTyping内部实现

/** @deprecated */
@Deprecated
public ObjectMapper enableDefaultTyping(ObjectMapper.DefaultTyping applicability, As includeAs) {
    return this.activateDefaultTyping(this.getPolymorphicTypeValidator(), applicability, includeAs);
}

查看activateDefaultTyping内部实现

public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv, ObjectMapper.DefaultTyping applicability, As includeAs) {
    if (includeAs == As.EXTERNAL_PROPERTY) {
        throw new IllegalArgumentException("Cannot use includeAs of " + includeAs);
    } else {
        TypeResolverBuilder<?> typer = this._constructDefaultTypeResolverBuilder(applicability, ptv);
        typer = typer.init(Id.CLASS, (TypeIdResolver)null);
        typer = typer.inclusion(includeAs);
        return this.setDefaultTyping(typer);
    }
}

这里我们可以直接调用activateDefaultTyping方法了,从而不用调用过期的enableDefaultTyping方法。

再看activateDefaultTyping的参数默认是哪些呢?代码里有这样一个静态初始化:

static {
    DEFAULT_BASE = new BaseSettings((ClassIntrospector)null, DEFAULT_ANNOTATION_INTROSPECTOR, (PropertyNamingStrategy)null, TypeFactory.defaultInstance(), (TypeResolverBuilder)null, StdDateFormat.instance, (HandlerInstantiator)null, Locale.getDefault(), (TimeZone)null, Base64Variants.getDefaultVariant(), LaissezFaireSubTypeValidator.instance);
}

3.2 解决

从而我们知道,默认的参数有哪些,

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

//objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
objectMapper.activateDefaultTyping(

     LaissezFaireSubTypeValidator.instance , 
    ObjectMapper.DefaultTyping.NON_FINAL,

     JsonTypeInfo.As.WRAPPER_ARRAY);

jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

 

4 DefaultTyping 类型定义

如果想知道详细的说明,大家google去吧:

public static enum DefaultTyping {
    JAVA_LANG_OBJECT,
    OBJECT_AND_NON_CONCRETE,
    NON_CONCRETE_AND_ARRAYS,
    NON_FINAL,
    EVERYTHING;
    private DefaultTyping() {
    }
}

 DefaultTyping有四个选项:

JAVA_LANG_OBJECT: 当对象属性类型为Object时生效;

OBJECT_AND_NON_CONCRETE: 当对象属性类型为Object或者非具体类型(抽象类和接口)时生效;

NON_CONCRETE_AND+_ARRAYS: 同上, 另外所有的数组元素的类型都是非具体类型或者对象类型;

NON_FINAL: 对所有非final类型或者非final类型元素的数组。

因此,当开启DefaultTyping后,会开发者在反序列化时指定要还原的类,过程中调用其构造方法setter方法或某些特殊的getter方法,当这些方法中存在一些危险操作时就造成了代码执行。

具体参考链接

https://blog.csdn.net/panda1103/article/details/106021599/?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.control&spm=1001.2101.3001.4242

 

 

标签:NON,jackson,RedisTemplate,DefaultTyping,类型,enableDefaultTyping,objectMapper,Obje
来源: https://www.cnblogs.com/shanheyongmu/p/15157378.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有