首页 > 解决方案 > 无法在 Spring REST Web 服务中成功使用验证

问题描述

我正在尝试在我的 SPRING REST-API 上应用验证,但我遇到了这个异常:

Apr 10, 2020 12:05:26 PM org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver doResolveHandlerMethodExceptionWARNING: Failed to invoke @ExceptionHandler method: public com.luv2code.springdemo.exceptionhandling.RestFieldErrorValidation com.luv2code.springdemo.exceptionhandling.GlobalExceptionHandler.processValidationError(org.springframework.web.bind.MethodArgumentNotValidException)org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class com.luv2code.springdemo.exceptionhandling.RestFieldErrorValidation    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:226)

实体类:

@Entity@Table(name="customer")
public class Customer {     

@Id 
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")  
private int id; 

@Column(name="first_name")
@NotNull(message = "Firstname is necessary")    
@Size(min=1,message="This field is required")
private String firstName;   

@Column(name="last_name")   
@NotNull(message = "Lastname is necessary") 
@Size(min=1,message="This field is required")
private String lastName;    

@Column(name="email")   
private String email;         
       // getters and setters
}

FieldValidation 处理程序类:

public class RestFieldError {

    private String field;    
    private String message;

    public RestFieldError() {

    }

    // getters and setters
}

public class RestFieldErrorValidation {

    private List<RestFieldError> fieldErrors = new ArrayList<>();

    public RestFieldErrorValidation() {

    }

    public void addFieldError(String path, String message) {
        RestFieldError error = new RestFieldError(path, message);
        fieldErrors.add(error);
    }

}

休息控制器代码:

@RestController
@RequestMapping("/api")
public class CustomerRestController {

    // autowire the CustomerService
    @Autowired
    private CustomerService customerService;

    @InitBinder
    public void initBinder(WebDataBinder dataBinder) {
        System.out.println("Entered init binder");
        StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true);
        dataBinder.registerCustomEditor(String.class, stringTrimmerEditor);
    }

// add the mapping for POST/customers (add a new customer)
    @PostMapping("/customers")
    @ResponseBody
    public Customer addCustomer(@Valid @RequestBody Customer theCustomer) {
        System.out.println("theCustomer :"+theCustomer.getFirstName());

        theCustomer.setId(0);
        customerService.saveCustomer(theCustomer);

        return theCustomer;
    }

}

异常处理类:

@ControllerAdvice
public class GlobalExceptionHandler {


    // Adding Validation Support on REST APIs--------------------------------------------------------->
        private MessageSource messageSource;

        @Autowired
        public GlobalExceptionHandler(MessageSource messageSource) {
            this.messageSource = messageSource;
        }   

        @ExceptionHandler(MethodArgumentNotValidException.class)
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        @ResponseBody
        public RestFieldErrorValidation processValidationError(MethodArgumentNotValidException ex) {
            BindingResult result = ex.getBindingResult();
            List<FieldError> fieldErrors = result.getFieldErrors();

            return processFieldErrors(fieldErrors);
        }

        private RestFieldErrorValidation processFieldErrors(List<FieldError> fieldErrors) {
            RestFieldErrorValidation dto = new RestFieldErrorValidation();

            for (FieldError fieldError: fieldErrors) {
                String localizedErrorMessage = resolveLocalizedErrorMessage(fieldError);
                dto.addFieldError(fieldError.getField(), localizedErrorMessage);
            }

            return dto;
        }

        private String resolveLocalizedErrorMessage(FieldError fieldError) {
            Locale currentLocale =  LocaleContextHolder.getLocale();
            String localizedErrorMessage = messageSource.getMessage(fieldError, currentLocale);

            //If the message was not found, return the most accurate field error code instead.
            //You can remove this check if you prefer to get the default error message.
            if (localizedErrorMessage.equals(fieldError.getDefaultMessage())) {
                String[] fieldErrorCodes = fieldError.getCodes();
                localizedErrorMessage = fieldErrorCodes[0];
            }

            return localizedErrorMessage;
        }

}

如果您可以检查代码,这是该项目的谷歌驱动器链接:

https://drive.google.com/open?id=1QSFVMi3adHGkc7BqXsqAY0P_tO2UfT2I

这是我关注的文章:

https://www.petrikainulainen.net/programming/spring-framework/spring-from-the-trenches-adding-validation-to-a-rest-api/

标签: javaspringspring-mvcspring-restcontrollerhibernate-validator

解决方案


我假设您在这里使用的是普通的 Spring,而不是 Spring Boot。

问题是:你到底想把你的RestFieldErrorValidation object? XML?JSON?

无论哪种方式,您都需要在您的类路径中使用适当的第三方库,以便 Spring 可以自动进行转换。

对于 JSON,您可能希望将此依赖项添加到您的项目中。

  <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.10.2</version>
  </dependency>

推荐阅读