java—有人知道为什么@valid无法使用javax.validation并使用SpringStarter验证吗

vatpfxk5  于 2021-09-13  发布在  Java
关注(0)|答案(1)|浏览(665)

我有以下控制器:

  1. @PostMapping( "v1/libraryEvent" )
  2. public ResponseEntity<LibraryEvent> postLibraryEvent( @RequestBody @Valid LibraryEvent libraryEvent )
  3. throws JsonProcessingException
  4. {
  5. //Does some stuff
  6. }

其中包括使用此依赖关系的:

  1. import javax.validation.Valid;

libraryevent dto如下所示:

  1. @NoArgsConstructor
  2. @AllArgsConstructor
  3. @Data
  4. @Builder
  5. public class LibraryEvent
  6. {
  7. private Integer libraryEventId;
  8. private LibraryEventType libraryEventType;
  9. @Valid
  10. @NotNull
  11. private Book book;
  12. }

图书馆事件中的书如下所示:

  1. @AllArgsConstructor
  2. @NoArgsConstructor
  3. @Data
  4. @Builder
  5. public class Book
  6. {
  7. @NotNull
  8. private Integer bookId;
  9. @NotNull
  10. private String bookName;
  11. @NotNull
  12. private String bookAuthor;
  13. }

我还有一个测试,它使用mockmvc向控制器发送模拟请求,以测试该请求:

  1. @Test
  2. void postLibraryEvent_4xx() throws Exception {
  3. //given
  4. final Book book = Book.builder()
  5. .bookId( null )
  6. .bookAuthor( null )
  7. .bookName( "Kafka using spring boot" )
  8. .build();
  9. final LibraryEvent libraryEvent = LibraryEvent.builder()
  10. .book( book )
  11. .build();
  12. final String json = objectMapper.writeValueAsString( libraryEvent );
  13. mockMvc.perform(post("/v1/libraryEvent")
  14. .content(json)
  15. .contentType(MediaType.APPLICATION_JSON))
  16. .andExpect(MockMvcResultMatchers.status().is4xxClientError());
  17. }

到目前为止一切都很好,问题是我的 build.gradle 我使用的是javax.validation依赖项,当我使用该依赖项运行测试时 @Valid 注解不起作用,因为它返回了httpstatus.ok(200),而不是错误的请求(400),这应该是因为该书的id和作者被传递为null。这就是我的gradle文件的“我的依赖项”部分是如何用javax设置的:

  1. dependencies {
  2. implementation 'org.springframework.boot:spring-boot-starter-web'
  3. implementation 'javax.validation:validation-api:2.0.1.Final'
  4. testImplementation 'org.awaitility:awaitility:4.0.3'
  5. compileOnly 'org.projectlombok:lombok'
  6. annotationProcessor 'org.projectlombok:lombok'
  7. testImplementation ('org.springframework.boot:spring-boot-starter-test') {
  8. exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
  9. }
  10. }

我解决了这个问题,用spring boot starter validation替换了javax依赖项,一旦我在更改后再次运行测试,它就通过了,并且 @Valid 在控制器中,由于测试返回4xx http状态,因此控制器正常工作。我的gradle现在看起来像这样:

  1. dependencies {
  2. implementation 'org.springframework.boot:spring-boot-starter-web'
  3. implementation 'org.springframework.boot:spring-boot-starter-validation'
  4. testImplementation 'org.awaitility:awaitility:4.0.3'
  5. compileOnly 'org.projectlombok:lombok'
  6. annotationProcessor 'org.projectlombok:lombok'
  7. testImplementation ('org.springframework.boot:spring-boot-starter-test') {
  8. exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
  9. }
  10. }

但这很奇怪,因为spring验证应该使用与javax相同的验证,或者至少使用 @Valid 我们应该以同样的方式行事。所以我的问题是,有人能解释一下javax验证和spring验证之间的区别吗?为什么javax验证失败了,而spring验证失败了?
提前谢谢你!

k5hmc34c

k5hmc34c1#

spring文档位于https://docs.spring.io/spring-framework/docs/5.3.9/reference/html/core.html#validation-beanvalidation spring为引导bean验证提供程序提供了以下示例:

  1. import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
  2. @Configuration
  3. public class AppConfig {
  4. @Bean
  5. public LocalValidatorFactoryBean validator() {
  6. return new LocalValidatorFactoryBean();
  7. }
  8. }

接着是评论:
bean验证提供程序(如hibernate验证程序)预计会出现在类路径中,并被自动检测到。
SpringBootStarter验证依赖项似乎只做这两件事。

相关问题