百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

Spring中的@Valid 和 @Validated 区别

ztj100 2025-01-02 20:33 11 浏览 0 评论

1.概述#

本文我们将重点介绍Spring中 @Valid和@Validated注解的区别 。

验证用户输入是否正确是我们应用程序中的常见功能。Spring提供了@Valid和@Validated两个注解来实现验证功能,下面我们来详细介绍它们。

2. @Valid和@Validate注解#

在Spring中,我们使用@Valid 注解进行方法级别验证,同时还能用它来标记成员属性以进行验证。

但是,此注释不支持分组验证。@Validated则支持分组验证。

3.例子#

让我们考虑一个使用Spring Boot开发的简单用户注册表单。首先,我们只有名称密码属性:

Copypublic class UserAccount {

    @NotNull
    @Size(min = 4, max = 15)
    private String password;

    @NotBlank
    private String name;

    // standard constructors / setters / getters / toString

}

接下来,让我们看一下控制器。在这里,我们将使用带有@Valid批注的saveBasicInfo方法来验证用户输入:

Copy@RequestMapping(value = "/saveBasicInfo", method = RequestMethod.POST)
public String saveBasicInfo(
  @Valid @ModelAttribute("useraccount") UserAccount useraccount, 
  BindingResult result, 
  ModelMap model) {
    if (result.hasErrors()) {
        return "error";
    }
    return "success";
}

现在让我们测试一下这个方法:

