启动时自动查询码表存储至缓存–>根据注解识别带转码字段–>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
项目启动自动加载码表的实现逻辑
@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
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;
}



