后端实习产出--通过自定义注解、反射、进行切面编程实现一个转化工具

news2024/9/21 20:51:07

前置知识:

需要会自定义注解方法自定义注解字段AOP切面编程,反射等...

核心代码结构:

核心代码实现:

package com.***.config;


import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import com.***.common.entity.dto.PageResult;
import com.***.common.utils.R;
import com.***.util.DictUtil;
import lombok.SneakyThrows;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

@Component
@Aspect
public class IntdDictMethodAop {

    @SneakyThrows
    @Around("@annotation(IntdDictMethod)")
    public Object around(ProceedingJoinPoint pjp) {
        Object proceed = pjp.proceed();
        Map<String, Map<String, String>> map = Maps.newHashMap();
        if (proceed instanceof R) {

            Object data = objParse(R.class, proceed).getData();
            if (data != null) {
                if (data.getClass().isArray() || data instanceof Collection) {

                    Collection<Object> collections = listParse(Object.class, data);
                    //如果返回数据是数组或集合,则遍历其中的每个元素并调用 convertData 方法进行转换
                    for (Object datum : collections) {
                        convertData(datum, map);
                    }
                } else if (data instanceof PageResult) {
                    Collection<Object> innerData = listParse(Object.class, objParse(PageResult.class, data).getData());
                    for (Object obj : innerData) {
                        convertData(obj, map);
                    }
                } else {
                    convertData(data, map);
                }
            }
        } else if (proceed instanceof PageResult) {
            Collection<Object> innerData = listParse(Object.class, objParse(PageResult.class, proceed).getData());
            for (Object obj : innerData) {
                convertData(obj, map);
            }
        } else if (proceed instanceof Collection) {
            Collection<Object> collections = listParse(Object.class, proceed);
            for (Object datum : collections) {
                convertData(datum, map);
            }
        } else {
            convertData(proceed, map);
        }
        return proceed;
    }
    public static <T> T objParse(Class<T> clazz, Object value) {
        return clazz.cast(value);
    }

    public static <T> Collection<T> listParse(Class<T> clazz, Object obj) {
        if (obj == null) {
            return new ArrayList<>();
        }
        Collection<T> result = new ArrayList<>();
        for (Object o : (Collection<?>) obj) {
            result.add(clazz.cast(o));
        }
        return result;
    }
    @SneakyThrows
    private void convertData(Object o, Map<String, Map<String, String>> map) {
        if (o == null) {
            return;
        }
        Class<?> sourceClass = o.getClass();
        for (; sourceClass != Object.class; sourceClass = sourceClass.getSuperclass()) {
            Field[] fields = sourceClass.getDeclaredFields();
            for (Field field : fields) {
                Class<?> type = field.getType();
                field.setAccessible(true);
                if (type.getClassLoader()!=null) {
                    Object o1 = field.get(o);
                    convertData(o1,map);
                    continue;
                }
                if (List.class.isAssignableFrom(type)) {
                    List fieldListObj = (List) field.get(o);
                    if (fieldListObj != null && fieldListObj.size() > 0) {
                        for (int i = 0; i < fieldListObj.size(); i++) {
                            Object o1 = fieldListObj.get(i);
                            if (o1 != null) {
                                if (o1.getClass().getClassLoader() != null) {
                                    convertData(o1,map);
                                }
                            }
                        }
                    }
                    continue;
                }

                IntdDict intdDict = field.getAnnotation(IntdDict.class);
                if (intdDict == null) {
                    continue;
                }
                String typeCode = getTypeCode(intdDict, sourceClass, o);
                if (StrUtil.isEmpty(typeCode)) {
                    continue;
                }
                String dictCodeField = crmDict.dictCodeField();
                Field declaredField = sourceClass.getDeclaredField(dictCodeField);
                declaredField.setAccessible(true);
                String dictCode = null;
                if (declaredField.getType().equals(String.class)) {
                    dictCode = (String) declaredField.get(o);
                }
                if(declaredField.getType().equals(Integer.class)){
                    dictCode = declaredField.get(o)!=null ? declaredField.get(o).toString() : null;
                }
                if (StrUtil.isEmpty(dictCode)) {
                    continue;
                }
                Map<String, String> dictTypeMap = map.get(typeCode);
                if (dictTypeMap != null) {
                    String val = dictTypeMap.get(dictCode);
                    if (!StrUtil.isEmpty(val)) {
                        field.set(o, val);
                    }
                } else {
                    DictUtil dictUtil=new DictUtil();
                    Map<String, String> dictMap = dictUtil.dictMap(typeCode);
                    if (dictMap != null) {
                        map.put(typeCode, dictMap);
                        String val = dictMap.get(dictCode);
                        if (!StrUtil.isEmpty(val)) {
                            field.set(o, val);
                        }
                    }
                }
            }
        }
    }
    @SneakyThrows
    private String getTypeCode(IntdDict intdDict, Class<?> sourceClass, Object o) {
        String type = intdDict.type();
        if ("1".equals(type)) {
            return intdDict.typeCode();
        } else if ("2".equals(type)) {
            String typeCode = intdDict.typeCode();
            Field typeCodeField = sourceClass.getDeclaredField(typeCode);
            typeCodeField.setAccessible(true);
            return (String) typeCodeField.get(o);
        }
        return null;
    }
}

