当前位置: 首页 > news >正文

SpringBoot中一行代码解决字符串向枚举类型转换的问题

1. 场景

在WEB开发,客户端和服务端传输的数据中经常包含一些这样的字段:字段的值只包括几个固定的字符串。 这样的字段意味着我们需要在数据传输对象(Data Transfer Object, DTO)中对该字段进行校验以避免客户端传输的非法数据持久化到我们的系统中。

public record UserCreateDto(String userName,// userType的值为NORMAL, SILVER_CARD, GOLD_CARD, String userType) {}

我们可以采用多种办法验证userType的正确性,如:

方法一:利用Validation和正则表达式进行验证

public record UserCreateDto(String userName,// userType的值为NORMAL, SILVER_CARD, GOLD_CARD@Pattern(regexp = "^NORMAL$|^SILVER_CARD$|^GOLD_CARD$")String userType) {
}

方法二:在代码中写validate方法,在使用到DTO代码中调用validate方法

public record UserCreateDto(String userName,// userType的值为NORMAL, SILVER_CARD, GOLD_CARDString userType) {public void validate() {if (List.of("NORMAL", "SILVER_CARD", "GOLD_CARD").contains(userType)) {return;}throw new IllegalArgumentException("userType must be NORMAL, SILVER_CARD, GOLD_CARD");}
}

比较这两种方法,两种方法各有优缺点:

优点缺点
方法一在DTO创建时(即参数的入口处)就可以验证数据的有效性在@Pattern中使用字符串常量不方便,意味着开发者很难在整个代码中使用统一的自定义常量,为后期的修改带来不便
方法二开发者可以在整个代码中使用统一的自定义常量,方便后续的修改需要开发者主动调用validate方法,容易遗漏调用

2. 面向对象的解决办法

可能你早已想到用枚举来解决上述场景中的问题,没错,在面向对象编程中,枚举是解决这种问题的最好的解决办法。

public enum UserType {NORMAL, SILVER_CARD, GOLD_CARD
}public record UserCreateDto(String userName,// userType的值为NORMAL, SILVER_CARD, GOLD_CARD@NotNullUserType userType) {
}

枚举让我们的参数具有类型约束,并且具有可复用性易修改等特性。

但是在SpringBoot中默认是不支持String到Enum的转换(读者可以尝试一下,不管客户端传入的userType正确与否,在DTO中userType值均为null )。

为了解决这个问题很多开发者都是通过自定义Conveter来进行String到Enum的转换的。如此常见的场景,作为开发者的我们都能想到使用统一的Converter,难到作为框架的开发者想不到?

3. 一行代码解决String到Enum的转换问题

先上解决方案。

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {@Overridepublic void addFormatters(FormatterRegistry registry) {// 通过ApplicationConversionService向应用中注入ConverterApplicationConversionService.configure(registry);}

就是这么简单,在应用中自定义WebMvcConfigurer,覆写addFormatters方法,并通过ApplicationConversionService向应用中注入String到Enum的Converter。

4. 原理分析

通过分析ApplicationConversionService的时序图,我们可以看到ApplicationConversionService最终通过DefaultConversonService调用ConverterRegister向应用注册了StringToEnumConverterFactory,从名字可以看出来StringToEnumConverterFactory就是负责String向Enum转换的。
在这里插入图片描述
StringToEnumConverterFactory的代码如下:

final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {@Overridepublic <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {return new StringToEnum(ConversionUtils.getEnumType(targetType));}private static class StringToEnum<T extends Enum> implements Converter<String, T> {private final Class<T> enumType;StringToEnum(Class<T> enumType) {this.enumType = enumType;}@Override@Nullablepublic T convert(String source) {if (source.isEmpty()) {// It's an empty enum identifier: reset the enum value to null.return null;}return (T) Enum.valueOf(this.enumType, source.trim());}}
}

可以看出,StringToEnumConverterFactory中也是通过Enum的valueOf方法完成String到Enum的转换的。

5. 方案的不足

采用Spring框架提供的StringToEnum Converter带给我们便利性的同时,也存在一些约束,如:

  • Enum中实例的大小写必须和字符串的大小写一致,如字符串是小写的normal、silver_card、gold_card,Enum定义的实例也必须是normal、silver_card、gold_card,这个可能并不符合代码规范(通常Enum的实例都要球全大写);
  • 字符串中包含一些特殊字符是Java命名规范不允许的,如中划线。

因此,选用哪种方法完成字符串到Enum的转换还要根据实际的应用场景出发。

相关文章:

SpringBoot中一行代码解决字符串向枚举类型转换的问题

1. 场景 在WEB开发&#xff0c;客户端和服务端传输的数据中经常包含一些这样的字段&#xff1a;字段的值只包括几个固定的字符串。 这样的字段意味着我们需要在数据传输对象&#xff08;Data Transfer Object, DTO&#xff09;中对该字段进行校验以避免客户端传输的非法数据持…...

Praat之基频分析

Praat之基频分析 测量基频F0的方法 自相关 Autocorrelation&#xff08;易出现pitch-halving\pitch-double&#xff09;窄带谱图 Narrowband spectrogram&#xff08;第一谐波就是基频&#xff09;倒谱分析 Cepstral analysis测量声门波 glottal pluse&#xff08;通过波形&a…...

乡村企业门户网站

技术&#xff1a;Java、JSP等摘要&#xff1a;随着时代的发展&#xff0c;电脑与Internet已经进入我们的生活。信息时代的来临&#xff0c;知识经济的扩张&#xff0c;网站已越来越靠近我们的生活。据CNNIC报告显示&#xff0c;中国上网用户有6800万。通过Internet来经营运作一…...

Deploy Workshop|DIY部署环境,让OceanBase跑起来

2023 年 3 月 25 日&#xff0c;我们将在北京开启首次 OceanBase 开发者大会&#xff0c;与开发者共同探讨单机分布式、云原生、HTAP 等数据库前沿趋势&#xff0c;分享全新的产品 Roadmap&#xff0c;交流场景探索和最佳实践&#xff0c;此外&#xff0c;OceanBase 开源技术全…...

【CPP】定义一个类

一&#xff1a;当实现一个类的时候&#xff0c;编译器都做了什么 前言&#xff1a;当我们实现一个类的时候&#xff0c;编译器为我们做了什么&#xff1b;在对类进行操作的时候&#xff0c;有哪些特殊的成员函数可以帮助我们更好的操纵类&#xff1b; class A {A();//默认构造…...

谷歌广告投放步骤流程是什么?一文带你全方位了解实操细节

谷歌&#xff0c;大家都不陌生吧&#xff0c;一个人们很常用的搜索引擎。而谷歌还可以打广告&#xff0c;即谷歌广告&#xff0c;那这跟跨境电商有什么关心呢&#xff1f;东哥告诉大家&#xff0c;关系大了去了&#xff0c;毕竟如果用户搜索与我们相关的关键词&#xff0c;就有…...

TypeScript 怎么去查找类型定义的?

TypeScript 怎么去查找类型定义的&#xff1f;类型文件分类第三方库的类型自定义类型结论类型文件分类 我们项目中的类型文件分为两种&#xff1a;一类是第三方库的类型&#xff0c;一类是在项目中的自定义类型。 第三方库的类型 &#xff08;1&#xff09;Jquery&#xff1…...

NPM包管理器

文章目录一、NPM包管理器1、简介2、安装NPM3、使用npm管理项目3.1项目初始化3.2修改npm镜像3.3 npm install命令的使用3.4其它命令一、NPM包管理器 1、简介 什么是NPM NPM全称Node Package Manager&#xff0c;是Node.js包管理工具&#xff0c;是全球最大的模块生态系统&…...

IT英语记录

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言1、Classification2、Logistic Regression3、网络相关3.1 WAN&#xff08;Wide Area Network&#xff09;、LAN&#xff08;Local Area Network&#xff09;网络…...

SRS4.0 源码分析- RTC模块相关类

前言 本文介绍SRS4.0涉及RTC模块的C类&#xff0c;主要包括RTC Server和Session相关的。 SrsGoApiRtcPlay 处理webrtc client的播放请求&#xff0c;解析client的offer&#xff0c;并且生成server的answer&#xff0c;并且为这次请求创建一个session。SrsRtcServer 监听udp端…...

数位DP

数位dp的题目一般会问&#xff0c;某个区间内&#xff0c;满足某种性质的数的个数。 利用前缀和&#xff0c;比如求区间[l,r]中的个数&#xff0c;转化成求[0,r]的个数 [0,l-1]的个数。利用树的结构来考虑&#xff08;按位分类讨论&#xff09; 1081. 度的数量 #include<…...

剑指offer(一)-链表

&#xff08;一&#xff09;找出链表的环的入口结点 JZ23 链表中环的入口结点 中等 通过率&#xff1a;36.78% 时间限制&#xff1a;1秒 空间限制&#xff1a;64M 知识点链表哈希双指针 描述 给一个长度为n链表&#xff0c;若其中包含环&#xff0c;请找出该链表的环的入口结点…...

CDH大数据平台入门篇之搭建与部署

一、CDH介绍 1.CDH 是一个强大的商业版数据中心管理工具 提供了各种能够快速稳定运行的数据计算框架&#xff0c;如Spark&#xff1b; 使用Apache Impala做为对HDFS、HBase的高性能SQL查询引擎&#xff1b; 使用Hive数据仓库工具帮助用户分析数据&#xff1b; 提供CM安装HBas…...

Spark Join

Spark Join关联形式内关联外关联左外关联右外关联全外关联左半/逆关联关联机制NLJSMJHJ分发模式Join 选择等值 Join不等值 JoinJoin 按照关联形式&#xff08;Join Types&#xff09;划分 : 内关联、外关联、左关联、右关联 Join 按实现机制划分 : NLJ (Nested Loop Join) 、S…...

数字的转化规则?

数字的转化规则&#xff1f;js将字符串转换为数字的方式有哪些&#xff1f;1. 使用 parseInt()2. 使用 Number()3. 使用一元运算符 ()4.使用parseFloat()5. 使用 Math.floor()和Math.ceil()6.乘以数字7. 双波浪号 (~~) 运算符其它值到数字的转化规则1.Undefined 类型2.Null 类型…...

MySQL面试题-锁相关

目录 1.MySQL 锁的类型有哪些呢&#xff1f; 2.如何使用全局锁 3.如果要全库只读&#xff0c;为什么不使用set global readonlytrue的方式&#xff1f; 4.表级锁和行级锁有什么区别&#xff1f; 5.行级锁的使用有什么注意事项&#xff1f; 6.InnoDB 有哪几类行锁&#xff…...

Windows 终端编译 C代码

E:\My_SoftWare\Window gcc\windowbianji\mingw64\bin 此电脑--》属性--》系统--》高级系统设置--》环境变量--》Path--》新建--》粘贴路径 E:\My_SoftWare\Window gcc\windowbianji\mingw64\bin 打开命令终端 E: 回车 dir 显示所有文件 cd E:\My_SoftWare\Window gcc\C_co…...

SpringCloud:Feign的使用及配置

目录 Feign的使用及配置 1、Feign替代RestTemplate 2、使用Fegin步骤 3、自定义配置 4、Feign使用优化 5、Feign的最佳实践方式 Feign的使用及配置 1、Feign替代RestTemplate RestTemplate方式远程调用的问题 问题&#xff1a; 1、代码可读性差&#xff0c;编程体验不同…...

Parquet学习与使用之BloomFilter的应用

写在前面 最近在自己做自定义的OLAP系统&#xff0c;文件格式上用的是Parquet&#xff0c;但是发现Parquet各个API的示例代码很少。所以就打算把这个系列的文章写一下。 1. Parquet的Filter Parquet的过滤支持两大类&#xff0c;一类是基于Footer中的元数据进行RowGroup级别…...

95%置信区间计算-理解

机器学习中做多次试验后&#xff0c;需要计算指标的95%置信区间。 假设做了10次试验&#xff0c;计算得出的某指标分别为{x1,…,x10} 其均值为μ(x1...x10)/10\mu(x1 ... x10)/10μ(x1...x10)/10 方差σ∑(xi−μ)2/10\sigma\sum(x_i -\mu)^2/10σ∑(xi​−μ)2/10 95%置信…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...