• aop+springboot实现数据字典表


    概要

    spingboot+aop实现数据字典方式

    例如:

    我们在想数据库中存储文字的时候,效率不高,这个时候我们会考虑存储,code编码格式数据,然后利用aop返回给前端的时候翻译code编码将值给code编码

    整体架构流程

    我们会新建三张表

    1.第一张表是aop_student学生表存储学生等级,兴趣,爱好,我们这里分别存储是code编码并不是存储真实的数据方式,我们会将真实的数据存储到aop_item
    2.第二张表是aop_item这张表存储我们真实的数据信息,我们通过code和属性名称查询对应的值

    在这里插入图片描述

    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for aop_dict
    -- ----------------------------
    DROP TABLE IF EXISTS `aop_dict`;
    CREATE TABLE `aop_dict`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `aop_datasource` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '科目',
      `aop_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of aop_dict
    -- ----------------------------
    INSERT INTO `aop_dict` VALUES (1, 'aop_level', '数学');
    INSERT INTO `aop_dict` VALUES (2, 'aop_english', '语文');
    INSERT INTO `aop_dict` VALUES (3, 'aop_hobby', '兴趣');
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for aop_item
    -- ----------------------------
    DROP TABLE IF EXISTS `aop_item`;
    CREATE TABLE `aop_item`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `aop_datasource` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
      `aop_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
      `aop_val` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of aop_item
    -- ----------------------------
    INSERT INTO `aop_item` VALUES (1, 'aop_english', '1', '优秀');
    INSERT INTO `aop_item` VALUES (2, 'aop_level', '1', '优秀');
    INSERT INTO `aop_item` VALUES (3, 'aop_level', '2', '良好');
    INSERT INTO `aop_item` VALUES (4, 'aop_english', '2', '良好');
    INSERT INTO `aop_item` VALUES (5, 'aop_hobby', '1', 'A');
    INSERT INTO `aop_item` VALUES (6, 'aop_hobby', '2', 'B');
    INSERT INTO `aop_item` VALUES (7, 'aop_hobby', '3', 'C');
    INSERT INTO `aop_item` VALUES (8, 'aop_hobby', '4', 'D');
    INSERT INTO `aop_item` VALUES (9, 'aop_hobby', '5', 'E');
    INSERT INTO `aop_item` VALUES (10, 'aop_hobby', '6', 'G');
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for aop_student
    -- ----------------------------
    DROP TABLE IF EXISTS `aop_student`;
    CREATE TABLE `aop_student`  (
      `id` int(11) NOT NULL,
      `aop_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '姓名',
      `aop_enlish` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '英语',
      `aop_level` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '等级',
      `aop_hobby` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '爱好',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of aop_student
    -- ----------------------------
    INSERT INTO `aop_student` VALUES (1, '天天', '1', '1', '1,2,3');
    INSERT INTO `aop_student` VALUES (2, '拜拜', '2', '2', '4,5');
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    例如:
    在语言模型中,编码器和解码器都是由一个个的 Transformer 组件拼接在一起形成的。

    目录结构方式

    在这里插入图片描述

    pom文件信息

       <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>2.7.7</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <version>2.7.7</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
                <version>2.7.7</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.31</version>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba.fastjson2</groupId>
                <artifactId>fastjson2</artifactId>
                <version>2.0.22</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
                <version>2.7.7</version>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.2.2</version>
            </dependency>
        </dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    application.yml文件信息

    server:
      port: 10001
    spring:
      datasource:
        url: jdbc:mysql://192.168.47.128:3306/mycnblog?characterEncoding=utf8&useSSL=false
        username: root
        password: 123456
        driver-class-name: com.mysql.jdbc.Driver
      #redis连接信息
      redis:
        port: 6379
        host: 192.168.47.128
    mybatis:
      mapper-locations: classpath:/mapper/*Dao.xml
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    aop实现方式(重点方式)

    我们这里主要的实现了,就是在前段请求数据的时候,我们利用aop,拦截数据,将code编码进行翻译,翻译的方式就是我们将code值,获取重新在数据库中查询到的值,存储到code,重新返回给前段展示
    
    package com.cn.aop;
    
    import com.alibaba.fastjson2.JSON;
    import com.alibaba.fastjson2.JSONObject;
    import com.cn.common.Result;
    import com.cn.log.DictRedis;
    import com.cn.service.AopItemService;
    import com.cn.utils.BeanUtil;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    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.junit.platform.commons.util.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StopWatch;
    
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Objects;
    
    
    @Aspect
    @Component
    public class DictAspect {
    
        private Logger log = LoggerFactory.getLogger(DictAspect.class);
    
    
        @Autowired
        private AopItemService aopItemService;
    
        @Pointcut("execution(* com.cn.controller.*.*(..))")
        public void execute(){
    
        }
    
        @Around("execute()")
        public Object around(ProceedingJoinPoint point) throws Throwable {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            Object result = point.proceed();
            stopWatch.stop();
            log.info("获取数据时间:{}",result);
            stopWatch.start();
            translateDict(result);
            stopWatch.stop();
            log.info("翻译字典时间:{}",stopWatch.getLastTaskTimeMillis());
            return result;
        }
    
        /**
         * 翻译字典
         * @param result
         */
        private void translateDict(Object result) {
            if (result instanceof Result){
            	//封装返回的值
                List<JSONObject> items = new ArrayList<>();
    			//将获取对象强制转化成Result对象
                Result dictResult = (Result)result;
    			//获取的Result获取getData()转化成list
                List<?> list = (List<?>)dictResult.getData();
    			//循环list获取里面注册标注的数据添加值
                for (Object o : list) {
                	//获取值进行json格式的转化
                    ObjectMapper mapper = new ObjectMapper();
    
                    String json = "{}";
    
                    try {
                        json=mapper.writeValueAsString(o);
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
    
                    JSONObject parseObject = JSON.parseObject(json);
    				
    				//遍历获取对象中的属性和名称
                    for (Field field : BeanUtil.getAllFields(o)) {
                    	//获取注解标注的值
                        if (field.getAnnotation(DictRedis.class)!=null){
                            String dictDataSource = field.getAnnotation(DictRedis.class).dictDataSource();
                            String dictText = field.getAnnotation(DictRedis.class).dictText();
                            //获取当前key值
                            String keys = String.valueOf(parseObject.get(field.getName()));
                            //获取当前字典中的值
                            String textValue = translateTextValue(dictDataSource,keys);
                            if (StringUtils.isNotBlank(dictText)){
                                parseObject.put(dictText,textValue);
                            }else {
                                parseObject.put(field.getName()+"cc",textValue);
                            }
                        }
                    }
                    items.add(parseObject);
                }
                dictResult.setData(items);
            }
        }
    
        /**
         * 获取字典中的值
         * @param dictDataSource 名称
         * @param keys 值
         * @return
         */
        private String translateTextValue(String dictDataSource, String keys) {
            if (StringUtils.isBlank(dictDataSource) || StringUtils.isBlank(keys)){
                return null;
            }
            StringBuffer buffer = new StringBuffer();
    		
    		//分割key将分割的key循环便利进行查询
            String[] key = keys.split(",");
            for (String k : key) {
                String tempValue =null;
                if (k.trim().length()==0){
                    continue;
                }
                log.info("字典中的值:{}",k);
                tempValue = aopItemService.selectByDatasourceKey(dictDataSource,k);
    
                if (StringUtils.isNotBlank(tempValue)){
                    if (!"".equals(buffer.toString())){
                        buffer.append(",");
                    }
                    buffer.append(tempValue);
                }
            }
            return buffer.toString();
        }
    
    
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143

    注解

    我们注释在需要翻译的实体类上 这个字段必须是经过在aop_item表中的字段我们通过code和datasource数据方式来确定这个val值
    package com.cn.log;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DictRedis {
    
        /**
         * 方法描述:类型dataSource
         * @return
         */
        String dictDataSource();
    
        /**
         * 返回后台的put到json中的文件key值
         * @return
         */
        String dictText() default "";
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    package com.cn.log;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DoDict {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    工具类

    获取所有属性中的名称

    package com.cn.utils;
    
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class BeanUtil {
        /**
         * 通过反射包括父类的所有属性类型
         * @param object
         * @return
         */
        public static Field[] getAllFields(Object object){
            Class<?> clazz = object.getClass();
            List<Field> fieldList = new ArrayList<>();
            while (clazz!=null){
                fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
                clazz = clazz.getSuperclass();
            }
            Field[] fields = new Field[fieldList.size()];
            fieldList.toArray(fields);
            return fields;
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    实体类文件信息

    package com.cn.entity;
    
    
    import com.cn.log.DictRedis;
    
    import java.io.Serializable;
    
    /**
     * (AopStudent)实体类
     *
     * @author makejava
     * @since 2023-05-24 18:35:57
     */
    public class AopStudent implements Serializable {
        private static final long serialVersionUID = 127399537035303507L;
        
        private Integer id;
        /**
        * 姓名
        */
        private String aopName;
        /**
        * 英语
        */
        @DictRedis(dictDataSource = "aop_english",dictText = "aop-cc")
        private String aopEnlish;
        /**
        * 等级
        */
        @DictRedis(dictDataSource = "aop_level")
        private String aopLevel;
        /**
        * 爱好
        */
        @DictRedis(dictDataSource = "aop_hobby")
        private String aopHobby;
    
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getAopName() {
            return aopName;
        }
    
        public void setAopName(String aopName) {
            this.aopName = aopName;
        }
    
        public String getAopEnlish() {
            return aopEnlish;
        }
    
        public void setAopEnlish(String aopEnlish) {
            this.aopEnlish = aopEnlish;
        }
    
        public String getAopLevel() {
            return aopLevel;
        }
    
        public void setAopLevel(String aopLevel) {
            this.aopLevel = aopLevel;
        }
    
        public String getAopHobby() {
            return aopHobby;
        }
    
        public void setAopHobby(String aopHobby) {
            this.aopHobby = aopHobby;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    controller信息

    package com.cn.controller;
    
    import com.cn.common.Constant;
    import com.cn.common.Result;
    import com.cn.entity.AopStudent;
    import com.cn.log.DoDict;
    import com.cn.service.AopStudentService;
    import org.springframework.web.bind.annotation.*;
    
    import javax.annotation.Resource;
    import java.util.List;
    
    /**
     * (AopStudent)表控制层
     *
     * @author makejava
     * @since 2023-05-24 18:35:59
     */
    @RestController
    @RequestMapping("aopStudent")
    public class AopStudentController {
        /**
         * 服务对象
         */
        @Resource
        private AopStudentService aopStudentService;
    
        /**
         * 通过主键查询单条数据
         *
         * @param id 主键
         * @return 单条数据
         */
        @GetMapping("selectOne")
        public AopStudent selectOne(Integer id) {
            return this.aopStudentService.queryById(id);
        }
    
        /**
         * 获取所有学生的信息
         * @return 返回所有学生信息
         */
        @DoDict
        @GetMapping("findAll")
        public Result findAll(){
            List<AopStudent> all =aopStudentService.findAll();
            return new Result(Constant.success,"成功获取信息",all);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    测试

    访问地址信息
    http://localhost:10001/aopStudent/findAll
    在这里插入图片描述

    小结

    这里我们查询效率更高,主要的方式通过分表的方式和aop注解方式进行提升效率方式

  • 相关阅读:
    R语言 titanic 数据挖掘作业
    领域驱动设计(Domain-Driven Design DDD)——通过重构找到深层次模型2
    机器学习 第11章 特征选择与稀疏学习
    VisualStudio Code 支持C++11插件配置
    java-net-php-python-ssm高校学生学业分析及预警系统查重PPT计算机毕业设计程序
    TornadoFx的TableView组件使用
    SpringCloud--链路追踪之Sleuth的简单使用
    【开发备忘】QGroundControl编译
    JavaGUI------------常用的组件(单选、复选框、下拉列表)
    JavaScript面向对象动态添加标签页 (ES6)
  • 原文地址:https://blog.csdn.net/weixin_51885039/article/details/130864542