还在用if校验参数?SpringBoot使用validation优雅实现参数校验

👩🏽‍💻个人主页:阿木木AEcru (更多精彩内容可进入主页观看)

🔥 系列专栏:《Docker容器化部署系列》 《Java每日面筋》

💹每一次技术突破,都是对自我能力的挑战和超越。

一、前言

你还在使用if else 的方式进行入参的校验吗?

能看的出来,这样的校验方式看起来很不优雅,当然也是能达到目的。如果说有非常多的参数需要校验的话,就要写非常多的if else ,就像老太婆的裹脚布一样,又臭又长,让人看起来非常的难受。话不多说,下面我就给大家推荐一个优雅校验入参的方式吧!

二、使用SpringBoot-Validation

2.1 添加依赖

   <!-- spring-boot 2.3及以上的版本需要引入包 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>

2.2 注解使用说明

注解说明
@NotNull验证注解的元素必须非空(即非null且非空字符串)
@NotEmpty验证注解的字符串元素必须非空且长度大于0
@NotBlank验证注解的字符串元素必须非空,并且至少包含一个非空白字符
@Null验证注解的元素必须为null
@AssertTrue验证布尔值必须为true
@AssertFalse验证布尔值必须为false
@Size验证注解的字符串或集合元素的数量是否在指定的范围内
@Length验证注解的字符串元素的长度是否在指定的范围内
@Min验证注解的数值是否大于或等于指定的最小值
@Max验证注解的数值是否小于或等于指定的最大值
@DecimalMin验证注解的数值是否大于或等于指定的十进制最小值
@DecimalMax验证注解的数值是否小于或等于指定的十进制最大值
@Email验证注解的字符串是否是有效的电子邮件地址
@Pattern验证注解的字符串是否与指定的正则表达式匹配
@Past验证注解的日期元素是否在当前日期之前
@Future验证注解的日期元素是否在当前日期之后
@Valid递归验证关联对象的属性
@Positive验证注解的数值是否大于0
@Negative验证注解的数值是否小于0
@Digits验证注解的数值是否有正确的整数位数和小数位数

2.3 注解应用到实体


@Data
public class TestOneDTO {@NotNull(message = "用户名不允许为空")@Size(min = 3, max = 50, message = "用户名长度必须在3到50个字符之间")private String username;@NotNull(message = "密码不允许为空")@Size(min = 6, max = 20, message = "密码长度必须在6到20个字符之间")private String password;@Email(message = "电子邮箱格式不正确")private String email;@Min(value = 18, message = "年龄必须至少为18岁")@Max(value = 100, message = "年龄不允许超过100岁")private Integer age;@Past(message = "生日不能大于当前时间")private LocalDateTime birthDate;@Pattern(regexp = "^((\\+86)|(0086))?(-\\d{3}-)?\\d{8}$", message = "手机号码格式不正确")private String phoneNumber;// 校验对象中的另一个对象(对象内容如下)@Validprivate Address address;public boolean validate() {if (username == null || username.length() < 3 || username.length() > 50) {System.out.println("用户名长度必须在3到50个字符之间");return false;}if (password == null || password.length() < 6 || password.length() > 20) {System.out.println("密码长度必须在6到20个字符之间");return false;}if (email == null || !email.contains("@")) {System.out.println("电子邮箱格式不正确");return false;}if (age == null || age < 18 || age > 100) {System.out.println("年龄必须至少为18岁且不允许超过100岁");return false;}if (birthDate != null && birthDate.isAfter(LocalDateTime.now())) {System.out.println("生日必须是过去的时间");return false;}if (phoneNumber != null && !phoneNumber.matches("^((\\+86)|(0086))?(-\\d{3}-)?\\d{8}$")) {System.out.println("手机号码格式不正确");return false;}return true;}
}@Data
class Address {@NotBlank(message = "地址不允许为空")@Size(min = 5, max = 200, message = "地址长度必须在5到200个字符之间")private String street;@NotBlank(message = "城市不允许为空")private String city;}

2.4 测试是否生效

可以看出,这里没有任何请求内容依然成功了,这是因为还少了一个注解 @Valid 需要在入参前面添加上。


加上 @Valid 注解后,再次请求可以看到已经有异常信息了,这时就能使用 全局异常处理器 进行捕获处理,格式化响应的异常信息内容。

2.5 全局异常捕获

全局异常捕获类如下


