Tomcat中部署的Spring启动应用程序中没有@ExceptionHandler返回@ResponseBody
我有一个 Spring Boot Web 应用程序,它从 STS 运行得很好,但在 Tomcat 中从 WAR 文件运行时显示不同的行为.
I have a Spring Boot web app that runs just fine from STS but shows different behavior when running in Tomcat from a WAR file.
我使用 Thymeleaf 来处理我的所有网页,但我有几个页面使用 jQuery 发送异步调用并使用户体验更加动态.
I use Thymeleaf to handle all my web pages but I have a couple pages that are using jQuery to send async calls and make user experience more dynamic.
无论如何,我有一个调用服务方法的控制器方法,该方法可能抛出一个RuntimeException
,我是这样处理的:
Anyway, I have a Controller method that calls a service method which may throw a RuntimeException
which I handle this way :
@ExceptionHandler(MyRuntimeException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public @ResponseBody String handleMyRuntimeException(MyRuntimeException exception) {
return "Oops an error happened : " + exception.getMessage();
}
在 JS 中,我使用上面返回的响应正文在屏幕上显示一条消息.
In JS, I use the response body I return above to display a message on screen.
在 STS 中运行我的应用程序时效果很好,但是一旦我切换到在 Tomcat 中部署它,ErrorPageFilter
就会被调用,而在 doFilter()
中它会:>
That works perfectly fine when running my app in STS but once I switch to deploy it in Tomcat the ErrorPageFilter
gets invoked and in doFilter()
it does:
if (status >= 400) {
handleErrorStatus(request, response, status, wrapped.getMessage());
response.flushBuffer();
}
在 handleErrorStatus()
中,它会创建一个带有状态和相关消息的错误,但不返回我的响应.
In handleErrorStatus()
it creates an error with the status and associated message but doesn't return my response.
我还没有想出如何解决这个问题,如果有人能提供帮助,我将不胜感激.
I haven't figured out how to solve this and I'd really appreciate if anybody could help.
谢谢!
我通过执行以下操作解决了这个问题(我认为这是 Spring Boot 问题).
I went around this issue (I would think that is a Spring Boot issue) by doing the following.
独立的 Rest 和 Mvc 控制器在此处查看我的问题:Spring MVC:在@ExceptionHandler 上的@RequestStatus 中获取 i18n 消息的原因
注入 Jackson 转换器并自己编写响应:
Inject Jackson converter and write response myself :
@ControllerAdvice(annotations = RestController.class)
@Priority(1)
@ResponseBody
public class RestControllerAdvice {
@Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;
@ExceptionHandler(RuntimeException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public void handleRuntimeException(HttpServletRequest request, HttpServletResponse response, RuntimeException exception) {
try {
jacksonMessageConverter.write(new MyRestResult(translateMessage(exception)), MediaType.APPLICATION_JSON, new ServletServerHttpResponse(response));
response.flushBuffer(); // Flush to commit the response
} catch (IOException e) {
e.printStackTrace();
}
}
}