简介

AOP也是我们常说的面向切面编程,AOP在我们开发过程中应用也比较多,在这里我们就基于AOP来实现一个数据字典转换的案例。

案例介绍

相信各位在写代码的时候肯定有过这样的经历,我们设计数据库时对于字典类的数据一般都会采用字典码进行存储,而不是直接使用字典值。首先是因为这是一种开发规范,其次使用编码也会利于数据存储,数据整体也会比较干净整洁。

数据字典编码的定义一般也会做一些分类,比如说U01开头代表用户类型,U02开头代表用户性别等等,这样也有助于我们进行数据分析。

下面我们就简单以一个用户表来做数据字典转换。

案例实现

创建表:

CREATE TABLE `t_user` (
  `id` BIGINT(12) NOT NULL AUTO_INCREMENT,
  `user_code` VARCHAR(20) NOT NULL,
  `user_name` VARCHAR(50) NOT NULL,
  `user_type` CHAR(5) NOT NULL COMMENT '用户类型 -> U0101:普通用户,U0102:VIP用户',
  `gender` CHAR(5) NOT NULL COMMENT '用户性别 -> U0299:未知,U0201:男,U0202:女',
  PRIMARY KEY (`id`) 
) CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

代码结构:

相关代码可由逆向工程去生成,我们就简单的编写了从控制层请求到服务层的业务处理再到dao层的数据处理,在这里我就一一将代码展示出来了各位还需要自己多动手。下面就直接上代码结构图

测试接口:

接下来我们在UserController类中写一个测试接口,根据userCode查询用户信息如下:

@GetMapping("/{userCode}")
public UserVo queryUser(@PathVariable("userCode") String userCode) {
    UserDto userDto = userService.queryUserByCode(userCode);
    return userMapStruct.userDtoToUserVo(userDto);
}

初始化测试数据:

切面定义

定义注解类:用于标记哪个地方需要进行数据字典转换切面。

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DictParam {
    /**
     * 映射目标属性,为空默认直接映射到field,替换掉原来的field
     * @return
     */
    String targetField() default "";

    /**
     * 映射来源属性
     * @return
     */
    String field();

    /**
     * 数据字典类型
     * @return
     */
    String dictType();
}
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DictHelper {
    /**
    * 字典转换参数配置
    */
    DictParam[] value();
}

定义注解切面类:主要实现字典转换的核心内容。

@Slf4j
@Aspect
public class DictHelperAspect {
    public DictHelperAspect() {
    }
    @Around("@annotation(dictHelper)")
    public Object doAround(ProceedingJoinPoint joinPoint, DictHelper dictHelper) {
        try {
            // 执行方法得到结果
            Object result = joinPoint.proceed();

            DictParam[] values = dictHelper.values();
            if (values == null || values.length == 0) {
                return result;
            }

            // 字典转换开始(使用反射)
            for (DictParam value : values) {
                Class<?> clazz = result.getClass();
                // 反射调用get方法获取字段值
                Method sourceMethod = clazz.getMethod("get"   firstToUppercase(value.field()));
                Object fieldValue = sourceMethod.invoke(result);
                // 获取字典值
                String dictValue = DictConfig.DICT_MAPPER.get(value.dictType()).get(fieldValue.toString());
                // 获取目标方法进行设值
                String targetField = StringUtils.isBlank(value.targetField()) ? value.field() : value.targetField();
                Method targetMethod = clazz.getMethod("set"   firstToUppercase(targetField), dictValue.getClass());
                targetMethod.invoke(result, dictValue);
            }
            return result;
        }
        catch (Throwable throwable) {
            log.error("error:", throwable);
            return null;
        }
    }

    private String firstToUppercase(String str) {
        return str.substring(0, 1).toUpperCase()   str.substring(1);
    }
}

Service层添加字典转换的切面扫描注解:

