如何解决使用MethodValidationPostProcessor
我的测试Spring Boot应用程序有问题。它工作正常,但是当我通过添加依赖等并添加@Configuration
来启用Spring验证时:
@Configuration
public class TestConfiguration {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
我的测试端点为404。
{
"timestamp": 1601507037178,"status": 404,"error": "Not Found","message": "No message available","path": "/test"
}
我已经针对类似问题(例如here或here)应用了一些解决方案/建议,但没有成功。
这是我的代码: https://github.com/zolv/error-handling-test
API接口:
@Validated
public interface TestApi {
@PostMapping(
value = "/test",produces = {"application/json"},consumes = {"application/json"})
@ResponseBody
ResponseEntity<TestEntity> getTest(@Valid @RequestBody(required = false) TestEntity request);
}
TestEntity
仅用于发送邮件:
@Data
public class TestEntity {
@JsonProperty("test")
@NotNull
private String test;
}
控制器实现:
@RestController
@RequiredArgsConstructor
@Validated
public class TestController implements TestApi {
@Override
@ResponseBody
public ResponseEntity<TestEntity> getTest(@Valid @RequestBody TestEntity request) {
return ResponseEntity.ok(request);
}
}
我的控制器建议
@ControllerAdvice
public class DefaultErrorHandlerAdvice extends ResponseEntityExceptionHandler {
@ExceptionHandler(value = {ConstraintViolationException.class})
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
public ResponseEntity<String> handleValidationFailure(ConstraintViolationException ex) {
StringBuilder messages = new StringBuilder();
for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
messages.append(violation.getMessage());
}
return ResponseEntity.badRequest().body(messages.toString());
}
@Override
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex,HttpHeaders headers,HttpStatus status,WebRequest request) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.contentType(MediaType.APPLICATION_PROBLEM_JSON)
.body("problem");
}
}
应用程序:
@SpringBootApplication
@EnableWebMvc
@ComponentScan(basePackages = "com.test")
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class,args);
}
}
我使用的测试,但使用邮递员也失败:
@SpringJUnitConfig
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class TestControllerTest {
@Autowired protected TestRestTemplate restTemplate;
@Test
void registrationHappyPath() throws Exception {
/*
* Given
*/
final TestEntity request = new TestEntity();
/*
* When/
*/
final ResponseEntity<String> response =
restTemplate.postForEntity("/test",request,String.class);
/*
* Then
*/
Assertions.assertEquals(HttpStatus.BAD_REQUEST,response.getStatusCode());
final String body = response.getBody();
Assertions.assertNotNull(body);
}
}
如果我注释掉TestConfiguration
,则一切正常。
预先感谢您的帮助。
解决方法
您应该设置MethodValidationPostProcessor#setProxyTargetClass(true)
,因为默认情况下MethodValidationPostProcessor
使用JDK代理,这会导致在Spring上下文中丢失控制器。
调用AbstractHandlerMethodMapping#processCandidateBean
时isHandler(Class<?> beanType)
将返回false
,因为JDK代理不包含@RestController
批注。
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor mvProcessor = new MethodValidationPostProcessor();
mvProcessor.setProxyTargetClass(true);
return mvProcessor;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。