Java通过注解实现AOP字典转换

一、需求描述:

某一字段在数据库中存储的为数值,而在返回前端时想将它转换为对应的文字,从而不需要前端去维护。

这是在字典表里面具体代表的文字,1代表推送成功,0代表推送失败。

二、解决方案:

1、编写方法注解DictCovert 

作用于controller方法上,用于获取返回的数据

import java.lang.annotation.*;

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DictCovert {

}

2、编写字段注解Dict 

作业于需要转换的字段上,用于后续找到该需要转换的字段

import java.lang.annotation.*;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Dict {

    /**
     * 字典类型名称
     */
    String dictTypeName() default "";

    /**
     * 字典存放后缀
     * 默认 "Text"
     * 例 原始字段名:type  翻译储存的字段名:typeText
     **/
    String suffix() default "Text";

}

3、编写字典转换工具类DictUtil 

DictUtil自行适当修改

import cn.hutool.core.util.ObjectUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class DictUtil {

    /**
     * 使用个缓存,避免列表数据多次进行字典查询
     */
    private static ThreadLocal<Map<String,Map<String,String>>> cache  = ThreadLocal.withInitial(ConcurrentHashMap::new);

    //mapper查询数据库,查询字典数字对应的文字
    @Autowired
    private DictionariesItemMapper dictionariesItemMapper;

    private static DictUtil dictUtil;

    @PostConstruct
    public void init() {
        dictUtil = this;
        dictUtil.dictionariesItemMapper = this.dictionariesItemMapper;
    }

    public static Object parseResult(Object result) throws Exception {
        //判断空
        if (Objects.isNull(result)) {
            return null;
        }
        //判断结果类型
        if (result instanceof List) {
            //LIST类型
            List<Object> list = Lists.newArrayList();
            for (Object obj : (List<Object>) result) {
                list.add(parseDict(obj));
            }
            return list;
        } else if (result instanceof TableDataInfo) {
            //自定义的分页返回结果集类型  实际结果在 list字段中。 处理和LIST一致
            TableDataInfo tableDataInfo = (TableDataInfo) result;
            List<Object> list = Lists.newArrayList();
            for (Object obj : tableDataInfo.getRows()) {
                list.add(parseDict(obj));
            }
            //分页数据中 重新放入结果
            tableDataInfo.setRows(list);
            return tableDataInfo;
        } else if (result instanceof AjaxResult){
            //自定义的返回结果集类型  实际结果在 data字段中。 处理和LIST一致
            AjaxResult ajaxResult = (AjaxResult) result;
            Object data = ajaxResult.get("data");
            return AjaxResult.success(parseDict(data));
        } else {
            //单实例对象
            return parseDict(result);
        }
        //.....根据自己的需求判断相应的类型
    }

    /**
     * 字典转换
     *
     * @param obj
     */
    private static Object parseDict(Object obj) throws NoSuchFieldException, IllegalAccessException {
        Field[] fields = obj.getClass().getDeclaredFields();
        //非空判断
        if (ObjectUtil.isEmpty(fields)) {
            return null;
        }
        for (Field field : fields) {
            //判断每一个字典是否有Dict注解
            if (Objects.nonNull(field.getAnnotation(Dict.class))) {
                handleDict(obj, field);
            }
        }
        return obj;
    }


    /**
     * 处理字典注解的字段
     *
     * @param obj
     * @param field
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    private static void handleDict(Object obj, Field field) throws NoSuchFieldException, IllegalAccessException {
        Dict dict = field.getAnnotation(Dict.class);
        String dictTypeName = dict.dictTypeName();
        String suffix = dict.suffix();
        Map<String, String> dictitemValMap = getDictmap(dictTypeName);

        Field name = obj.getClass().getDeclaredField(field.getName() + suffix);

        field.setAccessible(true);
        Object key = field.get(obj);

        name.setAccessible(true);
        name.set(obj, dictitemValMap.get(key.toString()));

        name.setAccessible(false);
        field.setAccessible(false);
    }

    private static Map<String, String> getDictmap(String dictTypeName) {
        Map<String, Map<String, String>> dictMap = cache.get();
        if(dictMap.containsKey(dictTypeName)){
            return dictMap.get(dictTypeName);
        }

        List<DictionariesItem> dictionariesItemList = dictUtil.dictionariesItemMapper.getDictionariesItemMap(dictTypeName);
        Map<String, String> dictItemMap = new HashMap<>();
        if (CollectionUtils.isEmpty(dictionariesItemList)) {
            return dictItemMap;
        }
        for (DictionariesItem dictionariesItem : dictionariesItemList) {
            dictItemMap.put(dictionariesItem.getItemValue(), dictionariesItem.getItemName());
        }
        dictMap.put(dictTypeName,dictItemMap);
        cache.set(dictMap);
        return dictItemMap;
    }


    /**
     * 清除缓存
     */
    public static void clearCache(){
        cache.remove();
    }

}

4、编写AOP类DictAspect

import com.jl.pfs.utils.DictUtil;
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.context.annotation.Configuration;


@Aspect
@Configuration
public class DictAspect {

    @Pointcut("@annotation(com.jl.pfs.aop.dict.DictCovert)")
    public void dictCovert() {
    }

    @Around("dictCovert()")
    public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
        //1.执行原方法
        Object proceed = joinPoint.proceed();
        //2.拿到原方法的原返回值 调用parseResult进行字典转换
        Object result = DictUtil.parseResult(proceed);
        DictUtil.clearCache();
        return result;
    }
}

5、将相应的注解放在相应的地方

@DictCovert作用于Controller上

@Dict作用于属性上

三、实现效果:

统一实现返回时增加的字段显示对应的文字,当字典修改时,返回的文字也会跟着修改

如果你使用的是阿里巴巴的 easyexcel 库,可以通过实现自定义的 Converter 接口来将数据字典转换为字符串。 首先定义一个实现了 Converter 接口的类,实现 convertToExcelData() 方法和 convertToJavaData() 方法,分别用于将 Java 对象转换为 Excel 数据和将 Excel 数据转换Java 对象。在 convertToExcelData() 方法中,你可以根据数据字典Java 对象中的字段值转换为字符串;在 convertToJavaData() 方法中,你需要将 Excel 数据中的字符串转换为对应的 Java 对象。 下面是一个简单的示例代码: ```java public class DictionaryConverter implements Converter<String> { private Map<String, String> dictionary; // 数据字典 public DictionaryConverter(Map<String, String> dictionary) { this.dictionary = dictionary; } @Override public Class supportJavaTypeKey() { return Object.class; } @Override public CellDataTypeEnum supportExcelTypeKey() { return CellDataTypeEnum.STRING; } @Override public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception { return cellData.getStringValue(); } @Override public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception { String stringValue = dictionary.get(value); // 根据数据字典转换值为字符串 return new CellData(stringValue); } } ``` 在导出 Excel 时,可以将该 Converter 对象传递给 WriteSheet 的 setConverterMap() 方法,以将指定字段的值转换为字符串。 ```java // 创建 WriteSheet 对象 WriteSheet sheet = EasyExcel.writerSheet().build(); // 设置 Converter 对象,将数据字典转换为字符串 Map<Integer, Converter> converterMap = new HashMap<>(); converterMap.put(0, new DictionaryConverter(dictionary)); sheet.setConverterMap(converterMap); // 写入数据 List<User> userList = userService.listUsers(); EasyExcel.write(outputStream, User.class).sheet(sheet).doWrite(userList); ``` 其中,0 代表要转换的字段的索引,dictionary 是数据字典
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值