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机制
原文地址:http://blog.51cto.com/xinzhilian/2055797
时间: 2024-10-09 00:00:05