带有CookieLocaleResolver的Spring Boot应用程序中的错误页面

时间:2016-08-21 06:14:20

标签: spring-boot jboss-eap-6

我有一个Spring Boot应用程序,其中B用于区域设置解析程序。如果有org.springframework.web.servlet.i18n.CookieLocaleResolver之类的语言Cookie无效,则会出现例外!en

问题是这个异常不是由Spring Boot处理而是转发到Servlet容器。因此,显示了容器的默认错误页面(在我的例子中是JBoss EAP 6),它将显示堆栈跟踪。

控制器的其他异常处理得当。例如,我有一个控制器映射,它将抛出正确处理的java.lang.IllegalArgumentException: Locale part "!en" contains invalid characters

我在web.xml中尝试了错误页面配置,如下所示。

/ by zero error

并将<error-page> <location>/500</location> </error-page> /error映射到MVC控制器,如下所示。

/500

但我仍然收到了容器的默认错误页面。如何解决这个问题。

2 个答案:

答案 0 :(得分:2)

处理请求的FrameworkServlet在通过调度程序发送请求之前确定Locale,因为解析Locale时抛出的异常不会被processDispatchResult捕获,因此不会像正常的WebMvc错误那样处理。对于上下文,FrameworkServletDispatcherServlet扩展,覆盖buildLocaleContext(request),然后调用CookieLocaleResolver intance。

/**
 * Process this request, publishing an event regardless of the outcome.
 * <p>The actual event handling is performed by the abstract
 * {@link #doService} template method.
 */
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    long startTime = System.currentTimeMillis();
    Throwable failureCause = null;

    // Here the locale is determined
    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
    LocaleContext localeContext = buildLocaleContext(request);

    RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
    ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());

    initContextHolders(request, localeContext, requestAttributes);

    try {
        // here is where the WebMvc processing happens
        doService(request, response);
    }
    catch (ServletException ex) {
        failureCause = ex;
        throw ex;
    }
    catch (IOException ex) {
        failureCause = ex;
        throw ex;
    }
    catch (Throwable ex) {
        failureCause = ex;
        throw new NestedServletException("Request processing failed", ex);
    }

    finally {
        resetContextHolders(request, previousLocaleContext, previousAttributes);
        if (requestAttributes != null) {
            requestAttributes.requestCompleted();
        }

        if (logger.isDebugEnabled()) {
            if (failureCause != null) {
                this.logger.debug("Could not complete request", failureCause);
            }
            else {
                if (asyncManager.isConcurrentHandlingStarted()) {
                    logger.debug("Leaving response open for concurrent processing");
                }
                else {
                    this.logger.debug("Successfully completed request");
                }
            }
        }

        publishRequestHandledEvent(request, response, startTime, failureCause);
    }
}

buildLocaleContext()的DispatcherServlet方法

/**
 * Build a LocaleContext for the given request, exposing the request's primary locale as current locale.
 * <p>The default implementation uses the dispatcher's LocaleResolver to obtain the current locale,
 * which might change during a request.
 * @param request current HTTP request
 * @return the corresponding LocaleContext
 */
@Override
protected LocaleContext buildLocaleContext(final HttpServletRequest request) {
    if (this.localeResolver instanceof LocaleContextResolver) {
        return ((LocaleContextResolver) this.localeResolver).resolveLocaleContext(request);
    }
    else {
        return new LocaleContext() {
            @Override
            public Locale getLocale() {
                return localeResolver.resolveLocale(request);
            }
        };
    }
}

答案 1 :(得分:1)

我认为您还需要在error-code的参数中提及web.xml,如下所示。它对我有用。

<error-page>
    <error-code>500</error-code>
    <location>/500</location>
</error-page>

然后将其捕获到controller

@RequestMapping(value = "/500", method = RequestMethod.GET)
public String error500(Model model) {
    //System.out.println("Error 500 ");
    return "500"; //will return the 500.jsp
}