Java:Springboot和React中枚举值(数据字典)的使用

这篇具有很好参考价值的文章主要介绍了Java:Springboot和React中枚举值(数据字典)的使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、开发中的需求

开发和使用过程中,通常会涉及四个角色:数据库管理员、后端开发人员、前端开发人员、浏览者

  • 数据库使用int类型的数值进行存储(eg: 0、1、2)
  • Java代码使用enum枚举类型的对象进行逻辑判断(eg: SexEnum.UNKOWN SexEnum.MAN、SexEnum.WOMAN)
  • 接口返回枚举值的字符串形式用于必要的逻辑判断(eg: UNKOWN、MAN、WOMAN)
  • 显示给用户查看(eg: 未知、男性、女性)
使用方 数值类型 用途 示例
数据库 int数值 存储 0、1、2
后端代码 Enum枚举类 逻辑判断 SexEnum.UNKOWN SexEnum.MAN、SexEnum.WOMAN
前端代码 string常量字符串 逻辑判断 UNKOWN、MAN、WOMAN
用户视图 string字符串 查看 未知、男性、女性

假设:

1、如果后端返回数字,数字本身没有很直观的意思,不便于前端人员检查问题,如果书写错误,同样会导致不容易发现的问题。

2、如果后端返回用户友好的字符串,前端如果需要做逻辑判断就很不好,毕竟不知道产品经理什么时候会把显示的内容修改掉,比如:男性 改为 男

3、如果后端返回枚举类型的常量字符串,那每次需要显示的时候,都必须做一个映射转换,前端人员也很苦恼

综上:

后端同时返回 枚举字符串 和 用户友好的字符串 比较好,既方便前端人员做逻辑判断,也方便给用户展示;

一般情况下,枚举类型统一在后端维护,如果需要修改,也只需要修改一个地方就可以

如果,前端也需要使用枚举值进行逻辑判断,那么前端也需要和后端约定好的映射关系自己定义好枚举,可以直接使用常量字符串作为枚举,前端显示的值可以和后端约定好,什么数值,显示什么字符串

同时,需要给前端返回一个枚举映射关系表,用于下拉选择等业务

2、实现效果

1、列表页

  1. 顶部筛选类型由接口返回,接口增加类型后,前端代码不用修改,直接生效
  2. 列表性别 列,直接显示后端返回sexLabel的字段
  3. 列表颜色 列,由于前端需要根据不同的值,做一些逻辑判断,所以前端代码也需要做好枚举,做逻辑判断,此时需要注意默认值 ,预防后端增加类型之后,前端代码增加容错

Java:Springboot和React中枚举值(数据字典)的使用,Java学习路线,java,spring boot,react.js
2、添加页

性别颜色 都使用后端返回的配置数据即可,后端增加类型数据之后,前端无需修改代码
Java:Springboot和React中枚举值(数据字典)的使用,Java学习路线,java,spring boot,react.js

3、后端代码

配合MyBatis-Plus使用,可以很容易进行数据库和代码之间的转换

定义3个值,由后端代码统一维护

code  # 用于数据库存储
value # 用于后端和前端的逻辑判断
label # 用户展示给用户

如果有其他属性,也可以增加

先定义一个通用的枚举接口

package com.example.demo.enums;

/**
 * 字典枚举接口
 */
public interface IDictEnum {
    Integer getCode();

    String getLabel();

    String name();

    // @JsonValue // 标记响应json值
    default String getValue() {
        return this.name();
    }
}


定义枚举类

package com.example.demo.enums;

import com.baomidou.mybatisplus.annotation.EnumValue;

/**
 * 性别枚举
 */
public enum SexEnum implements IDictEnum {

    /**
     * 男性
     */
    MAN(1, "男性"),

    /**
     * 女性
     */
    WOMEN(2, "女性");

    /**
     * 存储值
     */
    @EnumValue // 配置 mybatis-plus 使用 标记数据库存的值是 code
    private final Integer code;

    /**
     * 显示值
     */
    private final String label;

    SexEnum(Integer code, String label) {
        this.code = code;
        this.label = label;
    }

    @Override
    public Integer getCode() {
        return this.code;
    }

    @Override
    public String getLabel() {
        return this.label;
    }
}

自动扫描枚举类

package com.example.demo.config;

import com.example.demo.vo.EnumVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 枚举配置类
 */
@Slf4j
@Component
public class DictEnumConfig {

    // 通同匹配
    private static final String RESOURCE_PATTERN = "/**/*Enum.class";

    // 扫描的包名
    private static final String BASE_PACKAGES = "com.example.demo.enums";

    private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();

