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

本文介绍了如何使用SpringAOP结合注解,实现在Java应用中,数据库字段值返回前端时自动转换为对应的文本描述,通过DictCovert和Dict注解,以及DictUtil工具类,实现字段字典映射并支持实时更新效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、需求描述:

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

这是在字典表里面具体代表的文字,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作用于属性上

三、实现效果:

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值