注解以及基础类说明
实体注解:Translate
将注解标记在翻译结果存取字段,eg:需将commodityCode翻译结果赋值到commodityName字段上,则在commodityName加注解,指定需要翻译的字段名.不指定默认需要翻译的字段为本字段并且翻译结果覆盖本字段。
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Translate {
// 需要翻译的字段名称
String code() default "";
// 日期格式
String datePartten() default DateUtilConstant.NORM_DATETIME_PATTERN;
/**
* 数据字典类型(对应dictionary表code字段,多个以英文状态下的逗号分割,数据字典翻译必传!!!)
*
* @return
*/
String[] dictionaryType() default "";
/**
* 是否批量翻译字符串,多个值用英文状态下逗号","进行分割 如 1,2,3
*
* @return
*/
boolean whetherStr() default false;
/**
* 需要翻译的枚举信息,需implements EnumUtils.IEnum
* {@link com.ltd.cloud.meteorological.common.utils.EnumUtils}
*
* @return
*/
Class EnumClaz() default Void.class;
/**
* 翻译类型
* {@link com.ltd.cloud.meteorological.biz.translate.constant.TranslateConstant}
*
* @return
*/
int type();
}
Type常量类:TranslateConstant
public class TranslateConstant {
private TranslateConstant() {
}
/**
* 用户单位(key:用户单位id,value:用户单位名称)
*/
public static final int USER_UNIT = 1;
/**
* 枚举(需实现EnumUtils.IEnum<C, M>)
*/
public static final int ENUM_CLAZ = 2;
/**
* 数据字典(key:数据字典value,value:数据字典dict_desc)
*/
public static final int DICTION = 3;
/**
* 日期(指定格式常量类:DateUtilConstant)
*/
public static final int DATE = 4;
/**
* 地区
*/
public static final int DIVISION = 5;
}
枚举工具类:EnumUtils
public class EnumUtils {
/**
* 根据code获取枚举类的值
* @param enumType 枚举类
* @param code 枚举值
* @param <C> 枚举值类
* @param <T> 对应值类
* @return 返回整个枚举
*/
public static <C, T extends IEnum<Integer, String>> T getEnumValue(Class<T> enumType, C code) {
try {
//如果是枚举类型 则调用values方法
if (enumType.isEnum()) {
Method values = enumType.getDeclaredMethod("values");
T[] ts = (T[]) values.invoke(null);
for (T t : ts) {
if (code.equals(t.getCode())) {
return t;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 根据code获取枚举Code
*
* @param enumType 枚举类型
* @param code 枚举值
* @param <C> 编码类
* @param <T> 对应值类
* @return 对应值
*/
public static <C, T extends IEnum<Object, String>> String getMessageByCode(Class<T> enumType, C code) {
try {
if (enumType.isEnum()) {
Method m = enumType.getDeclaredMethod("values");
T[] ts = (T[]) m.invoke(null);
for (T t : ts) {
if (code.equals(t.getCode())) {
return t.getMessage();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public interface IEnum<C, M> { //如果是成员方法共通,可以抽象为接口或把属性也加上变为抽象类,这里以接口为例子
/**
* 获取枚举值
* @return 枚举值
*/
C getCode();
/**
* 获取对应值
* @return 对应值
*/
M getMessage();
}
}
基础实体:TranslateEntity
@Data
@ApiModel("翻译实体")
public class TranslateEntity {
@ApiModelProperty("翻译类型")
private Integer translateType;
@ApiModelProperty("翻译字段,key-需要翻译的字段 value-接收翻译值字段")
private Pair<String, String> pair;
@ApiModelProperty("数据字典类型(对应dictionary表code字段)")
private String[] dictionaryType;
@ApiModelProperty("枚举类")
private Class enumClass;
@ApiModelProperty("翻译字段信息")
private Field field;
@ApiModelProperty("翻译结果字段信息")
private Field translateField;
@ApiModelProperty("是否批量翻译字符串")
private Boolean whetherStr;
@ApiModelProperty("日期格式")
private String datePartten;
}
翻译对象实体:TranslateObjectEntity
@Data
@ApiModel("翻译对象实体")
public class TranslateObjectEntity {
@ApiModelProperty("翻译信息实体")
private List<TranslateEntity> translateInfo;
@ApiModelProperty("对象信息")
private Class<?> aClass;
@ApiModelProperty("部门信息")
private Map<Long, String> userUnits;
@ApiModelProperty("字典信息(Map<code_value,dictDesc>)")
private Map<String, String> dictions;
}
翻译工具类:TranslateUtils
@Slf4j
public class TranslateUtils {
private static UserUnitService userUnitService = SpringContextHolder.getBean(UserUnitService.class);
private static DivisionService divisionService = SpringContextHolder.getBean(DivisionService.class);
/**
* 根据code翻译字段名称
*
* @param list 需要翻译的集合
*/
public static <T> void translateList(List<T> list) {
if (CollectionUtil.isEmpty(list)) {
return;
}
TranslateObjectEntity info = getObjectInfo(list.get(0));
if (ObjectUtil.isEmpty(info)) {
return;
}
for (T obj : list) {
translateObject(obj, info);
}
}
/**
* 根据code翻译字段名称(转化为指定实体集合)
*
* @param list 需要翻译的集合
*/
public static <T, R> List<R> translateList(List<T> list, Class<R> targetClazz) {
List<R> targrts = new ArrayList<>();
if (CollectionUtil.isEmpty(list)) {
return targrts;
}
TranslateObjectEntity info = null;
for (T obj : list) {
R targetObj = BeanUtil.copyProperties(obj, targetClazz);
if (ObjectUtil.isEmpty(info)) {
info = getObjectInfo(targetObj);
}
translateObject(targetObj, info);
targrts.add(targetObj);
}
return targrts;
}
/**
* 翻译单个实体
*
* @param obj 实体信息
* @param <T>
*/
public static <T> void translateObject(T obj) {
if (ObjectUtil.isEmpty(obj)) {
return;
}
TranslateObjectEntity info = getObjectInfo(obj);
if (ObjectUtil.isEmpty(info)) {
return;
}
translateObject(obj, info);
}
/**
* 翻译单个实体
*
* @param obj 实体信息
* @param targetClazz 需返回的实体class
* @param <T> 原实体
* @param <R> 返回实体
* @return
*/
public static <T, R> R translateObject(T obj, Class<R> targetClazz) {
if (ObjectUtil.isEmpty(obj) || ObjectUtil.isEmpty(targetClazz)) {
return null;
}
R properties = BeanUtil.copyProperties(obj, targetClazz);
TranslateObjectEntity info = getObjectInfo(properties);
if (ObjectUtil.isEmpty(info)) {
return null;
}
translateObject(properties, info);
return properties;
}
/**
* 翻译单个对象(获取需要翻译的对象实体信息)
*
* @param obj 对象信息
* @param <T> 对象字段翻译信息
*/
private static <T> TranslateObjectEntity getObjectInfo(T obj) {
if (ObjectUtil.isEmpty(obj)) {
return null;
}
Class<?> aClass = obj.getClass();
TranslateObjectEntity objectEntity = new TranslateObjectEntity();
objectEntity.setAClass(aClass);
Map<String, Field> fields = getAllFileds(aClass);
List<TranslateEntity> translateInfo = new ArrayList<>();
TranslateEntity translateEntity = null;
Pair<String, String> pair = null;
// 用户单位
Map<Long, String> userUnits = null;
// 数据字典
Map<String, String> dictions = null;
List<String> dictionsCodes = new ArrayList<>();
for (Field field : fields.values()) {
if (field.isAnnotationPresent(Translate.class)) {
translateEntity = new TranslateEntity();
translateEntity.setTranslateField(field);
Translate annotation = field.getAnnotation(Translate.class);
String translateCode = annotation.code();
if (StringUtils.isBlank(translateCode)) {
translateCode = field.getName();
}
translateEntity.setField(fields.get(translateCode));
int translateType = annotation.type();
pair = Pair.of(translateCode, field.getName());
translateEntity.setTranslateType(translateType);
translateEntity.setPair(pair);
if (TranslateConstant.ENUM_CLAZ == translateType) {
translateEntity.setEnumClass(annotation.EnumClaz());
}
if (TranslateConstant.USER_UNIT == translateType && CollUtil.isEmpty(userUnits)) {
userUnits = getUserUnits();
}
if (TranslateConstant.DICTION == translateType && CollUtil.isEmpty(dictions)) {
String[] dictionaryType = annotation.dictionaryType();
List<String> strings = Arrays.asList(dictionaryType);
if (CollUtil.isEmpty(strings)) {
Asserts.fail("数据字典类型不能为空");
}
dictionsCodes.addAll(strings);
translateEntity.setDictionaryType(annotation.dictionaryType());
}
if (TranslateConstant.DATE == translateType) {
translateEntity.setDatePartten(annotation.datePartten());
}
translateEntity.setWhetherStr(annotation.whetherStr());
translateInfo.add(translateEntity);
}
}
dictions = getDictions(dictionsCodes);
objectEntity.setUserUnits(userUnits);
objectEntity.setDictions(dictions);
objectEntity.setTranslateInfo(translateInfo);
return objectEntity;
}
/**
* 获取所有字段含父级
*
* @param aClass 实体类
* @return 所有字段信息
*/
private static Map<String, Field> getAllFileds(Class<?> aClass) {
Map<String, Field> fileds = new HashMap<>();
List<Field> fieldList = new ArrayList<>();
Class tempClass = aClass;
//当父类为null的时候说明到达了最上层的父类(Object类).
while (tempClass != null) {
fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
tempClass = tempClass.getSuperclass(); //得到父类,然后赋给自己
}
for (Field field : fieldList) {
fileds.put(field.getName(), field);
}
return fileds;
}
/**
* 翻译单个实体
*
* @param obj 实体信息
* @param info 翻译对象信息
* @param <T>
*/
private static <T> void translateObject(T obj, TranslateObjectEntity info) {
try {
// 地区信息集合
Map<String, String> areasInfo = new HashMap<>();
for (TranslateEntity entity : info.getTranslateInfo()) {
Integer type = entity.getTranslateType();
Field field = entity.getField();
field.setAccessible(true);
Object codeInfo = field.get(obj);
Field translate = entity.getTranslateField();
translate.setAccessible(true);
if (null == codeInfo) {
continue;
}
Object value = null;
String key = codeInfo.toString();
switch (type) {
case TranslateConstant.USER_UNIT:
// 用户单位
if (info.getUserUnits().containsKey(Long.parseLong(key))) {
value = info.getUserUnits().get(Long.parseLong(key));
}
break;
case TranslateConstant.ENUM_CLAZ:
// 枚举
Class enumClass = entity.getEnumClass();
value = EnumUtils.getMessageByCode(enumClass, codeInfo);
break;
case TranslateConstant.DICTION:
String[] types = entity.getDictionaryType();
if (entity.getWhetherStr()) {
String[] split = key.split(",");
List<String> values = new ArrayList<>();
for (String str : split) {
String result = null;
for (String s : types) {
String strs = s + CommonSymbolConstant.UNDERLINE + str;
if (StringUtils.isBlank(result) && info.getDictions().containsKey(strs)) {
result = info.getDictions().get(strs);
values.add(result);
break;
}
}
}
value = StringUtils.join(values, ",");
} else {
for (String s : types) {
String mapKey = s + CommonSymbolConstant.UNDERLINE + key;
// 数据字典
if (info.getDictions().containsKey(mapKey)) {
value = info.getDictions().get(mapKey);
break;
}
}
}
break;
case TranslateConstant.DATE:
Class<?> aClass = codeInfo.getClass();
if (aClass == LocalDateTime.class) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(entity.getDatePartten());
value = ((LocalDateTime) codeInfo).format(dateTimeFormatter);
}
break;
case TranslateConstant.DIVISION:
if (areasInfo.containsKey(key)) {
value = areasInfo.get(key);
} else {
value = getAreaNameById(key);
}
break;
default:
break;
}
translate.set(obj, value);
}
} catch (Exception e) {
log.error("翻译失败:{}", e);
}
}
/**
* 根据地区id获取地区名字
*
* @param areaId 地区id
* @return 地区名字
*/
private static String getAreaNameById(String areaId) {
String name = null;
try {
DivisionDTO divisionDTO = divisionService.getDivisionById(Long.valueOf(areaId));
if (ObjectUtil.isNotEmpty(divisionDTO)) {
name = divisionDTO.getName();
}
} catch (Exception e) {
log.error("获取地区名字失败:{}", e.getMessage());
}
return name;
}
/**
* 获取所有用户单位信息
*
* @return 用户单位信息
*/
private static Map<Long, String> getUserUnits() {
Map<Long, String> map = new HashMap<>();
try {
List<UserUnitDto> dtos = userUnitService.list(null);
for (UserUnitDto Dto : dtos) {
map.put(Dto.getId(), Dto.getName());
}
} catch (Exception e) {
log.error("用户单位信息获取失败:{}", e.getMessage());
}
return map;
}
/**
* 获取数据字典集合
*
* @param codes 数据字典code
* @return 数据字典集合
*/
private static Map<String, String> getDictions(List<String> codes) {
Map<String, String> diction = new HashMap<>();
try {
List<DictionaryDO> list = DictionaryUtils.getDictListByCodes(codes);
for (DictionaryDO dictionaryDO : list) {
diction.put(dictionaryDO.getCode() + CommonSymbolConstant.UNDERLINE + dictionaryDO.getValue(), dictionaryDO.getDictDesc());
}
} catch (Exception e) {
log.error("数据字典查询失败:{}", e.getMessage());
}
return diction;
}
}
使用举例
实体使用
@Data
@ApiModel("品种信息实体")
public class CommodityDTO {
@ApiModelProperty(value = "所属类型数据字典code:RISK_DATA_TYPE;风险评估专题库、气象灾害指数专题库")
private String belongTypeCode;
@ApiModelProperty(value = "所属类型名称")
@Translate(code = "belongTypeCode", type = TranslateConstant.DICTION, dictionaryType = DictionaryCodeConstant.RISK_DATA_TYPE)
private String belongTypeName;
@ApiModelProperty(value = "是否预测数据(数据类型) 0-否 1-是")
private Integer whetherForecast;
@ApiModelProperty(value = "是否预测数据(数据类型) ")
@Translate(code = "whetherForecast", type = TranslateConstant.ENUM_CLAZ, EnumClaz = WhetherForecastEnum.class)
private String whetherForecastName;
@ApiModelProperty(value = "评估时间")
@ExcelIgnore
private LocalDateTime evaluationTime;
@ApiModelProperty(value = "评估时间")
@ExcelProperty("评估时间")
@Translate(code = "evaluationTime", type = TranslateConstant.DATE)
private String evaluationTimeStr;
}
方法调用
TranslateUtils.translateList(list);