【问题标题】:Spring - @Valid not working after calling methodSpring - 调用方法后@Valid不起作用
【发布时间】:2021-10-06 12:20:55
【问题描述】:

我写了端点示例来理解我的问题的含义。

我意识到由于@Valid 注释,我的测试没有通过。

例如。如果有人打旧的端点,我有两个端点,需要检查是否设置了电子邮件,因为它有一个 @NotBlank 注释。 但是当我用一组电子邮件询问我的端点时,@Valid 没有被执行,我意识到在使用无效数据进行测试之后。而且我无法在oldPutContact 中设置@Valid,因为有些联系人没有电子邮件。

我的问题是为什么putContact 没有执行@Valid 注释。

    @PutMapping(value = "/contact/{contactid}", )
    public String oldPutContact(@RequestBody Contact contact)
        if(StringUtils.isBlank(contact.getEmail())){
            contact.setEmail("randomEmail@ups.cm") ;
        }
        return putContact(contact);
    }
    @PutMapping(value = "/contact/update/{contactid}")
    public String putContact(@RequestBody @Valid Contact contact) {
        contactService.updateContact(contact);
    }

想象一下联系人实体看起来像这样

 @Builder(toBuilder=true)
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Contact {

        private static final String SOME_PATTERN = "";
       private static final String SOME_EMAIL_PATTERN = "";
        private static final String SOME_PATTERN2 = "";
      
        @NotBlank
        private String id;

        @NotNull
        private Boolean isActive;

        @NotBlank
        @Pattern(regexp = SOME_PATTERN)
        private String name;

        @NotBlank
        @Pattern(regexp = SOME_PATTERN)
        private String surname;
        
       @NotBlank
        @Email(regexp = SOME_EMAIL_PATTERN)
        private String email;

        @NotBlank
        @Pattern(regexp = SOME_PATTERN2)
        private String telephone;

    }

【问题讨论】:

  • 你应该如何让 Spring 知道应该如何准确验证传递的字符串?
  • 代码是一个例子来理解它的意思。我有一个实体,我在其中使用了很多注释,例如 Pattern、NotNull、NotBlank 等。如果我使用 Valid 注释,我说他需要检查实体中的字段。当我第一次使用 setEmail 访问 oldPutConctact 端点,然后使用 putContact 时,他正在这样做,但不是在上述情况下。如果我只点击 putContact 端点,则考虑 Valid 注释。
  • 测试已经完成,但这是测试没有通过的一种情况,我不明白为什么没有执行 VALid 注释
  • 显示你传递给putContact端点的完整模型类,或者至少它是必不可少的部分(电子邮件)
  • 如果实体只有String,spring 应该如何验证它?您的方法签名采用 String not 您的实体(此 putContact(@RequestBody @Valid String contact) 是您发布的内容!)。如果这只是一个错字,请删除您拥有的 javax.validation 依赖项并添加 spring-boot-starter-validation。最后,内部调用不会执行 @Valid,因为这是您在此处绕过的请求处理的一部分,当与 @Validated 一起使用时,它也不会工作,因为它使用 AOP,因此它不使用代理使用内部方法调用通过代理。

标签: java spring spring-boot validation


【解决方案1】:

首先,您应该为您的参数定义验证规则。 例如(注意 NotBlank 注释):

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @NotBlank(message = "Name is mandatory")
    private String name;

    @NotBlank(message = "Email is mandatory")
    private String email;

    // standard constructors / setters / getters / toString
    
}

然后你可以在rest api控制器中使用有效的注解。 像这样:

@RestController
public class UserController {

    @PostMapping("/users")
    ResponseEntity<String> addUser(@Valid @RequestBody User user) {
        // persisting the user
        return ResponseEntity.ok("User is valid");
    }

    // standard constructors / other methods

}

您不能定义验证规则。所以spring不知道如何验证参数。

更多信息请参考Spring validation

----通过阅读@nusia的评论,添加以下描述。

从示例代码“public String putContact(@RequestBody @Valid String contact)”中,我看不到您在哪里为参数 String contact 定义了 @NotBlank 注释,或者您的意思是参数“contact”的类型是不是字符串?如果“联系人”的类型是已定义的实体,并且其电子邮件字段具有 NotBlank 注释。然后从 HTTP PUT 请求调用新端点“putContact”将触发弹簧验证,但如果您的意思是从旧方法“oldPutContact”调用新方法“putContact”,弹簧验证将不会被触发,原因类似于Call spring annotation method from same class.

【讨论】:

  • 也许我把问题定义错了。我得到了你所说的一切,在 RestContoller 注释之上还必须有一个 Validated 注释。但是我的问题是,考虑到 putMapping 存在一个旧端点,因此两个端点一个旧端点一个新端点。他们需要在那里。有时基于用户示例,有时未设置旧用户的电子邮件,因此我需要在服务中执行某些操作之前手动设置它。将继续
  • 因此考虑两种情况,一些用户设置了电子邮件,一些用户没有设置电子邮件。当具有设置电子邮件的用户调用旧端点时,我们检查电子邮件是否为空白,并且由于某些没有设置电子邮件的用户在哪里不是有效注释。我们将他重定向到用户案例中的新端点 addUser /users 有效注释没有被执行。
  • 这就是为什么 Spring 没有看到 @Valid 注释的问题
  • 我意识到在对无效数据进行了一些测试后,我发现这个注释没有被执行
  • 不,你不需要控制器上的@Validated(请停止这样做,因为它服务于完全不同的用例)。
猜你喜欢
  • 2017-10-04
  • 2020-09-11
  • 2011-05-16
  • 1970-01-01
  • 1970-01-01
  • 2013-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多