You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Springdoc中使用validation-api分组校验?

问题:Springdoc无法识别Validation分组注解导致DTO字段必填标识错误

在Spring Boot应用中使用validation-api与Springdoc时,希望通过复用单个DTO类处理相似请求。Springdoc能识别@NotBlank、@NotNull等校验注解,但无法识别注解的groups分组属性(如@NotBlank(groups = {GetGroup.class}))。

代码示例

public class MyController {
  
  @GetMapping
  public MyResponseDto getFoo(@ParameterObject @Validated(GetGroup.class) MyRequestDto request) {
    ...
  }

  @PostMapping
  public Long postFoo(@ParameterObject @Validated(PostGroup.class) MyRequestDto request) {
    ...
  }
}

public class MyRequestDto {
  
  @NotNull(groups = {GetGroup.class})
  private String field01;

  @NotNull(groups = {PostGroup.class})
  private String field02;
}

未集成Springdoc时,@Validated(GetGroup.class)会校验field01必填,@Validated(PostGroup.class)会校验field02必填,但Springdoc会将这两个字段都标记为必填项,需要解决此问题。


解决方案

方法1:自定义OperationCustomizer处理分组校验

通过实现OperationCustomizer接口,根据控制器方法上的@Validated分组信息,过滤DTO中不属于当前分组的校验注解,修正OpenAPI的参数必填标识:

@Component
public class ValidatedGroupOperationCustomizer implements OperationCustomizer {

    @Override
    public Operation customize(Operation operation, HandlerMethod handlerMethod) {
        // 获取方法上的@Validated注解
        Validated validated = handlerMethod.getMethodAnnotation(Validated.class);
        if (validated == null || validated.value().length == 0) {
            return operation;
        }
        Class<?>[] groups = validated.value();
        // 获取请求参数对应的DTO类型
        MethodParameter methodParam = handlerMethod.getMethodParameters()[0];
        Class<?> dtoClass = methodParam.getParameterType();
        
        // 遍历DTO所有字段,校验分组匹配情况
        for (Field field : dtoClass.getDeclaredFields()) {
            // 处理@NotNull注解
            processValidationAnnotation(operation, field, NotNull.class, groups);
            // 处理@NotBlank注解
            processValidationAnnotation(operation, field, NotBlank.class, groups);
            // 按需添加其他校验注解类型(如@NotEmpty)
        }
        return operation;
    }

    private <T extends Annotation> void processValidationAnnotation(Operation operation, Field field, Class<T> annotationClass, Class<?>[] targetGroups) {
        T annotation = field.getAnnotation(annotationClass);
        if (annotation == null) {
            return;
        }
        try {
            // 通过反射获取注解的groups属性
            Method groupsMethod = annotationClass.getMethod("groups");
            Class<?>[] annotationGroups = (Class<?>[]) groupsMethod.invoke(annotation);
            
            // 判断当前字段的校验注解是否属于目标分组
            boolean isMatch = Arrays.stream(annotationGroups)
                    .anyMatch(group -> Arrays.asList(targetGroups).contains(group));
            
            if (!isMatch) {
                // 找到对应参数并设置为非必填
                operation.getParameters().stream()
                        .filter(param -> param.getName().equals(field.getName()))
                        .findFirst()
                        .ifPresent(param -> param.setRequired(false));
            }
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            // 异常处理
            e.printStackTrace();
        }
    }
}

方法2:使用@Schema注解手动指定字段必填性

在DTO字段上通过@Schema的requiredMode属性,结合分组场景控制不同接口下的必填显示:

public class MyRequestDto {
  
  @NotNull(groups = {GetGroup.class})
  @Schema(requiredMode = RequiredMode.NOT_REQUIRED)
  private String field01;

  @NotNull(groups = {PostGroup.class})
  @Schema(requiredMode = RequiredMode.NOT_REQUIRED)
  private String field02;
}

同时配合自定义逻辑,在不同接口方法上动态设置对应字段的必填性,或者结合Springdoc的参数过滤功能实现分组匹配。

方法3:升级Springdoc至最新稳定版

Springdoc后续版本(如v1.6.0及以上)对Validation分组注解的支持有优化,升级后可能无需额外配置即可自动识别分组信息,正确标记对应字段的必填性。建议优先尝试升级版本。


内容的提问来源于stack exchange,提问作者Rurien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 05:32:42