    @Bean(name = "enumConfig")
    public Map<String, List<EnumVO>> enumConfig() {
        Map<String, List<EnumVO>> enumMap = new HashMap<>();

        try {
            // 根据classname生成class对应的资源路径,需要扫描的包路径
            //ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            String pattern = ClassUtils.convertClassNameToResourcePath(BASE_PACKAGES) + RESOURCE_PATTERN;
            // 获取classname的IO流资源
            Resource[] resources = resourcePatternResolver.getResources(pattern);
            // MetadataReaderFactory接口 ,MetadataReader的工厂接口。允许缓存每个MetadataReader的元数据集
            MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);

            for (Resource resource : resources) {
                if (resource.isReadable()) {
                    // 通过class资源(resource)生成MetadataReader
                    MetadataReader reader = readerFactory.getMetadataReader(resource);
                    // 获取class名
                    String className = reader.getClassMetadata().getClassName();
                    Class<?> clz = Class.forName(className);

                    if (!clz.isEnum()) {
                        continue;
                    }

                    // 将枚举类名首字母转小写,去掉末尾的Enum
                    enumMap.put(clz.getSimpleName(), this.enumToList(clz));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return enumMap;
    }

    public List<EnumVO> enumToList(Class<?> dictEnum) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        List<EnumVO> list = new ArrayList<>();

        Method valuesMethod = dictEnum.getMethod("values");
        Object[] values = (Object[]) valuesMethod.invoke(null);

        for (Object obj : values) {
            EnumVO enumVO = new EnumVO();
            BeanUtils.copyProperties(obj, enumVO);
            list.add(enumVO);
        }

        return list;
    }
}

4、前端代码

前端定义一个全局的变量,来存储数据字典,可以在应用初始化前就请求接口获取数据,确保后续组件中正常使用

import http from "../api/index.js";

/**
 * 全局静态数据
 */
export const globalData = {
  SexEnum: [],
  ColorEnum: [],
};

// 初始化
export async function initGlobalData() {
  const res = await http.get("/getEnumConfig");

  for (const key in globalData) {
    globalData[key] = res[key];
  }
}

// === getter ===
export function getSexEnumFilterOptions() {
  console.log(globalData);

  return [{ value: "", label: "全部" }, ...globalData.SexEnum];
}

export function getSexEnumOptions() {
  return globalData.SexEnum;
}

export function getColorEnumOptions() {
  return globalData.ColorEnum;
}

前端需要进行逻辑判断,可自行枚举

/**
 * 颜色枚举,前端代码需要逻辑判断
 */
export const ColorEnum = {
  // 红色
  RED: 'RED',
  // 绿色
  GREEN: 'GREEN',
  // 蓝色
  BLUE: 'BLUE',
};

export const ColorEnumOptions = [
  {
    // 红色
    value: ColorEnum.RED,
    color: 'error',
  },
  {
    // 绿色
    value: ColorEnum.GREEN,
    color: 'success',
  },
  {
    // 蓝色
    value: ColorEnum.BLUE,
    color: 'processing',
  },
];

export function getColorEnumColor(value) {
  return (
    ColorEnumOptions.find((item) => item.value === value)?.color || 'default'
  );
}

5、接口数据

直接返回value和label字段,便于直接对接element和antd UI组件库,不需要再进行数据转换

获取枚举配置

GET http://localhost:8080/getEnumConfig

{
  "ColorEnum": [
    {
      "value": "RED",
      "label": "红色"
    },
    {
      "value": "GREEN",
      "label": "绿色"
    },
    {
      "value": "BLUE",
      "label": "蓝色"
    }
  ],
  "SexEnum": [
    {
      "value": "MAN",
      "label": "男性"
    },
    {
      "value": "WOMEN",
      "label": "女性"
    }
  ]
}

前端提交数据

POST http://localhost:8080/addUser
Content-Type: application/json

{
    "name": "Steve",
    "sex": "WOMEN"
}

前端获取数据

GET http://localhost:8080/getUserList

[
    {
      "id": 21,
      "name": "Steve",
      "sex": "WOMEN",
      "color": null,
      "sexLabel": "女性",
      "colorLabel": ""
    }
]

sexLabel 为方便前端显示数据而增加的字段

6、完整代码

后端代码:https://github.com/mouday/spring-boot-demo/SpringBoot-Enum
前端代码:https://gitee.com/mouday/react-enum文章来源地址https://www.toymoban.com/news/detail-694481.html

7、参考文章

