如果RequestBody参数的某些属性为null,如何返回400 HTTP错误代码?

我有以下示例:

这是请求正文:

public class UserLoginData implements Serializable { private static final long serialVersionUID = 1L; private String username; private String password; //... getter and setters } 

这是控制器:

 @RequestMapping(value = {"/login"}, method = RequestMethod.POST) @ResponseBody public LoginResponse login(@RequestBody(required = true) UserLoginData loginData){ //... some code } 

这是我调用服务的方式:

 POST /login {"username":"neuquino"} 

我希望Spring返回HTTP 400 BAD REQUEST错误,因为密码丢失了。 但不是这样,它返回HTTP 500 INTERNAL SERVER错误,带有以下堆栈跟踪:

 java.lang.NullPointerException at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:948) ~[spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838) ~[spring-webmvc-3.2.2.RELEASE.jar:3.2.2.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:755) ... 

如何向Spring指定用户名和密码是请求体中的必填字段?

@ Bart的回答对于找到我的最终解决方案非常有用:

 public class UserLoginData implements Serializable { private static final long serialVersionUID = 1L; @NotNull @NotBlank private String username; @NotNull @NotBlank private String password; //... getter and setters } 

在我的控制器上我有:

 public LoginResponse login( @RequestBody(required = true) @Valid UserLoginData loginData){ //... login code } 

直到这里非常相似,但它更清晰,因为控制器的方法没有错误validation。 而不是那样,我使用了另一个带有ControllerAdvice注释的类

 @ControllerAdvice public class RestErrorHandler { private MessageSource messageSource; @Autowired public RestErrorHandler(@Qualifier("messageSource") MessageSource messageSource) { this.messageSource = messageSource; } @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseBody public ValidationError processValidationError(MethodArgumentNotValidException ex) { BindingResult result = ex.getBindingResult(); List fieldErrors = result.getFieldErrors(); return this.processFieldErrors(fieldErrors); } private ValidationError processFieldErrors(List fieldErrors) { ValidationError dto = new ValidationError(); for (FieldError fieldError : fieldErrors) { String localizedErrorMessage = this.resolveLocalizedErrorMessage(fieldError); dto.getErrors().put(fieldError.getField(), localizedErrorMessage); } return dto; } private String resolveLocalizedErrorMessage(FieldError fieldError) { Locale currentLocale = LocaleContextHolder.getLocale(); String localizedErrorMessage = this.messageSource.getMessage(fieldError, currentLocale); return localizedErrorMessage; } } 

现在我的服务正在返回:

 { "errors":{ "country":"country cannot be null" } } 

我希望它可以帮助别人。

为了得到这个解决方案,我也使用了这篇文章中的内容 。

如果缺少密码,则在创建UserLoginData对象时不会设置密码。 它不会检查该值是否有效。 如果您需要validation登录数据,请使用正确的validation。

您可以使用hibernatevalidation程序包中的注释进行声明性validation,例如

 public class UserLoginData implements Serializable { private static final long serialVersionUID = 1L; @NotNull @NotBlank private String username; @NotNull @NotBlank private String password; //... getter and setters } 

然后可以将您的方法编写为(注意@Valid注释):

 public LoginResponse login( @RequestBody(required = true) @Valid UserLoginData loginData, BindingResult result, HttpServletResponse response){ if (result.hasErrors()) { // Validation problems! response.sendError(400, "Bad login data"); } }