Spring MVC 级联对象参数校验

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 【6月更文挑战第6天】在 Spring MVC 的使用过程中,我们会发现很多非常符合直觉的功能特性,但往往我们会习惯这种「被照顾得很好」的开发方式,依靠直觉去判断很多功能特性的用法。

相关文章:Spring MVC 是如何对对象参数进行校验的

在上述的这篇文章里,介绍了我们常用的 Spring MVC 的对象参数校验,是怎么完成校验的过程的,这篇来介绍一个更深入的问题。因为上篇中介绍的过程,适用于对象中的属性都是常用的 Java 数据类型,比如基本数据类型或者字符串等,如果这个对象中包含一个其它类型的参数,会怎么样呢?

比如这样的类型:

@Data
public class User{
   

    @Size(min = 6, max = 20)
    private String username;

    private Avatar avatar;

    @Data
    public static class Avatar{
   

        @NotNull
        private String imageUrl;

    }

}

在 User 类型中,有一个 Avatar 类型的属性,Avatar 类型中有一个 String 类型的属性 imageUrl 需要校验非空。

在上一篇中,最后介绍了执行校验过程的 AbstractMessageConverterMethodProcessor 类中的 validateIfApplicable 方法,在这个方法中,最后对符合要求的参数对象执行校验的是:

binder.validate(validationHints);

其具体执行的代码,可以在 ValidatorImpl 类的 validate 方法中找到。

@Override
public final <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {
   
   Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() );
   sanityCheckGroups( groups );

   @SuppressWarnings("unchecked")
   Class<T> rootBeanClass = (Class<T>) object.getClass();
   BeanMetaData<T> rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass );

   if ( !rootBeanMetaData.hasConstraints() ) {
   
      return Collections.emptySet();
   }

   BaseBeanValidationContext<T> validationContext = getValidationContextBuilder().forValidate( rootBeanClass, rootBeanMetaData, object );

   ValidationOrder validationOrder = determineGroupValidationOrder( groups );
   BeanValueContext<?, Object> valueContext = ValueContexts.getLocalExecutionContextForBean(
         validatorScopedContext.getParameterNameProvider(),
         object,
         validationContext.getRootBeanMetaData(),
         PathImpl.createRootPath()
   );

   return validateInContext( validationContext, valueContext, validationOrder );
}

在这里,会根据要校验的对象的类型,构建一个 BeanMetaData 类型的元信息,这个元信息中包含了需要做校验的字段和校验相关的信息。在构建 BeanMetaData 的过程中,会判断是否需要对成员字段进行级联校验,判断的方式就是这个字段是否被 @Valid 修饰(注意不是 @Validated)。级联校验的过程,与宿主对象的校验过程大体相同。

因此,文章开头的写法,Spring 不会去校验 Avatar 中的 imageUrl 是否合法,如果需要让这个校验生效,则需要给 avatar 属性增加 @Valid 注解:

@Valid
private Avatar avatar;

这样才会对 avatar 中的 imageUrl 进行校验。

在 Spring MVC 的使用过程中,我们会发现很多非常符合直觉的功能特性,比如将请求参数绑定到 Controller 的方法参数,或者直接返回一个 Java 对象就可以完成 JSON 数据的转换等等。但往往我们会习惯这种「被照顾得很好」的开发方式,依靠直觉去判断很多功能特性的用法。

如果遇到类似的问题,运行结果不符合开发时的预期,最好的方式就是搞懂其中的原理,从原理中寻找最佳地解决方式。

目录
相关文章
|
10天前
|
前端开发 Java Spring
Spring MVC 是如何对对象参数进行校验的
【6月更文挑战第4天】对象参数校验是使用 SpringMVC 时常用的功能,这篇文章尝试分析了,Spring 是如何实现这一功能的。
24 5
|
4天前
|
前端开发 Java Spring
Spring MVC 请求处理流程
Spring MVC 请求处理流程
6 0
|
1月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
85 0
|
1月前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
32 0
|
10月前
|
存储 开发框架 前端开发
[回馈]ASP.NET Core MVC开发实战之商城系统(五)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,banner条,友情链接,降价促销,新品爆款】,商品列表页面,商品详情等功能的开发,今天继续讲解购物车功能开发,仅供学习分享使用,如有不足之处,还请指正。
132 0
|
11月前
|
开发框架 前端开发 .NET
[回馈]ASP.NET Core MVC开发实战之商城系统(三)
[回馈]ASP.NET Core MVC开发实战之商城系统(三)
72 0
|
11月前
|
开发框架 前端开发 .NET
[回馈]ASP.NET Core MVC开发实战之商城系统(一)
[回馈]ASP.NET Core MVC开发实战之商城系统(一)
125 0
|
11月前
|
SQL 开发框架 前端开发
[回馈]ASP.NET Core MVC开发实战之商城系统(开篇)
[回馈]ASP.NET Core MVC开发实战之商城系统(开篇)
157 0
|
11月前
|
开发框架 缓存 JSON
ASP.NET Core MVC 从入门到精通之Filter
ASP.NET Core MVC 从入门到精通之Filter
136 0
|
7月前
|
开发框架 自然语言处理 前端开发
基于ASP.NET MVC开发的、开源的个人博客系统
基于ASP.NET MVC开发的、开源的个人博客系统
56 0