Как написать правильный глобальный обработчик ошибок с Spring MVC / Spring Boot

Я пишу веб-приложение для Spring 4.0.4 и Spring Boot 1.0.2 с использованием Tomcat в качестве встроенного веб-контейнера и хочу реализовать глобальную обработку исключений, которая перехватывает все исключения и регистрирует их особым образом. Мои простые требования:

Я хочу глобально обрабатывать все исключения, которые еще не были обработаны где-то еще (например, в обработчике исключений контроллера). Я хочу записать сообщение в журнал и показать пользователю сообщение об ошибке.Я не хочу, чтобы Spring или веб-контейнер регистрировали какие-либо ошибки самостоятельно, потому что я хочу сделать это сам.

Пока что мое решение выглядит так (упрощенно, без регистрации и без перенаправления на представление ошибок):

@Controller
@RequestMapping("/errors")
public class ErrorHandler implements EmbeddedServletContainerCustomizer
{
    @Override
    public void customize(final ConfigurableEmbeddedServletContainer factory)
    {
        factory.addErrorPages(new ErrorPage("/errors/unexpected"));
        factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/errors/notfound"));
    }

    @RequestMapping("unexpected")
    @ResponseBody
    public String unexpectedError(final HttpServletRequest request)
    {
        return "Exception: " + request.getAttribute("javax.servlet.error.exception");
    }

    @RequestMapping("notfound")
    @ResponseBody
    public String notFound()
    {
        return "Error 404";
    }
}

В результате исключения, выдаваемые в контроллерах, корректно обрабатываютсяunexpectedError метод и 404 кода состояния обрабатываютсяnotFound метод. Пока все хорошо, но у меня есть следующие проблемы:

Tomcat или Spring (не уверен, кто за это отвечает) все еще регистрируют сообщение об ошибке. Я не хочу этого, потому что я хочу регистрировать это самостоятельно (с дополнительной информацией), и я не хочу дублировать сообщения об ошибках в журнале. Как я могу предотвратить ведение журнала по умолчанию?Способ, которым я получаю доступ к объекту исключения, кажется неправильным. Извлекаю если из атрибута запросаjavax.servlet.error.exception, И это даже не брошенное исключение, это примерorg.springframework.web.util.NestedServletException и мне нужно погрузиться в это вложенное исключение, чтобы получить настоящее. Я уверен, что есть более простой способ, но я не могу его найти.

Итак, как я могу решить эти проблемы? Или, может быть, способ, которым я реализовал этот глобальный обработчик исключений, совершенно неправильный, и есть лучшая альтернатива?

Ответы на вопрос(1)

Ваш ответ на вопрос