核心代码是一个数据转换操作的方法,主要作用是将 Java 对象中被自定义注解@IntdDict指定的字段上的字典编码转换为字典值。下面我逐行解析这个方法是如何实现的。

  1. 第一行的方法签名 private void convertData(Object o, Map<String, Map<String, String>> map) 中,参数 o 是需要进行字典编码转换的 Java 对象,参数 map 是存储字典数据的双重映射表。

  2. 第二行判断对象是否为空,如果为空则直接返回。

  3. 第三行获取对象的类类型,并遍历该类及其父类上的所有成员变量。

  4. 第四行获取当前成员变量的类型,并设置该成员变量可访问。

  5. 第五行判断当前成员变量的类型是否为自定义类型,如List等。如果是自定义类型,则递归调用 convertData 方法,继续进行字典编码转换。

  6. 第九行判断当前成员变量上是否存在 IntdDict 注解,如果不存在则继续遍历下一个成员变量。

  7. 第十行调用 getTypeCode 方法获取该成员变量的字典类型编码。

  8. 第十二到第二十七行,根据成员变量的字典类型编码和字典编码,从 map 中获取相应的字典值并设置回成员变量上。如果 map 中没有包含该字典类型,则调用 DictUtil 类获取该字典类型的字典数据,并将其存储到 map 中。

  9. 最后一行结束方法的执行。

总体来说,这段代码实现了一个自动化的 Java 对象转换工具,能够快速地将对象中的字典编码转换为相应的字典值,大大简化了对字典数据的操作。它的主要思路是通过反射获取对象属性上的注解信息,然后通过该注解信息获取需要进行转换的字典编码和字典类型,最后从预先加载到内存中的 map 表中获取相应的字典值并设置回属性中。该代码通过提高字典数据的查询效率和方便性,大大提高了开发效率并优化了程序性能。

优点:这个工具类被我封装为了一个starter,有微服务模块都能引用我这个代码,实现低耦合,开发过程只需要引用我这个自定义注解即可实现功能。且前端开发也无需自己处理这类数据,直接获取展示到界面就可以。

缺点:这个递归写的不是很完美,途中出过bug,调试了很久发现不能在实体类上用这个注解@Slf4j不然递归会很深导致栈溢出,需要继续完善,测试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/535842.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【pyq文案】可可爱爱の朋友圈文案

1.我在该生儿育女的年纪&#xff0c;选择了生椰拿铁 2.我妈年轻时候工资2000&#xff0c;我现在工资也2000&#xff0c;这就叫薪火相传 3.不要讨厌自己&#xff0c;有什么事怪星座生肖八字和mbti就好了 4.人是会和动物共情的&#xff0c;我开始理解急每天早起&#xff0c;然…

FL Studio2023最新中文免费版水果音乐制作软件

FL Studio(水果音乐制作软件)是一款强大的音乐制作编曲软件&#xff0c;非常容易上手。FL让你的计算机就像是全功能的录音室&#xff0c;漂亮的大混音盘&#xff0c;先进的创作工具&#xff0c;让你的音乐突破想象力的限制。一款强大的音乐制作软件&#xff0c;可以进行音乐编曲…

云计算期中测试

云计算期中测试 文章目录 云计算期中测试一、前言二、第一题1、命令方式2、java API方式 三、第二题1、创建CSV文件并将其上传到HDFS2、编写利用MapReduce框架的java代码3、打包java项目4、在Hadoop集群上提交jar文件来运行MapReduce作业 一、前言 在实验开始之前我们需要在虚…

MySQL高级_第05章_存储引擎

MySQL高级_第05章_存储引擎 1. 查看存储引擎 查看mysql提供什么存储引擎&#xff1a; show engines ; show engines \G ; 显式如下&#xff1a; *************************** 1. row *************************** Engine : InnoDB Support: DEFAULT Comment : Su…

企业管理OA系统在企业数字化转型中带来的变化,简直难以想象

目前企业管理面临到哪些痛点 1.信息孤岛&#xff1a;企业内部信息流动不畅&#xff0c;各部门数据独立&#xff0c;互相之间信息难以共享和沟通。 2.流程繁琐&#xff1a;企业业务流程较为繁琐&#xff0c;审批流程漫长&#xff0c;给业务员和经理带来不必要的工作压力。 3.…

Hbase入门篇03---Java API使用,HBase高可用配置和架构设计

Hbase入门篇03---Java API使用&#xff0c;HBase高可用配置和架构设计 需求环境搭建表的CRUD坑命令执行卡住不动 &#xff1f;RegionServer只在本地127.0.0.1监听16020端口导致外网连接被拒RegionServer所在主机的/etc/hosts文件存在额外的回环地址映射信息,导致客户端拿到无法…

亚马逊云科技使用Inf2实例运行GPT-J-6B模型

