当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内部服务器错误:
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
}
到这里为止非常相似,但是更清楚了,因为控制器的方法没有错误验证。取而代之的是,我使用了另一个带有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<FieldError> fieldErrors = result.getFieldErrors();
return this.processFieldErrors(fieldErrors);
}
private ValidationError processFieldErrors(List<FieldError> 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"
}
}
我希望它可以帮助其他人。
为了获得此解决方案,我还使用了本文中的内容。