如何在请求正文 Spring Boot Rest Controller 中指定订单验证

Posted

技术标签:

【中文标题】如何在请求正文 Spring Boot Rest Controller 中指定订单验证【英文标题】:How to specify order validation in Request body Spring Boot Rest Controller 【发布时间】:2022-01-22 18:31:33 【问题描述】:

所以我在Spring Boot 中有一个Rest Controller,对于端点,我需要验证它的Request Body

控制器:

@RestController
@Validated
@RequestMapping("/my_endpoint")
public class WorkflowController 

    @PostMapping(value = "/blablabla/", consumes = MediaType.APPLICATION_JSON_VALUE)
    public List<Object> createDisconnectRequestRest(@RequestBody List<@CustomValidator @Valid RequestObj> dtos)  // here at the validators is the question
        ... //nevermind
       return null;
    

请求对象:

@Data
public class RequestObj

    private String comment;

    @NotNull // this @NotNull annotation validator is triggered AFTER the custom validator is done. I want this to be first validated and then the custom validator should take place
    private List<Long> ids = new ArrayList<>();




@Target(FIELD, TYPE_USE)
@Retention(RUNTIME)
@Constraint(validatedBy = CustomValidator.class)
@Documented
public @interface ValidRequest 

    String message() default "Invalid request";

    Class<?>[] groups() default ;

    Class<? extends Payload>[] payload() default ;

自定义验证器:

public class CustomValidator implements ConstraintValidator<ValidRequest, RequestObj> 

 // repositories, constructor 

    @Override
    public boolean isValid(RequestObj request, ConstraintValidatorContext constraintValidatorContext) 
     
         myRepository.findAllById(request.getIds()); // I want the @NotNull annotation validate the object before this custom validator

        return true;
    

这是问题

要触发的第一个是 CustomValidator,然后正在验证 RequestObj。换句话说,验证从@CustomValidator 注释开始,然后是@Valid 注释。我希望第一个被触发的是@Valid 注释(所以@NotNull 注释将首先验证对象)然后@CustomValidator 应该完成它的工作。例如,如果 body 字段 ids 为 NULL,我希望 @CustomValidator 甚至无法启动,因为验证已经失败。

【问题讨论】:

您是否尝试过更改注释的顺序? 是的,没用。 【参考方案1】:

这可能是因为您在类级别应用了@CustomValidator 注释,并且类在属性之前首先加载,这可能是您看到此顺序或执行的原因。

你有几个选择:

1- 在特定属性级别应用此 @CustomValidator

2- 将您的CustomValidator 设置为@Component,并从类级别中删除@CustomValidator 注释。然后在您的控制器方法中执行以下操作:

   @Autowired
   private CustomValidator customValidator;

    @PostMapping(value = "/blablabla/", consumes = MediaType.APPLICATION_JSON_VALUE)
    public List<Object> createDisconnectRequestRest(@RequestBody List<@Valid RequestObj> dtos)  // here at the validators is the question
        customValidator.validate(xyz);
    

--- 未经检验的理论 ---

您能否尝试更改在方法级别应用的注释的顺序,看看是否有所不同:

@PostMapping(value = "/blablabla/", consumes = MediaType.APPLICATION_JSON_VALUE)
public List<Object> createDisconnectRequestRest(@RequestBody List<@Valid @CustomValidator RequestObj> dtos)  // here at the validators is the question
    ... //nevermind
   return null;

【讨论】:

1.在特定属性级别添加 @CustomValidator 不是一种选择。我正在验证不同类型的属性组合 2. 更改顺序也不起作用。 3. 我想避免在控制器方法内部进行验证的解决方法 我在@GroupSequence 注释中找到了与此主题相关的内容。我正在阅读它,如果我找到任何解决方案,我会更新主题 @GroupSequence 用于对注释进行分组,在您的情况下,您正在查看 Validators 的优先顺序,所以我怀疑它是否会起作用。

以上是关于如何在请求正文 Spring Boot Rest Controller 中指定订单验证的主要内容,如果未能解决你的问题,请参考以下文章

如何在 spring-boot Web 客户端中发送请求正文?

Spring Data Rest:如何使用请求正文发送多部分文件

如何在 Spring Boot Rest 调用中传递 Date 类型的值?

如何在 Spring Boot 服务应用程序中的 REST 服务调用之间按原样传递请求参数?

如何在 Spring REST 控制器中获取原始 JSON 正文?

ControllerAdvice 的异常处理程序在使用 Spring Boot 的 Rest API 获取请求中不起作用。如何解决?