java spring rest 处理空请求体(400 Bad Request)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41292788/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 05:47:41  来源:igfitidea点击:

spring rest Handling empty request body (400 Bad Request)

javaspringrestspring-bootspring-4

提问by rvit34

I am developing RESTful app using Spring4. I want to handle case when in POST request no body was passed. I wrote custom exception handler :

我正在使用 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) {...}
 } 

But when it happens these methods won't called. I just got response with 400 BAD REQUEST http status and empty body. Does anybody know how to handle it?

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

回答by rvit34

I found how to catch it. My solution is:

我找到了如何抓住它。我的解决办法是:

    @ControllerAdvice
    public class RestExceptionHandler extends ResponseEntityExceptionHandler {

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

回答by Nguyen Minh Hien

In my case, I need to handle all requests that have invalid parameters. So I extend my class with ResponseEntityExceptionHandlerand override the method handleMissingServletRequestParameter. You can find your own handlers defined inside the class ResponseEntityExceptionHandler

就我而言,我需要处理所有具有无效参数的请求。所以我扩展了我的类ResponseEntityExceptionHandler并覆盖了方法handleMissingServletRequestParameter。您可以在类中找到自己定义的处理程序ResponseEntityExceptionHandler

@ControllerAdvice 
public class YourExceptionHandler extends 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!");
    } 
}

回答by www

If You already have a class annotated with @ControllerAdviceand don't want to create new one, You could use this piece of code:

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

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

It should have the same behaviour as rvit34's solution.

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

回答by Bandi Kishore

I faced a similar issue and it didn't work for me because the component-scanpackage provided didn't include the package where my @ControllerAdvicewas provided.

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

My XML had :

我的 XML 有:

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

My package had a typo com.bandi.test.spring.exception. After changing it to com.bandi.rest.spring.exceptionit started working.

我的包裹有一个错字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);
    }
}

Also, if you need to handle scenario where your requested resource was not found (bad URL), then you'll have to add another configuration to your dispatcher servlet.

此外,如果您需要处理未找到请求的资源(错误 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>

Complete Working code is available here

完整的工作代码可在此处获得

回答by Vivek

I have encountered the same issue, after spending lot of time debugging the issue I found the Hymanson is not properly deserializing the ErrorResponseobject.

我遇到了同样的问题,在花了很多时间调试问题后,我发现 Hymanson 没有正确反序列化ErrorResponse对象。

This was because I didn't added the getters and setters for the field defined in the ErrorResponseobject. I was initializing the fields using constructor and there were no getters and setters defined for those fields.

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

SOLUTION:

解决方案:

So when I updated my ErrorResponseobject from

所以当我更新我的ErrorResponse对象时

import com.fasterxml.Hymanson.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;
  }
}

to the following one with getters and setters

到以下带有 getter 和 setter 的

import com.fasterxml.Hymanson.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;
  }
}

Hymanson is now deserializing the ErrorResponseproperly and I'm getting the serialized body in the response.

Hymanson 现在正在ErrorResponse正确地反序列化,我在响应中得到了序列化的主体。