渲染时的jsp/spring-mvc异常 - 如何获取自定义错误页面并记录异常

Boz*_*zho 5 java jsp tomcat servlets spring-mvc

如果服务或控制器中发生异常,则由Spring的HandlerExceptionResolvers处理.但是,如果.jsp处理中存在异常(例如PropertyNotFoundException,即使使用JSTL也会发生),则spring不会通过其异常处理机制传递此异常.此外,它不被视为错误500,因此<error-page>不考虑配置

相反,异常将传播到servlet容器.这很好,但我实际上无法得到我想要的行为:

  • 显示(500)错误页面
  • 记录异常

我目前的设置:

  • 500.jsp有 isErrorPage=true
  • 所有jsps都包含一个公共文件 <%@ page errorPage="500.jsp" %>

会发生什么 - 在任何地方都没有记录异常.并且未显示错误页面.相反,请求的页面显示为半渲染.如果我增加缓冲区大小(足以到达有问题的代码段),则只显示错误页面.(再次,没有记录)

那么,我如何实现我想要的目标呢?无需更改缓冲区大小,无需使用<c:catch>,也无需ex.printStackTrace()在错误页面中)

Ale*_*yak 2

将其添加到 web.xml 中:

<servlet>
  <servlet-name>ErrorServlet</servlet-name>
  <servlet-class>package.of.ErrorServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>ErrorServlet</servlet-name>
  <url-pattern>/WEB-INF/servlets/error</url-pattern>
</servlet-mapping>

<error-page>
  <exception-type>java.lang.Throwable</exception-type>
  <location>/WEB-INF/servlets/error</location>
</error-page>
Run Code Online (Sandbox Code Playgroud)

在 ErrorServlet 实现doService方法中,因为 servlet 容器将转发任何​​当前操作(GET、POST 等)。

添加这个辅助方法

    public static < T extends Throwable > T getExceptionFromRequest (
            final Class< T > exception_class,
            final HttpServletRequest request                
        )
    {
        final T ret_val =
            exception_class.cast(
                request.getAttribute( SERVLET_EXCEPTION_ATTR )
            );

        if ( ret_val != null )
        {
            return ret_val;
        }

        return
            exception_class.cast(
                request.getAttribute( JSP_EXCEPTION_ATTR )
            );
    }
Run Code Online (Sandbox Code Playgroud)

这两个常数:

    public final static String SERVLET_EXCEPTION_ATTR =
        "javax.servlet.error.exception";

    public final static String JSP_EXCEPTION_ATTR =
        "javax.servlet.jsp.jspException";
Run Code Online (Sandbox Code Playgroud)

这在 Tomcat 中一直为我工作。