spring rest处理空请求正文(400 Bad Request)

时间:2016-12-22 22:52:35

标签: java spring rest spring-boot spring-4

我正在使用Spring4开发RESTful应用程序。我想在POST请求中没有传递正文时处理大小写。 我编写了自定义异常处理程序:

@ControllerAdvice
public class MyRestExceptionHandler {

  @ExceptionHandler
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public ResponseEntity<MyErrorResponse> handleJsonMappingException(JsonMappingException ex) {
      MyErrorResponse errorResponse = new MyErrorResponse("request has empty body");
      return new ResponseEntity<MyErrorResponse>(errorResponse, HttpStatus.BAD_REQUEST);
  }   
  @ExceptionHandler(Throwable.class)
  public ResponseEntity<MyErrorResponse> handleDefaultException(Throwable ex) {
    MyErrorResponse errorResponse = new MyErrorResponse(ex);
    return new ResponseEntity<MyErrorResponse>(errorResponse, HttpStatus.BAD_REQUEST);
  }

}
 @RestController
 public class ContactRestController{
    @RequestMapping(path="/contact", method=RequestMethod.POST)
    public void save(@RequestBody ContactDTO contactDto) {...}
 } 

但是当它发生时,这些方法不会被召唤。我刚收到400 BAD REQUEST http状态和空身的响应。有人知道如何处理吗?

7 个答案:

答案 0 :(得分:12)

我找到了如何抓住它。我的解决方案是:

    @ControllerAdvice
    public class RestExceptionHandler extends ResponseEntityExceptionHandler {

        @Override
        protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
            // paste custom hadling here
        }
    }

答案 1 :(得分:1)

我遇到了类似的问题但它对我不起作用,因为提供的component-scan软件包不包含我提供@ControllerAdvice的软件包。

我的XML有:

<context:component-scan base-package="com.bandi.rest" />

我的包裹有一个拼写错误com.bandi.test.spring.exception。将其更改为com.bandi.rest.spring.exception后,它就开始工作了。

@ControllerAdvice
public class SpringRestExceptionHandler {

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public @ResponseBody ResponseEntity<ErrorResponse> handleNoMethodException(HttpServletRequest request,
            NoHandlerFoundException ex) {
        ErrorResponse errorResponse = new ErrorResponse(ex);
        errorResponse.setErrorMessage("resource not found with exception");
        return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Throwable.class)
    public @ResponseBody ResponseEntity<ErrorResponse> handleDefaultException(Throwable ex) {
        ErrorResponse errorResponse = new ErrorResponse(ex);
        errorResponse.setErrorMessage("request has empty body  or exception occured");
        return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.BAD_REQUEST);
    }
}

此外,如果您需要处理未找到所请求资源的情况(错误的URL),那么您必须向调度程序servlet添加另一个配置。

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>throwExceptionIfNoHandlerFound</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
</servlet>

完整的工作代码可用here

答案 2 :(得分:1)

我遇到了同样的问题,在花费大量时间调试问题后,我发现杰克逊没有正确地反序列化ErrorResponse对象。

这是因为我没有为ErrorResponse对象中定义的字段添加getter和setter方法。我正在使用构造函数初始化字段,并且没有为这些字段定义getter和setter。

解决方案:

因此,当我从{p>

ErrorResponse

与以下带有吸气剂和吸气剂的

import com.fasterxml.jackson.annotation.JsonRootName;
import java.util.List;

@JsonRootName("error")
public class ErrorResponse {

  private String message;
  private List<String> details;

  public ErrorResponse(String message, List<String> details) {
    this.message = message;
    this.details = details;
  }
}

Jackson现在正在正确地反序列化import com.fasterxml.jackson.annotation.JsonRootName; import java.util.List; @JsonRootName("error") public class ErrorResponse { private String message; private List<String> details; public ErrorResponse(String message, List<String> details) { this.message = message; this.details = details; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public List<String> getDetails() { return details; } public void setDetails(List<String> details) { this.details = details; } } ,并且在响应中得到了序列化的正文。

答案 3 :(得分:1)

在控制器类中,我把方法放在下面,它解决了我的问题。不需要控制器建议或任何其他。只需使用我们的用户异常与 body 本身覆盖 spring 默认异常即可解决问题。

@ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = {MissingServletRequestParameterException.class})
    ApiError handleMethodArgumentNotValid(MissingServletRequestParameterException ex) {

        return new ApiError(ErrorCode.MISSING_REQUIRED_PARAMS, ex.getMessage());
    }

答案 4 :(得分:0)

如果您已经有一个用@ControllerAdvice注释的类,并且不想创建新的类,则可以使用以下代码:

@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<?> handleMissingRequestBody(Exception ex) {
    return handle(BAD_REQUEST, ex);
}

它的行为应与 rvit34 的解决方案相同。

答案 5 :(得分:0)

就我而言,我需要处理所有具有无效参数的请求。因此,我使用 ResponseEntityExceptionHandler 扩展了我的类,并覆盖了方法 handleMissingServletRequestParameter 。您可以在类 ResponseEntityExceptionHandler

中找到自己定义的处理程序

@ControllerAdvice 公共类YourExceptionHandler扩展了ResponseEntityExceptionHandler {

@ExceptionHandler(Exception.class)
public final ResponseEntity handleAllExceptions(Exception ex) {
    // Log and return
}

@Override
public ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
    // Do your code here
    return new ResponseEntity<>("YOUR REQUEST PARAMS NOT MATCH!");
}

}

答案 6 :(得分:0)

override handleExceptionInternal 方法处理所有异常,所以你不需要重写每个处理方法:

    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, 
HttpStatus status, WebRequest request) {
        MyErrorResponse myErrorResponse = new MyErrorResponse();
        MyErrorResponse.setMessage(ex.getMessage());
        return new ResponseEntity<>(myErrorResponse, status);
    }