Java 如何使用SpringMVC/SpringBoot编写适当的全局错误处理程序

Java 如何使用SpringMVC/SpringBoot编写适当的全局错误处理程序,java,spring,tomcat,spring-mvc,spring-boot,Java,Spring,Tomcat,Spring Mvc,Spring Boot,我正在使用Spring 4.0.4和Spring Boot 1.0.2编写一个web应用程序,使用Tomcat作为嵌入式web容器,我想实现一个全局异常处理,它拦截所有异常并以特定方式记录它们。我的简单要求是: 我希望全局处理所有尚未在其他地方处理的异常(例如,在控制器异常处理程序中)。我想记录消息,并向用户显示自定义错误消息 我不希望Spring或web容器自己记录任何错误,因为我想自己这样做 到目前为止,我的解决方案是这样的(简化、无日志记录和无错误视图重定向): @控制器 @请求映射(

我正在使用Spring 4.0.4和Spring Boot 1.0.2编写一个web应用程序,使用Tomcat作为嵌入式web容器,我想实现一个全局异常处理,它拦截所有异常并以特定方式记录它们。我的简单要求是:

  • 我希望全局处理所有尚未在其他地方处理的异常(例如,在控制器异常处理程序中)。我想记录消息,并向用户显示自定义错误消息
  • 我不希望Spring或web容器自己记录任何错误,因为我想自己这样做
到目前为止,我的解决方案是这样的(简化、无日志记录和无错误视图重定向):

@控制器
@请求映射(“/errors”)
公共类ErrorHandler实现EmbeddedServletContainerCustomizer
{
@凌驾
public void定制(最终可配置EmbeddedServletContainer工厂)
{
factory.AddErrorPage(新错误页(“/errors/unexpected”);
factory.addErrorPages(新错误页(HttpStatus.NOT_FOUND,“/errors/notfound”);
}
@请求映射(“意外”)
@应答器
公共字符串意外错误(最终HttpServletRequest请求)
{
返回“Exception:+request.getAttribute(“javax.servlet.error.Exception”);
}
@请求映射(“未找到”)
@应答器
未找到公共字符串()
{
返回“错误404”;
}
}
结果是,控制器中抛出的异常由
unexpectedError
方法正确处理,404状态代码由
notFound
方法处理。到目前为止还不错,但我有以下问题:

  • Tomcat或Spring(不确定谁负责)仍在记录错误消息。我不想这样,因为我想自己记录它(带有附加信息),并且我不想在日志中重复错误消息。如何防止此默认日志记录
  • 我访问异常对象的方式似乎不正确。我从请求属性
    javax.servlet.error.exception
    获取if。这甚至不是抛出的异常,它是
    org.springframework.web.util.NestedServletException
    的一个实例,我必须深入研究这个嵌套异常才能获取真正的异常。我很确定有更简单的方法,但我找不到

那么我该如何解决这些问题呢?或者我实现这个全局异常处理程序的方式完全错误,还有更好的选择吗?

看看ControllerAdvice 你可以这样做:

@ControllerAdvice
public class ExceptionHandlerController {

    public static final String DEFAULT_ERROR_VIEW = "error";

    @ExceptionHandler(value = {Exception.class, RuntimeException.class})
    public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) {
            ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW);

        mav.addObject("datetime", new Date());
        mav.addObject("exception", e);
        mav.addObject("url", request.getRequestURL());
        return mav;
    }
}

谢谢,这个很好用。但是现在我发现了另一个需求,它不是我原来问题的一部分,所以我创建了一个新的需求。也许你也可以帮忙:最干净的解决方案。另一个值得添加的可能是@ResponseStatus to 500,它将按预期返回HTTP 500中的响应。请注意,此解决方案还将捕获Spring安全异常,如AuthenticationException。因此,登录后重定向到受保护的资源将不起作用。说明:输入受保护的资源通常会将您重定向到登录页面。登录后,您应该返回到受保护的资源(Spring Security通过捕获AuthenticationException来解决此问题),但当您捕获所有类似的异常时,Spring Security将不再捕获它。您的解决方案缺少一个可供使用的注释@@EnableWebMvc@@ControllerAdvice公共类GlobalExceptionHandler{}对于restful api,您可能需要使用
@RestControllerAdvice