Spring Boot2.0之十 使用自定义注解、Json序列化器实现自动转换字典类型字段

news/2025/2/28 19:37:26/

前言

项目中经常需要后端将字典类型字段值的中文名称返回给前端。通过sql中关联字典表或者自定义函数不仅影响性能还不能使用mybatisplus自带的查询方法,所以推荐使用自定义注解、Json序列化器,Spring的缓存功能实现自动转换字典类型字段。以下实现SpringBoot版本为2.6.13。

一、自定义字典注解

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.common.utils.DictSerializer;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/**定义一个自定义注解,用于标识需要进行字典自动翻译的字段。**/
@Target({ElementType.FIELD}) //表示它只能应用在类的字段上。
@Retention(RetentionPolicy.RUNTIME) //确保注解在运行时可用。
@JacksonAnnotationsInside 
@JsonSerialize(using = DictSerializer.class)//指定使用DictSerializer来处理被注解字段的序列化,不加@Dict注解的字段不会被DictSerializer处理。
public @interface Dict {/*** 字典代码*/String type() default "";/*** 字段后缀*/String suffix() default "Name";
}

二、自定义Json序列化器

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.SneakyThrows;
import java.io.IOException;
import java.util.Objects;/**@Dict注解中引入了JsonSerializer,加了@Dict注解的字段的序列化会被DictSerializer处理。不能在DictSerializer 类上加@JsonComponent注解或者自定义配置类 JacksonConfig来注册Json序列化器,使用注解或配置类注册序列化器会使其全局生效,任何字段的序列化会被DictSerializer处理。**/
public class DictSerializer extends JsonSerializer<Object> {@SneakyThrows@Overridepublic void serialize(Object value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException {// 写入原字段的值gen.writeObject(value);if (Objects.nonNull(value)) {// 获取数据字典项服务实例// 不使用全局变量和在构造函数中获取Bean,延迟加载Bean,避免构造函数初始化空指针问题DictService dictService = SpringContextHolder.getBean(SysDictItemService.class);// 序列化字段名称String fieldName = gen.getOutputContext().getCurrentName();// 字典项注解对象Dict dictAnno = gen.getCurrentValue().getClass().getDeclaredField(fieldName).getAnnotation(Dict.class);String dictItemName = dictService.getDictItemName(dictAnno.type(), value);// 写入新字段名称gen.writeFieldName(fieldName + dictAnno.suffix());// 写入新字段的值gen.writeString(dictItemName);}}
}

三、Spring上下文工具类

@Component
public class SpringContextHolder implements ApplicationContextAware {private static ApplicationContext context;public static <T> T getBean(Class<T> clazz) {return context.getBean(clazz);}@Overridepublic void setApplicationContext(ApplicationContext ctx) {context = ctx;}
}

三、字典服务层(含缓存)

1.SpringBoot启动类上加@EnableCaching注解开启缓存功能

2.根据字典代码和字典项代码查询字典项名称

	/*** @Cacheable为SpringBoot自带的缓存注解,使用字典代码+字典项代码作为缓存的key,使用该注解会自动		   * 缓存getDictItemName方法的返回值。*/@Cacheable(value = "dictCache", key = "#dictCode+':'+#code")@Overridepublic String getDictItemName(String dictCode, Object code) {List<SysDictItem> itemList = ......;String value = null;if(CollectionUtils.isNotEmpty(itemList)){value = itemList.get(0).getItemName();}return Optional.ofNullable(value).orElse(code.toString());}

3.新增或修改字典项

 	 /*** @CachePut注解是SpringBoot自带的缓存注解,使用该注解在更新字典时会自动更新字典缓存,注意此处	* 的key要与getDictItemName方法@Cacheable注解中的key一致,saveOrUpdateDictItem方法必须要返回要* 缓存的内容,即字典项名称。*/@CachePut(value = "dictCache", key = "#dictItem.dictCode+':'+#dictItem.itemCode")@Overridepublic String saveOrUpdateDictItem(SysDictItem dictItem) {String itemName = null;int con;if(StringUtils.isBlank(dictItem.getItemId())){//新增con = baseMapper.insert(dictItem);} else {//修改con = baseMapper.updateById(dictItem);}if(con > 0){itemName = dictItem.getItemName();}return itemName;}

参考资料:
1.百度DeepSeek-R1满血版搜索结果
2.csdn收藏(Springboot)中的https://blog.csdn.net/hangbingbihai/article/details/145452376?spm=1001.2014.3001.5506
https://blog.csdn.net/demo_yo/article/details/129157902?spm=1001.2014.3001.5506


http://www.ppmy.cn/news/1575578.html

相关文章

云原生周刊:云原生和 AI

开源项目推荐 FlashMLA DeepSeek 于北京时间 2025 年 2 月 24 日上午 9 点正式开源了 FlashMLA 项目。FlashMLA 是专为 NVIDIA Hopper 架构 GPU&#xff08;如 H100、H800&#xff09;优化的高效多头潜在注意力&#xff08;MLA&#xff09;解码内核&#xff0c;旨在提升大模型…

如何实现日志采集以及存储以及问题排查

以下是10个可以实现从机器上采集日志并存储到HDFS或Elasticsearch&#xff08;ES&#xff09;中的开源项目推荐&#xff0c;这些项目可以帮助您高效地完成日志采集和存储任务&#xff0c;便于后续的问题排查&#xff1a; 1. **Apache Flume** Apache Flume 是一个分布式、…

计算机网络————(一)HTTP讲解

基础内容分类 从TCP/IP协议栈为依托&#xff0c;由上至下、从应用层到基础设施介绍协议。 1.应用层&#xff1a; HTTP/1.1 Websocket HTTP/2.0 2.应用层的安全基础设施 LTS/SSL 3.传输层 TCP 4.网络层及数据链路层 IP层和以太网 HTTP协议 网络页面形成基本 流程&#xff1a…

绕过信息过滤与注入限制

绕过 information_schema 过滤 information_schema 是 MySQL 中存储元数据的系统数据库&#xff0c;常用于 SQL 注入中获取表名、列名等信息。当 information_schema 被过滤时&#xff0c;可以通过以下方法绕过。 1 替代视图 使用 sys 库&#xff08;MySQL 5.7&#xff09; …

【Deepseek】根文件系统挂载在/dev/sda1下,如何对其扩容

1. 扩展虚拟磁盘大小 首先&#xff0c;需要在虚拟机管理工具中扩展虚拟磁盘的大小。以下是常见虚拟机工具的扩展方法&#xff1a; VMware: 关闭虚拟机。在 VMware 中右键虚拟机 -> 设置 -> 硬盘 -> 扩展&#xff0c;调整磁盘大小。启动虚拟机。 VirtualBox: 关闭虚拟…

【idea】关于idea中新建springboot项目Java版本不能选择11和8的解决办法

原因&#xff1a; spring2.X版本在2023年11月24日停止维护了&#xff0c;因此创建spring项目时不再有2.X版本的选项&#xff0c;只能从3.1.X版本开始选择 而Spring3.X版本不支持JDK8&#xff0c;JDK11&#xff0c;最低支持JDK17&#xff0c;因此JDK11也无法选择了 当然&…

Scala 字符串插值的简单介绍

在 Scala 中&#xff0c;字符串插值是通过在字符串前添加特定前缀实现的&#xff0c;主要有三种标准插值器&#xff1a;s、f 和 raw。它们的核心用法如下&#xff1a; 1. s 插值器&#xff08;简单插值&#xff09; 作用&#xff1a;将变量或表达式直接嵌入字符串。语法&#…

Python生成器250224

是由函数与yield关键字创造出来的写法&#xff0c;在特定情况下&#xff0c;可以帮助我们节省内存执行一个生成器函数&#xff0c;函数体代码不会运行&#xff0c;会返回一个生成器对象要想执行函数体内容&#xff0c;就需要使用这个生成器对象来执行 def func():print(123)yi…