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

@Valid与@Validated的区别

1.介绍

说明: 其实@Valid 与 @Validated都是做数据校验的,只不过注解位置与用法有点不同。

不同点:
(1)
@Valid是使用Hibernate validation的时候使用。@Validated是只用Spring Validator校验机制使用。

(2)
@Valid 可以嵌套验证
@Validation 不能进行嵌套验证

(3)
@Valid:可以用在方法、构造函数、方法参数和成员属性(field)上。
@Validated:用在类、方法和方法参数上。但不能用于成员属性(field)。
(如果@Validated注解在成员属性上,则会报不适用于field的错误。)

(4)
@Valid:没有分组功能。
@Validated:提供分组功能,可以在参数验证时,根据不同的分组采用不同的验证机制。

2.用法

(1)@Valid用法

a.导入依赖
SpringBoot项目:

<dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId><version>1.1.0.Final</version>
</dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>5.4.1.Final</version>
</dependency>

b.使用前提是实体类中属性使用注解进行校验

package com.example.demo.pojo;import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
import org.springframework.format.annotation.DateTimeFormat;import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;//lombok
@Data
public class User implements Serializable {//用户名@NotBlank(message = "请输入名称")@Length(message = "名称不能超过个 {max} 字符", max = 10)private String username;//年龄@NotNull(message = "请输入年龄")@Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100)private String age;}

c.在Controller方法参数中加上@Valid注解

package com.example.demo.controller;import com.example.demo.pojo.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;
import java.util.List;@RestController
public class UserController {public static final Logger logger = LoggerFactory.getLogger(UserController.class.getName());@PostMapping("/add")@ResponseBodypublic String add(@Validated User user, BindingResult bindingResult){if(bindingResult.hasErrors()){List<ObjectError> allErrors = bindingResult.getAllErrors();allErrors.forEach( v ->{logger.error(v.getObjectName()+"======"+v.getDefaultMessage());});return "添加失败";}return "添加成功";}
}

经过测试填写错误数据,会在控制台输出报错信息。

=

(2)@Validated用法

a.开启校验框架(与上面一样)

<!--1.导入JSR303规范-->
<dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId>
</dependency>
<!--使用hibernate框架提供的校验器做实现-->
<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId>
</dependency>

c.在需要开启校验功能的类上使用注解@Validated开启校验功能,对具体的字段设置校验规则,这里讲的是可以在类上使用@Validated注解,配合xml数据绑定。

@Component
@Data
@ConfigurationProperties(prefix = "servers")
//开启对当前bean的属性注入校验
@Validated
public class ServerConfig {//设置具体的规则@Max(value = 8888,message = "最大值不能超过8888")@Min(value = 202,message = "最小值不能低于202")private int port;
}

(3)@Validated实现分组校验

注意 分组校验就是把条件加入组中,可以自由选择开启那些组的校验方式。

a.分组接口

package com.example.demo.pojo;public interface Group {interface Update{};interface FindAll{};
}

b.实体类

package com.example.demo.pojo;import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
import org.springframework.format.annotation.DateTimeFormat;import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;//lombok
@Data
public class User implements Serializable {//用户名@NotBlank(message = "请输入用户名不能为空",groups = {Group.FindAll.class})@Length(message = "名称不能超过个 {max} 字符", max = 10 ,groups = {Group.FindAll.class})private String username;//年龄@NotBlank(message = "请输入年龄不能为空",groups = {Group.Update.class})@Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100,groups = {Group.Update.class})private String age;}

c.controller接口:
注意 @Validated有参数 value中写分组名称

package com.example.demo.controller;import com.example.demo.pojo.Group;
import com.example.demo.pojo.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;
import java.util.List;@RestController
public class UserController {public static final Logger logger = LoggerFactory.getLogger(UserController.class.getName());@PostMapping("/add")@ResponseBody//注意@Validated有参数 value中写分组名称public String add(@Validated(value = {Group.Update.class}) User user, BindingResult bindingResult){if(bindingResult.hasErrors()){List<ObjectError> allErrors = bindingResult.getAllErrors();allErrors.forEach( v ->{logger.error(v.getObjectName()+"======"+v.getDefaultMessage());});return "添加失败";}return "添加成功";}
}

(4)@Valid 实现嵌套校验

注: 嵌套检测就是在一个User类中,存在另外一个User2类的属性。嵌套检测User同时也检测User2。

a.实体类User

package com.example.demo.pojo;import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
import org.springframework.format.annotation.DateTimeFormat;import javax.persistence.*;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;//lombok
@Data
public class User implements Serializable {//用户名@NotBlank(message = "请输入用户名不能为空1")private String username;//年龄@NotBlank(message = "请输入年龄不能为空1")private String age;@Valid@NotNull(message = "user2不能为空1")private User2 user2;}}

b.实体类User2

package com.example.demo.pojo;import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
import org.springframework.format.annotation.DateTimeFormat;import javax.persistence.*;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;package com.example.demo.pojo;import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;import javax.validation.constraints.NotNull;
import java.io.Serializable;//lombok
@Data
public class User2 implements Serializable {//用户名@Length(message = "名称不能超过个 {max} 字符2", max = 10 )private String username2;//年龄@Range(message = "年龄范围为 {min} 到 {max} 之间2", min = 1, max = 100)private String age2;}

c.Controller类(这里使用@Valid)

package com.example.demo.controller;import com.example.demo.pojo.Group;
import com.example.demo.pojo.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;
import java.util.List;@RestController
public class UserController {public static final Logger logger = LoggerFactory.getLogger(UserController.class.getName());@PostMapping("/add")@ResponseBodypublic String add(@Valid User user, BindingResult bindingResult){if(bindingResult.hasErrors()){List<ObjectError> allErrors = bindingResult.getAllErrors();allErrors.forEach( v ->{logger.error(v.getObjectName()+"======"+v.getDefaultMessage());});return "添加失败";}return "添加成功";}
}

总结:

了解这两个注解可以让你的校验数据更加方便。

相关文章:

@Valid与@Validated的区别

1.介绍 说明&#xff1a; 其实Valid 与 Validated都是做数据校验的&#xff0c;只不过注解位置与用法有点不同。 不同点&#xff1a; &#xff08;1&#xff09; Valid是使用Hibernate validation的时候使用。Validated是只用Spring Validator校验机制使用。 &#xff08;2&…...

【LeetCode】剑指 Offer 09. 用两个栈实现队列 p68 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/ 1. 题目介绍&#xff08;09. 用两个栈实现队列&#xff09; 用两个栈实现一个队列。队列的声明如下&#xff0c;请实现它的两个函数 appendTail 和 deleteHead &#xff0c;分别…...

Java并发编程面试题——JUC专题

文章目录一、AQS高频问题1.1 AQS是什么&#xff1f;1.2 唤醒线程时&#xff0c;AQS为什么从后往前遍历&#xff1f;1.3 AQS为什么用双向链表&#xff0c;&#xff08;为啥不用单向链表&#xff09;&#xff1f;1.4 AQS为什么要有一个虚拟的head节点1.5 ReentrantLock的底层实现…...

CAS概述

目录一、CAS与原子类1.1 CAS1.2 乐观锁与悲观锁1.3 原子操作类二、 synchronized优化2.1 轻量级锁2.2 轻量级锁-无竞争2.3 轻量级锁-锁膨胀2.4 重量级锁-自旋2.5 偏向锁2.6 synchronized-其他优化一、CAS与原子类 1.1 CAS CAS&#xff08;一种不断尝试&#xff09;即Compare …...

Ansys Zemax / SPEOS | 光源文件转换器

本文解释了如何在 SPEOS 与 Zemax 之间转换二进制光源文件。 下载 联系工作人员获取附件 简介 在本文中&#xff0c;为用户提供了一组Python代码&#xff0c;用于在Zemax和SPEOS之间转换源文件。 有些光源&#xff0c;如 .IES 文件&#xff0c;可在 SPEOS 和 Zemax 中进行…...

PRML笔记2-关于回归参数w的先验的理解

接上篇&#xff0c;现在考虑给w\boldsymbol{w}w加入先验&#xff0c;考虑最简单的假设&#xff0c;也就是w\boldsymbol{w}w服从均值为0&#xff0c;协方差矩阵为α−1I\alpha^{-1}\boldsymbol{I}α−1I的高斯分布。 p(w∣α)N(w∣0,α−1I)(α2π)(M1)/2exp⁡{−α2wTw}\begin{…...

Selenium原理

我们使用Selenium实现自动化测试&#xff0c;主要需要3个东西1.测试脚本&#xff0c;可以是python&#xff0c;java编写的脚本程序&#xff08;也可以叫做client端&#xff09;2.浏览器驱动, 这个驱动是根据不同的浏览器开发的&#xff0c;不同的浏览器使用不同的webdriver驱动…...

Disconf、Apollo和Nacos分布式配置框架差异对比

差异对比表格&#xff1a; 功能点DisconfApolloNacos依赖高可用框架完全依赖于Zookeeper来实现监听拉取&#xff0c;向外提供了HTTP拉取数据接口依赖于Eureka实现内部服务发现注册&#xff0c;提供HTTP接口给Client SDK拉取监听数据内部自研实现框架高可用CAP理论偏重点Zookee…...

高新技术企业认定条件条件 高企认定要求

高新技术企业认定条件 一、成立年限&#xff1a;申报企业须注册成立365个日历天数&#xff0c;而非一个会计年度。 二、知识产权 &#xff08;1&#xff09;申报企业必须拥有在中国境内授权或审批审定的知识产权&#xff0c;且知识产权在有效保护期内。知识产权权属人应为申请企…...

华为OD机试 - 新学校选址(JavaScript) | 机试题+算法思路+考点+代码解析 【2023】

新学校选址 题目 为了解新学期学生暴涨的问题,小乐村要建立所新学校 考虑到学生上学安全问题,需要所有学生家到学校的距离最短. 假设学校和所有学生家都走在一条直线之上,请问学校建立在什么位置, 能使得到学校到各个学生家的距离和最短 输入 第一行: 整数 n 取值范围 [1,1…...

二进制部署K8S

目录 一、环境准备 1、常见的k8s部署方式 2、关闭防火墙 3、关闭selinux 4、关闭swap 5、根据规划设置主机名 6、在master添加hosts 7、将桥接的IPv4流量传递到iptables的链 8、时间同步 二、部署etcd集群 1、master节点部署 2、查看证书的信息 2.1 创建k8s工作目…...

高效获知Activity的生命周期

Activity生命周期监听 使用 Instrumentation 对 Activity 生命周期进行监听。 优点&#xff1a; 全局仅一次反射&#xff0c;性能影响极小所有Activity的生命周期都能够被监听到由于Java的单继承&#xff0c;为了拓展性&#xff0c;可以使用装饰器模式对Instrumentation进行功…...

分析现货黄金价格一般有什么方法

分析现货黄金价格一般有什么方法呢&#xff1f;我相信很多投资者都会说&#xff0c;是技术分析。很多人并不知道技术分析是什么&#xff0c;并且技术分析是如何去分析现货黄金价格的&#xff0c;那么本文就介绍一下技术分析的主要分类。可以说&#xff0c;小编的其他文章都是以…...

Spring中的拦截器

这里写目录标题基本概念HandlerInterceptor拦截器HandlerInterceptor讲解MethodInterceptor拦截器二者的区别基本概念 在web开发中&#xff0c;拦截器是经常用到的功能。它可以帮我们预先设置数据以及统计方法的执行效率等等。 Spring中拦截器主要分两种&#xff0c;一个是Han…...

【Linux操作系统】【综合实验四 Linux的编译环境及线程编程】

文章目录一、实验目的二、实验要求三、实验内容四、实验报告要求一、实验目的 要求熟悉Linux环境中的程序编译、调试与项目管理过程并能实现具体操作&#xff1b;熟练使用基础函数库中与线程库中的管理函数&#xff0c;实现用户线程编程过程&#xff0c;并深入了解Linux的线程…...

Switch 如何使用NSCB 转换XCI NSP NSZ教程

很多小白经常碰到Switch游戏文件格式和预期不符的情况&#xff0c;比如碰到nsz自己不会安装&#xff08;安装NSZ格式文件教程&#xff09;&#xff1b;或者是碰到xci格式的&#xff0c;想转换为nsp&#xff1b;抑或想将nsz格式文件还原回nsp格式。本文对此提供了解决方案。 文中…...

JVM12 字节码指令集

1. 概述 2. 加载与存储指令 2.1. 局部变量压栈指令 iload 从局部变量中装载int类型值 lload 从局部变量中装载long类型值 fload 从局部变量中装载float类型值 dload 从局部变量中装载double类型值 aload 从局部变量中装载引用类型值&#xff08;refernce&#xff09; iload_0 从…...

centos之python安装与多版本python之间的共存

一、背景 随着python版本迭代加快&#xff0c;有写python模块再低版本无法运行&#xff0c;此时需要我们在进行安装一个python版本 例如&#xff1a;uvloop 在python3.7上运行&#xff1b;python 3.6官方不再维护与更新 有些模块或不支持较低版本、有些模块支持较高版本python…...

SpringBoot学习笔记(一)

Idea中隐藏指定文件或指定类型文件 setting->File Types->Ignored Files and Folders输入要隐藏的文件名&#xff0c;支持*号通配符回车确认添加 SpringBoot概述 parent 小结&#xff1a; 开发SpringBoot程序要继承spring-boot-starter-parentspring-boot-starter-pa…...

美国原装KEYSIGHT E4981A(安捷伦) E4981A电容计

KEYSIGHT E4981A&#xff08;安捷伦&#xff09; Keysight E4981A&#xff08;安捷伦&#xff09;电容计为生产线中的陶瓷电容器测试提供了高速、可靠的测量。E4981A 实现了电容从小到大的测量能力&#xff0c;测量准确。Agilent E4981A 电容计有助于提高测试吞吐量&#xff0…...

leetcode sql50题

在中文站没找到对应的集合&#xff0c;想来自己动手拷贝过来&#xff0c;方便大家面试复习用&#xff0c;对应英文站点&#xff1a; https://leetcode.com/studyplan/top-sql-50/ Select #1757. 可回收且低脂的产品 链接: https://leetcode.cn/problems/recyclable-and-low-fa…...

学习英语。

1. 先自己翻译一遍&#xff08;葫芦背书法&#xff09; 结构 补充修饰 最核心的记忆 然后再修饰 2.意群之间翻译&#xff1a; 1.意群 对于两个意群合起来翻译 方法1就是着重某一 6.或者意群之间 核心词一个介词 于 对于 介词化修饰 3.句子之间关系 主句1 after句子2 那么句…...

c语言超详细知识点总结 1500行手写源码 持续更新中ing 从25年5月到6月5日

想象一下&#xff0c;我们身处的数字世界&#xff0c;如同一座座宏伟的建筑。操作系统、编译器、数据库、嵌入式设备乃至绚丽的游戏引擎&#xff0c;它们都是这座大厦的重要组成部分。而C语言&#xff0c;正是构建这一切的坚固基石。自丹尼斯里奇于贝尔实验室孕育出这颗编程界的…...

破解HTTP无状态:基于Java的Session与Cookie协同工作指南

HTTP协议自身是属于“无状态”协议 无状态是指&#xff1a;默认情况下&#xff0c;HTTP协议的客户端和服务器之间的这次通信&#xff0c;和下次通信之间没有直接的关系 但在实际开发中&#xff0c;我们很多时候是需要知道请求之间的关联关系的 上述图中的令牌&#xff0c;通常就…...

【Linux】Ubuntu 创建应用图标的方式汇总,deb/appimage/通用方法

Ubuntu 创建应用图标的方式汇总&#xff0c;deb/appimage/通用方法 对于标准的 Ubuntu&#xff08;使用 GNOME 桌面&#xff09;&#xff0c;desktop 后缀的桌面图标文件主要保存在以下三个路径&#xff1a; 当前用户的桌面目录&#xff08;这是最常见的位置&#xff09;。所…...

基于SpringBoot实现的大创管理系统设计与实现【源码+文档】

基于SpringBootVue实现的大创管理系统采用前后端分离架构方式&#xff0c;系统设计了管理员、学生、指导老师、院系管理员两种角色&#xff0c;系统实现了用户登录与注册、个人中心、学生管理、指导老师管理、院系管理员管理、优秀项目管理、项目类型管理、项目信息管理、项目申…...

项目-- Json-Rpc框架

目录 项目简介环境搭建Ubuntu-22.04 第三方库使用JsonCppMuduo基础类EventLoop类TcpConnection类Buffer类TcpClient类TcpServer类 服务端基本搭建客户端基本搭建 future 项目设计通用模块设计Rpc功能模块设计发现者设计提供者设计服务注册中心设计 Topic功夫模块设计主题管理中…...

python:Tkinter 开发邮件客户端,能编写邮件,发送邮件带附件

Python Tkinter 邮件客户端 下面是一个使用 Python Tkinter 开发的简单邮件客户端&#xff0c;支持编写邮件和发送邮件功能&#xff1a; 功能说明 这个邮件客户端包含以下功能&#xff1a; 邮件编写功能&#xff1a; 收件人地址输入抄送地址输入邮件主题输入邮件正文编辑区&…...

android 之 MediaExtractor

MediaExtractor 是Android多媒体处理的基础组件&#xff0c;解封装是其核心价值。 一、功能与定位 MediaExtractor 是Android多媒体框架中的媒体解封装工具&#xff0c;主要作用是从媒体文件&#xff08;如MP4、MKV、MP3&#xff09;中分离音视频轨道数据&#xff0c;为后续解…...

element-plus 单选组件 el-radio,选不上,又没报错,直接复制官网也不行解决方案

在使用 Vue 框架开发项目时&#xff0c;Element UI 是常用的组件库。最近在开发中遇到了 Element 单选框组件el-radio的双向绑定问题&#xff0c;直接复制element官网上的的案例下来也是不得&#xff0c;经过调试和探索&#xff0c;终于找到了解决方案&#xff0c;特此记录分享…...