Spring MVC - Détectez les exceptions levées par la page d'affichage
Voici le scénario, le contrôleur retourne un ModelAndView, et une exception est levée lors du rendu de la page de vue JSP, la raison en est que le code du message est introuvable.
org.apache.jasper.JasperException: org.springframework.context.NoSuchMessageException: No message found under code 'Diff.userform.password' for locale 'en_US'. org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:549) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:470) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334) javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
Une exception est levée et affiche directement une page d'erreur HTTP 500.
1. Problème
Déclaré un gestionnaire d'exceptions globalement, mais toujours incapable d'attraper lesNoSuchMessageException
?
@ControllerAdvice public class GlobalExceptionHandler { private final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); @ExceptionHandler(value = Exception.class) public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception { logger.error("[URL] : {}", req.getRequestURL(), e); ModelAndView mav = new ModelAndView(); mav.addObject("exception", e); mav.addObject("url", req.getRequestURL()); mav.setViewName("error""); return mav; } }
2. Solution
Non, vous ne pouvez pas intercepter l'exception qui est levée par la page d'affichage. Le@ExceptionHandler
est utilisé pour intercepter les exceptions levées par la classe Controller uniquement.
Le mieux que vous puissiez faire est de définir une page d'erreur enweb.xml
web.xml
500 /WEB-INF/views/jsp/error.jsp /WEB-INF/views/jsp/error.jsp
Note
Dites-moi si vous avez une meilleure solution :)
3. Filtre de servlet
Alternativement, vous pouvez créer un filtre et intercepter toutes les demandes sur votre application Web. Si des exceptions sont levées, connectez-vous ou faites ce que vous voulez.
package com.example.form.web; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.context.support.WebApplicationContextUtils; import com.example.form.service.UserService; public class ErrorHandleFilter implements Filter { private final Logger logger = LoggerFactory.getLogger(ErrorHandleFilter.class); //Your custom bean to handle error ErrorHandlerSpecialForce errHandle; @Override public void destroy() { // ... } @Override public void init(FilterConfig filterConfig) throws ServletException { //Get bean from Spring container errHandle = (ErrorHandlerSpecialForce) WebApplicationContextUtils .getRequiredWebApplicationContext(filterConfig.getServletContext()) .getBean("errorHandlerSpecialForce"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { // your code, do whatever errHandle.handle(request, response); chain.doFilter(request, response); } catch (Exception ex) { logger.error("Error : {}", ex); //log it request.setAttribute("errorMessage", ex); request.getRequestDispatcher("/WEB-INF/views/jsp/error.jsp") .forward(request, response); } } }
Pour vous inscrire au-dessus du filtre, le déclare enweb.xml
web.xml
org.springframework.web.context.ContextLoaderListener errorHandlerFilter com.example.form.web.ErrorHandleFilter errorHandlerFilter /*
Ou le déclare dans une classe d'initialisation.
package com.example.form.config.servlet3; import javax.servlet.Filter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import com.example.form.web.ErrorHandleFilter; public class MyWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { //... @Override protected Filter[] getServletFilters() { return new Filter[]{new ErrorHandleFilter()}; } }