序言
在我们日常开发中,时常会遇到需要字典翻译的情况,那么如何优雅的实现字典翻译呢?本文将介绍通过注解的方式,在序列化返回前端时,进行字典翻译。
需求背景
因为公司的业务表存的字典的id,所以字典翻译以此需求背景来开发。
依赖引入
1.集成spring-cache+redis作为我们缓存方案,翻译时,从缓存取数据,具体集成过程不过多赘述,感兴趣可以看我另外的分享文章。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
新增自定义注解
1.在@DictCode注解中,可以指定翻译后的字段名称。
@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD})
@JsonSerialize(using = DictSerialize.class)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JacksonAnnotation
public @interface DictCode {
String fieldName() default "";
}
实现json序列化接口
1.如果不指定fieldName属性,则默认使用原字段名 + "Name"作为翻译后的字段名称。
2.如果指定了fieldName属性,则使用指定的字段名称作为翻译后的字段名称。
3.前端直接取fieldName属性中定义的字段即可。
在序列化过程中,DictSerialize序列化器会根据@DictCode注解的配置,远程调用字典服务获取翻译后的字段值,并将其添加到JSON中。
通过使用@DictCode注解,您可以方便地对需要进行字典翻译的字段进行配置,并在序列化过程中自动获取翻译后的字段值。
注:无需定义翻译后的字段,添加注解后,在序列化时,自动新增一个跟注解里面的fieldName名称相同的字段。如果没定义,默认是使用原字段名 + "Name"作为翻译后的字段名称。
package cn.healthlink.bmc.master.common.serialize;
import cn.healthlink.bmc.master.common.annotation.DictCode;
import cn.healthlink.bmc.system.api.feign.DictFeignClient;
import cn.healthlink.bmc.system.api.vo.DictVO;
import cn.springsoter.core.tool.api.R;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.boot.jackson.JsonComponent;
import java.io.IOException;
import java.util.Objects;
/**
* @author HXQ
*/
@JsonComponent
@Slf4j
public class DictSerialize extends JsonSerializer<Long> implements ContextualSerializer {
private final DictFeignClient dictFeignClient;
String fieldName = "";
public DictSerialize(DictFeignClient dictFeignClient) {
this.dictFeignClient = Objects.requireNonNull(dictFeignClient, "dictFeignClient must not be null");
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty property) {
//获取该字段上的dict注解
DictCode dict = property.getAnnotation(DictCode.class);
if (dict != null && StringUtils.isNotBlank(dict.fieldName())) {
this.fieldName = dict.fieldName();
} else {
this.fieldName = property.getName() + "Name";
}
log.info("字典序列化时,字段名称:{}", fieldName);
return this;
}
@Override
public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeNumber(value);
try {
R<DictVO> dict = dictFeignClient.getDict(value);
if (dict != null && dict.getData() != null) {
log.info("字典值为:{}", dict.getData());
gen.writeStringField(fieldName, dict.getData().getName());
}
} catch (Exception e) {
log.error("远程调用获取字典内容失败", e);
//处理远程调用异常,提供默认值或写入空值
gen.writeStringField(fieldName, " ");
}
}
}