Spring 独立启动 Tomcat 忽略 DeferredResults 中设置的异常
Spring Boot in standalone Tomcat ignores exceptions set in DeferredResults
我是 运行 一个 Spring Boot 1.2.1 独立应用程序 Tomcat。
我有两个控制器映射,为了简单起见,它们总是抛出异常。第一个用于 GET 请求,它 returns 一个用于视图名称的字符串:
@RequestMapping(value = {
"/index"
}, method = RequestMethod.GET)
public String init() throws MyRequestProcessingException {
if (true) {
throw new MyRequestProcessingException(
"Something went wrong processing request");
}
return "init";
}
这是异常定义:
@ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR)
public class MyRequestProcessingException extends Exception {
public MyRequestProcessingException(String message) {
super(message);
}
}
在嵌入式 Tomcat 以及独立 Tomcat 中,尝试访问 /index 总是会导致 500 错误数据返回给客户端。
我的控制器有另一种方法接受 POST 和 returns 一个 DeferredResult:
@RequestMapping(value = "html/start", method = RequestMethod.POST, consumes = APPLICATION_FORM_URLENCODED)
public DeferredResult<String> start(final HttpServletResponse response,
@Valid @ModelAttribute final InitialisationStartAttributes model,
final SessionData sessionExisting) throws MyRequestProcessingException {
final DeferredResult<String> finalResult = new DeferredResult<>(5000);
// Just return an error, so we can test
if (true) {
finalResult.setErrorResult(new MyRequestProcessingException(
"Something went wrong processing request"));
}
return finalResult;
}
在嵌入式 Tomcat 中,一个 POST 到 /html/start returns 一个 500,在响应正文中有一些 JSON 数据,就像其他请求一样方法。但是,当我尝试使用独立的 Tomcat 实例重现此行为时,我总是收到没有响应正文的 200 响应。
我在嵌入式中使用 Tomcat 8,独立使用 Tomcat 7.0.52,但我也尝试过使用独立的 Tomcat 8,但没有什么区别.
我的应用程序通过修改 /etc/tomcat/Catalina/localhost/ROOT.xml.
部署在根应用程序上下文中
编辑:我做了更多的测试,看起来 DeferredResult 确实是罪魁祸首。我还没有覆盖 handleErrorResult() 看看会发生什么。不过我有点惊讶,因为我不记得在文档中看到过任何关于在嵌入式和独立模式下返回 DeferredResult 之间的区别的内容 Tomcat.
如果您在 @RequestMapping
中抛出异常并且没有在任何地方处理它,那么在您点击 ErrorPageFilter
之前不会设置响应状态。如果你想在定制器中将状态映射到错误路径,你需要处理错误并在过滤器链中的某处获取状态集(例如,使用 @ExceptionHandler
或使用 Exception
和 @ResponseStatus
).另一种让自定义错误页面呈现的方法是使用 new ErrorPage(Exception.class, "/html/error")
.
映射异常而不是(或同时映射)HttpStatus
此行为是由于 Spring Boot 的 ErrorPageFilter 中的一个错误; see bug report on GitHub。它已在 Spring Boot 1.2.3 中修复。
我是 运行 一个 Spring Boot 1.2.1 独立应用程序 Tomcat。
我有两个控制器映射,为了简单起见,它们总是抛出异常。第一个用于 GET 请求,它 returns 一个用于视图名称的字符串:
@RequestMapping(value = {
"/index"
}, method = RequestMethod.GET)
public String init() throws MyRequestProcessingException {
if (true) {
throw new MyRequestProcessingException(
"Something went wrong processing request");
}
return "init";
}
这是异常定义:
@ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR)
public class MyRequestProcessingException extends Exception {
public MyRequestProcessingException(String message) {
super(message);
}
}
在嵌入式 Tomcat 以及独立 Tomcat 中,尝试访问 /index 总是会导致 500 错误数据返回给客户端。
我的控制器有另一种方法接受 POST 和 returns 一个 DeferredResult:
@RequestMapping(value = "html/start", method = RequestMethod.POST, consumes = APPLICATION_FORM_URLENCODED)
public DeferredResult<String> start(final HttpServletResponse response,
@Valid @ModelAttribute final InitialisationStartAttributes model,
final SessionData sessionExisting) throws MyRequestProcessingException {
final DeferredResult<String> finalResult = new DeferredResult<>(5000);
// Just return an error, so we can test
if (true) {
finalResult.setErrorResult(new MyRequestProcessingException(
"Something went wrong processing request"));
}
return finalResult;
}
在嵌入式 Tomcat 中,一个 POST 到 /html/start returns 一个 500,在响应正文中有一些 JSON 数据,就像其他请求一样方法。但是,当我尝试使用独立的 Tomcat 实例重现此行为时,我总是收到没有响应正文的 200 响应。
我在嵌入式中使用 Tomcat 8,独立使用 Tomcat 7.0.52,但我也尝试过使用独立的 Tomcat 8,但没有什么区别.
我的应用程序通过修改 /etc/tomcat/Catalina/localhost/ROOT.xml.
部署在根应用程序上下文中编辑:我做了更多的测试,看起来 DeferredResult 确实是罪魁祸首。我还没有覆盖 handleErrorResult() 看看会发生什么。不过我有点惊讶,因为我不记得在文档中看到过任何关于在嵌入式和独立模式下返回 DeferredResult 之间的区别的内容 Tomcat.
如果您在 @RequestMapping
中抛出异常并且没有在任何地方处理它,那么在您点击 ErrorPageFilter
之前不会设置响应状态。如果你想在定制器中将状态映射到错误路径,你需要处理错误并在过滤器链中的某处获取状态集(例如,使用 @ExceptionHandler
或使用 Exception
和 @ResponseStatus
).另一种让自定义错误页面呈现的方法是使用 new ErrorPage(Exception.class, "/html/error")
.
HttpStatus
此行为是由于 Spring Boot 的 ErrorPageFilter 中的一个错误; see bug report on GitHub。它已在 Spring Boot 1.2.3 中修复。