在项目中,我们经常会使用到字典,数据库中保存字典编码,前端展示时需要显示字典名称。有很多方式可以实现,最简单粗暴的就是通过SQL关联查询,这种方式相对简单,但表的关联会一定程度上影响性能;另外一种方式是查询后,通过代码获取字典名称,我们可以将字典信息进行缓存提高效率,但这种方式对业务代码的入侵太多;还有一种方式是前端缓存字典信息,后端返回字典编码后再翻译为字典名称,这种方式需要考虑字典信息的一致性问题。
本文介绍的方案是在第二种方案基础上做了调整,尽可能减少对业务代码的入侵。
1、思路
我们获取获取字典名称只是为了在前端展示,实际业务处理中并不需要字典名称,因此是否可以将字典编码转名称这个工作放到最后一步(即实体序列化为JSON的时候)?通过搜索相关资料发现fasterxml(本文针对的fasterxml JSON序列化工具)提供了 com.fasterxml.jackson.databind.AnnotationIntrospector 抽象类,可以对序列化实体中的注解进行拦截,实现对字典的翻译(编码转名称)。好了,不废话,直接上代码。
2、定义注解@Dict
自定义一个注解,@Dict
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.FIELD,ElementType.METHOD})
public @interface Dict {
/**
* 数据字典类型
* @return
*/
String value() default "";
/**
* 数据字典名称属性名,翻译后字典名称保存的属性名称
* @return
*/
String name() default "";
}
3、AnnotationIntrospector.java
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
*
* @author Even
*/
public class DefaultAnnotationIntrospector extends JacksonAnnotationIntrospector {
private static final Logger logger =
LoggerFactory.getLogger(DefaultAnnotationIntrospector.class);
/**
* <自定义注解类名,注解处理类>
*/
private Map<String,AnnotationHandler> annotationHandlerMap;
@Override
public Object findSerializer(Annotated am) {
//如果没有设置任何注解处理类,则直接返回
if(annotationHandlerMap==null || annotationHandlerMap.isEmpty()) {
return super.findSerializer(am);
}
Iterator<Map.Entry<String,AnnotationHandler>> it =
annotationHandlerMap.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String,AnnotationHandler> entry = it.next();
//获取注解
Annotation an = getAnnotation(am,entry.getKey());
if(an != null){
String fieldName = am.getName();
//获取属性名
if(fieldName.startsWith("get")){
String first = String.valueOf(fieldName.charAt(3)).toLowerCase();
fieldName = first + fieldName.substring(4);
}
if(logger.isDebugEnabled()){
logger.debug("serialize {} by {}",fieldName,entry.getValue());
}
return new AnnotationJsonSerializer