思路:
使用aop的拦截器拦截所有controller的所有返回类型为Ajaxresult和TableDataInfo的方法,查询其内的全部T实体对象,查找添加了@Dict注解的属性,每个属性去查询一遍字典值,再重新注入T实体对象返回。
Dict.java
package com.leomoon.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author: limaopeng
* 需要引入DictAspect.java拦截器往Controller的TableDataInfo和AjaxResult返回结果的实体注入字典翻译
* @Description:
* @Date: 2020/11/20
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Dict {
/**
* 方法描述:数据类型dictType
* @return 返回类型: String
*/
String dictType();
/**
* 方法描述:这是返回后Put到josn中的文本key值
* @return 返回类型: String
*/
String dictLabel() default "";
}
DictAspect.java
package com.leomoon.common.interceptor;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.leomoon.common.annotation.Dict;
import com.leomoon.common.core.domain.AjaxResult;
import com.leomoon.common.core.domain.TableDataInfo;
import com.leomoon.commoon.DictDataFeign;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* @Author: limaopeng
* @Description:
* @Date: Create in 11:26 2020/11/20
*/
@Aspect
@Component
@Slf4j
public class DictAspect {
//表对应字段加上DictLabel即可显示出文本
private static String DICT_TEXT_SUFFIX = "_DictLabel";
@Autowired
private DictDataFeign dictDataFeign;
/**
* 定义切点Pointcut拦截所有对服务器的请求
*/
@Pointcut("execution(* com.leomoon..controller..*(..))")
public void excudeService() {
}
/**
* 这是触发DictionariesService的时候会执行的,在环绕通知中目标对象方法被调用后的结果进行再处理
* @param pjp
* @return
* @throws Throwable
*/
@Around("excudeService()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
//这是定义开始事件
long time1 = System.currentTimeMillis();
//这是方法并获取返回结果
Object result = pjp.proceed();
//这是获取到结束时间
long time2 = System.currentTimeMillis();
log.info("获取JSON数据耗时:" + (time2 - time1) + "ms");
//解析开始时间
long start = System.currentTimeMillis();
//开始解析(翻译字段内部的值凡是打了@Dict这玩意的都会被翻译)
this.parsedictLabel(result);
//解析结束时间
long end = System.currentTimeMillis();
log.info("解析注入JSON数据耗时:" + (end - start) + "ms");
return result;
}
private void parsedictLabel(Object result) {
if (result instanceof TableDataInfo) {
List<JSONObject> items = new ArrayList<>();
TableDataInfo pageUtils = (TableDataInfo) result;
//循环查找出来的数据
for (Object record : pageUtils.getRows()) {
ObjectMapper mapper = new ObjectMapper();
String json = "{}";
try {
//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
json = mapper.writeValueAsString(record);
} catch (JsonProcessingException e) {
log.error("Json解析失败:" + e);
}
JSONObject item = JSONObject.parseObject(json);
//解决继承实体字段无法翻译问题
for (Field field : getAllFields(record)) {
//解决继承实体字段无法翻译问题
if (field.getAnnotation(Dict.class) != null) {
//如果该属性上面有@Dict注解,则进行翻译
String dictType = field.getAnnotation(Dict.class).dictType();//拿到注解的dictType属性的值
String text = field.getAnnotation(Dict.class).dictLabel();//拿到注解的dictLabel属性的值
//获取当前带翻译的值
String key = String.valueOf(item.get(field.getName()));
//翻译字典值对应的text值
String textValue = translateDictValue(dictType, key);
//DICT_TEXT_SUFFIX的值为,是默认值:
//public static final String DICT_TEXT_SUFFIX = "_dictLabel";
log.debug("字典Val: " + textValue);
log.debug("翻译字典字段:" + field.getName() + DICT_TEXT_SUFFIX + ": " + textValue);
//如果给了文本名
if (!StringUtils.isBlank(text)) {
item.put(text, textValue);
} else {
//走默认策略
item.put(field.getName() + DICT_TEXT_SUFFIX, textValue);
}
}
//date类型默认转换string格式化日期
if (field.getType().getName().equals("java.util.Date") && field.getAnnotation(JsonFormat.class) == null && item.get(field.getName()) != null) {
SimpleDateFormat aDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
}
}
items.add(item);
}
pageUtils.setRows(items);
} else if (result instanceof AjaxResult) {
AjaxResult bean = (AjaxResult) result;
//循环查找出来的数据
Object record = bean.getData();
ObjectMapper mapper = new ObjectMapper();
String json = "{}";
try {
//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
json = mapper.writeValueAsString(record);
} catch (JsonProcessingException e) {
log.error("Json解析失败:" + e);
}
JSONObject item = JSONObject.parseObject(json);
//解决继承实体字段无法翻译问题
for (Field field : getAllFields(record)) {
//解决继承实体字段无法翻译问题
if (field.getAnnotation(Dict.class) != null) {
//如果该属性上面有@Dict注解,则进行翻译
String dictType = field.getAnnotation(Dict.class).dictType();//拿到注解的dictType属性的值
String text = field.getAnnotation(Dict.class).dictLabel();//拿到注解的dictLabel属性的值
//获取当前带翻译的值
String key = String.valueOf(item.get(field.getName()));
//翻译字典值对应的text值
String textValue = translateDictValue(dictType, key);
//DICT_TEXT_SUFFIX的值为,是默认值:
//public static final String DICT_TEXT_SUFFIX = "_dictLabel";
log.debug("字典Val: " + textValue);
log.debug("翻译字典字段:" + field.getName() + DICT_TEXT_SUFFIX + ": " + textValue);
//如果给了文本名
if (!StringUtils.isBlank(text)) {
item.put(text, textValue);
} else {
//走默认策略
item.put(field.getName() + DICT_TEXT_SUFFIX, textValue);
}
}
//date类型默认转换string格式化日期
if (field.getType().getName().equals("java.util.Date") && field.getAnnotation(JsonFormat.class) == null && item.get(field.getName()) != null) {
SimpleDateFormat aDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
}
}
bean.setData(record);
}
}
/**
* 翻译字典文本
* @param dictType
* @param key
* @return
*/
private String translateDictValue(String dictType, String key) {
//如果key为空直接返回就好了
if (isEmpty(key)) {
return null;
}
StringBuffer textValue = new StringBuffer();
//分割key值
String[] keys = key.split(",");
//循环keys中的所有值
for (String k : keys) {
String tmpValue = null;
log.debug("字典key:" + k);
if (k.trim().length() == 0) {
continue;//跳过循环
}
tmpValue = dictDataFeign.dataLabel(dictType, k.trim());
if (tmpValue != null) {
if (!"".equals(textValue.toString())) {
textValue.append(",");
}
textValue.append(tmpValue);
}
}
//返回翻译的值
return textValue.toString();
}
public static Field[] getAllFields(Object object) {
Class<?> clazz = object.getClass();
List<Field> fieldList = new ArrayList<>();
while (clazz != null) {
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
clazz = clazz.getSuperclass();
}
Field[] fields = new Field[fieldList.size()];
fieldList.toArray(fields);
return fields;
}
public static boolean isEmpty(Object object) {
if (object == null) {
return (true);
}
if ("".equals(object)) {
return (true);
}
if ("null".equals(object)) {
return (true);
}
return (false);
}
}
User.java
package com.leomoon.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.leomoon.common.annotation.Dict;
import lombok.Data;
/**
*
* @author limaopeng
* @date 2020-11-08 16:32
*/
@Data
@TableName("user")
public class EmphasisObject{
@TableId(type = IdType.UUID)
private String id;
@Dict(dictType="user_type",dictLabel = "userTypeLabel")
private String userType;
}
4.返回结果
json:
{
"id": "1",
"userType": "1",
"userTypeLabel": "普通用户"
}