前言场景正文
一 添加配置二 添加项目内省器三 自定义序列化规则四 字典缓存工具五 测试对象六 测试接口七 测试结果 总结
前言在前后端分离的项目中,存在很多字段是下拉框选项的情况。
比如:性别字段
在数据库中,存的是代码值,前端显示的时候,需要显示值。这时候,在返回的时候,就需要做一次代码转换。
(为什么不是前端自己转换?为了统一管理和方便变更。)
字典字段为空,则不转换。一个对象中的多个字段是字典字段。对象中的子对象也有字典字段。对象的子对象是集合,也存在字典字段。 正文
因为在业务开发过程中,存在非常多的这种实体,所以需要制定一个统一处理。减少业务开发的工作量。
(最终结果,减少到只需要一行注解)
项目中都有 fasterxml 的依赖吧,没有自己添加。
添加类 JacksonConfig,用于配置自定义内省器。
import com.cah.project.conf.serializer.ProjectJacksonAnnotationIntrospector; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; @Configuration public class JacksonConfig { public JacksonConfig() {} @Bean @Primary @ConditionalOnMissingBean({ObjectMapper.class}) public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.createXmlMapper(false).build(); // 定义 不为空,才能进行序列化 objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 添加 自定义 项目注解内省器 objectMapper.setAnnotationIntrospector(new ProjectJacksonAnnotationIntrospector()); return objectMapper; } }二 添加项目内省器
import com.cah.project.core.annotation.Dict; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; public class ProjectJacksonAnnotationIntrospector extends JacksonAnnotationIntrospector { public ProjectJacksonAnnotationIntrospector() {} @Override public Object findSerializer(Annotated a) { // 如果是字典注解 Dict dict = _findAnnotation(a, Dict.class); if(dict != null) { return new DictSerializer(dict.type(), dict.separator()); } // 其他扩展。。。 return super.findSerializer(a); } }
其中 Dict 注解类 为自定义注解。内容如下:
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) public @interface Dict { String type(); String desc() default ""; String separator() default ","; }三 自定义序列化规则
import com.cah.project.core.cache.DictCacheUtil; import com.cah.project.core.domain.bo.DictData; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.IOException; public class DictSerializer extends StdSerializer四 字典缓存工具
字典缓存工具,使用的是hutool工具包中的缓存。
至于缓存如何清理与同步,这是另外一个问题。也可以从redis中获取缓存。
缓存是为了加快转换速度。各自发挥就好了。
import cn.hutool.cache.Cache; import cn.hutool.cache.CacheUtil; import com.cah.project.core.domain.bo.DictData; import java.util.HashMap; import java.util.Map; public class DictCacheUtil { protected static Cache五 测试对象> dictCache = CacheUtil.newLFUCache(10000); public static void put(String type, DictData dd) { Map map = dictCache.get(type); if(map == null) { map = new HashMap<>(); dictCache.put(type, map); } map.put(dd.getValue(), dd); } public static DictData get(String type, String value) { Map map = dictCache.get(type); if(map == null) { return new DictData(type, value, value); } return map.getOrDefault(value, new DictData(type, value, value)); } public static String getLabel(String type, String value) { Map map = dictCache.get(type); if(map == null) { return value; } DictData dd = map.get(value); return dd != null ? dd.getLabel() : value; } }
测试对象为返回的实体对象。其中字段字段都添加了 @Dict 注解
import com.cah.project.core.annotation.Dict; import lombok.Data; import java.io.Serializable; import java.util.List; @Data public class TestOutVO implements Serializable { private String name; @Dict(type = "STATUS_CD") private String status; @Dict(type = "SEX_CD") private String sex; private Listchildren; }
import com.cah.project.core.annotation.Dict; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @Data @Builder @NoArgsConstructor @AllArgsConstructor public class ChildOutVO { private String name; @Dict(type = "TYPE_CD") private Integer type; @Dict(type = "SEX_CD") private String sex; }六 测试接口
import cn.hutool.core.collection.ListUtil; import com.cah.project.core.domain.out.CommonResult; import com.cah.project.test.out.ChildOutVO; import com.cah.project.test.out.TestOutVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Lazy; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @Api(tags = {"测试 控制层"}) @RestController @RequestMapping("/test") @RequiredArgsConstructor(onConstructor_ = {@Lazy}) public class TestController { @GetMapping("getById") @ApiOperation(value="测试获取数据") public CommonResult七 测试结果 总结getById(@RequestParam("id") String id){ TestOutVO outVO = new TestOutVO(); outVO.setName("名称"); outVO.setStatus("1"); outVO.setSex("0,1"); ChildOutVO c1 = ChildOutVO.builder().name("子1").type(2).sex("0").build(); ChildOutVO c2 = ChildOutVO.builder().name("子2").type(3).sex("1").build(); List list = ListUtil.toList(c1, c2); outVO.setChildren(list); return CommonResult.data(outVO); } }
通过以上的方式,可以解放业务开发过程中反复的字典映射 *** 作。但是也存在一些问题。比如复杂的转换,非缓存数据转换等。
对于以上问题,可以使用 @JsonSerialize(using = XxxSerializer.class)
的方式进行处理。
代码地址
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)