spring boot 与mvc的原理一直,所以存在view层的Resolver,可以进行配置和重写
那么问题来了:
从写之后的视图渲染器,如何对视图页面不存在的情况进行处理呢
首先,对于spring mvc的机制,404,以及500或是一些异常的处理,主要集中在controller的处理逻辑中
而视图渲染,如下例:
重写了ViewResolver,如果这个过程中发生异常,或是反回了一个空的view,环境如何处理,如何调到异常页面
public class MultiViewResover extends InternalResourceViewResolver {
private static List<ViewResolver> resolvers = new ArrayList<>();
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
View view = null;
for (ViewResolver resolver : resolvers) {
view = resolver.resolveViewName(viewName, locale);
if(view != null) {
break;
}
}
// if(view == null) {
// MustacheView mustacheView = new MustacheView();
// mustacheView.setUrl("pages/error");
// view = mustacheView;
// }
return view;
}
查了下源码:
也就是说,如果视图是空的时候,这里会抛出ServletException
/**
* Render the given ModelAndView.
* <p>This is the last stage in handling a request. It may involve resolving the view by name.
* @param mv the ModelAndView to render
* @param request current HTTP servlet request
* @param response current HTTP servlet response
* @throws ServletException if view is missing or cannot be resolved
* @throws Exception if there's a problem rendering the view
*/
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine locale for request and apply it to the response.
Locale locale = this.localeResolver.resolveLocale(request);
response.setLocale(locale);
View view;
if (mv.isReference()) {
// We need to resolve the view name.
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
"' in servlet with name '" + getServletName() + "'");
}
}
else {
// No need to lookup: the ModelAndView object contains the actual View object.
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
"View object in servlet with name '" + getServletName() + "'");
}
}
// Delegate to the View object for rendering.
if (logger.isDebugEnabled()) {
logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
}
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
getServletName() + "'", ex);
}
throw ex;
}
}
而doDispatch中对所有的异常进行了捕获:
按照这里描述,可以在interceptor的afterCompletion中进行异常的处理
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
但interceptor的afterCompletion是在视图处理完成或发生异常之后的再处理工作
所以可以返回一些静态页面,但如果需要使用一些模板引擎,就需要进行繁琐的处理了
综上所述,针对于视图层异常的处理,只能有一下两种方法了:
1.跳转到一个固定的异常请求,之后进行再次渲染,这里就需要控制好自己实现的viewResolver了,需要针对于异常界面进行特殊处理
2.springboot 提供的ErrorController机制
转载于:https://blog.51cto.com/xinzhilian/2055797