spring boot 与mvc的原理一直,所以存在view层的Resolver,可以进行配置和重写


那么问题来了:

从写之后的视图渲染器,如何对视图页面不存在的情况进行处理呢


首先,对于spring mvc的机制,404,以及500或是一些异常的处理,主要集中在controller的处理逻辑中


而视图渲染,如下例:

重写了ViewResolver,如果这个过程中发生异常,或是反回了一个空的view,环境如何处理,如何调到异常页面

publicclassMultiViewResoverextendsInternalResourceViewResolver{privatestaticList<ViewResolver>resolvers=newArrayList<>();@OverridepublicViewresolveViewName(StringviewName,Localelocale)throwsException{Viewview=null;for(ViewResolverresolver:resolvers){view=resolver.resolveViewName(viewName,locale);if(view!=null){break;}}//if(view==null){//MustacheViewmustacheView=newMustacheView();//mustacheView.setUrl("pages/error");//view=mustacheView;//}returnview;}

查了下源码:

也就是说,如果视图是空的时候,这里会抛出ServletException

/***RenderthegivenModelAndView.*<p>Thisisthelaststageinhandlingarequest.Itmayinvolveresolvingtheviewbyname.*@parammvtheModelAndViewtorender*@paramrequestcurrentHTTPservletrequest*@paramresponsecurrentHTTPservletresponse*@throwsServletExceptionifviewismissingorcannotberesolved*@throwsExceptionifthere'saproblemrenderingtheview*/protectedvoidrender(ModelAndViewmv,HttpServletRequestrequest,HttpServletResponseresponse)throwsException{//Determinelocaleforrequestandapplyittotheresponse.Localelocale=this.localeResolver.resolveLocale(request);response.setLocale(locale);Viewview;if(mv.isReference()){//Weneedtoresolvetheviewname.view=resolveViewName(mv.getViewName(),mv.getModelInternal(),locale,request);if(view==null){thrownewServletException("Couldnotresolveviewwithname'"+mv.getViewName()+"'inservletwithname'"+getServletName()+"'");}}else{//Noneedtolookup:theModelAndViewobjectcontainstheactualViewobject.view=mv.getView();if(view==null){thrownewServletException("ModelAndView["+mv+"]neithercontainsaviewnamenora"+"Viewobjectinservletwithname'"+getServletName()+"'");}}//DelegatetotheViewobjectforrendering.if(logger.isDebugEnabled()){logger.debug("Renderingview["+view+"]inDispatcherServletwithname'"+getServletName()+"'");}try{if(mv.getStatus()!=null){response.setStatus(mv.getStatus().value());}view.render(mv.getModelInternal(),request,response);}catch(Exceptionex){if(logger.isDebugEnabled()){logger.debug("Errorrenderingview["+view+"]inDispatcherServletwithname'"+getServletName()+"'",ex);}throwex;}}

而doDispatch中对所有的异常进行了捕获:

按照这里描述,可以在interceptor的afterCompletion中进行异常的处理

catch(Throwableerr){//Asof4.3,we'reprocessingErrorsthrownfromhandlermethodsaswell,//makingthemavailablefor@ExceptionHandlermethodsandotherscenarios.dispatchException=newNestedServletException("Handlerdispatchfailed",err);}processDispatchResult(processedRequest,response,mappedHandler,mv,dispatchException);}catch(Exceptionex){triggerAfterCompletion(processedRequest,response,mappedHandler,ex);}

但interceptor的afterCompletion是在视图处理完成或发生异常之后的再处理工作

所以可以返回一些静态页面,但如果需要使用一些模板引擎,就需要进行繁琐的处理了

综上所述,针对于视图层异常的处理,只能有一下两种方法了:

1.跳转到一个固定的异常请求,之后进行再次渲染,这里就需要控制好自己实现的viewResolver了,需要针对于异常界面进行特殊处理

2.springboot 提供的ErrorController机制