No @ResponseBody returned from @ExceptionHandler i

2019-05-18 16:09发布

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.

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.

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();
}

In JS, I use the response body I return above to display a message on screen.

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();
}

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.

Thanks!

1条回答
Explosion°爆炸
2楼-- · 2019-05-18 16:40

I went around this issue (I would think that is a Spring Boot issue) by doing the following.

  1. Separate Rest and Mvc controllers See my question here : Spring MVC: Get i18n message for reason in @RequestStatus on a @ExceptionHandler

  2. 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();
            }
        }
    }
    
查看更多
登录 后发表回答