目录
  1. 类图
  2. 属性
  3. 渲染流程
springMVC(10) View实现之InternalResourceView

类图

属性

结合InternalResourceView及其父类,我们可以发现它有如下一些属性:

1
2
3
4
5
6
7
8
9
10
11
12
String beanName;
String contentType = "text/html;charset=ISO-8859-1";
String requestContextAttribute;
Map<String, Object> staticAttributes = new LinkedHashMap<String, Object>(); // 静态属性,会与model进行合并
exposePathVariables = true; // 决定请求路径中的变量是否与合并到model中

String url;

boolean alwaysInclude = false; // 如果为true,则总是调用RequestDispatcher的include方式
boolean exposeContextBeansAsAttributes = false; // 决定是否将context中的beans作为属性暴露
Set<String> exposedContextBeanNames; // 决定需要暴露的beans的名称
boolean preventDispatchLoop = false; // 决定是否允许循环循环

渲染流程

整合InternalResourceView及其父类的渲染部分,

1
2
3
4
5
6
7
8
9
10
11
// AbstractView
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isTraceEnabled()) {
logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
" and static attributes " + this.staticAttributes);
}

Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
prepareResponse(request, response); // 用来解决IE的https下载的bug
renderMergedOutputModel(mergedModel, request, response);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// InternalResourceView
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

// Determine which request handle to expose to the RequestDispatcher.
HttpServletRequest requestToExpose = getRequestToExpose(request);

// Expose the model object as request attributes.
exposeModelAsRequestAttributes(model, requestToExpose);

// Expose helpers as request attributes, if any.
exposeHelpers(requestToExpose);

// Determine the path for the request dispatcher.
String dispatcherPath = prepareForRendering(requestToExpose, response);

// Obtain a RequestDispatcher for the target resource (typically a JSP).
RequestDispatcher rd = getRequestDispatcher(requestToExpose, dispatcherPath);
if (rd == null) {
throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
"]: Check that the corresponding file exists within your web application archive!");
}

// If already included or response already committed, perform include, else forward.
if (useInclude(requestToExpose, response)) {
response.setContentType(getContentType());
if (logger.isDebugEnabled()) {
logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
rd.include(requestToExpose, response);
}

else {
// Note: The forwarded resource is supposed to determine the content type itself.
if (logger.isDebugEnabled()) {
logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
rd.forward(requestToExpose, response);
}
}

我们可以分析整个处理流程如下,

  1. 进行model合并(将静态属性、地址变量和原model合并,与staticAttributes和exposePathVariables属性有关)
  2. 将请求处理器暴露给RequestDispatcher(与exposeContextBeansAsAttributes和exposedContextBeanNames属性有关)
  3. 将合并后的model作为属性暴露给请求
  4. 将helper作为请求属性暴露
  5. 设置路径(这里主要是做了一个url循环判断,与preventDispatchLoop属性的设置有关)
  6. 获取请求、路径对应的RequestDispatcher
  7. 通过include或forward进行请求处理
文章作者: 谷河
文章链接: https://www.lyytaw.com/spring/springMVC(10)-View%E5%AE%9E%E7%8E%B0%E4%B9%8BInternalResourceView/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 谷河|BLOG