Jackson多态反序列化的使用
Posted yueguanghaidao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jackson多态反序列化的使用相关的知识,希望对你有一定的参考价值。
缘起
最近看Apache Druid的源代码(0.5很老的版本),印象最深的就是对Jackson的多态反序列化和注入的使用了,这里也属于自己的知识盲点,看着复杂的json直接反序列化为可用对象,直呼过瘾。所以一直想找个机会实践一下,这不需求就来了。
需求
我们的实时指标统计是通过Flink Steam SQL计算为维度、指标后后入Hbase,然后通过Phoenix SQL给前台展示。现在新接入Kylin数据源,需要兼容查询Kylin数据源。
看到这个需求,变化点在查询方式上,抽象出查询服务,提供多态支持,但各个指标查询需要的信息是不同的。如Kylin数据源需要查询的表名,聚合函数等,但Hbase数据源压根不需要这些信息,这时候就该Jackson多态反序列化出厂了。
实践
数据库新增querySpec字段,描述指标的个性化需求,如“type”:“rc”,“tableName”:“TASK_SNAPSHOT”,“fieldName”:“EVENTCODE”
“type”:“hbase”
看如下代码:
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
/**
* Created by yihaibo on 2019-09-11.
*/
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, property = "type", defaultImpl = HbaseQuerySpec.class )
@JsonSubTypes(value =
@JsonSubTypes.Type(value = HbaseQuerySpec.class, name = "hbase"),
@JsonSubTypes.Type(value = RcHttpQuerySpec.class, name = "rc")
)
public interface QuerySpec
String getMetricQueryServiceName();
/**
* hbase数据源个性化信息
*/
public class HbaseQuerySpec implements QuerySpec
@Override
public String getMetricQueryServiceName()
return "hbaseQueryService";
/**
* kylin数据源个性化信息(已通过http服务化)
*/
public class RcHttpQuerySpec implements QuerySpec
@Getter
@Setter
@JsonProperty
private String tableName;
@Getter
@Setter
@JsonProperty
private String fieldName;
@Override
@JsonIgnore
public String getMetricQueryServiceName()
return "rcMetricQueryService";
我们看到新增了getMetricQueryServiceName方法,用于指定处理该数据源的service名称。
有了个性化参数,可以写查询服务了
public interface MetricQueryService
/**
*
* @param dataQueryDTO 通用查询参数
* @param querySpec 个性化配置信息
* @return
*/
List<Map<String,Object>> queryData(DataQueryDTO dataQueryDTO, QuerySpec querySpec);
/**
* 查询Hbase原始数据
* */
@Service("hbaseQueryService")
public class HbaseMetricQueryService implements MetricQueryService
@Override
public List<Map<String,Object>> queryData(DataQueryDTO dataQueryDTO, QuerySpec querySpec)
....
/**
* 查询kylin数据
* */
@Service("rcMetricQueryService")
public class RcMetricQueryService implements MetricQueryService
@Override
public List<Map<String, Object>> queryData(DataQueryDTO dataQueryDTO, QuerySpec querySpec)
RcHttpQuerySpec rcHttpQuerySpec = (RcHttpQuerySpec)querySpec;
...
反序列化querySpec,获取服务名称,然后通过spring获取到该service bean,传递处理参数
QuerySpec querySpec = JsonUtil.decode(querySpec, QuerySpec.class);
String serviceName = querySpec.getMetricQueryServiceName();
MetricQueryService metricQueryService = CtxUtil.getBean(serviceName, MetricQueryService.class);
List<Map<String,Object>> data = metricQueryService.queryData(dataQueryDTO, querySpec);
@Component
@Slf4j
public class CtxUtil implements ApplicationContextAware
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException
applicationContext = ctx;
log.info("init ctx ok");
public static <T> T getBean(Class<T> clazz)
return applicationContext.getBean(clazz);
public static <T> T getBean(String name, Class<T> clazz)
return applicationContext.getBean(name, clazz);
反思
Jackson多态反序列化的确是开发力气,可以去掉不少if else样例代码,精简配置。但感觉用Jackson注入还是不太合适,Jackson对象还是作为POJO比较合适,逻辑层还是service层或单独bo去处理,需要注入可以用spring或guice,职则方面,方便test case。
最近在研究Apache Druid,主要学习一些分布式处理知识,以及想看下列式存储到底是如何做的。实时OLAP的确用处多多,Apache Kylin也在扩展实时处理,期待两着的碰撞与融合。
以上是关于Jackson多态反序列化的使用的主要内容,如果未能解决你的问题,请参考以下文章