Spring Boot 实战:基于 Validation 注解实现分层数据校验与校验异常拦截器统一返回处理
1. 概述
本文介绍了在spring boot框架下,使用validation数据校验注解,针对不同请求链接的前端传参数据,进行分层视图对象的校验,并通过配置全局异常处理器捕获传参校验失败异常,自动返回校验出错的异常数据。
2. 依赖包导入
导入校验注解,本文使用的是spring boot框架下的validation校验包,首先将如下代码配置到pom.xml中并更新maven
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>
3. 校验规则注解
在java Bean中针对需要校验的属性字段编写对应的校验注解
3.1 视图对象分层的意义
对同一个数据库中同一张表进行不同操作,前端传入的入参校验法则是不一样的,甚至相互之间还有冲突,因此针对同一个javaBean使用同一套入参数据校验是不可行的。
举个例子,比如对如下java Bean数据进行新增操作和更新操作,其ID字段的校验规则就完全冲突,新增时,要求前端不传入,因为这个字段是数据库自增字段。而在更新操作时,ID字段是必传字段,因为是通过这个字段定位到具体要修改的那条数据。因此需要根据不同的入参需求建立分层视图对象,进行分别校验。
@Data
public class Employee {private Long id;private String name;private Integer age;private String email;private String gender;private String address;private BigDecimal salary;
}
3.2 分层对象的设计模式
设计模式:单一职责 (新建和修改用到的校验规则不一致)
JavaBean也要分层,各种xxO:
Pojo:普通java类
Dao:Database Access Object : 专门用来访问数据库的对象
DTO:Data Transfer Object: 专门用来传输数据的对象;
TO:transfer Object: 专门用来传输数据的对象;
BO:Business Object: 业务对象(Service),专门用来封装业务逻辑的对象;
VO:View/Value Object: 值对象,视图对象(专门用来封装前端数据的对象)
3.3 视图对象最佳实践举例
根据如上设计模式,本文分别针对新增和更新操作建立两个视图对象,如下所示:
新增视图对象,仅供新增接口使用的入参接收对象
@Data
public class EmployeeAddVo {@NotBlank(message = "姓名不能为空")private String name;@NotNull(message = "年龄不能为空")@Max(value = 150, message = "年龄不能超过150岁")@Min(value = 0, message = "年龄不能小于0岁")private Integer age;@Email(message = "邮箱格式不正确")private String email;@Pattern(regexp = "^男|女$",message = "性别只能为男或者女")private String gender;private String address;private BigDecimal salary;
}
更新视图对象,仅供更新接口使用的入参接收对象
@Data
public class EmployeeUpdateVo {@NotNull(message = "id不能为空")private Long id;private String name;@Max(value = 150, message = "年龄不能超过150岁")@Min(value = 0, message = "年龄不能小于0岁")private Integer age;@Email(message = "邮箱格式不正确")private String email;@Pattern(regexp = "^男|女$",message = "性别只能为男或者女")private String gender;private String address;private BigDecimal salary;
}
3.4 非空校验注解混淆区分
上述注解中运用到了非空校验注解,@NotNull、@NotEmpty、@NotBlank 都是用于在数据校验中检查字段值是否为空的注解,但是它们的用法和校验规则有所不同。
@NotNull (包装类型不为null) : @NotNull 注解是 JSR 303 规范中定义的注解,当被标注的字段值为 null 时,会认为校验失败而抛出异常。该注解不能用于字符串类型的校验,若要对字符串进行校验,应该使用 @NotBlank 或 @NotEmpty 注解。
@NotEmpty (集合类型长度大于0) :@NotEmpty 注解同样是 JSR 303 规范中定义的注解,对于 CharSequence、Collection、Map 或者数组对象类型的属性进行校验,校验时会检查该属性是否为 Null 或者 size()==0,如果是的话就会校验失败。但是对于其他类型的属性,该注解无效。需要注意的是只校验空格前后的字符串,如果该字符串中间只有空格,不会被认为是空字符串,校验不会失败。
@NotBlank (字符串,不为null,切不为" "字符串): @NotBlank 注解是 Hibernate Validator 附加的注解,对于字符串类型的属性进行校验,校验 时会检查该属性是否为 Null 或 “” 或者只包含空格,如果是的话就会校验失败。需要注意的是,@NotBlank 注解只能用于字符串类型的校验。
4. 校验生效注解
在controller层使用 @Valid 告诉 SpringMVC 进行校验,通过在入参中作用@Valid注解,让视图对象中各个属性的数据校验生效,见如下代码:
@RestController
@CrossOrigin
@RequestMapping("api/v1")
public class EmployeeRestController {@Autowiredprivate EmployeeService employeeService;/*** 新增员工;* 要求:前端发送请求把员工的json放在请求体中* @param employee* @return*/@PostMapping("/employee")public R add(@RequestBody @Valid EmployeeAddVo vo){//把vo转为do;Employee employee = new Employee();//属性对拷BeanUtils.copyProperties(vo,employee);employeeService.saveEmp(employee);return R.ok();}/*** 修改员工* 要求:前端发送请求把员工的json放在请求体中; 必须携带id* @param vo* @return*/@PutMapping("/employee")public R update(@RequestBody @Valid EmployeeUpdateVo vo){Employee employee = new Employee();BeanUtils.copyProperties(vo,employee);employeeService.updateEmp(employee);return R.ok();}}
同时还需要配合使用BeanUtils.copyProperties方法,将视图对象对拷贝到数据库对象中,完成数据库的操作。
5. 失败返回处理
编写全局异常处理器,统一返回校验失败提示信息。根据上述@Valid注解作用于入参后,如果数据校验不通过,controller层会自动抛出校验不通过异常:MethodArgumentNotValidException,因此只需要使用全局拦截器捕获这个异常进行统一处理即可。
@RestControllerAdvice // @ControllerAdvice + @ResponseBody
public class GlobalExceptionHandler {@ExceptionHandler(value = MethodArgumentNotValidException.class)public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e){BindingResult result = e.getBindingResult();Map<String,String> errorsMap = new HashMap<>();for (FieldError fieldError : result.getFieldErrors()) {// 1. 获取到属性名String field = fieldError.getField();// 2. 获取到错误信息String defaultMessage = fieldError.getDefaultMessage();errorsMap.put(field,defaultMessage);}return R.error(500,"校验失败",errorsMap);}
}
6. 最终效果展示
通过如上操作后,当进行新增和更新访问请求数据校验不通过时,就会出发数据校验失败异常,通过全局拦截器给前端返回需要的提示的内容:
新增数据校验示例:

更新数据校验示例:

相关文章:
Spring Boot 实战:基于 Validation 注解实现分层数据校验与校验异常拦截器统一返回处理
1. 概述 本文介绍了在spring boot框架下,使用validation数据校验注解,针对不同请求链接的前端传参数据,进行分层视图对象的校验,并通过配置全局异常处理器捕获传参校验失败异常,自动返回校验出错的异常数据。 2. 依赖…...
20241125复盘日记
昨日最票: 南京化纤 滨海能源 广博股份 日播时尚 众源新材 返利科技 六国化工 丰华股份 威领股份 凯撒旅业 华扬联众 泰坦股份 高乐股份高均线选股: 理邦仪器高乐股份日播时尚领湃科技威领股份资金最多的票: 资金攻击最多的票: …...
【Excel】拆分多个sheet,为单一表格
Private Sub 分拆工作表() Application.ScreenUpdating True 让屏幕显示操作过程, Dim sht As Worksheet Dim MyBook As Workbook Set MyBook ActiveWorkbook For Each sht In MyBook.Sheets If sht.Visible True Then 隐藏的sheet跳过,否则会报1004无…...
类和对象plus版
一.类的定义 1.1类定义的格式 图中class为关键字,Stack为类的名字,用{}框住类的主体,类定义完后;不能省略。 为了区分成员变量,一般习惯在成员变量前面或后面加一个特殊标识,_或者m_ 1.2访问限定符 c采用…...
shell练习
开篇小贴士:为创建的sh(当然可以是任何一个文件)文件添加开头的注释 1、进入到家目录,然后通过 ls -a 查看全部文件 2、找到并编辑一个名为 .vimrc (Vim编辑器的核心配置文件)的配置文件,下图…...
ApiChain 从迭代到项目 接口调试到文档生成单元测试一体化工具
项目地址:ApiChain 项目主页 ApiChain 简介 ApiChain 是一款类似 PostMan 的接口网络请求与文档生成软件,与 PostMan 不同的是,它基于 项目和迭代两个视角管理我们的接口文档,前端和测试更关注版本迭代中发生变更的接口编写代码…...
Vercel 设置自动部署 GitHub 项目
Vercel 设置自动部署 GitHub 项目 问题背景 最近 Vercel 调整了其部署政策,免费版用户无法继续使用自动部署功能,除非升级到 Pro 计划。但是,我们可以通过配置 Deploy Hooks 来实现同样的自动部署效果。 解决方案 通过设置 Vercel 的 Dep…...
SQL进阶:如何跳过多个NULL值取第一个非NULL值?
NULL 一、问题描述二、ORACLE<一>、last_value () over ()<二>、lag () over()<三>、相关子查询 三、MYSQL<一>、全局变量<二>、coalesce() lag() over()<三>、相关子查询<四>、 recursive<五>、lag() over() min() over() …...
laravel 5.5 增加宏指令 joinSub, 省去->toSql() 和 addBinding($bindings);
laravel 5.5 增加宏指令 joinSub, 省去->toSql() 和 addBinding($bindings); 1. 在laravel5使用join 子查询时 $sub_query DB::table(table1)->select([table1.id, cate_id])->join(table2, table1.id, , table2.id)->where(table1.cate_id, 2)->orderBy(tabl…...
远程控制软件:探究云计算和人工智能的融合
在数字化时代,远程控制工具已成为我们工作与生活的重要部分。用户能够通过网络远程操作和管理另一台计算机,极大地提升了工作效率和便捷性。随着人工智能(AI)和云计算技术的飞速发展,远程控制工具也迎来了新的发展机遇…...
网络协议之DNS
一、DNS概述 域名系统(Domain Name System,缩写:DNS)是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS使用TCP和UDP端口53,通过递归查询请求的方式来…...
.net6 使用 FreeSpire.XLS 实现 excel 转 pdf - docker 部署
FreeSpire.XLS && Aspose.Cells包都可以实现。实现过程中发现如下问题: 本地测试通过, docker部署服务器后报错: The type initializer for Spire.Xls.Core.Spreadsheet.XlsPageSetupBase threw an exception. 由于缺少依赖…...
QML学习 —— 28、3种等待指示控件(附源码)
效果如下 说明 BusyIndicator应用于指示在加载内容或UI被阻止等待资源可用时的活动。BusyIndicator类似于一个不确定的ProgressBar。两者都可以用来指示背景活动。主要区别在于视觉效果,ProgressBar还可以显示具体的进度(当可以确定时)。由于视觉差异,繁忙指示器和不确定的…...
flutter 专题十一 Fair原理篇Fair逻辑动态化架构设计与实现
数据逻辑处理布局中的逻辑处理Flutter类型数据处理 一、数据逻辑处理 我们接触的每一个Flutter界面,大多由布局和逻辑相关的代码组成。如Flutter初始工程的Counting Demo的代码: class _MyHomePageState extends State<MyHomePage> {// 变量 in…...
利用开源图床的技巧与实践
随着互联网的普及,图片的使用变得越来越广泛。无论是个人博客、社交媒体还是企业网站,都离不开图片的呈现。而图床作为图片存储和管理的工具,可以帮助开发者和内容创作者高效地管理图片资源。本文将探讨如何利用开源图床,并提供相…...
C++数据结构与算法
C数据结构与算法 1.顺序表代码模版 C顺序表模版 #include <iostream> using namespace std; // 可以根据需要灵活变更类型 #define EleType intstruct SeqList {EleType* elements;int size;int capacity; };// Init a SeqList void InitList(SeqList* list, int capa…...
Paddle Inference部署推理(三)
三:Paddle Inference推理 导出模型 Paddle Inference支持使用飞桨静态图模型进行推理,您可以通过以下两种方式获取静态图模型: (1)飞桨框架导出推理模型 飞桨框架在训练模型过程中,会在本地存储最终训练…...
python(四)os模块、sys模块
一、os模块 os 模块提供了很多程序与操作系统直接交互的功能 名称描述示例os.getcwd()得到当前工作目录,即当前Python脚本工作的目录路径‘D:\python’os.listdir()返回指定目录下的所有文件和目录名>>> os.listdir()os.remove()函数用来删除一个文件>…...
Oracle 数据库 IDENTITY 列
IDENTITY列是Oracle数据库12c推出的新特性。之所以叫IDENTITY列,是由于其支持ANSI SQL 关键字 IDENTITY,其内部实现还是使用SEQUENCE。 不过推出这个新语法也是应该的,毕竟MyQL已经有 AUTO_INCREMENT列,而SQL Server也已经有IDENT…...
【前端】js vue 屏蔽BackSpace键删除键导致页面后退的方法
【前端】js vue 屏蔽BackSpace键删除键导致页面后退的方法 方法一:通过全局事件监听阻止 Backspace 导致页面后退 在 main.js 或组件的 mounted 中添加以下代码: //【前端】js vue 屏蔽BackSpace键删除键导致页面后退的方法 document.addEventListener…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
