我有一个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
但我仍然收到了容器的默认错误页面。如何解决这个问题。
答案 0 :(得分:2)
处理请求的FrameworkServlet
在通过调度程序发送请求之前确定Locale,因为解析Locale时抛出的异常不会被processDispatchResult
捕获,因此不会像正常的WebMvc错误那样处理。对于上下文,FrameworkServlet
由DispatcherServlet
扩展,覆盖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
}