您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

一招教你解决页面中关联id的转换

时间:2024-05-17 11:55:40  来源:Java技术指北  作者:

在工作中,我们经常有这样的业务情况,实体间通过id实现数据业务上的关联,比如订单和用户,订单的创建人id、商品id等,在页面查询时我们需要将对应的id信息转换成对应的中文描述,比如用户中文名称,商品中文名称等。如果是单条数据的展示还好,但是设计到列表查询,如何高效、优雅地实现这个效果呢?

现在接口返回的数据基本都是JSON格式,比如spring中使用了jackson,在controller层对结果进行json序列化,而我们要做的就是在序列化的过程中,实现id的转换

使用方式

定义实体转换接口

由于需要对订单实体中的创建人id进行转换

public interface UserConvert {

    String USER_CACHE = "USER_CACHE";

    String userId();

    default ConvertItem getUserConvert(){
        if( userId() == null ){
            return null;
        }
        return new ConvertItem(userId(), USER_CACHE);
    }

}

定义接口转换适配器

基于上面UserConvert的处理,基于缓存实现,同时支持一个实体中多个,比如商品名称、商品分类等

public class UserConvertProvider extends CacheItemConvertAdapter {

    private static String name = UserConvert.USER_CACHE;

    public UserConvertProvider() {
        super(name, User.class);
    }

    @Override
    public boolean support(ConvertItem convertItem) {
        return convertItem != null && convertItem.getName().equals(name);
    }

    @Override
    public String convert(ConvertItem convertItem) {
        if( convertItem == null ){
            return null;
        }
        User user = (User) fromCache(convertItem.getId());
        return user != null ? user.getCaption() : null;
    }
}

需要转换的数据缓存

该实现依赖缓存,需要优先对需要转换的数据进行缓存,因此示例中添加了缓存示例

public void init(){
    Cache cache = cacheManager.getCache(UserConvert.USER_CACHE);
    if( cache != null ){
        cache.put("u1", new User("u1","Tom"));
    }
}

实体定义

实体中需要通过实现接口UserConvert,这样对多个数据项转换时可以继续扩展

public class Order implements UserConvert {

    private String id;

    private String name;

    private LocalDateTime createTime = LocalDateTime.now();

    /**
     * 创建用户
     */
    private String creator;

    @Override
    public String userId() {
        return creator;
    }
}

实现效果

可以看到,在输出json中,多了一列userConvert,也就是接口中定义的get*方法

{
    "id": "1",
    "name": "测试订单",
    "createTime": "2024-05-08T21:55:51.5747507",
    "creator": "u1",
    "userConvert": "Tom"
}

实现原理

上面说的,主要实现基于缓存,在web查询结果进行json序列化时,依赖于jackson的扩展,对输出结果匹配的类型进行转换。

@EnableCaching
@Configuration
public class JacksonCustomConfiguration{

    @Bean
    public Jackson2ObjectMApperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer(){
        return jacksonObjectMapperBuilder -> configureMapperBuilder(jacksonObjectMapperBuilder);
    }

    private void configureMapperBuilder(Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder) {
        jackson2ObjectMapperBuilder.serializers(convertSerializer());
    }

    @Bean
    public ItemConvertSerializer convertSerializer(){
        return new ItemConvertSerializer(ConvertItem.class);
    }
}
  1. 在配置文件中基于Jackson2ObjectMapperBuilderCustomizer对jackson进行扩展
  2. 定义ItemConvertSerializer对ConvertItem类型的属性进行处理,该类主要继承于StdSerializer
  3. 在ItemConvertSerializer中基于ConvertItem的name属性来匹配对应的缓存并进行转换
  4. 注意开启spring缓存*@EnableCaching*
  5. 最后基于spring特性,定义*/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports*来实现自动注入配置
  • ConvertItem示例
@Getter
@Setter
public class ConvertItem {

    private String id;

    private String text;

    private String name;

    public ConvertItem() {

    }

    public ConvertItem(String id, String name) {
        this.id = id;
        this.name = name;
    }
}
  • ItemConvertAdapter扩展适配器,主要于ConvertItem搭配扩展
public interface ItemConvertAdapter {

    /**
     * @param convertItem
     * @return
     */
    boolean support(ConvertItem convertItem);

    /**
     *
     * @param convertItem
     * @return
     */
    String convert(ConvertItem convertItem);

}
  • ItemConvertSerializer示例
public class ItemConvertSerializer extends StdSerializer<ConvertItem> implements ApplicationContextAware {

    private List<ItemConvertAdapter> itemConvertAdapters;

    public ItemConvertSerializer(Class<ConvertItem> t) {
        super(t);
    }

    @Override
    public void serialize(ConvertItem value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        String text = "";
        if(!CollectionUtils.isEmpty(itemConvertAdapters)){
            for (ItemConvertAdapter itemConvertAdapter : itemConvertAdapters) {
                if( itemConvertAdapter.support(value) ){
                    text = itemConvertAdapter.convert(value);
                    break;
                }
            }
        }
        gen.writeString(text);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, ItemConvertAdapter> itemConvertAdapterMap
                = BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ItemConvertAdapter.class, true, false);
        if( !itemConvertAdapterMap.isEmpty() ){
            itemConvertAdapters = new ArrayList<>(itemConvertAdapterMap.values());
            itemConvertAdapters.sort(OrderComparator.INSTANCE);
        }
    }
}

