Tomcat中部署的Spring引导应用程序中的@ExceptionHandler没有返回@ResponseBody
Posted
技术标签:
【中文标题】Tomcat中部署的Spring引导应用程序中的@ExceptionHandler没有返回@ResponseBody【英文标题】:No @ResponseBody returned from @ExceptionHandler in Spring boot app deployed in Tomcat 【发布时间】:2015-05-18 11:15:24 【问题描述】:我有一个 Spring Boot Web 应用程序,它在 STS 中运行良好,但在 Tomcat 中从 WAR 文件运行时显示不同的行为。
我使用 Thymeleaf 处理我的所有网页,但我有几个页面使用 jQuery 发送异步调用并使用户体验更加动态。
无论如何,我有一个 Controller 方法调用一个服务方法,它可能会抛出一个 RuntimeException
我以这种方式处理:
@ExceptionHandler(MyRuntimeException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public @ResponseBody String handleMyRuntimeException(MyRuntimeException exception)
return "Oops an error happened : " + exception.getMessage();
在 JS 中,我使用上面返回的响应正文在屏幕上显示消息。
在 STS 中运行我的应用程序时效果很好,但是一旦我切换到在 Tomcat 中部署它,ErrorPageFilter
就会被调用,而在 doFilter()
中它会:
if (status >= 400)
handleErrorStatus(request, response, status, wrapped.getMessage());
response.flushBuffer();
在handleErrorStatus()
中,它会在状态和相关消息中创建一个错误,但不会返回我的响应。
我还没有想出如何解决这个问题,如果有人可以提供帮助,我将不胜感激。
谢谢!
【问题讨论】:
目前,我的解决方法是捕获我的服务抛出的异常并返回一个带有 SUCCESS 或 FAILURE 状态以及相应消息和/或结果数据的 JSON 对象。 【参考方案1】:我通过执行以下操作解决了这个问题(我认为这是一个 Spring Boot 问题)。
单独的 Rest 和 Mvc 控制器 在这里查看我的问题:Spring MVC: Get i18n message for reason in @RequestStatus on a @ExceptionHandler
注入 Jackson 转换器并自己编写响应:
@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();
【讨论】:
调用flushBuffer()方法很重要,否则这将不起作用。 真正不同的是您删除了@ResponseStatus(请参阅jira.spring.io/browse/SPR-8251)。相反,您可以简单地返回一个 ResponseEntity。没有必要通过杰克逊写自己。 我会试试的,谢谢!但是,如果我在我的 ResponseEntity 中返回 HttpStatus.BAD_REQUEST,我不会得到相同的行为吗? 返回一个新的 ResponseEntity@RestControllerAdvice
带注释的全局异常处理程序将正确地将ResponseEntity
作为JSON 传递给客户端,但它不会在@ExceptionHandler(value = ConstraintViolationException.class)
的处理程序上将其传递给客户端。你的解决方案让我给客户一个个性化的 Repsonse 约束。以上是关于Tomcat中部署的Spring引导应用程序中的@ExceptionHandler没有返回@ResponseBody的主要内容,如果未能解决你的问题,请参考以下文章
Tomcat中的spring-boot应用程序战争部署,现有的spring web应用程序失败
两个springboot项目如何部署在同一个服务上,两个spring启动应用程序部署在同一台服务器上