@DictHelper(values = {
        @DictParam(field = "userType", targetField = "userTypeShow", dictType = "USER_TYPE"),
        @DictParam(field = "gender", targetField = "genderShow", dictType = "GENDER")
})
public UserDto queryUserByCode(String userCode) {
    UserEntity userEntity = userMapper.selectUser(userCode);
    return userMapStruct.userEntityToUserDto(userEntity);
}

如上代码主要分三个步骤:

  • 根据@DictParam注解配置的数据来源字段通过返回调用数据返回对象获取数据来源字典编码。
  • 根据字典编码通过字典编码表(这里直接使用静态DictConfig直接调用)找到对应字典值。
  • 根据@DictParam注解配置的目标数据字典,将匹配到的数据字典值通过反射将数据回填到对象中。

注意:各位开发者朋友们,看到这里是不是以为很简单呢,但是在实际开发过程中我们更注重的是程序的安全、稳定、可靠,所以这也不难看出上面的代码当中省去了许多校验

静态字典:实际开发过程中,不建议这么配置,因为这样是完全不灵活的,这里只是为了方便演示而已。实际业务当中可以自定义一种数据字典加载策略(服务启动成功后加载或者定期刷新加载),将字典加载到内存,或者使用数据库结合redis做内存也可以,数据字典还是要避免频繁直接的去查数据库。

public class DictConfig {
    public static final Map<String, Map<String, String>> DICT_MAPPER = new HashMap<>();
    static {
        Map<String, String> USER_TYPE = new HashMap<>();
        USER_TYPE.put("U0101", "普通用户");
        USER_TYPE.put("U0102", "VIP用户");
        DICT_MAPPER.put("USER_TYPE", USER_TYPE);

        Map<String, String> GENDER = new HashMap<>();
        GENDER.put("U0201", "男");
        GENDER.put("U0202", "女");
        GENDER.put("U0299", "未知");
        DICT_MAPPER.put("GENDER", GENDER);
    }
}

运行结果:

总结

利用切面编程还可以做很多事,本文所展示的数据字典转换也仅仅只是冰山一角,像用的比较多的分页处理我们也一样可以用这种方式去做。

数据字典在我们开发设计当中是必不可少的,合理的使用好数据字典还是很有必要的。

到此这篇关于如何利用Java使用AOP实现数据字典转换的文章就介绍到这了,更多相关Java AOP字典转换内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

如何利用Java使用AOP实现数据字典转换的更多相关文章

  1. NT IIS下用ODBC连接数据库

    $connection=intodbc_connect建立数据库连接,$query_string="查询记录的条件"如:$query_string="select*fromtable"用$cur=intodbc_exec检索数据库,将记录集放入$cur变量中。再用while{$var1=odbc_result;$var2=odbc_result;...}读取odbc_exec()返回的数据集$cur。最后是odbc_close关闭数据库的连接。odbc_result()函数是取当前记录的指定字段值。

  2. Thinkphp5框架实现获取数据库数据到视图的方法

    这篇文章主要介绍了Thinkphp5框架实现获取数据库数据到视图的方法,涉及thinkPHP5数据库配置、读取、模型操作及视图调用相关操作技巧,需要的朋友可以参考下

  3. 如何在PHP环境中使用ProtoBuf数据格式

    这篇文章主要介绍了如何在PHP环境中使用ProtoBuf数据格式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

  4. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. Python爬取奶茶店数据分析哪家最好喝以及性价比

    这篇文章主要介绍了用Python告诉你奶茶哪家最好喝性价比最高,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

  6. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. Android本地存储方法浅析介绍

    这篇文章主要介绍了Android本地存储案例,方法简单可以实现存储并达到节省内存的效果,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

  9. Java实现世界上最快的排序算法Timsort的示例代码

    Timsort 是一个混合、稳定的排序算法,简单来说就是归并排序和二分插入排序算法的混合体,号称世界上最好的排序算法。本文将详解Timsort算法是定义与实现,需要的可以参考一下

  10. 详解Python如何实现Excel数据读取和写入

    这篇文章主要为大家详细介绍了python如何实现对EXCEL数据进行读取和写入,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部