您好,欢迎访问一九零五行业门户网

基于Springboot一个注解如何搞定数据字典

问题引出:最近开了新项目,项目中用到了数据字典,列表查询数据返回的时候需要手动将code转换为name,到前台展示。项目经理表示可以封装一个统一的功能,避免程序员各自写各自的,代码混乱,风格不统一。
要求:基于微服务架构,数据字典通过服务获取;
简化代码,使用简单;
使用redis;
方案大致的方向是自定义注解,在序列化的时候进行数据处理; 考虑到微服务,需要将主要逻辑放到common中,然后对外提供接口,各业务服务实现接口以获取字典数据; 考虑redis,序列化处理数据时,首先通过redis获取,获取不到在通过接口获取,拿到数据后存到redis中,然后再返回处理; 也可以多做一步,在新增、修改数据字典时,同步更新redis内容,以保证数据有效性。
实现定义注解
@target({elementtype.field})@retention(retentionpolicy.runtime)@jacksonannotationsinside@jsonserialize(using = dictserializer.class)public @interface dict { /** 字典类型 */ string type();}
指定注解添加位置
指定注解生效时间
指定序列化处理类
序列化处理类
public class dictserializer extends stdserializer<object> implements contextualserializer { /** 字典注解 */ private dict dict; public dictserializer() { super(object.class); } public dictserializer(dict dict) { super(object.class); this.dict = dict; } private string type; @override public void serialize(object value, jsongenerator gen, serializerprovider provider) throws ioexception { if (objects.isnull(value)) { gen.writeobject(value); return; } if (objects.nonnull(dict)){ type = dict.type(); } // 通过数据字典类型和value获取name gen.writeobject(value); gen.writefieldname(gen.getoutputcontext().getcurrentname()+"name"); gen.writeobject(label); } @override public jsonserializer<?> createcontextual(serializerprovider prov, beanproperty beanproperty) throws jsonmappingexception { if (objects.isnull(beanproperty)){ return prov.findvalueserializer(beanproperty.gettype(), beanproperty); } dict dict = beanproperty.getannotation(dict.class); if (objects.nonnull(dict)){ type = dict.type(); return this; } return prov.findnullvalueserializer(null); }}
这里处理的逻辑是原先的字段内容不变,添加一个新的字段用来存储转化后的值;
数据字典获取
private static string changelabel(string type,string code) { if(code.indexof(",") > -1) { string[] strs = code.split(","); if (strs.length > 1) { stringbuilder sb = new stringbuilder(); for (string str : strs) { // 从缓存中获取字典。如果不行,通过springutil.getbean(); 获取服务处理 sb.append(dictdatacache.getlabel(type, str)).append(separator); } return sb.substring(0, sb.length() - 1); } } // 从缓存中获取字典。如果不行,通过springutil.getbean(); 获取服务处理 return dictdatacache.getlabel(type, code);}
考虑存在多选的情况,先判断下是否是多选的,默认逗号拼接,后期添加入参控制;
@overridepublic string getdictdataoptions(string typecode,string value) { if (redistemplate.haskey("dict:"+typecode+":"+value)){ return (string) redistemplate.opsforvalue().get("dict:"+typecode+":"+value); } list<dictdataoptions> dictdatalist = getdictdatahandler().getdictdataoptions(typecode); if(collutil.isnotempty(dictdatalist)) { put(typecode, dictdatalist); } if (redistemplate.haskey("dict:"+typecode+":"+value)){ return (string) redistemplate.opsforvalue().get("dict:"+typecode+":"+value); } return null;}
根据key判断redis中是否存在,存在则直接获取,不存在则通过接口获取,获取到直接放到redis中,然后再次从redis获取。
protected void put(string typecode, list<dictdataoptions> datalist) { if (collutil.isnotempty(datalist)){ for (dictdataoptions dictdataoptions : datalist) { abstractdicthandler.redistemplate.opsforvalue().set("dict:"+typecode+":"+dictdataoptions.getdatalabel(),dictdataoptions.getdatavalue()); } }}
循环放置数据字典值
@overridepublic list<dictdataoptions> getdictdataoptions(string typecode) { return isysdictservice.querydictitemsbycode(typecode).stream() .map(e -> dictdataoptions.builder().typecode(typecode).datalabel(e.getvalue()).datavalue(e.gettext()).build()) .collect(collectors.tolist());}
根据数据字典类型,通过接口获取数据;注意该实现类需要每个微服务实现一个;然后为了避免基础数据服务挂掉,调用报错,common中提供一个默认实现。
4.使用
@dict(type = "inspecttype")private string checktype;
在返回前端的实体中,对应字段添加注解,并指定数据字典type值
{ "id": "1522492702905954306", "professionname": "专业名称888", "checkcode": "检测项编码8", "checkproject": "rrrr检测项目88", "checkdevice": "52", "checkstandard": "检测项编码88", "referencestandard": "wq参考标准8", "checktype": "1", "checktypename": "尺寸", "remarks": "ef备注备注8" },
前端获取的json会多一个字段:checktypename,内容为checktype 的中文值。
以上就是基于springboot一个注解如何搞定数据字典的详细内容。
其它类似信息

推荐信息