当URL以文件扩展名作为后缀时,Spring Restful ControllerAdvice异常处理程序响应html

当URL以文件扩展名作为后缀时,Spring Restful ControllerAdvice异常处理程序响应html,spring,rest,exception-handling,Spring,Rest,Exception Handling,我使用@RestControllerAdvice全局处理控制器引发的异常,并向客户端响应json字符串。我的rest控制器@RequestMapping路径可以接受以文件扩展名为后缀的URL。如果控制器抛出异常,并且URL以已知扩展名作为后缀,则异常处理程序将响应html而不是json 格雷德尔先生 ... dependencies { compile 'com.google.code.gson:gson:2.7' compileOnly 'org.apache.tomcat

我使用@RestControllerAdvice全局处理控制器引发的异常,并向客户端响应json字符串。我的rest控制器@RequestMapping路径可以接受以文件扩展名为后缀的URL。如果控制器抛出异常,并且URL以已知扩展名作为后缀,则异常处理程序将响应html而不是json

格雷德尔先生

...
dependencies {
     compile 'com.google.code.gson:gson:2.7'
     compileOnly 'org.apache.tomcat:tomcat-servlet-api:8.0.33'
     compile 'org.springframework:spring-webmvc:4.3.1.RELEASE'
}
servlet-context.xml

...
    <mvc:annotation-driven/>
    <context:component-scan base-package="com.demo"/>
...
RestExceptionHandler

@RestControllerAdvice
public class RestExceptionHandler {
    @ExceptionHandler(Exception.class)
    public Message handleException(Exception ex, WebRequest request) {
           Message ret=new Message(System.currentTimeMillis(),ex.getMessage());
           return ret;
    }
}
客户

$ curl localhost:8080/abc                     //no extension, it's ok
{"time":1479235304196,"url":"abc"}            
$ curl localhost:8080/abc.opq                 //unknown extension, ok
{"time":1479235545303,"url":"abc.opq"}
$ curl localhost:8080/abc.jpg
<!DOCTYPE html><html><head><title>Apache Tomcat/8.0.33 - Error report</title> ...
...
$curl localhost:8080/abc//没有扩展,没问题
{“时间”:1479235304196,“url”:“abc”}
$curl localhost:8080/abc.opq//未知扩展名,确定
{“时间”:1479235545303,“url:“abc.opq”}
$curl localhost:8080/abc.jpg
ApacheTomcat/8.0.33-错误报告。。。
...

最后输出的是html,这不是我想要的,怎么了?你能帮我吗,谢谢

如果请求路径有一个未知的扩展名,那么Spring似乎不知道如何处理handleException的返回值,并返回HTML。您可以通过直接在handleException方法中呈现JSON来修复此问题。这在我的例子中是有效的,因为我的API在出现错误时总是返回JSON,而不是protobuf或csv或任何东西

@RestControllerAdvice(annotations = {RestController.class})
public class ApiExceptionHandler {

    private final ObjectMapper objectMapper;

    public ApiExceptionHandler(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @ExceptionHandler
    public void exceptionHandler(HttpServletRequest req, HttpServletResponse res, Exception x) throws IOException {
        Message ret = new Message(System.currentTimeMillis(),ex.getMessage());
        res.setStatus(500);
        res.setContentType(MediaType.APPLICATION_JSON_UTF8.toString());
        objectMapper.writeValue(res.getOutputStream(), ret);
    }
}

如果请求路径有一个未知的扩展名,那么Spring似乎不知道如何处理handleException的返回值,并返回HTML。您可以通过直接在handleException方法中呈现JSON来修复此问题。这在我的例子中是有效的,因为我的API在出现错误时总是返回JSON,而不是protobuf或csv或任何东西

@RestControllerAdvice(annotations = {RestController.class})
public class ApiExceptionHandler {

    private final ObjectMapper objectMapper;

    public ApiExceptionHandler(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @ExceptionHandler
    public void exceptionHandler(HttpServletRequest req, HttpServletResponse res, Exception x) throws IOException {
        Message ret = new Message(System.currentTimeMillis(),ex.getMessage());
        res.setStatus(500);
        res.setContentType(MediaType.APPLICATION_JSON_UTF8.toString());
        objectMapper.writeValue(res.getOutputStream(), ret);
    }
}