Spring mvc架构图:
DispatcherServlet:
1. doGet()/doPost()
2. doService()
3. doDispatch()核心方法
4. processDispatchResult()主要处理异常、请求状态及触发请求完成事件
5. render()图的渲染
源码
视图解析
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 view;
if (mv.isReference()) {
// ViewResolver接口定义了如何通过view 名称来解析对应View实例的行为
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
...
}
else {
// 先到缓存中查找,若没有则创建
// 在创建视图前会检查返回值是否是以:"redirect:" 或 "forward:" 开头的。
// 如果是重定向:则创建一个重定向视图,返回创建的视图。如果是转发:则返回通过 转发 url 创建的 InternalResourceView 视图。
// No need to lookup: the ModelAndView object contains the actual View object.
view = mv.getView();
...
}
// 进行View的渲染
try {
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
...
}
}
视图渲染
public void render(Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
// 创建整合后需要返回给浏览器的Model
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
// 设置response 报文头
prepareResponse(request, response);
// 渲染数据,这个留给InternalResourceView来实现
renderMergedOutputModel(mergedModel, request, response);
}
有三种情况redirect视图,forward视图,普通视图,进行了不同处理
JstlView:
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 将model中的数据设置到request(因为不见得所有数据都是通过request.setAttribute加入的)
exposeModelAsRequestAttributes(model, request);
// 本类中的此函数是空函数,留给子类比如JstlView去实现自定义逻辑
exposeHelpers(request);
// 设置跳转目的页面路径
String dispatcherPath = prepareForRendering(request, response);
// 获取跳转控制器RequestDispatcher
RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
...
// 决定跳转到另一个控制器即forward操作还是返回用户请求资源,
// 如果用户设置或配置INCLUDE_REQUEST_URI_ATTRIBUTE
// 属性或response已经提交数据则直接返回资源给用户
if (useInclude(request, response)) {
response.setContentType(getContentType());
...
rd.include(request, response);
}
else { //携带request和response跳转到另一个控制器方法
...
rd.forward(request, response);
}
}
forward 跳向服务器的servlet, JSP文件, 或者 HTML文件。
Includes 响应写入源文件 - servlet, JSP page,HTML file
这一步完成后SpringMVC就基本上完成自己的使命了,当找到对应的url路径,springmvc就继续访问url对应的servlet,剩下的渲染工作就交由Servlet去处理了,所以由此我们不难看出,springmvc实际是在tomcat和servlet中间加了一层,处理request将浏览器传递的参数封装成model再由应用来加工处理这些数据后,再将这些数据传递给servlet让servlet将这些经过应用处理的数据在页面上表现出来,从而完成web请求,目的在于页面和数据分离即页面表现和业务逻辑的分离,使开发中可以集中精力处理业务逻辑提高开发效率。