我使用@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,这不是我想要的,有什么关系?你能帮助我吗,谢谢你!
答案 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);
}
}