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.

  1. 独立的 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();
        }
    }
}