Java/Spring > 当请求中没有发送正文时,使用@RequestBody 处理控制器方法的错误请求响应
Java/Spring > Handle Bad Request response for controller method with @RequestBody when no body is sent in request
长话短说:我正在创建应该是 100% REST 的 API。
我正在尝试覆盖以下情况的默认响应:
我的@RestController 中有一个方法,它以@RequestBody 作为属性
@RequestMapping(value = {"register"}, method = RequestMethod.POST, produces = "application/hal+json")
public Resource<User> registerClient(@RequestBody User user, HttpServletRequest request)
如果我发送正确的请求,该方法工作正常。但是当我不这样做时就会出现问题。当请求的主体为空时,我会收到一个状态为 400 的通用 Tomcat 错误页面,我需要它只发送一个字符串或一个 JSON 对象。
到目前为止,我尝试在我的 RestControllerAdvice 中为包 org.springframework.web.binding 中的所有 Spring 异常添加异常处理程序,但它也没有用。
我已经知道对于某些与安全相关的错误,必须在配置中创建处理程序,但我不知道是否属于这种情况。
有人遇到过类似的问题吗?有什么我想念的吗?
在正常情况下,您的控件永远不会到达您的请求方法。
如果你想要一个好看的页面,你可以使用 web.xml
并配置它来产生你的答案。
<error-page>
<error-code>404</error-code>
<location>/pages/resource-not-found.html</location>
</error-page>
一般来说,如果您想解决这个 400 问题,您必须在 User.java
中添加一些注释,以避免在反序列化时出现任何未知字段。
解决方案是简单地将 required = false 放在 RequestBody 注释中。之后,我可以轻松地添加一些逻辑来抛出自定义异常并在 ControllerAdvice 中处理它。
@RequestMapping(value = {"register"}, method = RequestMethod.POST, produces = "application/hal+json")
public Resource<User> registerClient(@RequestBody(required = false) User user, HttpServletRequest request){
logger.debug("addClient() requested from {}; registration of user ({})", getClientIp(request), user);
if(user == null){
throw new BadRequestException()
.setErrorCode(ErrorCode.USER_IS_NULL.toString())
.setErrorMessage("Wrong body or no body in reqest");
} (...)
首先,我建议您使用 BindingResult
作为 POST 调用的参数,并检查 return 是否有错误。
@RequestMapping(value = {"register"}, method = RequestMethod.POST, produces = "application/hal+json")
public ResponseEntity<?> registerClient(@RequestBody User user, HttpServletRequest request, BindingResult brs)
if (!brs.hasErrors()) {
// add the new one
return new ResponseEntity<User>(user, HttpStatus.CREATED);
}
return new ResponseEntity<String>(brs.toString(), HttpStatus.BAD_REQUEST);
}
其次,调用可能会抛出一些错误,一个好的做法是 carch 它们并 return 它们本身或将它们转换为您自己的异常对象。优点是它确保调用所有 update/modify 方法(POST、PUT、PATCH)
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public ResponseEntity<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
return new ResponseEntity<List<MethodArgumentNotValidException>>(e, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler({HttpMessageNotReadableException.class})
@ResponseBody
public ResponseEntity<?> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
return new ResponseEntity<List<HttpMessageNotReadableException>>(e, HttpStatus.BAD_REQUEST);
}
长话短说:我正在创建应该是 100% REST 的 API。 我正在尝试覆盖以下情况的默认响应: 我的@RestController 中有一个方法,它以@RequestBody 作为属性
@RequestMapping(value = {"register"}, method = RequestMethod.POST, produces = "application/hal+json")
public Resource<User> registerClient(@RequestBody User user, HttpServletRequest request)
如果我发送正确的请求,该方法工作正常。但是当我不这样做时就会出现问题。当请求的主体为空时,我会收到一个状态为 400 的通用 Tomcat 错误页面,我需要它只发送一个字符串或一个 JSON 对象。
到目前为止,我尝试在我的 RestControllerAdvice 中为包 org.springframework.web.binding 中的所有 Spring 异常添加异常处理程序,但它也没有用。
我已经知道对于某些与安全相关的错误,必须在配置中创建处理程序,但我不知道是否属于这种情况。
有人遇到过类似的问题吗?有什么我想念的吗?
在正常情况下,您的控件永远不会到达您的请求方法。
如果你想要一个好看的页面,你可以使用 web.xml
并配置它来产生你的答案。
<error-page>
<error-code>404</error-code>
<location>/pages/resource-not-found.html</location>
</error-page>
一般来说,如果您想解决这个 400 问题,您必须在 User.java
中添加一些注释,以避免在反序列化时出现任何未知字段。
解决方案是简单地将 required = false 放在 RequestBody 注释中。之后,我可以轻松地添加一些逻辑来抛出自定义异常并在 ControllerAdvice 中处理它。
@RequestMapping(value = {"register"}, method = RequestMethod.POST, produces = "application/hal+json")
public Resource<User> registerClient(@RequestBody(required = false) User user, HttpServletRequest request){
logger.debug("addClient() requested from {}; registration of user ({})", getClientIp(request), user);
if(user == null){
throw new BadRequestException()
.setErrorCode(ErrorCode.USER_IS_NULL.toString())
.setErrorMessage("Wrong body or no body in reqest");
} (...)
首先,我建议您使用 BindingResult
作为 POST 调用的参数,并检查 return 是否有错误。
@RequestMapping(value = {"register"}, method = RequestMethod.POST, produces = "application/hal+json")
public ResponseEntity<?> registerClient(@RequestBody User user, HttpServletRequest request, BindingResult brs)
if (!brs.hasErrors()) {
// add the new one
return new ResponseEntity<User>(user, HttpStatus.CREATED);
}
return new ResponseEntity<String>(brs.toString(), HttpStatus.BAD_REQUEST);
}
其次,调用可能会抛出一些错误,一个好的做法是 carch 它们并 return 它们本身或将它们转换为您自己的异常对象。优点是它确保调用所有 update/modify 方法(POST、PUT、PATCH)
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public ResponseEntity<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
return new ResponseEntity<List<MethodArgumentNotValidException>>(e, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler({HttpMessageNotReadableException.class})
@ResponseBody
public ResponseEntity<?> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
return new ResponseEntity<List<HttpMessageNotReadableException>>(e, HttpStatus.BAD_REQUEST);
}