优缺点

  • 使用了jackson序列化的扩展,如果使用其他序列化工具,需要单独支持。
  • 依赖于数据缓存,一般针对通用数据才有数据转换的需要,比如用户、部门数据等,一般这些数据更适合缓存。


Tags:关联id   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
一招教你解决页面中关联id的转换
在工作中,我们经常有这样的业务情况,实体间通过id实现数据业务上的关联,比如订单和用户,订单的创建人id、商品id等,在页面查询时我们需要将对应的id信息转换成对应的中文描述,比如...【详细内容】
2024-05-17  Search: 关联id  点击:(0)  评论:(0)  加入收藏
▌简易百科推荐
一招教你解决页面中关联id的转换
在工作中,我们经常有这样的业务情况,实体间通过id实现数据业务上的关联,比如订单和用户,订单的创建人id、商品id等,在页面查询时我们需要将对应的id信息转换成对应的中文描述,比如...【详细内容】
2024-05-17    Java技术指北  Tags:关联id   点击:(0)  评论:(0)  加入收藏
Facebook背后的科技:从算法到人工智能的奥秘
Facebook作为全球最大的社交媒体平台,其背后涵盖了许多前沿科技,从复杂的算法到智能的人工智能系统。本文将深入探讨Facebook背后的科技奥秘,揭示其算法和人工智能技术在社交媒...【详细内容】
2024-05-15  田田甜字格    Tags:Facebook   点击:(2)  评论:(0)  加入收藏
中台过气、微服务回归单体,DDD的意义何在?
2015年之后,随着云原生、微服务、大中台等一系列技术名词诞生的同时,还有一个耳熟能详的名词“领域驱动”也开始被捧上神坛。笔者初次听到领域驱动是参加一个技术分享会,当时给...【详细内容】
2024-05-15    dbaplus社群  Tags:DDD   点击:(1)  评论:(0)  加入收藏
这一次,彻底搞懵 CRDT
我是前端西瓜哥,今天我们来简单入门一下 CRDT。CRDT 是什么?CRDT,全称为 conflict-free replicated data type(无冲突复制数据类型),它是一种数据类型,或者说是方案,确保在网络中的...【详细内容】
2024-05-15  前端西瓜哥  微信公众号  Tags:CRDT   点击:(3)  评论:(0)  加入收藏
Jenkins+Ansible+Gitlab 自动化部署三剑客
在快节奏的软件开发和运维环境中,自动化部署成为了提高效率、减少错误的关键环节。Jenkins、Ansible和GitLab作为自动化部署领域的佼佼者,被广大开发者亲切地称为“自动化部署...【详细内容】
2024-04-29  土豆切切切    Tags:自动化   点击:(8)  评论:(0)  加入收藏
什么是云原生,有哪些技术选型?
云原生(Cloud Native)是一种构建和运行应用程序的方法论,它代表着一种充分利用云计算模型的设计思想和工程实践。在云原生架构下,应用从设计之初就考虑到在分布式系统和云环境中...【详细内容】
2024-04-29  JaneYork    Tags:云原生   点击:(7)  评论:(0)  加入收藏
监控 Kafka,这十个指标请考虑!
使用消息队列可以帮助我们实现系统解耦、流量管控等功能。但使用过程中可能会遇到各种各样的问题,比如系统资源使用率高、集群节点宕机等,进而影响我们生产业务正常开展。为了...【详细内容】
2024-04-29  君哥聊技术  微信公众号  Tags:Kafka   点击:(16)  评论:(0)  加入收藏
引入缓存竟然会带来这么多问题?
哈喽,大家好呀,我是呼噜噜,最近很忙好久没更新了,今天我们通过缓存与数据库之间的一致性这个老生常谈的问题来切入,聊聊如何合理的设计一个缓存系统?如今互联网应用,无论是web还是...【详细内容】
2024-04-29  小牛呼噜噜  微信公众号  Tags:缓存   点击:(12)  评论:(0)  加入收藏
对DevOps的九大误解,是时候纠正了!
DevOps是开发和运维的结合,有助于集成和自动化测试过程以及部署存储库,还提供了透明度以及灵活性。DevOps的目标如下: 更快的上市时间(TTM); 减少各种修复之间的前置时间; 提高部...【详细内容】
2024-04-26  陈哥聊测试    Tags:DevOps   点击:(10)  评论:(0)  加入收藏
五种搭建LLM服务的方法和代码示例
在不断发展的大型语言模型(LLMs)领域中,用于支持这些模型的工具和技术正以与模型本身一样快的速度进步。在这篇文章中,我们将总结5种搭建开源大语言模型服务的方法,每种都附带详...【详细内容】
2024-04-23  DeepHub IMBA    Tags:LLM   点击:(17)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条