Java 使用SpringMVC,接受带有错误JSON的POST请求将导致返回默认的400错误代码服务器页面

Java 使用SpringMVC,接受带有错误JSON的POST请求将导致返回默认的400错误代码服务器页面,java,rest,spring-mvc,Java,Rest,Spring Mvc,我正在开发一个RESTAPI。接收带有错误JSON的POST消息(例如{sdfasdfasdf})会导致Spring返回400错误请求的默认服务器页面。我不想返回页面,我想返回一个自定义JSON错误对象 当使用@ExceptionHandler引发异常时,我可以这样做。因此,如果它是一个空白请求或一个空白JSON对象(例如{}),它将抛出一个NullPointerException,我可以用ExceptionHandler捕捉它,然后做我想做的任何事情 那么,问题是Spring实际上不会在语法无

我正在开发一个RESTAPI。接收带有错误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;
}
@RequestMapping(value=“/trackingNumbers”,method=RequestMethod.POST,consumes=“application/json”)
@应答器
公共响应属性setTrackingNumber(@RequestBody TrackingNumber TrackingNumber){
HttpStatus状态=空;
ResponseStatus ResponseStatus=null;
字符串结果=null;
ObjectMapper mapper=新的ObjectMapper();
trackingNumber服务。设置trackingNumber(trackingNumber);
status=HttpStatus.CREATED;
结果=trackingNumber.getCompany();
ResponseEntity response=新的ResponseEntity(结果、状态);
返回响应;
}
@ExceptionHandler({NullPointerException.class,EOFEException.class})
@应答器
公共响应解决例外()
{
HttpStatus状态=空;
ResponseStatus ResponseStatus=null;
字符串结果=null;
ObjectMapper mapper=新的ObjectMapper();
responseStatus=新的responseStatus(“400”,“这不是TrackingNumber对象的有效形式”+
“({\'company\':\'EXAMPLE\',\'pro\'bill\'id\':\'EXAMPLE123\',\'tracking\'num\':\'EXAMPLE123\'”);
status=HttpStatus.BAD_请求;
试一试{
结果=mapper.writeValueAsString(responseStatus);
}捕获(IOE1异常){
e1.printStackTrace();
}
ResponseEntity response=新的ResponseEntity(结果、状态);
返回响应;
}

这是Spring-JSON(jackson)@RequestBody编组引发尴尬异常的一个问题,在Spring 3.1M2中,在消息体丢失或无效的情况下,Spring抛出
org.springframework.http.converter.httpMessageNodeReadableException来修复这个问题

在您的代码中,您不能创建一个
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、other)版本您可能需要获得一个新的版本,该版本可以很好地与您正在使用的Spring的任何版本配合使用。

这里的线程解释了最可能发生的情况:基本上,ExceptionHandler方法只适用于它自己类中的RequestMappings。对于您的情况,请求没有到达该类中的任何映射,因为json无效。如果您使用的是Spring 3.2,请使用HandlerExceptionResolver或ControllerAdvice检查可能对您有帮助的不同问题和答案-@PavelHoll这是我的答案所描述的-使用
httpMessageEndableException
,但是要了解它是如何添加的以及它可以在哪个版本的Spring中使用的所有历史记录@而且你的答案更像是一个个人故事,最后的答案部分正确;)。这个问题只是关于如何处理无效的JSON响应。。。缺少
内容类型
和Spring找不到正确的处理程序的问题没有太大关系。@Pavelhol这个问题与捕获无效的帖子正文的异常有关。解释Spring如何在内部处理一个空的帖子正文,并说明如何捕获正确的异常,以及解释添加了哪个版本的Spring,这没有什么错。编辑@Pavelhol似乎因为其“个人”性质而生气,这正是我所需要的。我只是无法知道抛出了哪个异常。。。这就解决了问题。非常感谢!我也得到了马特和帕维霍尔上面的链接的帮助,他们帮助我设计了一个更干净的控制器架构。很高兴听到你让它工作起来了!
@ControllerAdvice
是对Spring3.2的一个很好的补充