數據字典回顯功能設計與實現
文章目錄
- 數據字典回顯功能設計與實現
- 1. 業務場景
- 2. 實現設計
- 2.1 注解+AOP切面
- 2.2 注解+mybatis攔截器
- 2.3 注解+序列化
- 2.4 涉及字段直接申明成字典引用類型+mybatis攔截器+反序列化處理
- 3. 具體實現
1. 業務場景
我們日常開發中經常會遇到:數據字典類型的字段存儲至數據庫的是id或者code,然而頁面顯示的時候卻是名稱
2. 實現設計
關于解決上述問題有以下幾種方案:
2.1 注解+AOP切面
注解主要起標記作用,然后采用切面處理標記字段,把id或code轉化成字典名稱。這種方式可以靈活的標記是否需要回顯轉化處理,后面我采用這種方式舉例說明
2.2 注解+mybatis攔截器
注解主要起標記作用,mybatis攔截器攔截之后,判斷注解標記字段,把id或code轉化成字典名稱
2.3 注解+序列化
注解主要起標記作用,需增加專門的序列化處理器,序列化的過程中判斷注解標記字段,把id或code轉化成字典名稱
2.4 涉及字段直接申明成字典引用類型+mybatis攔截器+反序列化處理
這種方式最為靈活,意思就是把涉及數據字典的字段,申明成字典類型(比如說DictData),前端就直接可以拿到字典的所有內容(包括id、code、名稱)。
該種方式的實現需要三步操作:
1.涉及字段直接申明成字典引用類型
2.mybatis攔截之后通過id或code補全字典數據
3.前端傳遞的id或code在反序列化的過程中補全字典數據
3. 具體實現
- 定義方法標記注解,主要用來判斷該接口是否需要字典轉化
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface NeedEchoDict {}
- 定義字段標記注解,主要用來判斷字典類型字段
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DictData {/*** 字典類型** @return*/String type() default "";
}
- AOP切面處理
@Slf4j
@Aspect
@Component
public class DictEchoAspect {@Around("@annotation(com.jiayuan.common.annotation.NeedEchoDict)")public Object translation(final ProceedingJoinPoint pjp) throws Throwable {//目標方法執行Object resultR = pjp.proceed();if (ObjectUtil.isNull(resultR)) {return resultR;}//獲取返回data值Object result = ((Result) resultR).getData();if (result instanceof PageData) {// 分頁的情況PageData page = (PageData) result;result = ((PageData) result).getList();result = translate(result);page.setList((List) result);((Result) resultR).setData(page);return resultR;}result = translate(result);((Result) resultR).setData(result);return resultR;}/*** 返回值轉換,增加字典回顯** @param result* @return*/private Object translate(Object result) {if (result instanceof List || result instanceof ArrayList) {for (Object entity : (List) result) {to(entity);}} else {to(result);}return result;}/*** 根據類上注解,設置目標屬性值** @param entity 返回對象*/public void to(Object entity) {Class c = entity.getClass();for (; c != Object.class; c = c.getSuperclass()) {try {Field[] fields = c.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);Object preValue = field.get(entity);Class<?> type = field.getType();if (ObjectUtil.isNotNull(preValue)) {//如果對象中包含list,判斷list中是否包含注解if (type.equals(List.class) || type.equals(ArrayList.class)) {// 當前集合的泛型類型Type genericType = field.getGenericType();if (null == genericType) {continue;}if (genericType instanceof ParameterizedType) {for (Object o : (List) preValue) {to(o);}}}//todo 自定義對象方式if (field.isAnnotationPresent(DictData.class)) {final String dictName = DictCache.getDictName(preValue.toString());//設置字典內容field.set(entity, dictName);}}}//父類存在子類不存在情況} catch (Exception e) {log.error("字典回顯失敗:{}", JSONUtil.toJsonStr(entity));e.printStackTrace();}}}}
- 使用案例
@NeedEchoDict
@GetMapping("pageForApproval")
@ApiOperation("審批分頁")
public Result<PageData<ApprovalAcademicActivityResponse>> pageForApproval(@Validated ApprovalAcademicActivityRequest request,@Validated PageDTO pageDTO) {PageData<ApprovalAcademicActivityResponse> page = academicActivityService.pageForApproval(request, pageDTO);return Result.ok(page);
}@Data
@ApiModel(value = "審批分頁學術活動結果")
public class ApprovalAcademicActivityResponse Serializable {private static final long serialVersionUID = -4402178057699015363L;@DictData@ApiModelProperty(value = "活動性質")private String activityNature;@DictData@ApiModelProperty(value = "活動范圍")private String activityScope;。。。
}