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

Springboot参数分组校验

Springboot参数分组校验

文章目录

    • Springboot参数分组校验
        • 简介
        • 代码准备
        • 单个或多个参数的校验
        • 非 JSON 格式的对象参数校验
        • JSON 格式的对象参数校验
        • Service 层校验
        • 项目地址

简介

Java API规范(JSR303)定义了Bean校验的标准validation-api,但没有提供实现。hibernate validation是对这个规范的实现,并增加了校验注解如@Email@Length等。

Spring Validation是对hibernate validation的二次封装,用于支持spring mvc参数自动校验。本文基于 JDK21 和 springboot3.1.5 进行整理。


代码准备

参数校验对象,以下实例都基于该对象进行。

package com.lzhch.practice.dto.req;import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;import java.io.Serial;
import java.io.Serializable;
import java.util.Date;/*** 参数分组校验入参* <p>* author: lzhch* version: v1.0* date: 2023/11/20 15:36*/@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ParamGroupValidatedReq implements Serializable {@Serialprivate static final long serialVersionUID = 1L;/*** 用户ID* 内部定义接口和统一定义接口任选其一即可*/// @NotNull(message = "用户id不能为空", groups = ParamGroupValidated.Create.class)@NotNull(message = "用户id不能为空") // Service 层不进行分组校验// @NotNull(message = "用户id不能为空", groups = ParamGroupValidatedReq.Save.class)private Long userId;/*** 用户名*/@NotBlank(message = "用户名不能为空")@Length(max = 20, message = "用户名不能超过20个字符")private String username;/*** 手机号*/@NotBlank(message = "手机号不能为空")private String mobile;/*** 性别*/private String sex;/*** 邮箱*/@NotBlank(message = "联系邮箱不能为空")@Email(message = "邮箱格式不对")private String email;/*** 密码*/private String password;/*** 创建时间*/// @Future(message = "时间必须是将来时间")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")private Date createTime;/*** 保存的时候校验分组*/public interface Save {}/*** 更新的时候校验分组*/public interface Update {}}

分组接口

import jakarta.validation.groups.Default;/*** 新增参数校验接口* <p>* author: lzhch* version: v1.0* date: 2023/11/20 17:20*/public interface ParamGroupValidated {/*** 在声明分组的时候加上 extend javax.validation.groups.Default* 否则, 在你声明 @Validated(Update.class)的时候, 就会出现你在默认没添加 groups = {} 的时候* 校验组 @Email(message = "邮箱格式不对") 会不去校验, 因为默认的校验组是 groups = {Default.class}.*/interface Create extends Default {}interface Update extends Default {}}

全局异常捕捉,参数校验报错分为 MethodArgumentNotValidException 和 ConstraintViolationException。

import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;import java.util.Objects;/*** 全局异常处理* <p>* author: lzhch* version: v1.0* date: 2023/11/20 17:51*/@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {/*** Controller 层参数校验** @param methodArgumentNotValidException: Controller 层参数校验失败异常类型* @return 统一封装的结果类, 含有代码code和提示信息msg* Author: lzhch 2023/11/21 15:13*/@ExceptionHandler(MethodArgumentNotValidException.class)public String handleMethodArgumentNotValidException(MethodArgumentNotValidException methodArgumentNotValidException) {log.error(methodArgumentNotValidException.getMessage(), methodArgumentNotValidException);FieldError fieldError = methodArgumentNotValidException.getBindingResult().getFieldError();if (Objects.isNull(fieldError)) {return methodArgumentNotValidException.getMessage();}return fieldError.getDefaultMessage();}/*** 捕获并处理未授权异常** @param e: Service 层参数校验失败异常类型* @return 统一封装的结果类, 含有代码code和提示信息msg* Author: lzhch 2023/11/21 15:13*/@ExceptionHandler(ConstraintViolationException.class)public String handleConstraintViolationException(ConstraintViolationException e) {return String.join(";", e.getConstraintViolations().stream().map(ConstraintViolation::getMessageTemplate).toList());}}

单个或多个参数的校验

比如根据 Id 查询、删除等,无需封装成对象,且无需使用 JSON 格式。

import com.alibaba.fastjson2.JSON;
import com.lzhch.practice.dto.req.ParamGroupValidatedReq;
import com.lzhch.practice.service.IParamGroupValidatedService;
import com.lzhch.practice.validatedtype.ParamGroupValidated;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotBlank;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 参数分组校验 controller* <p>* author: lzhch* version: v1.0* date: 2023/11/20 17:22*/@Slf4j
// 用于在 Controller 层的简单校验, 比如 simple 方法
@Validated
@RestController
@RequestMapping(value = "validated/paramGroup")
public class ParamGroupValidatedController {@Resourceprivate IParamGroupValidatedService paramGroupValidatedService;/*** 简单校验* 必须在 Controller 上添加 @Validated 注解* 指定 groups 可以进行分组校验*/@GetMapping(value = "simple")public void simple(@NotBlank(message = "username 不能是空的啊!!!", groups = ParamGroupValidated.Create.class) String username) {log.info("result {}", username);}}

非 JSON 格式的对象参数校验

Controller 和方法参数上需要添加 @Validated 注解;

对象里面增加相应类型的校验注解。

/*** 非 JSON 格式的对象校验* 使用 @Validated 注解的 value 属性指定分组*/
@GetMapping(value = "simple1")
public void simple1(@Validated ParamGroupValidatedReq paramGroupValidatedReq) {log.info("result {}", JSON.toJSONString(paramGroupValidatedReq));
}

JSON 格式的对象参数校验

不需要在 Controller 上添加 @Validated 注解

JSON 格式校验只需要增加 @RequestBody 注解。

/*** 统一接口分组测试新增* 使用 @Validated 注解的 value 属性指定分组*/
@PostMapping(value = "create")
public void create(@RequestBody @Validated(value = ParamGroupValidated.Create.class) ParamGroupValidatedReq paramGroupValidatedReq) {log.info("result {}", JSON.toJSONString(paramGroupValidatedReq));
}

Service 层校验

以上为在 Controller 里面进行的校验,接下来是 Service 层的校验代码。

接口:

在接口中必须添加 @Valid 以及 @NotBlank 等注解, 否则报错

package com.lzhch.practice.service;import com.lzhch.practice.dto.req.ParamGroupValidatedReq;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;/*** 分组校验接口* <p>* author: lzhch* version: v1.0* date: 2023/11/20 18:16*/public interface IParamGroupValidatedService {// 在接口中必须添加 @Valid 以及 @NotBlank 等注解, 否则报错/*** 字段校验*/void filedValidated(@NotBlank(message = "用户名不能为空") String username);/*** 不分组校验*/void create(@Valid ParamGroupValidatedReq paramGroupValidatedReq);/*** 分组校验*/// @Validated(value = ParamGroupValidated.Create.class)void create1(@Valid ParamGroupValidatedReq paramGroupValidatedReq);}

实现类:

必须给实现类添加 @Validated 注解!

import com.alibaba.fastjson2.JSON;
import com.lzhch.practice.dto.req.ParamGroupValidatedReq;
import com.lzhch.practice.service.IParamGroupValidatedService;
import com.lzhch.practice.validatedtype.ParamGroupValidated;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;/*** 分组校验接口实现类* <p>* author: lzhch* version: v1.0* date: 2023/11/20 18:16*/@Slf4j
@Service
// 在接口上添加 @Validated 注解, 对该类进行参数校验
@Validated
public class ParamGroupValidatedServiceImpl implements IParamGroupValidatedService {/*** 在方法的参数上可以直接使用 @NotBlank 等注解*/@Overridepublic void filedValidated(String username) {log.info("service username :{}", username);}/*** 不分组校验* 在方法上使用 @Valid 注解, 采用默认分组(实体也不指定分组)* 注意:接口中方法参数必须要加 @Valid 注解; 实现类中可加可不加** @param paramGroupValidatedReq param* @return: void* Author: lzhch 2023/11/21 14:56* Since: 1.0.0*/@Overridepublic void create(@Valid ParamGroupValidatedReq paramGroupValidatedReq) {log.info("service result :{}", JSON.toJSONString(paramGroupValidatedReq));}/*** 分组校验* 在不分组校验的基础上对方法添加使用 @Validated 注解, 并指定分组* 注意:接口中方法参数必须要加 @Valid 注解; @Validated 可在接口中也可在实现类中; 不能只在实现类中添加两个注解** @param paramGroupValidatedReq param* @return: void* Author: lzhch 2023/11/21 14:55* Since: 1.0.0*/@Override@Validated(value = ParamGroupValidated.Create.class)public void create1(ParamGroupValidatedReq paramGroupValidatedReq) {log.info("service result :{}", JSON.toJSONString(paramGroupValidatedReq));}}

项目地址

SpringBoot3-Practice/ParamGroupValidated at main · lzhcccccch/SpringBoot3-Practice (github.com)

相关文章:

Springboot参数分组校验

Springboot参数分组校验 文章目录 Springboot参数分组校验简介代码准备单个或多个参数的校验非 JSON 格式的对象参数校验JSON 格式的对象参数校验Service 层校验项目地址 简介 Java API规范(JSR303)定义了Bean校验的标准validation-api&#xff0c;但没有提供实现。hibernate …...

无缝集成 MongoDB Relational Migrator,Tapdata 提供关系型到 MongoDB 实时迁移优化方案

在去年的 MongoDB 用户大会纽约站上&#xff0c;MongoDB 正式宣布全面推出新工具 MongoDB Relational Migrator&#xff08;MongoDB RM&#xff09;&#xff0c;用以简化应用程序迁移和转换——即从传统关系型数据模型到现代的文档数据模型&#xff0c;助力组织快速提升运营效率…...

【C++】每日一题 146 LRU缓存

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0c;否则返回 -1 …...

CentOS搭建NAS服务器并使用

CentOS搭建NAS服务器并使用 文章目录 前言一、配置NAS服务器安装 NFS 服务&#xff1a;启动 NFS 服务&#xff1a;使 NFS 服务在系统启动时自动启动&#xff1a; 二、挂载服务器三、常见错误以及解决方案1、mount.nfs: No route to host2、mount.nfs: access denied by server …...

爬虫入门到精通_框架篇16(Scrapy框架基本使用)_名人名言的抓取

1 目标站点分析 抓取网站&#xff1a;http://quotes.toscrape.com/ 主要显示了一些名人名言&#xff0c;以及作者、标签等等信息&#xff1a; 点击next&#xff0c;page变为2&#xff1a; 2 流程框架 抓取第一页&#xff1a;请求第一页的URL并得到源代码&#xff0c;进行下…...

mac inter 芯片遇到程序无法打开(无法验证开发者)

mac inter 芯片遇到程序无法打开&#xff08;无法验证开发者&#xff09; 解决方案 终端运行命令&#xff1a; sudo xattr -r -d com.apple.quarantine 文件路径(直接把文件拖入到终端&#xff0c;可以自动找到文件路径)即可令其获得权限 补充知识&#xff1a; 通过gpt可以…...

科技成果鉴定测试如何进行?第三方检测机构进行鉴定测试的好处

科技成果鉴定测试&#xff0c;作为科技领域中一项重要的质量检验手段&#xff0c;具有广泛的应用范围。旨在为科技成果的研发者和使用者提供客观、科学、权威的鉴定结果&#xff0c;从而评估科技成果的技术水平和市场竞争力。   科技成果鉴定测试是对科技成果进行系统、全面的…...

八、词嵌入语言模型(Word Embedding)

词嵌入&#xff08;Word Embedding, WE&#xff09;&#xff0c;任务是把不可计算、非结构化的词转换为可以计算、结构化的向量&#xff0c;从而便于进行数学处理。 一个更官方一点的定义是&#xff1a;词嵌入是是指把一个维数为所有词的数量的高维空间&#xff08;one-hot形式…...

重学SpringBoot3-WebMvcConfigurer接口

摘要&#xff1a; 本文详细介绍了SpringBoot 3中的WebMvcConfigurer接口&#xff0c;旨在帮助读者深入理解其原理和实现&#xff0c;从而能够更好地使用SpringBoot进行Web开发。阅读本文需要大约30分钟。 关键词&#xff1a;SpringBoot, WebMvcConfigurer, SpringMVC, Web开发…...

《深入理解springCloud与微服务》笔记

第一章 微服务介绍 1.3 微服务的不足 1.3.2 分布式事务 CAP 理论&#xff0c;即同时满足“一致性”“可用性”和“分区容错”是 件不可能的事。 Consistency &#xff1a;指数据的强一致性。如果写入某个数据成功&#xff0c;之后读取&#xff0c;读到的都是新写入的数据&a…...

Vivado原语模板

1.原语的概念 原语是一种元件! FPGA原语是芯片制造商已经定义好的基本电路元件,是一系列组成逻辑电路的基本单元,FPGA开发者编写逻辑代码时可以调用原语进行底层构建。 2.原语的分类 原语可分为预定义原语和用户自定义原语。预定义原语为如and/or等门级原语不需要例化,可以…...

【linux本地安装tinycudann包教程】

【linux本地安装tinycudann包教程】 tiny-cuda-nn官网链接 如果你是windows 10系统的,想要安装tiny-cuda-nn可以参考我的文章——windows 10安装tiny-cuda-n包 根据官网要求:C++要求对应14,其实这样就已经告诉我们linux系统中的gcc版本不能高于9,同时下面又告诉我们gcc版…...

使用Nginx进行负载均衡

什么是负载均衡 Nginx是一个高性能的开源反向代理服务器&#xff0c;也可以用作负载均衡器。通过Nginx的负载均衡功能&#xff0c;可以将流量分发到多台后端服务器上&#xff0c;实现负载均衡&#xff0c;提高系统的性能、可用性和稳定性。 如下图所示&#xff1a; Nginx负…...

什么护眼台灯效果好?热门护眼台灯全方位测评推荐

台灯可以说是佳佳必备&#xff0c;尤其是家中有正在上学的孩子的更是需要一款好的台灯&#xff0c;不管是看书、写字都离不开台灯。不过很多家长在挑选台灯时往往仅关注到光线亮度是否充足&#xff0c;而忽略掉光线均匀度、舒适度等等方面的问题。所以选择一款优质的护眼台灯是…...

云上三问,迈向智能时代的关键

在今天的中国&#xff0c;第一热词是什么&#xff1f;面对这个问题&#xff0c;“新质生产力”当仁不让&#xff0c;而智能化技术毫无疑问是“新质生产力”最重要的来源之一。 在这样的大势下&#xff0c;大型政企是向新技术要“新质生产力”的时代先锋。云服务&#xff0c;则是…...

【网络安全】手机不幸被远程监控,该如何破解,如何预防?

手机如果不幸被远程监控了&#xff0c;用三招就可以轻松破解&#xff0c;再用三招可以防范于未然。 三招可破解可解除手机被远程监控 1、恢复出厂设置 这一招是手机解决软件故障和系统故障的终极大招。只要点了恢复出厂设置&#xff0c;你手机里后装的各种APP全部将灰飞烟灭…...

每日OJ题_哈希表④_力扣219. 存在重复元素 II

目录 力扣219. 存在重复元素 II 解析代码 力扣219. 存在重复元素 II 219. 存在重复元素 II 难度 简单 给你一个整数数组 nums 和一个整数 k &#xff0c;判断数组中是否存在两个 不同的索引 i 和 j &#xff0c;满足 nums[i] nums[j] 且 abs(i - j) < k 。如果存在&am…...

42.坑王驾到第八期:uniCloud报错

uniCloud 报错 今天调用云函数来调试小程序的时候突然暴了一个奇葩错误&#xff0c;require(…).main is not a function。翻官方文档后发现&#xff0c;原来是这样&#xff1a;**如果你写的是云对象&#xff0c;入口文件应为 index.obj.js&#xff0c;如果你写的是云函数入口…...

Linux常用操作命令

Linux常用操作命令 1.文件管理catfile 2.文档编辑3.文件传输4.磁盘管理5.磁盘维护6.网络通讯7.系统管理8.系统设置9.备份压缩10.设备管理 Linux 英文解释为 Linux is not Unix。 Linux内核最初只是由芬兰人李纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;在赫尔辛基大学上…...

OpenCV的常用数据类型

OpenCV涉及的常用数据类型除包含C的基本数据类型,如&#xff1a;char、uchar&#xff0c;int、unsigned int,short 、long、float、double等数据类型外, 还包含Vec&#xff0c;Point、Scalar、Size、Rect、RotatedRect、Mat等类。C中的基本数据类型不需再做说明下面重点介绍一下…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...