目录
需求:
一般情况下数据库表中字段对应的是字典值,但在查询或导出时需要展示字典名,若每次字典转换时都需要关联字典表查询,而且导出时还需要在做一次数据转换,这样处理比较繁琐,会存在冗余代码,不太合理,所以使用AOP自定义注解实现自动翻译。
结果展示 :
- 导出:
- 查询:
代码实现 :
- 新建自定义注解
/**
* @describe 编码值集
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DictMeaning {
String code() default "";
//转换后赋值到绑定字段
String targetField() default "";
}
- 新建拦截注解,用于方法上
/**
* @describe 返回数据处理
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ProcessResult {
}
- 拦截目标方法
public interface BankTestMapper {
/**
* 查询、导出数据
*
* @param BankTestVO
* @return
*/
@ProcessResult
List<BankTest> queryList(BankTestVO bankTestVO);
}
- 新建AOP切面类
/**
* @describe 编码值集转换
*/
@Slf4j
@Aspect
@Component
public class DictAspect {
@Autowired
private DictCodeService dictCodeService;
// 拦截@processResult标注的方法
@AfterReturning(value = "@annotation(processResult)", returning = "result")
public Object enumValue(JoinPoint joinPoint, ProcessResult processResult, Object result) {
if (Objects.isNull(result)) {
return null;
}
// 校验返回类型list
if (result instanceof List) {
List list = (List) result;
for (Object object : list) {
convertDictValue(object, object.getClass());
}
return result;
}
convertDictValue(result, result.getClass());
return result;
}
/**
* 通过反射获取Bean字段,拦截所使用@Dict注解字段进行数据转换值
*
* @param object 对象
* @param objClass 对象类
*/
private void convertDictValue(Object object, Class objClass) {
// 获取当前对象的所有字段
Field[] fields = objClass.getDeclaredFields();
if (fields.length == 0) {
return;
}
// 遍历字段上是否有自定义注解
for (Field field : fields) {
try {
// 设置可以访问私有变量的值
field.setAccessible(true);
// 字段为空,不执行后续操作
if (Objects.isNull(field.get(object))) {
continue;
}
// 解析自定义注解
DictMeaning annotation = field.getAnnotation(DictMeaning.class);
if (annotation == null) {
continue;
}
// 根据值集编码获取 value 含义
String valueMeaning = getValueMeaning(annotation.code());
if (StringUtils.isEmpty(valueMeaning)) {
continue;
}
// 编辑自定义字段
String setMethodName = null;
if (StringUtils.isNotEmpty(annotation.targetField())) {
// 驼峰命名
setMethodName = "set" + annotation.targetField().substring(0, 1).toUpperCase() + annotation.targetField().substring(1);
}
// set自定义字段
Method method = object.getClass().getMethod(setMethodName, String.class);
if (Objects.isNull(method)) {
continue;
}
method.invoke(object, valueMeaning);
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
}
// 递归获取父类的属性
convertDictValue(object, objClass.getSuperclass());
}
/**
* 根据值集编码获取 value 含义
*
* @param code
* @return
*/
private String getValueMeaning(String code) {
// TODO 先查询数据表,后续值集数据存入 Redis
String textValue = dictCodeService.getValueByCode(code);
if (StringUtils.isEmpty(textValue)) {
return null;
}
return textValue;
}
}
- 实体引用注解
/**
* 实体类
*/
@Data
@TableName("bank_test")
public class BankTest {
@TableId(value = "id", type = IdType.INPUT)
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "实体名称")
@ExcelProperty("实体名称")
private String name;
@ApiModelProperty(value = "系统编码")
@ExcelProperty("系统编码")
private String sysCode;
@ApiModelProperty(value = "状态", hidden = true)
@ExcelIgnore
@DictMeaning(code = "字典编码", targetField = "stateMeaning")
private Integer state;
@ApiModelProperty(value = "状态含义", hidden = true)
@ExcelProperty("状态")
@TableField(exist = false)
private String stateMeaning;
}