使用Spring MVC,接受JSON错误的POST请求会导致返回默认的400错误代码服务器页面


问题内容

我正在使用REST
API。接收到带有错误JSON的POST消息(例如{sdfasdfasdf})会使Spring返回默认服务器页面,以显示400错误请求错误。我不想返回页面,我想返回自定义JSON错误对象。

当使用@ExceptionHandler引发异常时,可以执行此操作。因此,如果它是一个空白请求或一个空白JSON对象(例如{}),它将抛出NullPointerException,我可以使用ExceptionHandler捕获它并做我想做的任何事情。

那么问题是,当Spring只是无效的语法时,它实际上并没有引发异常……至少我看不到。它只是从服务器返回默认错误页面,无论是Tomcat,Glassfish等。

所以我的问题是如何“拦截” Spring并使其使用我的异常处理程序,否则将阻止错误页面的显示并返回JSON错误对象?

这是我的代码:

@RequestMapping(value = "/trackingNumbers", method = RequestMethod.POST, consumes = "application/json")
@ResponseBody
public ResponseEntity<String> setTrackingNumber(@RequestBody TrackingNumber trackingNumber) {

    HttpStatus status = null;
    ResponseStatus responseStatus = null;
    String result = null;
    ObjectMapper mapper = new ObjectMapper();

    trackingNumbersService.setTrackingNumber(trackingNumber);
    status = HttpStatus.CREATED;
    result = trackingNumber.getCompany();


    ResponseEntity<String> response = new ResponseEntity<String>(result, status);

    return response;    
}

@ExceptionHandler({NullPointerException.class, EOFException.class})
@ResponseBody
public ResponseEntity<String> resolveException()
{
    HttpStatus status = null;
    ResponseStatus responseStatus = null;
    String result = null;
    ObjectMapper mapper = new ObjectMapper();

    responseStatus = new ResponseStatus("400", "That is not a valid form for a TrackingNumber object " + 
            "({\"company\":\"EXAMPLE\",\"pro_bill_id\":\"EXAMPLE123\",\"tracking_num\":\"EXAMPLE123\"})");
    status = HttpStatus.BAD_REQUEST;

    try {
        result = mapper.writeValueAsString(responseStatus);
    } catch (IOException e1) {
        e1.printStackTrace();
    }

    ResponseEntity<String> response = new ResponseEntity<String>(result, status);

    return response;
}

问题答案:

这是Spring的一个问题SPR-7439-JSON(jackson)@RequestBody编组抛出尴尬的异常-
在Spring
3.1M2中已通过org.springframework.http.converter.HttpMessageNotReadableException在消息正文丢失或无效的情况下让Spring抛出异常来解决。

在您的代码中,您不能创建一个,ResponseStatus因为它是抽象的,但是我测试了在Jetty 9.0.3.v20130506上运行的Spring
3.2.0.RELEASE在本地使用更简单的方法捕获此异常。

@ExceptionHandler({org.springframework.http.converter.HttpMessageNotReadableException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public String resolveException() {
    return "error";
}

并且我收到了400状态“错误”的字符串响应。

该缺陷已在 Spring论坛帖子中进行了讨论。

注意: 我开始使用Jetty
9.0.0.M4进行测试,但是还有其他一些内部问题阻止@ExceptionHandler完成,因此根据您的容器(Jetty,Tomcat,其他)版本,您可能需要获得一个可以与任何版本完美配合的较新版本您正在使用的Spring版本。