数据库脚本
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) ;
}
}