2

我想用我的@RepositoryRestController中的我的DTO進行驗證,並帶有javax註釋@Valid。 然而@RepositoryRestController目前不支持@Valid,你可以在此看到門票:https://jira.spring.io/browse/DATAREST-593@RepositoryRestController中的驗證

如果我使用一個@RestController@Valid會工作正常,但是後來我@RepositoryRestResource不再工作。我需要在我的@RestController中爲每個功能(findOne(),findAll()等)手動編寫一個方法。目前,我只能使用@RepositoryRestResource和Projection作爲方法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(); 
} 

控制器:

@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; 
    } 
} 

ChipHelper:

@Data 
public class ChipHelper { 
    @NotNull 
    private Long id; 

    @NotNull 
    @Size(min = 10) 
    private String identifier; 
} 
+0

與有效註解的成功? –

回答

0

似乎在這種情況下沒有好的解決方案,默認情況下不支持@Valid註釋,如DATAREST-593中所述。這就是爲什麼,以支持@RepositoryRestController方法@Valid註釋,我創建了以下@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(); 
    } 
}