@ControllerAdvice
@ResponseBody
@Component
@Slf4j
public class GlobalExceptionHandler {/*** @Valid校验异常处理* @param request* @param e* @return*/@ExceptionHandler(value = MethodArgumentNotValidException.class)public R methodArgumentNotValidExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException e){StringBuffer sb = new StringBuffer();List<ObjectError> allErrors = e.getAllErrors();if (CollUtil.isNotEmpty(allErrors)){for (ObjectError allError : allErrors) {sb.append(allError.getDefaultMessage()).append("|");}}return R.of(CommonConstants.FAIL,null,sb.toString());}@ExceptionHandler(value = Exception.class)public R exceptionHandler(HttpServletRequest request, Exception e){e.printStackTrace();log.info("Exception异常全局拦截:{}",e.getMessage());// 其余异常简单返回为服务器异常return R.failed("服务器繁忙,请联系管理员或稍后再试!");}}

加上之后再次请求


异常信息已经被格式化了,如果需要其他格式的异常信息提示,可以自主调整相关的异常信息格式化内容来满足你的需求。
在这里需要注意的是,当在同一个字段上使用多个注解时,校验框架会按照它们在类定义中出现的顺序进行校验。如果一个字段违反了前面的校验规则,后续的校验可能不会执行。

三、结尾

感谢观看至此,希望该文章能够帮助到您提升知识和技能。如果您喜欢我的内容,请不要忘记点赞和分享哦!👍
在这里插入图片描述

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

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

相关文章

鸿蒙APP架构及开发入门

1.鸿蒙系统 1.1 什么是鸿蒙 鸿蒙是一款面向万物互联时代的、全新的分布式操作系统。 在传统的单设备系统能力基础上&#xff0c;鸿蒙提出了基于同一套系统能力、适配多种终端形态的分布式理念&#xff0c;能够支持手机、平板、智能穿戴、智慧屏、车机、PC、智能音箱、耳机、…

深入解析食堂采购系统源码:打造高效食材供应链APP的核心

本篇文章&#xff0c;笔者将从系统架构、关键模块、技术选型和优化策略等方面&#xff0c;深入解析食堂采购系统的源码&#xff0c;为您揭示打造高效食材供应链APP的核心要点。 一、系统架构 食堂采购系统通常采用分层架构&#xff0c;以保证系统的可维护性和扩展性。主要包括…

Android 列表或网格形式展示大量数据:RecyclerView(二):缓存复用

一、缓存复用 为什么要了解这个呢&#xff1f;当我们rv出现卡顿&#xff0c;出现闪烁的时候&#xff0c;你应该如何优化呢&#xff1f; 为什么有时候onCreateViewHolder会被调用&#xff1f;onBindVilewHolder会被调用呢&#xff1f; visiable的使用&#xff0c;会导致重新绘制…

Linux---git工具

目录 初步了解 基本原理 基本用法 安装git 拉取远端仓库 提交三板斧 1、添加到缓存区 2、提交到本地仓库 3、提交到远端 其他指令补充 多人协作管理 windows用户提交文件 Linux用户提交文件 初步了解 在Linux中&#xff0c;git是一个指令&#xff0c;可以帮助我们做…

jionlp根据词典进行行政区划补全

背景 需要对地址数据进行行政区划补全的,可以用下面的方法,当然是有条件限制的,只限于提供本省的词典和补全本身的地址数据,否则容易错乱 效果测试 lp = LocationParser() loc = 侨英街道乐海南里170号 res = lp(loc) print(res)1、安装或者更新 python安装 pip insta…

Python爬虫技术 第18节 数据存储

Python 爬虫技术常用于从网页上抓取数据&#xff0c;并将这些数据存储起来以供进一步分析或使用。数据的存储方式多种多样&#xff0c;常见的包括文件存储和数据库存储。下面我将通过一个简单的示例来介绍如何使用 Python 爬取数据&#xff0c;并将其存储为 CSV 和 JSON 文件格…

LangChain4j-RAG高级-核心概念

RetrievalAugmentor整体概念 简单总结一下 LangChain4j中对于RetrievalAugmentor这里官方描述的比较模糊, 只在 DefaultRetrievalAugmentor章节给出来了一个灵感来源的文章(LangChain框架中的设计思路)和一个研究报告, 有兴趣可以看一下: Deconstructing RAGhttps://arxiv.o…

FRP配置内网穿透52版本以上适用

简述 适用frp配置内网穿透来说我们需要进行简单的区分&#xff0c;具有公网IP的服务器我们简称为服务端&#xff0c;内网的服务器我们可以简称为客户端&#xff0c;frp需要针对不同的服务器配置不同的文件 下载安装包 Linux下载地址 https://github.com/fatedier/frp/relea…

Flink SQL 的工作机制

前言 Flink SQL 引擎的工作流总结如图所示。 从图中可以看出&#xff0c;一段查询 SQL / 使用TableAPI 编写的程序&#xff08;以下简称 TableAPI 代码&#xff09;从输入到编译为可执行的 JobGraph 主要经历如下几个阶段&#xff1a; 将 SQL文本 / TableAPI 代码转化为逻辑执…

svelte - 5. 动画

动画函数 函数作用使用场景示例引入的模块使用示例tweened运动动画,做到渐变的效果控制进度条速度svelte/motion函数:tweened(0, { duration: 400 })spring运动动画,用于频繁变化的值控制鼠标红点顺滑度svelte/motion函数:spring({ x: 50, y: 50 }, { stiffness: 0.1, damp…

华为ensp中ISIS原理与配置(超详细)

isis原理与配置 8-20字节&#xff1b; 地址组成&#xff1a;area id&#xff0c;system id&#xff0c;set三部分组成&#xff1b; system id占6个字节&#xff1b;sel占一个&#xff0c;剩下的为area id区域号&#xff1b; system id 唯一&#xff0c; 一般将router id 配…

深入学习H264和H265

目录 前言 一 什么是H264/H265&#xff1f; H.264 (MPEG-4 AVC) H.265 (HEVC) 二 为什么要学习H264和H265&#xff1f; 1. 深入理解视频压缩原理 2. 硬件优化与集成 3. 调试与故障排除 4. 持续的技术更新 三 NAL&#xff08;Network Abstraction Layer&#xff09;详解…

【前端 11】初探DOM

JavaScript 对象 - DOM 初探 在Web开发中&#xff0c;DOM&#xff08;Document Object Model&#xff0c;文档对象模型&#xff09;是一个至关重要的概念。它不仅仅是一个API&#xff0c;更是Web页面与JavaScript代码之间的桥梁&#xff0c;允许开发者通过编程的方式动态地访问…

Redis:快速键值存储的入门指南

一、什么是Redis&#xff1f; Redis&#xff0c;全称为Remote Dictionary Server&#xff0c;是一种开源的、高性能的键值&#xff08;Key-Value&#xff09;存储系统。与传统的关系型数据库不同&#xff0c;Redis将数据主要存储在内存中&#xff0c;因此能够提供极低延迟的数…

【Unity2D 2022:UI】TextMeshPro组件无法显示中文

在Unity中创建了一个预制体Card&#xff0c;上面挂载了一些Text Mesh Pro组件用来显示卡牌信息。但是在输入文字后&#xff0c;发现无法显示中文&#xff1a; 解决方法如下&#xff1a; 一、导入字体文件&#xff08;ttf格式&#xff09;和常用字字集&#xff08;txt格式&…

Linux--Socket编程UDP

前文&#xff1a;Socket套接字编程 UDP协议特点 无连接&#xff1a;UDP在发送数据之前不需要建立连接&#xff0c;减少了开销和发送数据之前的时延。尽最大努力交付&#xff1a;UDP不保证可靠交付&#xff0c;主机不需要维持复杂的连接状态表。面向报文&#xff1a;UDP对应用层…

算法:[递归/搜索/回溯]二叉树的深搜

目录 题目一&#xff1a;计算布尔二叉树的值 题目二&#xff1a;求根节点到叶节点数字之和 题目三&#xff1a;二叉树剪枝 题目四&#xff1a;验证二叉搜索树 题目五&#xff1a;二叉搜索树中第k小的元素 题目六&#xff1a;二叉树的所有路径 题目一&#xff1a;计算布尔…

【C语言】宏定义常量加 ; 的错误

我在使用宏定义常量定义二维数组的时候&#xff0c;编译器报错&#xff1a;应输入“]”&#xff0c;如下&#xff1a; 原因是宏定义不是C语言规定的语句&#xff0c;它的结尾不加 ; 。在上图的 int mine[EASY_ROWS][EASY_COLS]; 中&#xff0c;把 EASY_ROWS 替换为了 9;2; &…

【秋招笔试题】小明的美食

解析&#xff1a;思维题。由于需要互不相同&#xff0c;每次操作取重复的值与最大值相加即可&#xff0c;这样即可保证相加后不会新增重复的值。因此统计重复值即可。 #include <iostream> #include <algorithm>using namespace std; const int maxn 1e5 5; int…

大模型算法面试题(十一)

本系列收纳各种大模型面试题及答案。 1、说一下目前主流或前沿的预训练模型&#xff0c;包括nlp&#xff08;百度ERNIE3.0&#xff0c;华为NEZHA&#xff0c;openAI gpt-3&#xff0c;nvidia MegatronLM&#xff0c;macrosoft T5&#xff09;和cv&#xff08;我只知道CLIP&…