jsp - springboot - ¿Cómo prioriza el servidor qué tipo de página de error web.xml usar?
spring rest exception handler example (2)
Tengo dos páginas de error; 1 es para SpecificExceptionA y el otro es para 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>
Si tengo ambos definidos en mi web.xml, todo va a /error/error.jsp.
Si solo tengo definida la excepción específica, va a la página correcta; pero otros errores van al valor predeterminado de tomcat (excepto 404)
¿Hay una mejor manera de especificar manejadores de excepciones específicos? Estoy usando la primavera 3.0.
Terminé usando Springs SimpleMappingExceptionResolver class
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.*.*.ResponseTimeExceededException">
<!-- the name of the jsp to use for this exception -->
error/timedout
</prop>
</props>
</property>
<property name="defaultErrorView" value="error/error"/>
</bean>
Esto no es específico de Tomcat. Esto es específico de la API de Servlet. La forma en que se determina la página de error se especifica en el capítulo 9.9.2 de la especificación de la API del servlet 2.5 . Aquí hay un extracto de relevancia:
SRV.9.9.2 Páginas de error
Si ninguna declaración de
error-page
contenga unexception-type
ajusta usando la coincidencia de jerarquía de clases, y la excepción lanzada es unaServletException
o subclase de la misma, el contenedor extrae la excepción envuelta, como se define en el métodoServletException.getRootCause
. Se realiza una segunda pasada sobre las declaraciones de la página de error, intentando nuevamente la coincidencia con las declaraciones de la página de error, pero utilizando la excepción envuelta.
Por lo tanto, es probable que su SpecificExceptionA
esté envuelta en ServletException
y, por lo tanto, java.lang.Throwable
es la coincidencia más cercana en 1st pase. Cuando elimine esta entrada, se realizará un segundo pase con la excepción envuelta y, por lo tanto, su SpecificExceptionA
obtendrá una coincidencia.
La forma correcta de definir una página de error HTTP 500 general es asignarla en el error-code
lugar del exception-type
de 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>
Si esto no es una opción por algún motivo poco claro, una de las formas de solución es crear un Filter
que escuche en un url-pattern
de url-pattern
de /*
y básicamente haga lo siguiente:
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;
}
}
}
Solo tiene que extenderse desde RuntimeException
para que funcione.