  1. 看看人家在接口中使用枚举类型的方式,那叫一个优雅!
  2. Spring IoC资源管理之ResourceLoader
  3. 通过Spring包扫描的形式将枚举以字典的形式返回
  4. MyBatis-Plus:通用枚举
  5. 用反射的方法获取枚举值(数据字典)

到了这里,关于Java:Springboot和React中枚举值(数据字典)的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引

    自学Java怎么学,找对方向很关键!在这里为大家分享最全的架构师级 Java全栈学习路线及知识清单 ! 包含 JavaSE基础 , JavaWeb , SSM框架 , Linux运维 , 分布式与微服务 , 大数据开发 ~ 本人研究人生一枚,自学Java中,后期会逐步分享清单中所有技术与知识的详细介绍文章,

    2024年02月03日
    浏览(49)
  • Java学习星球,Java学习路线

    大家好,我是哪吒,一个靠着热情攀登至C站巅峰的中年男子,CSDN粉丝40万+,2022CSDN博客之星Top1,2021CSDN博客之星Top2,8年开发管理经验,目前就职于某一线大厂,专注Java硬核干货分享,立志做到Java赛道全网Top N。 最近有很多小伙伴参加了我的新星计划2023·第1期【Java】赛道报

    2024年02月02日
    浏览(37)
  • (四)springboot 数据枚举类型的处理(从前端到后台数据库)

    枚举是一个被命名的整型常数的集合,用于声明一组带标识符的常数。枚举在曰常生活中很常见,例如一个人的性别只能是“男”或者“女”,一周的星期只能是 7 天中的一个等。类似这种当一个变量有几种固定可能的取值时,就可以将它定义为枚举类型。 注意实体类里的性

    2024年02月04日
    浏览(34)
  • Java学习路线(16)——异常

    一、异常 1、概念: 程序在“编译”或“执行”时可能出现的问题。(语法错误不算异常) 2、常见的异常 数组索引越界 空指针 日期格式化 … 3、作用: 触发异常后,如果没有提前处理,JVM将终止,提高程序的健壮性和安全性。 4、异常体系 Error: 系统级别问题、JVM退出等

    2024年02月06日
    浏览(50)
  • Java后端学习路线

    Java后端开发是一门非常广泛的领域,需要掌握的知识点也非常多。以下是一个比较全面的Java后端学习路线: 1. Java基础:掌握Java语言的基本语法、面向对象特性、集合框架、异常处理等基础知识。 2. 数据库基础:熟悉常用的关系型数据库(如MySQL、Oracle等)的基本操作、S

    2024年02月10日
    浏览(62)
  • Java学习路线(23)——反射机制

    一、概述 (一)什么是反射: 反射指的是任何一个Class类,在“运行时”都可以直接得到全部成分。 (二)动态可获取的对象: 构造器对象——Constructor,成员变量对象——Field,成员方法对象——Method。 (三)反射关键: 第一步都是得到编译后的Class对象,然后可以获得

    2024年02月08日
    浏览(44)
  • Java学习路线(4)——程序流程控制

    一、顺序结构 顺序结构是程序默认流程。 二、分支结构 if 作用: 主要用于区间匹配。 格式1: 格式2: 格式3: 注意: 当语句体只有一条程序时,可以将{}去除。 switch 作用: 适用于值匹配分支选择,即作为字典进行查找。 格式: 注意: (1)表达式类型仅支持byte、short、

    2024年02月05日
    浏览(45)
  • Java学习路线(8)——面向对象基础(2)

    一、static 概念: static是静态的意思,可以修饰成员变量和成员方法。当修饰成员变量时,在内存中 只存储一份 ,可以被 共享访问、修改 。当修饰成员方法时,可以被 共享访问 ,也被称为 公共方法 。 静态成员变量 访问格式: 【类名.静态成员变量】或【对象名.静

    2024年02月05日
    浏览(49)
  • 丁鹿学堂:前端学习进阶指南之react入门(react在html中使用数据绑定和修改)

    在html中使用react 今天跟大家分享react的基础语法。 我们采用最简单的方法,就是在html中引入react 因为一上来就使用脚手架的话,很多配置大家不一定清楚。 而在html中使用react的话,可以直接去学习react最基本的语法。 这是零基础学习react的最佳实践。 引入react的依赖 react也

    2024年02月14日
    浏览(63)
  • 【大数据】大数据学习路线

    首先明确一点:大数据涉及的知识面广度还是有的,需要学习的组件繁多,想要每一项精通几乎不可能,所以企业在招聘的时候会进行细分,基于某个方向进行招聘,比如,数据仓库工程师、数据治理工程师、大数据开发工程师、大数据算法工程师、ETL工程师等。我们

    2024年01月18日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包