Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
398 views
in Technique[技术] by (71.8m points)

jsp - How does server prioritize which type of web.xml error page to use?

I have two error pages; 1 is for SpecificExceptionA and the other is for Throwable.

<error-page>
  <exception-type>org.SpecificExceptionA</exception-type>
  <location>/WEB-INF/views/error/timedout.jsp</location>
</error-page>

<error-page>
  <exception-type>java.lang.Throwable</exception-type>
  <location>/WEB-INF/views/error/error.jsp</location>
</error-page>

If I have both of these defined in my web.xml everything goes to /error/error.jsp.

If I have just the specific exception defined, it goes to the proper page; but other errors go to the tomcat default (except 404)

Is there a better way to specify specific exception handlers? I'm using spring 3.0.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is not specific to Tomcat. This is specific to the Servlet API. How the error page is determined is specified in chapter 9.9.2 of Servlet API specification 2.5. Here's an extract of relevance:

SRV.9.9.2 Error Pages

If no error-page declaration containing an exception-type fits using the class-hierarchy match, and the exception thrown is a ServletException or subclass thereof, the container extracts the wrapped exception, as defined by the ServletException.getRootCause method. A second pass is made over the error page declarations, again attempting the match against the error page declarations, but using the wrapped exception instead.

So, your SpecificExceptionA was likely wrapped in a ServletException and thus the java.lang.Throwable is the closest match on 1st pass. When you remove this entry, a 2nd pass will be made with the wrapped exception and thus your SpecificExceptionA get a match.

The right way to define a general HTTP 500 error page is to map it on error-code instead of exception-type:

<error-page>
    <exception-type>org.SpecificExceptionA</exception-type>
    <location>/WEB-INF/views/error/timedout.jsp</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/WEB-INF/views/error/error.jsp</location>
</error-page>

If this is not an option for some unclear reason, one of the ways to workaround this is to create a Filter which listens on an url-pattern of /* and does basically the following:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
    try {
        chain.doFilter(request, response);
    } catch (ServletException e) {
        Throwable rootCause = e.getRootCause();
        if (rootCause instanceof SpecificExceptionA) {
            throw (SpecificExceptionA) rootCause;
        } else {
            throw e;
        }
    }
}

It only has to extend from RuntimeException to get it to work.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...