有谁知道为什么@Valid失败与javax.验证并与弹簧启动器验证一起工作



我有以下控制器:

@PostMapping( "v1/libraryEvent" )
public ResponseEntity<LibraryEvent> postLibraryEvent( @RequestBody @Valid LibraryEvent libraryEvent )
throws JsonProcessingException
{
//Does some stuff
}

使用此依赖项,其中包括:

import javax.validation.Valid;

LibraryEvent DTO如下所示:

@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class LibraryEvent
{
private Integer libraryEventId;
private LibraryEventType libraryEventType;
@Valid
@NotNull
private Book book;
}

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

@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class Book
{
@NotNull
private Integer bookId;
@NotNull
private String bookName;
@NotNull
private String bookAuthor;
}

我也有这个测试,它使用MockMvc发送一个模拟请求到控制器,以测试一个:

@Test
void postLibraryEvent_4xx() throws Exception {
//given
final Book book = Book.builder()
.bookId( null )
.bookAuthor( null )
.bookName( "Kafka using spring boot" )
.build();
final LibraryEvent libraryEvent = LibraryEvent.builder()
.book( book )
.build();
final String json = objectMapper.writeValueAsString( libraryEvent );
mockMvc.perform(post("/v1/libraryEvent")
.content(json)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().is4xxClientError());
}

一切都很好,到目前为止,问题是,在我的build.gradle我使用javax。验证依赖项,当我使用该依赖项运行测试时,@Valid注释不起作用,因为它返回HttpStatus。应该是OK(200)而不是Bad request(400),因为传递的id和作者是空的。这是我的gradle文件的依赖部分是如何设置javax:

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'javax.validation:validation-api:2.0.1.Final'
testImplementation 'org.awaitility:awaitility:4.0.3'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation ('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}

我通过用spring boot starter验证替换javax依赖项来解决问题,一旦我在该更改后再次运行测试,它就通过了,控制器中的@Valid工作,因为测试返回4XX HTTP状态。我的gradle现在看起来像这样:

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
testImplementation 'org.awaitility:awaitility:4.0.3'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation ('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}

但是这很奇怪,因为spring验证应该使用与javax使用相同的验证,或者至少@Valid应该以相同的方式表现。所以我的问题是,谁能向我解释一下javax验证和spring验证之间的区别是什么,以及为什么javax失败了,而spring验证却没有?

提前感谢!

https://docs.spring.io/spring-framework/docs/5.3.9/reference/html/core.html#validation-beanvalidation-spring上的Spring文档给出了引导Bean验证提供程序的示例:

import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
@Configuration
public class AppConfig {
@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
}

接着是注释:

Bean验证提供程序,如Hibernate验证器,预计会出现在类路径中,并被自动检测到。

spring-boot-start -validation依赖项似乎只做这两件事。

最新更新