Spring MVC - Attrape les exceptions levées par la page de vue

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()};
    }
}