目录
  1. 前言
  2. 类图
  3. AbstractCachingViewResolver类
  4. UrlBasedViewResolver类
  5. InternalResourceViewResolver类
  6. 总结
springMVC(8) ViewResolver实现之InternalResourceViewResolver

前言

为了能够对ViewResolver能够有一个更深入的理解,这次我又选择了jsp的解析部分InternalResourceViewResolver来阅读。可以从下面看到,与VelocityViewResolver类似的,InternalResourceViewResolver也同样继承了UrlBasedViewResolver类。

类图

AbstractCachingViewResolver类

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
public View resolveViewName(String viewName, Locale locale) throws Exception {
if (!isCache()) {
return createView(viewName, locale);
}
else {
Object cacheKey = getCacheKey(viewName, locale);
View view = this.viewAccessCache.get(cacheKey);
if (view == null) {
synchronized (this.viewCreationCache) {
view = this.viewCreationCache.get(cacheKey);
if (view == null) {
// Ask the subclass to create the View object.
view = createView(viewName, locale);
if (view == null && this.cacheUnresolved) {
view = UNRESOLVED_VIEW;
}
if (view != null) {
this.viewAccessCache.put(cacheKey, view);
this.viewCreationCache.put(cacheKey, view);
if (logger.isTraceEnabled()) {
logger.trace("Cached view [" + cacheKey + "]");
}
}
}
}
}
return (view != UNRESOLVED_VIEW ? view : null);
}
}
1
2
3
protected View createView(String viewName, Locale locale) throws Exception {
return loadView(viewName, locale);
}
1
protected abstract View loadView(String viewName, Locale locale) throws Exception;

可以看到解析viewName的过程是通过子类重写loadView来实现的。

UrlBasedViewResolver类

1
2
3
4
5
protected View loadView(String viewName, Locale locale) throws Exception {
AbstractUrlBasedView view = buildView(viewName);
View result = applyLifecycleMethods(viewName, view);
return (view.checkResource(locale) ? result : null);
}

这部分需要注意,InternalResourceView的checkResource方法默认为返回true。而Velocity则会有相应的判断资源是否存在的措施。

buildView方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass());
view.setUrl(getPrefix() + viewName + getSuffix());
String contentType = getContentType();
if (contentType != null) {
view.setContentType(contentType);
}
view.setRequestContextAttribute(getRequestContextAttribute());
view.setAttributesMap(getAttributesMap());
if (this.exposePathVariables != null) {
view.setExposePathVariables(exposePathVariables);
}
return view;
}

InternalResourceViewResolver类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
InternalResourceView view = (InternalResourceView) super.buildView(viewName);
if (this.alwaysInclude != null) {
view.setAlwaysInclude(this.alwaysInclude);
}
if (this.exposeContextBeansAsAttributes != null) {
view.setExposeContextBeansAsAttributes(this.exposeContextBeansAsAttributes);
}
if (this.exposedContextBeanNames != null) {
view.setExposedContextBeanNames(this.exposedContextBeanNames);
}
view.setPreventDispatchLoop(true);
return view;
}

InternalResourceViewResolver类中的buildView方法中首先执行了父类的buildView方法。之后又进行了一些view的属性设置。

总结

我们可以发现InternalResourceViewResolver与VelocityViewResolver的除了view属性设置不同外,有一个最大区别就是,InternalResourceViewResolver的checkResource方法不会起到拦截作用,即使没有相应的资源存在。所以InternalResourceViewResolver在配置时应该作为ViewResolver链的最后一环。

文章作者: 谷河
文章链接: https://www.lyytaw.com/spring/springMVC(8)-%20ViewResolver%E5%AE%9E%E7%8E%B0%E4%B9%8BInternalResourceViewResolver/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 谷河|BLOG