关于springboot整合springmvc的源码分析可以参考以下系列文章:
- springboot整合springmvc源码分析(1)--前言
- springboot整合springmvc源码分析(2)--承上启下
- springboot整合springmvc源码分析(3)--直击内容
该源码分析系列文章分如下章节:
- springmvc源码分析(1)-- DispatcherServlet
- springmvc源码分析(2)-- HandlerMapping
- springmvc源码分析(3)-- HandlerAdapter
- springmvc源码分析(3.1)-- HandlerMethodReturnValueHandler
- springmvc源码分析(4)-- ViewResolver
到该章,也就是视图解析器,这里是dispatcherServlet的最后一步调用,就是从HandlerAdapter拿回来的ModelView放入视图解析器 ViewResolver进行视图的解析,然后响应给用户浏览器。
我们这里选用freeMarker来做demo,那么下面也将是以FreeMarkerViewResolver的视图解析器来分析。
在分析前我们先来看看freeMarker的运用和集成在springboot的用法
一、简单的freeMarker使用
1.创建模板freemarker.ftl:
2.加载freemarker模板生成html:
public static void main(String[] args) throws IOException, TemplateException {
String dir="D:\\springbootDemo\\demo\\src\\main\\resources\\page";
Configuration conf = new Configuration();
//加载模板文件(模板的路径)
conf.setDirectoryForTemplateLoading(new File(dir));
// 加载模板
Template template = conf.getTemplate("/freemarker.ftl");
// 定义数据
Map data = new HashMap();
data.put("word", "Hello World");
// 定义输出
Writer out = new FileWriter(dir + "/freemarker.html");
template.process(data, out);
out.flush();
out.close();
}
3.执行结果:
二、springboot集成,使用freemarker视图解析器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
1.添加配置:
2.创建controller:
@Controller
@RequestMapping("page")
public class FreeMarkerController {
@RequestMapping("index")
ModelAndView index(){
ModelAndView mv=new ModelAndView();
mv.setViewName("freemarker");
mv.addObject("word", "hello freemarker");
return mv;
}
}
3.执行结果查看:
三、 FreeMarkerViewResolver源码分析
以下是该类的继承关系图:
我们依然按照springboot的套路来,直接从MATA-INF/spring.factories文件开始找它的配置类
然后进入该类:
这里我们从@import中进入FreeMarkerServletWebConfiguration这个配置类,这里面就有一个bean为FreeMarkerViewResolver:
这里viewClass放的是一个FreeMarkerView.class
接着我们回到dispatchServlet中初始方法,相关内容可查看springmvc源码分析(1)-- DispatcherServlet)
initViewResolvers进行所有实现ViewResolver接口的视图解析器的加载
接着我们回到dispatchServlet调用最后一步(相关内容可查看springmvc源码分析(1)-- DispatcherServlet),视图解析器:
前面章中HandlerAdapter已经返回modelAndView,这里将进入到最后一步调用processDispatchResult进行视图解析
其他的细节我们不需要去关注,我们只关心中心点就好,接着调用render方法:
这里获取到我们前面demo的视图名:freemarker,然后接着进入resolveViewName方法:
如上,遍历所有视图解析器,其中包括我们的FreeMarkerViewResolver
AbstractCachingViewResolver.resolveViewName > AbstractCachingViewResolver.createView > UrlBasedViewResolver.loadView >
我们看下bulidView,如下图;然后这里就获取前面viewClass的值FreeMarkerView.class创建一个View,AbstractUrlBasedView是其父类,将模板名加上前缀和后缀放入url
然后检查是否可以获取到模板文件,接着返回一个View对象也就是FreeMarkerView,接着回到前面的render方法:
mv.getModelInternal()是我们前面放入的值:
继续调用AbstractView.render:
createMergedOutputModel获取model值:
接着进入AbstractTemplateView.renderMergedOutputModel > FreeMarkerView.renderMergedTemplateModel >FreeMarkerView.doRender>
通过地址获取模板文件然后生成Template,和我们第一个例子那样,然后接着调用processTemplate
这里是不是很熟悉,也是前面第一个例子一样:
template.process(model, response.getWriter());之后就已经响应给浏览器
至此视图解析器就将我们的视图响应给浏览器,也就完成了我们springmvc的最后一个流程
springmvc源码分析系列文章到这里也就告一段落,如有什么不对的地方,望指出;这里也是博主的一个学习过程中的笔记罢了,感谢你的收看,喜欢可以关注下,后续会继续学习其他常用开源框架的源码