Spring MVC - ビューページでスローされた例外をキャッチします.

ここでは、コントローラがModelAndViewを返し、JSPビューページのレンダリング中に例外がスローされます。理由は、メッセージコードが見つからないという理由があります。

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)

例外がスローされ、HTTP 500エラーページが直接レンダリングされます。

1.問題

例外ハンドラをグローバルに宣言しましたが、 `NoSuchMessageException`を捕捉できませんでしたか?

@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.解決策

いいえ、ビューページによってスローされる例外をキャッチすることはできません。 `@ExceptionHandler`は、Controllerクラスによってスローされた例外を捕捉するために使用されます。

あなたができることは、 `web.xml`にエラーページを定義することです

web.xml

    <!-- This will catch Http 500 error -->
    <error-page>
        <error-code>500</error-code>
        <location>/WEB-INF/views/jsp/error.jsp</location>
    </error-page>

    <!-- This will catch any exception -->
    <error-page>
        <location>/WEB-INF/views/jsp/error.jsp</location>
    </error-page>

3.サーブレットフィルタ

また、フィルタを作成して、Webアプリケーション上のリクエスト全体をインターセプトすることもできます。例外がスローされた場合は、ログに記録するか、必要な操作を行います。

package com.mkyong.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.mkyong.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);

        }

    }

}

上記のフィルタを登録するには、 `web.xml`で宣言します。

web.xml

    <!-- must register this, else WebApplicationContext not found -->
    <listener>
        <listener-class>
                     org.springframework.web.context.ContextLoaderListener
                </listener-class>
    </listener>

    <filter>
        <filter-name>errorHandlerFilter</filter-name>
        <filter-class>com.mkyong.form.web.ErrorHandleFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>errorHandlerFilter</filter-name>
        <url-pattern>/** </url-pattern>
    </filter-mapping>

または、イニシャライザクラスで宣言します。

package com.mkyong.form.config.servlet3;

import javax.servlet.Filter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.mkyong.form.web.ErrorHandleFilter;

public class MyWebInitializer extends
    AbstractAnnotationConfigDispatcherServletInitializer {

   //...

    @Override
    protected Filter[]getServletFilters() {
        return new Filter[]{new ErrorHandleFilter()};
    }
}

参考文献

Spring MVCでの処理]。 link://spring-mvc/how-to-register-a-servlet-filter-in-spring-mvc/[どのようにして

Spring MVCにサーブレットフィルタを登録する]

前の投稿:サーブレットでのセッションタイムアウトの設定方法
次の投稿:Gradle JaCoCo - 互換性のないバージョン1006