Copy@Test
public void givenSaveBasicInfo_whenCorrectInput`thenSuccess() throws Exception {
    this.mockMvc.perform(MockMvcRequestBuilders.post("/saveBasicInfo")
      .accept(MediaType.TEXT_HTML)
      .param("name", "test123")
      .param("password", "pass"))
      .andExpect(view().name("success"))
      .andExpect(status().isOk())
      .andDo(print());
}

在确认测试成功运行之后,现在让我们扩展功能。下一步的逻辑步骤是将其转换为多步骤注册表格,就像大多数向导一样。第一步,名称密码保持不变。在第二步中,我们将获取其他信息,例如agephone。因此,我们将使用以下其他字段更新域对象:

Copypublic class UserAccount {

    @NotNull
    @Size(min = 4, max = 15)
    private String password;

    @NotBlank
    private String name;

    @Min(value = 18, message = "Age should not be less than 18")
    private int age;

    @NotBlank
    private String phone;

    // standard constructors / setters / getters / toString   

}

但是,这一次,我们将注意到先前的测试失败。这是因为我们没有传递年龄电话字段。

为了支持此行为,我们引入支持分组验证的@Validated批注。

分组验证,就是将字段分组,分别验证,比如我们将用户信息分为两组:BasicInfoAdvanceInfo

可以建立两个空接口:

Copypublic interface BasicInfo {
}
Copypublic interface AdvanceInfo {
}

第一步将具有BasicInfo接口,第二步 将具有AdvanceInfo 。此外,我们将更新UserAccount类以使用这些标记接口,如下所示:

Copypublic class UserAccount {

    @NotNull(groups = BasicInfo.class)
    @Size(min = 4, max = 15, groups = BasicInfo.class)
    private String password;

    @NotBlank(groups = BasicInfo.class)
    private String name;

    @Min(value = 18, message = "Age should not be less than 18", groups = AdvanceInfo.class)
    private int age;

    @NotBlank(groups = AdvanceInfo.class)
    private String phone;

    // standard constructors / setters / getters / toString   

}

另外,我们现在将更新控制器以使用@Validated注释而不是@Valid

Copy@RequestMapping(value = "/saveBasicInfoStep1", method = RequestMethod.POST)
public String saveBasicInfoStep1(
  @Validated(BasicInfo.class) 
  @ModelAttribute("useraccount") UserAccount useraccount, 
  BindingResult result, ModelMap model) {
    if (result.hasErrors()) {
        return "error";
    }
    return "success";
}

更新后,再次执行测试,现在可以成功运行。现在,我们还要测试这个新方法:

Copy@Test
public void givenSaveBasicInfoStep1`whenCorrectInput`thenSuccess() throws Exception {
    this.mockMvc.perform(MockMvcRequestBuilders.post("/saveBasicInfoStep1")
      .accept(MediaType.TEXT_HTML)
      .param("name", "test123")
      .param("password", "pass"))
      .andExpect(view().name("success"))
      .andExpect(status().isOk())
      .andDo(print());
}

也成功运行!

接下来,让我们看看@Valid对于触发嵌套属性验证是必不可少的。

4.使用@Valid批注标记嵌套对象#

@Valid 可以用于嵌套对象。例如,在我们当前的场景中,让我们创建一个 UserAddress 对象:

Copypublic class UserAddress {

    @NotBlank
    private String countryCode;

    // standard constructors / setters / getters / toString
}

为了确保验证此嵌套对象,我们将使用@Valid批注装饰属性:

Copypublic class UserAccount {

    //...

    @Valid
    @NotNull(groups = AdvanceInfo.class)
    private UserAddress useraddress;

    // standard constructors / setters / getters / toString 
}

5. 总结#

@Valid保证了整个对象的验证, 但是它是对整个对象进行验证,当仅需要部分验证的时候就会出现问题。 这时候,可以使用@Validated 进行分组验证。

参考#

  • https://www.baeldung.com/spring-valid-vs-validated

作者: JadePeng

出处:https://www.cnblogs.com/xiaoqi/p/spring-valid.html

版权:本文采用「署名-非商业性使用-相同方式共享 4.0 国际(欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接) 」知识共享许可协议进行许可。


分类: java编程

标签: Spring Boot, java

相关推荐

Java项目宝塔搭建实战MES-Springboot开源MES智能制造系统源码

大家好啊,我是测评君,欢迎来到web测评。...

一个令人头秃的问题,Logback 日志级别设置竟然无效?

原文链接:https://mp.weixin.qq.com/s/EFvbFwetmXXA9ZGBGswUsQ原作者:小黑十一点半...

实战!SpringBoot + RabbitMQ死信队列实现超时关单

需求背景之为什么要有超时关单原因一:...

火了!阿里P8架构师编写堪称神级SpringBoot手册,GitHub星标99+

Springboot现在已成为企业面试中必备的知识点,以及企业应用的重要模块。今天小编给大家分享一份来着阿里P8架构师编写的...

Java本地搭建宝塔部署实战springboot仓库管理系统源码

大家好啊,我是测评君,欢迎来到web测评。...

工具尝鲜(1)-Fleet构建运行一个Springboot入门Web项目

Fleet是JetBrains公司推出的轻量级编辑器,对标VSCode。该款产品还在公测当中,具体下载链接如下JetBrainsFleet:由JetBrains打造的下一代IDE。想要尝试的...

SPRINGBOOT WEB 实现文件夹上传(保留目录结构)

网上搜到的SpringBoot的代码不多,完整的不多,能用的也不多,基本上大部分的文章只是提供了少量的代码,讲一下思路,或者实现方案。之前一般的做法都是使用HTML5来做的,大部都是传文件的,传文件夹...

Java项目本地部署宝塔搭建实战报修小程序springboot版系统源码

大家好啊,我是测评君,欢迎来到web测评。...

新年IT界大笑料“工行取得基于SpringBoot的web系统后端实现专利

先看看专利描述...

看完SpringBoot源码后,整个人都精神了

前言当读完SpringBoot源码后,被Spring的设计者们折服,Spring系列中没有几行代码是我们看不懂的,而是难在理解设计思路,阅读Spring、SpringMVC、SpringBoot需要花...

阿里大牛再爆神著:SpringBoot+Cloud微服务手册

今天给大家分享的这份“Springboot+Springcloud微服务开发实战手册”共有以下三大特点...

WebClient是什么?SpringBoot中如何使用WebClient?

WebClient是什么?WebClient是SpringFramework5引入的一个非阻塞、响应式的Web客户端库。它提供了一种简单而强大的方式来进行HTTP请求,并处理来自服务器的响应。与传...

SpringBoot系列——基于mui的H5套壳APP开发web框架

  前言  大致原理:创建一个main主页面,只有主页面有头部、尾部,中间内容嵌入iframe内容子页面,如果在当前页面进行跳转操作,也是在iframe中进行跳转,而如果点击尾部按钮切换模块、页面,那...

在Spring Boot中使用 jose4j 实现 JSON Web Token (JWT)

JSONWebToken或JWT作为服务之间安全通信的一种方式而闻名。...

Spring Boot使用AOP方式实现统一的Web请求日志记录?

AOP简介AOP(AspectOrientedProgramming),面相切面编程,是通过代码预编译与运行时动态代理的方式来实现程序的统一功能维护的方案。AOP作为Spring框架的核心内容,通...

取消回复欢迎 发表评论: