我想使用 javax 注释 @RepositoryRestController
在我的 @Valid
中验证我的 DTO。
但是 @RepositoryRestController
目前不支持 @Valid
,正如您在此票证中所见:https://jira.spring.io/browse/DATAREST-593
如果我使用 @RestController
我的 @Valid
会正常工作,但是我的 @RepositoryRestResource
将不再工作。我需要在我的 @RestController
中为每个功能(findOne()、findAll() 等)手动编写一个方法。目前,我只能将 @RepositoryRestResource
与投影一起用于 findAll() 等方法。
如何验证 @RepositoryRestController
中的 DTO?
存储库:
@RepositoryRestResource(excerptProjection = ChipProjection.class)
public interface ChipRepository extends JpaRepository<Chip, Long> {
}
投影:
@Projection(name = "summary", types = Chip.class)
public interface ChipProjection {
Long getId();
ChipIdentifier getChipIdentifier();
}
Controller :
@RepositoryRestController
public class ChipRestController {
@Autowired
ChipService chipService;
@RequestMapping(value = "/chips", method = RequestMethod.POST)
public @ResponseBody ChipHelper saveChip(@Valid @RequestBody ChipHelper chip, BindingResult result){
List<FieldError> errors = result.getFieldErrors();
//errors is always empty, @Valid not working
chipService.save(chip);
return chip;
}
}
芯片助手:
@Data
public class ChipHelper {
@NotNull
private Long id;
@NotNull
@Size(min = 10)
private String identifier;
}
最佳答案
似乎在这种情况下没有好的解决方案,并且默认情况下不支持 @Valid
注释,如 DATAREST-593 中所述。这就是为什么,为了支持 @Valid
方法上的 @RepositoryRestController
注释,我创建了以下 @ControllerAdvice
类:
package com.tivoli.api.application.advice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;
import javax.validation.Valid;
import javax.validation.ValidationException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
/**
* Workaround class for making JSR-303 annotation validation work for controller method parameters.
* Check the issue <a href="https://jira.spring.io/browse/DATAREST-593">DATAREST-593</a>
*/
@ControllerAdvice
public class RequestBodyValidationProcessor extends RequestBodyAdviceAdapter {
private final Validator validator;
public RequestBodyValidationProcessor(@Autowired final Validator validator) {
this.validator = validator;
}
@Override
public boolean supports(final MethodParameter methodParameter, final Type targetType, final Class<? extends
HttpMessageConverter<?>> converterType) {
final Annotation[] parameterAnnotations = methodParameter.getParameterAnnotations();
for (final Annotation annotation : parameterAnnotations) {
if (annotation.annotationType().equals(Valid.class)) {
return true;
}
}
return false;
}
@Override
public Object afterBodyRead(final Object body, final HttpInputMessage inputMessage, final MethodParameter
parameter, final Type targetType, final Class<? extends HttpMessageConverter<?>> converterType) {
final Object obj = super.afterBodyRead(body, inputMessage, parameter, targetType, converterType);
final BindingResult bindingResult = new BeanPropertyBindingResult(obj, obj.getClass().getCanonicalName());
validator.validate(obj, bindingResult);
if (bindingResult.hasErrors()) {
throw new ValidationException(createErrorMessage(bindingResult));
}
return obj;
}
private String createErrorMessage(final BindingResult bindingResult) {
final StringBuilder stringBuilder = new StringBuilder("Invalid parameters specified.");
if (bindingResult.getFieldErrors() != null && !bindingResult.getFieldErrors().isEmpty()) {
stringBuilder.append(" Fields:");
bindingResult.getFieldErrors().forEach(fieldError -> stringBuilder
.append(" [ ")
.append(fieldError.getField())
.append(" : ")
.append(fieldError.getRejectedValue())
.append(" ] "));
} else if (bindingResult.getAllErrors() != null && !bindingResult.getAllErrors().isEmpty()) {
final ObjectError objectError = bindingResult.getAllErrors().get(0); // get the first error
stringBuilder.append(" Message: ")
.append(objectError.getDefaultMessage());
}
return stringBuilder.toString();
}
}
关于spring - @RepositoryRestController 中的验证,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37923994/