ViewResolver、View简介
ViewResolver:当DispatcherServlet调用handler处理完request以后会返回一个ModelAndView对象,这个对象里边包含着需要返回给客户端的数据。
View:View通过ViewResolver生成并返回,用来完成MVC视图层的渲染工作,以及对客户端内容响应;
官方介绍
ViewResolver:通过视图的名称返回给定的View视图;查看
View:渲染数据MVC视图层,数据是通过map保存的;查看
接口分析
这两个接口的核心方法分别是:
1) View resolverViewName(String viewName, Locale locale):返回View对象
2) void render(Map model, request, response):渲染model对象
继承结构分析
ViewResolver
可以看到Spring默认实现了许多resolver,每种resolver对应着不同的视图功能:
1.ViewResolverComposite
组合ViewResolver,含一个viewResolver的list,核心resolverViewName方法是通过遍历内部的resolver列表,找到一个不为null的view返回;
2.AbstractCachingViewResolver
1)抽象resolver,内部维护这一个map集合,每次解析后的view对象都会被缓存到这个集合里边,下次在请求的时候直接从缓存中查找;
2)如果继承这个类的话必须实现抽象方法View loadView(String
viewName, Locale locale)方法,由子类去实现创建view的过程;
3.BeanNameViewResolver
根据传入的viewName从spring的上下文去寻找名称为viewName的View对象,没有的话就返回null;
4.ContentNegotiatingViewResolver
1)内部维护着Spring上下文中的注册的viewResolver集合,它本身不解析view而是代理给集 合中的viewResolver去解析。
2)通过遍历viewResolver集合返回成功匹配的第一个View。
3)内部根据请求的文件名或者accept的头字段来解析View。
4)springboot默认会注入此类
5.UrlBasedViewResolver:
将controller返回的视图名称加上前缀或者后缀,即解析成url(eg:*.jsp),然后通过该url找到内部的资源文件;
6.InternalResourceViewResolver:
继承了UrlBasedViewResolver拥有父接口的功能,根据url将请求再转发到对应的资源。默认使用InternalResourceView返回视图。
1)支持解析InternalResourceView(即servlet和jsp)以及子类,比如JstlView;
2)默认使用InternalResourceView,如果类路径中有jstl那么默认为JstlView;
View
Spring定义了View的接口规范,能兼容多种返回类型的响应内容。具体的实现类有好多eg:基于text、Json、pdf、xml等;我们说几个比较重要的类,其它的View只是基于不同的响应内容对render()方法的不同实现。
1. AbstractView
View接口的抽象实现,为其子类提供将静态属性合并到controller返回的modal里边的功能;
2. AbstractUrlBasedView
继承自AbstractView接口,拥有父接口的功能的同时,为子类提供基于url定位视图的功能;
3. AbstractTemplateView
继承自AbstractUrlBasedView,将request、session里边的属性放到modal中的模板实现类(eg:FreeMarker)等同于拥有访问request和session的功能;
4. FreeMarkerView
视图采用freemarker作为模板引擎;
5. InternalResourceView
包装JSP,通过将请求转发到url指定的jsp处理,转发之前会先将model里边的属性放到了request里边(与AbstractTemplateView过程相反,前者要拥有访问request属性的功能,后者要将请求转发),然后再通过RequestDispatcher将请求进行转发;
6. MappingJackson2JsonView
将controller返回的model转化为json格式的数据,然后将数据写入到响应流中;
7. AbstractPdfView
和MappingJackson2JsonView类似,区别是将model转成pdf对象,然后将数据写入到响应流中;
实践操作
1. 使用InternalResourceView
2.使用MappingJackson2JsonView
3)使用pdf
4.使用FreeMarker
5.使用thymeleaf
结束语
1) ViewResolver的核心方法为View resolveViewName(String viewName, Locale locale);DispatcherServlet通过调用内部ViewRsolver实现类对象的该方法返回View对象;
2) View的核心方法为void render(map, request, response);DispatcherServler通过ViewRsolver实现类返回的View对象,然后调用该方法对客户端进行响应;
3) ViewResolver与View是成套的,如果我们需要自定义创建ViewResolver的实现类,那么同时也需要根据响应类型自定义View的实现类(有些第三方jar已经实现了,并不需要自己写);在ViewResolver的resolveViewName方法里面创建并返回View对象;
4) Spring提供了多个ViewResolver接口的抽象、实现类。上层的抽象类会实现一些基础的功能,中层的子类继承了上层基本功能的同时,通过新增抽象接口让子类去实现,以满足个性化的功能;我们在自定义ViewResolver的时候可以查看它每一层的大概功能,如果有现成的类,那么拿来用即可。如果不能直接用我们可以在它的基础上通过重写方法实现;(spring继承结构里边的类覆盖了绝大多数的场景需求,我们没有必要在创建自定义的子类中添加新的抽象方法了。因为spring的抽象类和实现类足够丰富所以大多数的时候只需要重写类里边的方法就可以了。其实感觉大多数时候都是不需要自己自定义,我们经常会使用第三方的jar)
下节预览:这节介绍了spring的视图层相关的视图解析器和视图,下一节我们要说的是handler也就是实际处理request过程的抽象类,这个类在整个MVC过程中承担着非常重要的职责。学习完这个类之后我们就会明白spring是如何将具体的业务代码分离出来让我们独立实现,然后又是怎么样调用我们的业务代码的;