数据库脚本
CREATE TABLE `data_dict` (
`id` bigint NOT NULL COMMENT '主键',
`dict_code` varchar(32) DEFAULT NULL COMMENT '字典编码',
`dict_name` varchar(64) DEFAULT NULL COMMENT '字典名称',
`dict_description` varchar(255) DEFAULT NULL COMMENT '字典描述',
`dict_status` tinyint DEFAULT NULL COMMENT '字典状态;0:禁用;1:启用',
`created_by` varchar(32) DEFAULT NULL COMMENT '创建人;姓名[域账号]',
`created_time` datetime DEFAULT NULL COMMENT '创建时间',
`updated_by` varchar(32) DEFAULT NULL COMMENT '更新人;姓名[域账号]',
`updated_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='数据字典';
INSERT INTO data_dict (id, dict_code, dict_name, dict_description, dict_status, created_by, created_time, updated_by, updated_time) VALUES(1889143437849174016, 'test', 'test', 'test', 1, 'xx', '2025-02-11 10:44:29', 'xx', '2025-02-11 10:44:29');
INSERT INTO data_dict (id, dict_code, dict_name, dict_description, dict_status, created_by, created_time, updated_by, updated_time) VALUES(1889143437849174017, 'test2', 'test2', 'test2', 1, 'xx', '2025-02-11 10:44:29', 'xx', '2025-02-11 10:44:29');
CREATE TABLE `data_dict_item` (
`id` bigint NOT NULL COMMENT '主键',
`dict_code` varchar(32) DEFAULT NULL COMMENT '字典编码',
`item_code` varchar(32) DEFAULT NULL COMMENT '条目编码',
`item_value` varchar(255) DEFAULT NULL COMMENT '条目值',
`item_description` varchar(255) DEFAULT NULL COMMENT '条目描述',
`item_status` tinyint DEFAULT NULL COMMENT '条目状态;0:禁用;1:启用',
`seq` int DEFAULT NULL COMMENT '序号',
`created_by` varchar(32) DEFAULT NULL COMMENT '创建人;姓名[域账号]',
`created_time` datetime DEFAULT NULL COMMENT '创建时间',
`updated_by` varchar(32) DEFAULT NULL COMMENT '更新人;姓名[域账号]',
`updated_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='数据字典条目';
INSERT INTO data_dict_item (id, dict_code, item_code, item_value, item_description, item_status, seq, created_by, created_time, updated_by, updated_time) VALUES(1889143437849174016, 'test', 'xxx', 'xx', 'xxx', 1, 1, 'xx', '2025-02-11 10:44:29', 'xx', '2025-02-11 10:44:29');
INSERT INTO data_dict_item (id, dict_code, item_code, item_value, item_description, item_status, seq, created_by, created_time, updated_by, updated_time) VALUES(1889143437849174017, 'test2', '111', '222', 'xxx', 1, 1, 'xx', '2025-02-11 10:44:29', 'xx', '2025-02-11 10:44:29');
INSERT INTO data_dict_item (id, dict_code, item_code, item_value, item_description, item_status, seq, created_by, created_time, updated_by, updated_time) VALUES(1889143437849174018, 'test2', '33', '44', 'xxx', 1, 1, 'xx', '2025-02-11 10:44:29', 'xx', '2025-02-11 10:44:29');
代码
package com.demo.dto.sys;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
/**
* 字典缓存
*
* @since 2025/02/11 上午 10:39
*/
@Data
@Accessors(chain = true)
public class DataDictItemCache implements Serializable {
@Serial
private static final long serialVersionUID = -2394718872868472043L;
/**
* 字典编码
*/
private String dictCode;
/**
* 条目编码
*/
private String itemCode;
/**
* 条目值
*/
private String itemValue;
/**
* 条目状态;0:禁用;1:启用
*/
private Integer itemStatus;
}
package com.demo.annotation;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.demo.config.DictSerializer;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 数据字典注解
*
* @since 2025/02/08 下午 01:41
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DictSerializer.class)
public @interface Dict {
/**
* 字典编码
*/
String dictCode();
}
// 使用方式如下
// @Data
// public class Test {
//
// @Dict(dictCode = "xxx")
// private String itemCode;
//
// private String other;
// }
// {
// "code": 200,
// "message": "操作成功",
// "result": {
// "itemCode": {
// "dictCode": "xxx",
// "itemCode": "111",
// "itemValue": "222",
// "itemStatus": 1
// },
// "other": null
// },
// "timestamp": "1739245075643"
// }
package com.demo.config;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
import com.demo.annotation.Dict;
import org.springframework.stereotype.Component;
import java.io.Serial;
/**
* 字典注解序列化拦截器
*
* @since 2025/02/08 下午 02:20
*/
@Component
public class DictAnnotationIntrospector extends NopAnnotationIntrospector {
@Serial
private static final long serialVersionUID = 5139608634773791712L;
@Override
public Object findSerializer(Annotated am) {
Dict dict = am.getAnnotation(Dict.class);
if (dict != null) {
return DictSerializer.class;
}
return null;
}
}
package com.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 修改被@Dict注解标注的属性字典序列化方式
*
* @since 2025/02/08 下午 02:22
*/
@Configuration
public class DictSerializerConfig {
@Autowired
private DictAnnotationIntrospector dictAnnotationIntrospector;
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> builder.annotationIntrospector(dictAnnotationIntrospector);
}
}
package com.demo.config;
import cn.hutool.extra.spring.SpringUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.demo.annotation.Dict;
import com.demo.service.sys.DataDictItemService;
import com.demo.dto.sys.DataDictItemCache;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.io.Serial;
import java.util.List;
/**
* 数据字典自定序列化类
*
* @since 2025/02/08 下午 02:18
*/
public class DictSerializer extends StdSerializer<Object> implements ContextualSerializer {
@Serial
private static final long serialVersionUID = -3774620761859983477L;
/**
* 字典编码
*/
private final String dictCode;
public DictSerializer() {
super(Object.class);
this.dictCode = null;
}
public DictSerializer(String dictCode) {
super(Object.class);
this.dictCode = dictCode;
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) {
Dict annotation = property.getAnnotation(Dict.class);
if (annotation != null) {
return new DictSerializer(annotation.dictCode());
}
return this;
}
@Override
public void serialize(Object itemCode, JsonGenerator gen, SerializerProvider provider) throws IOException {
DataDictItemCache itemCache = null;
if (StringUtils.isNotBlank(dictCode) && ObjectUtils.isNotEmpty(itemCode)) {
DataDictItemService service = SpringUtil.getBean(DataDictItemService.class);
List<DataDictItemCache> allItemCache = service.getDictItemCacheByDictCode(dictCode);
if (!CollectionUtils.isEmpty(allItemCache)) {
itemCache = allItemCache.stream()
.filter(item -> item.getItemCode().equals(itemCode))
.findFirst()
.orElse(null);
}
}
gen.writeObject(itemCache);
}
}