如果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"); } }