栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot基于jackson序列化的字典表转换的注解实现

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot基于jackson序列化的字典表转换的注解实现

基本实现流程

启动时自动查询码表存储至缓存–>根据注解识别带转码字段–>jackson序列化时自动去缓存中获取待转码的值。
本项目采用reids缓存

创建转码注解
@Target({FIELD})
@Retention(RUNTIME)
@Documented
@JacksonAnnotationsInside
@JsonSerialize(using = JacksonTranscodingSerializer.class)
public @interface JacksonTranscoding {

    
    String group();

}
自动转码的系列化实现

代码中涉及到的Constants为项目中自定义的一些常量,自己随意定义即可

public class JacksonTranscodingSerializer extends StdSerializer implements ContextualSerializer {


    private String redisKeyPer;

    public JacksonTranscodingSerializer(){
        super(String.class);
    }
    public JacksonTranscodingSerializer(String key) {
        super(String.class);
        this.redisKeyPer = key;
    }

    @Override
    public JsonSerializer createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        if (beanProperty != null) {
            if (beanProperty.getType().getRawClass().equals(String.class)) {
                JacksonTranscoding annotation = beanProperty.getAnnotation(JacksonTranscoding.class);
                if (annotation == null) {
                    return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
                } else {
                    String redisKey = Constants.DICT_PER + annotation.group();
                    return new JacksonTranscodingSerializer(redisKey);
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(beanProperty);
    }

    @Override
    public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        //该项目中通过redis缓存码表,根据项目实现修改下面获取转码值的代码
        Object value = SpringUtil.getBean(RedisService.class).get(redisKeyPer + ":" + s);
        if (value == null) {
            //字典不存在则使用原来值
            jsonGenerator.writeString(s);
        } else {
            jsonGenerator.writeString((String) value);
        }
    }

}
自动查询数据库并将转码对应关系缓存至缓存的注解
@Target({METHOD})
@Retention(RUNTIME)
@Documented
public @interface TranscodingStatement {


    
    String codeField();

    
    String valueField();

    
    String group() default "";

}

使用示例:

public interface TranscodingMapper {

    @TranscodingStatement(group = "ent_status", codeField = "code",valueField = "name")
    List code_ex02();

}
项目启动自动加载码表的实现逻辑
@Component
@Slf4j
public class TranscodingComponet implements ApplicationRunner {

    @Resource
    private TranscodingMapper transcodingMapper;
    @Resource
    private RedisService redisService;


    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("==========开始加载码表数据至redis!======");
        //额 还没有加扫描所有mapper的代码,感觉写在一个mapper里就可以了,因此在这里指定了mapper的名称
        //获取带有@TranscodingStatement注解的方法
        List publicMethods = ClassUtil.getPublicMethods(TranscodingMapper.class, (method) -> {
            TranscodingStatement annotation = method.getAnnotation(TranscodingStatement.class);
            method.getReturnType();
            return annotation != null;
        });
        //仅执行返回结果会处理list,具体内容会根据map(调用get方法)和entity(直接获取属性值)单独处理
        for (Method method : publicMethods) {
            TranscodingStatement annotation = method.getAnnotation(TranscodingStatement.class);
            String keyPer = Constants.DICT_PER + (StrUtil.isEmpty(annotation.group()) ? method.getName() + "-" : annotation.group() + ":");
            Object res = method.invoke(transcodingMapper);
            if (res instanceof List) {
                List list = (List) res;
                for (Object obj : list) {
                    setDictionaryCache(obj, annotation, keyPer);
                }
            } else {
                setDictionaryCache(res, annotation, keyPer);
            }
        }
        log.info("==========码表数据加载至redis完成!本次操作缓存了{}张码表数据======", publicMethods.size());
    }

    
    private void setDictionaryCache(Object obj, TranscodingStatement annotation, String redisKeyPer) {
        Object key;
        Object value;
        if (obj instanceof Map) {
            //处理大小写的问题,oracle查询select*时map的key默认为大写
            key = ((Map) obj).get(annotation.codeField());
            key = key == null?((Map) obj).get(annotation.codeField().toUpperCase()):key;
            value = ((Map) obj).get(annotation.valueField());
            value = value == null?((Map) obj).get(annotation.valueField().toUpperCase()):value;
        } else {
            key = BeanUtil.getFieldValue(obj, annotation.codeField());
            value = BeanUtil.getFieldValue(obj, annotation.valueField());
        }
        redisService.set(redisKeyPer + key, value);
    }
}
使用

添加完上述代码后就完成了所有的准备工作了。
1:在mapper中添加查询的方法
使用示例:
mapper接口如下

public interface TranscodingMapper {

    @TranscodingStatement(group = "ent_status", codeField = "code",valueField = "name")
    List code_ex02();

}

xml如下

	

2:在实体类待转码属性上添加注解即可

@ApiModel(value = "企业基础信息表")
@Data
@TableName(value = "ENT_BASE_INFO")
public class EntBaseInfo implements Serializable {
    private static final long serialVersionUID = 7809446069751653511L;

	
    @TableField(value = "ENTSTATUS_NAME")
    @ApiModelProperty(value = "企业状态")
    @JacksonTranscoding(group = "ent_status")
    private String entstatusName;
    
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/995204.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号