当我将@Validated
添加到Spring RestConstroller
时,我收到了该Controllers端点的HTTP 404响应。在添加注释之前,发现端点没有任何问题。
问题特别是与@PathVariable
有关,并且我可以使用非基本RequestBody参数正确验证(使用@Valid
)。
关于此的文章很多,我花了大量时间尝试几种变体而没有成功。最简单的是。
根据这个简单的示例https://sdqali.in/blog/2015/12/05/validating-requestparams-and-pathvariables-in-spring-mvc/,我认为它应该与向控制器添加@Validated
,为PathVariable参数保留@Valid
并添加MethodValidationPostProcessor
一样简单豆角,扁豆。最好我用@Valid
代替@Validated
。
我正在使用Spring 5(不是启动),并且在类路径上具有hibernate-validator 6.0.16.Final
问题性RestController
@Validated
@RestController
@RequestMapping(value = "practices")
public class RestPracticeResource implements PracticeResource {
@Override
@GetMapping("/{id}")
public ResponseEntity<Practice> getPractice(@Id @PathVariable("id") final String id) throws ResourceNotFoundException {
final UUID uuidId = UUID.fromString(id);
}
}
为RequestBody使用RestController
@RestController
@RequestMapping(value = "accounts")
public class RestAccountResource implements AccountResource {
@Override
@PostMapping
public ResponseEntity<AccountDto> create(@NotNull @Valid @RequestBody final CreateAccountDto createAccountDto)
throws ResourceAlreadyExistsException {
...
}
}
ID注释
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = Id.IdValidator.class)
public @interface Id {
// ... Stock standard code here
class IdValidator implements ConstraintValidator<Id, String> {
@Override
public void initialize(final Id id) {}
@Override
public boolean isValid(final String id, final ConstraintValidatorContext constraintValidatorContext) {
// Basic REGEX match for UUID format
return ValidationUtil.isValidId(id);
}
}
}
ExceptionHander
@ExceptionHandler(ConstraintViolationException.class)
public final ResponseEntity<ApiError> handleConstraintViolationException(final ConstraintViolationException ex,
final WebRequest webRequest) {
// .. extract violations into standard format
return new ResponseEntity<>(apiError, BAD_REQUEST);
}
MethodValidationPostProcessor bean
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
实际结果
一旦添加@Validated
,我将收到/practices/{id}
端点的Http 404响应,无论我提供哪种格式的ID。如果删除@Validated
,则可以传递有效的UUID,并且一切正常,或者传递无效的UUID,并从UUID.fromString(id)
引发异常。
@Id
,则会忽略 @Valid
。
预期结果
添加@Validated
将启用@Id
批注验证,并且在提供非UUID格式的ConstraintViolationException
时抛出{id}
。
答案 0 :(得分:0)
这是一个与此类似的老问题,我找到了我想要的解决方案。链接:Spring rest controller @RequestParam validation
总结Szymon Stepniak的答案。这是spring-mvc错误。我使用的是休眠版本5.2.4.Final和spring-webmvc 4.3.8.RELEASE版本。
如果rest控制器实现了一个接口,并且我们还添加了@Validated注释,则RequestMappingHandlerMapping将不会注册端点。我不知道根本原因。但是删除“实现接口”对我来说解决了这个问题。
答案 1 :(得分:0)
使用代理目标类,它将与
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
答案 2 :(得分:0)
我添加了您所做的常用内容(pom 中的库、RequestBody 上的 @Valid 等),并且也得到了 404!
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.3.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.1-b11</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
Spring 文档(和许多博客)的微妙之处在于 Spring 会寻找一个退出点来抛出错误,但如果该退出点不存在,它将回复 404。在阅读了很多之后,尤其是这个 { {3}},添加这个类让 Spring 识别 @Valid 并找到一个退出点来抛出错误
@RestControllerAdvice
@Order(1)
public class RestControllerExceptionHandler {
@RequestMapping(value = { "error/404" }, method = RequestMethod.GET)
@ExceptionHandler(Exception.class)
public String handleUnexpectedException(Exception e) {
return "views/base/rest-error";
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public String handlemethodArgumentNotValid(MethodArgumentNotValidException exception) { //
// TODO you can choose to return your custom object here, which will then get transformed to json/xml etc.
return "Sorry, that was not quite right: " + exception.getMessage();
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(ConstraintViolationException.class)
public String handleConstraintViolation(ConstraintViolationException exception) { //
// TODO you can choose to return your custom object here, which will then get transformed to json/xml etc.
return "Sorry, that was not quite right: " + exception.getMessage();
}
}