Spring中的@Valid 和 @Validated注解_yzc_sky的博客-程序员秘密_spring validate 注解

技术标签: spring  java  

Spring中的@Valid 和 @Validated注解

1. 概述

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

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

2. @Valid和@Validate注解

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

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

3. 例子

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

public class UserAccount {
    

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

    @NotBlank
    private String name;

    // standard constructors / setters / getters / toString
}

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

@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";
}

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

@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());
}

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

public 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批注。

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

可以建立两个空接口:

public interface BasicInfo {
    
}
Copy
public interface AdvanceInfo {
    
}

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

public 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;
}

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

@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";
}

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

@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());
}

也成功运行!

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

接下来,让我们看看@Valid对于触发嵌套属性验证是必不可少的。@Valid 可以用于嵌套对象。例如,在我们当前的场景中,让我们创建一个 UserAddress 对象:

public class UserAddress {
    

    @NotBlank
    private String countryCode;

    // standard constructors / setters / getters / toString
}

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

public class UserAccount {
    
    //...
    @Valid
    @NotNull(groups = AdvanceInfo.class)
    private UserAddress useraddress;
    // standard constructors / setters / getters / toString 
}

5. 总结

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

参考
Spring中的@Valid 和 @Validated注解你用对了吗

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yzc_sky/article/details/118002789

智能推荐

linux升级openssh提示密码错误,Linux升级openssh及问题总结_weixin_39875832的博客-程序员秘密

系统版本:[[email protected] ~]# uname -aLinux db 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013x86_64 x86_64 x86_64 GNU/Linux[[email protected] ~]# cat /etc/redhat-releaseRed Hat Enterprise Linux Server release 6...

再次换博客,地址http://iwood.co.nr_不会种地的老农的博客-程序员秘密

再次换博客, Geek woodworker . 请猛点进入。博入其名,内容有计算机技术相关的,比如 http://ifq.github.com/blog/2012/09/10/baidu-blog-to-octo/ ,介绍如何通过脚本将百度博客的数据导入到octopress的博客系统中。也有木工相关的,木工作为一种业余爱好在国内并不被人熟知,可以说手工木工在中国基本绝迹,没有生态环境。我

Windows 10 安装Tensorflow gpu-1.3.0_Icoding_F2014的博客-程序员秘密

硬件配置:cpu: 锐龙1700x 显卡:GTX 1060OSWindows 10 64 企业版配置过程安装cuda8.0官网链接:https://developer.nvidia.com/cuda-80-ga2-download-archive 如果官方下载失败,则使用网盘资源: 链接:https://pan.baidu.com/s/1o9uby2m

python编程在哪里写程序-教你如何编写、保存与运行Python程序的方法_weixin_37988176的博客-程序员秘密

第一步接下来我们将看见如何在 Python 中运行一个传统的“Hello World”程序。Python教程本章将会教你如何编写、保存与运行 Python 程序。通过 Python 来运行的你的程序有两种方法——使用交互式解释器提示符或直接运行一个源代码文件。我们将了解如何使用他们二者的功能。使用解释器提示符在你的操作系统中打开终端(Terminal)程序(正如我们先前在安装章节所讨论过的那样)然...

学习PXE高效批量网络装机_码薯的博客-程序员秘密

PXE概述PXE 的全称是 preboot execute environment它其实是Intel在很久以前提出来的一项用于通过网络来引导系统的标准。允许客户机通过网络从远程服务器上下载引导镜像,并加载安装文件或者整个操作系统。实现的硬件条件1.BIOS支持2.网卡支持(现在基本都已支持)3.需要在bios中开启开关,服务器一般没打开(bmc界面里打开)4.网络中有一台 DHCP 服务器以便为客户机自动分配地址、指定引导文件位置5.服务器通过 tftp服务(简单文件...

计算广告学_X-Dragon烟雨任平生的博客-程序员秘密_计算广告学

计算广告学计算广告1、在线广告综述1.1 广告的定义与目的1.1.1 定义:1.2 在线广告类型1.3 在线广告简史1.4 广告有效性原理1.5 在线广告相关行业协会计算广告作者:刘鹏 北冥乘海生 参考视频链接:https://www.bilibili.com/video/BV1jz411z7UT笔记:X-Dragon [email protected]、在线广告综述广告越占一个国家GDP的0.5%-1%左右。网络广告》电视广告》报纸广告(后面会逐渐消退)数据:个性化流量:规模化

随便推点

为什么分布式一定要有消息队列?_LiangGzone的博客-程序员秘密

虽然已经年底了,但腾讯、字节等大厂还在招人,其他公司也开始为来年的项目储备候选人。我有个朋友,最近面试屡屡碰壁,一问原因,都是算法、高并发、消息队列这些问题。拿消息队列来说,大多数人工作...

linux系统改装win10教程,技术编辑为你解答win10系统安装Linux Mint的图文方案_苏慕凉的博客-程序员秘密

win10系统稳定性好,使用者众多;免不了会遇到win10系统安装Linux Mint这样的问题要处理,大部分伙计都是第一次看到win10系统安装Linux Mint这样的事情,有的朋友想试着解决一下win10系统安装Linux Mint的问题却不知怎样下手,其实解决方法很简单,只需采取以下两步措施:1、你需要安装新的操作系统之前做明显的事情。第一个也是最重要的一点是要备份你坐在你的计算机上的任何...

[Err] 2013 - Lost connection to MySQL server during query 的解决_咕噜呜的博客-程序员秘密

[Err] 2013 - Lost connection to MySQL server during query 的解决mysql导入表结构和数据报错在配置中找到my.ini文件,我的是mysql5.7加入max_allowed_packet = 500Mmysql配置详解: max_allowed_packethttps://www.jianshu.com/p/45967d3408d4原链接地址:https://blog.csdn.net/weixin_42259631/arti

Android 菜单(Menu)控件的使用_stoneson的博客-程序员秘密_android menu 控件

<br /><br />1.通过XML布局添加菜单<br />首先在项目目录res下建立文件夹menu,然后在新建的menu文件夹下添加<br />menu.xml<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/about" android:title="About" />

rxjs为什么用的人少_为什么刘邦的“狐朋狗友”,都是治国大才?_weixin_39780784的博客-程序员秘密

来源:朝文社(ID:ailishi777)作为明太祖朱元璋之前,中国历代皇帝里最神奇的“创业奇迹”。汉高祖刘邦常被人津津乐道(吐槽)的,就是其无比“草根”的“创业团队”。刘邦的“创业团队”有多“草根”?以东汉学者王符的话说:“ 高祖所以共取天下者,缯肆、狗屠也;骊山之徒,钜野之盗,皆为名将”。特别是那几位最早跟刘邦“创业”的团队成员,樊哙“以屠狗为事”,夏侯婴“为沛厩司御”,灌婴“贩缯者...

页面重绘和回流以及优化_追寻北极的博客-程序员秘密

在讨论页面重绘、回流之前。需要对页面的呈现流程有些了解,页面是怎么把html结合css等显示到浏览器上的,下面的流程图显示了浏览器对页面的呈现的处理流程。可能不同的浏览器略微会有些不同。但基本上都是类似的。1.  浏览器把获取到的HTML代码解析成1个DOM树,HTML中的每个tag都是DOM树中的1个节点,根节点就是我们常用的document对象。DOM树里包含了所有HTML标签,包括d

推荐文章

热门文章

相关标签