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

时间:2016-11-15 18:54:31

标签: spring rest exception-handling

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

的build.gradle

...
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"/>
...

DemoController.java

@RestController
public class DemoRestController {
    @RequestMapping(value = "/{name:.+}")
    public String doSomething(@PathVariable String name){
       throw new  RuntimeException(name);
    }
}

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> ...
...

最后一个输出是html,这不是我想要的,有什么关系?你能帮助我吗,谢谢你!

1 个答案:

答案 0 :(得分:0)

似乎如果请求路径有一个未知的扩展,那么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);
    }
}