在2019年的亚马逊云科技re:Invent上&#xff0c;亚马逊云科技发布了Inferentia芯片和Inf1实例这两个基础设施。Inferentia是一种高性能机器学习推理芯片&#xff0c;由亚马逊云科技定制设计&#xff0c;其目的是提供具有成本效益的大规模低延迟预测。时隔四年&#xff0c;2023年…

生成bean的注解@Component极其衍生和@ComponentScan@Configuration

Component Spring 2.5 以后&#xff0c;除了提供基本的 Component 注解之外&#xff0c;还提供了 Service Controller Repository 三个注解。在 Spring 源码中&#xff0c;后面三个注解都在开始部分引入了 Component 注解&#xff0c;除此以外这四个注解的源码内容没有任何区别…

Json介绍

文章目录 1. 什么是 JSON&#xff1f;2. JSON语法格式3. JSON在Java中的用途3.1 FastJSON1. FastJSON概述与下载2. FastJSON常用方法 3.2. Jackson1. Jackson下载与使用2. Jackson常用类与方法3. ObjectMapper类常用方法 1. 什么是 JSON&#xff1f; JSON:JavaScript Object N…

C语言函数大全-- _w 开头的函数(2)

C语言函数大全 本篇介绍C语言函数大全-- _w 开头的函数 1. _wexecl 1.1 函数说明 函数声明函数功能int _wexecl(const wchar_t *path, const wchar_t *arg0, ... /* , const wchar_t *arg1, ..., NULL */);它是一个 Windows 平台下的 C 标准库函数&#xff0c;用于在新进程…

〖大学生·技术人必学的职业规划白宝书 - 职业规划篇②〗- 进入职场前必须要考虑的问题

历时18个月&#xff0c;采访 850 得到的需求。 不管你是在校大学生、研究生、还是在职的小伙伴&#xff0c;该专栏有你想要的职业规划、简历、面试的答案。说明&#xff1a;该文属于 大学生技术人职业规划白宝书 专栏&#xff0c;购买任意白宝书体系化专栏可加入TFS-CLUB 私域社…

leecode106——使用中序遍历和后序遍历构造一棵二叉树

leecode106 中序遍历和后序遍历构造一棵二叉树 &#x1f50e;中序遍历和后续遍历的性质 在后序遍历中&#xff0c;最后一个元素二叉树的根节点 在中序遍历序列中&#xff0c;根节点的左边为左子树&#xff0c;右边为右子树 &#x1f50e;1.二叉树的还原过程描述 1.首先&am…

HTTP协议基本格式

HTTP协议基本格式 TCP/IP的分层管理HTTP的基本格式 TCP/IP的分层管理 TCP/IP协议族里重要的一点就是分层。TCP/IP协议族按层次分别分为5层&#xff1a; 应用层、传输层、网络层、数据链路层、物理层。 TCP/IP层次化的好处。 如果互联网只由一个协议统筹&#xff0c;某个地方需…

不动点定理的及其有趣应用

最近读高观点下的数学这本书&#xff0c;对书中介绍的布劳威尔不动点定理的有趣性质印象很深&#xff0c;原因是这个定理的某些性质能够解释我们生活中的一些常见现象&#xff0c;这里结合一个例题&#xff0c;聊以记录。 从一个数学题讲起&#xff1a; f(x)是定义在[0,1]上的…

IPB60R099CP-ASEMI代理英飞凌高压MOS管IPB60R099CP

编辑&#xff1a;ll IPB60R099CP-ASEMI代理英飞凌高压MOS管IPB60R099CP 型号&#xff1a;IPB60R099CP 品牌&#xff1a;英飞凌 封装&#xff1a;TO-263 最大漏源电流&#xff1a;31A 漏源击穿电压&#xff1a;600V RDS&#xff08;ON&#xff09;Max&#xff1a;99mΩ …

【MySQL】MySQL百万数据深度分页优化思路分析

文章目录 一、业务背景二、瓶颈再现三、问题分析回表覆盖索引IOLIMTI 2000,10 &#xff1f; 四、问题总结五、解决方案优化前后性能对比 一、业务背景 一般在项目开发中会有很多的统计数据需要进行上报分析&#xff0c;一般在分析过后会在后台展示出来给运营和产品进行分页查看…

软考A计划-真题-分类精讲汇总-第十五章(数据库设计)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

如何做到乡村振兴?主要包括以下几点

乡村振兴是现代化发展的常记口号&#xff0c;也是中国整体经济发展的必备条件&#xff0c;乡村振兴是一个多元化的问题&#xff0c;其中包含人文、经济、文化、生态、人才等&#xff0c;那么如何做到乡村振兴呢&#xff1f; 主要包括以下几点&#xff1a; 1.合理利用土地资源…

SpringBoot配置文件敏感信息加密(四十六)

新的生活会开始&#xff0c;直到完成自己的目标. 一. 配置文件敏感信息加密 我们以前在编写 application.yml 文件时&#xff0c;服务器的ip, 数据库的配置&#xff0c;Redis的密码配置等都是明文&#xff0c;这是很不安全的。 我们可以通过 jasypt-spring-boot-starter 插件进…

Python学习26:个人所得税计算器

描述‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬ 2018年10月1日以前&#xff…