【Freemarker】SpringMVC&Freemarker视图渲染的两级缓存

    开发springmvc+freemarker项目时经常要调试页面模版的元素,为了使修改立即生效,就得关闭缓存,否则视图渲染一直走得缓存。关闭缓存就要注意了,如果使用FreeMarkerViewResolver视图解析器(freemarker模版的解析器),则需要关闭两处缓存。

   第一级缓存,FreeMarkerViewResolver的视图缓存(viewAccessCache)。这级缓存是springmvc的视图缓存,mvc会将之前解析得到的view对象缓存到一个map里面。当map的size达到一定数值时(默认是1024),则删除第一个元素。想要关闭这级缓存只需要将缓存的限制值(cacheLimit)为0即可。

<!-- Spring MVC页面层FreeMarker的处理类 -->
<bean id="freeMarkerViewResolver"
    class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
    <property name="viewClass"
        value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/>
    <property name="cacheLimit" value="0" />
</bean>

springmvc用了巧妙的方式来保证map的size不超过cacheLimit。mvc维护了两个map,一个是viewAccessCache,另一个是viewCreationCache。viewAccessCache用于访问,viewCreationCache用于创建。mvc怎么保证map的size不超过cacheLimit呢?它在创建viewCreationCache时重载了removeEldestEntry方法,viewCreationCache添加元素后当map的size > cacheLimit时就会删除viewAccessCache里面对应key的view对象,并返回true从而使viewCreationCache也删除自己保存的对象。

public abstract class AbstractCachingViewResolver 
extends WebApplicationObjectSupport implements ViewResolver {
    ......

	/** Fast access cache for Views, returning already cached instances without a global lock */
	private final Map<Object, View> viewAccessCache = 
                new ConcurrentHashMap<Object, View>(DEFAULT_CACHE_LIMIT);

	/** Map from view key to View instance, synchronized for View creation */
	@SuppressWarnings("serial")
	private final Map<Object, View> viewCreationCache =
			new LinkedHashMap<Object, View>(DEFAULT_CACHE_LIMIT, 0.75f, true) {
				@Override
				protected boolean removeEldestEntry(Map.Entry<Object, View> eldest) {
					if (size() > getCacheLimit()) {
						viewAccessCache.remove(eldest.getKey());
						return true;
					}
					else {
						return false;
					}
				}
			};
    ......
}

viewReslver解析view的时候判断有没有开启缓存(cacheLimit > 0时isCache就会返回true)。如果有就去获取viewAccessCache是否有缓存,有则返回。如果viewAccessCache没有就去创建view对象,创建成功后把view对象put到viewAccessCache和viewCreationCache。注意viewCreationCache重载了方法removeEldestEntry,put对象进去就会触发该方法删除viewAccessCache(当size > cacheLimit时),同时返回true从而使viewCreationCache也删除自己维护的对象。

public abstract class AbstractCachingViewResolver 
extends WebApplicationObjectSupport implements ViewResolver {
    ......
	@Override
	public View resolveViewName(String viewName, Locale locale) throws Exception {
		//笔者注:cacheLimit > 0 isCache返回true
        if (!isCache()) {
			return createView(viewName, locale);
		} else {
			Object cacheKey = getCacheKey(viewName, locale);
            //笔者注:判断viewAccessCache里面有没有,没有则去创建流程
			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.viewAccessCache.put(cacheKey, view);
                            //笔者注:put就会触发上面重载的方法(removeEldestEntry)
							this.viewCreationCache.put(cacheKey, view);
				            ......
						}
					}
				}
			}
			return (view != UNRESOLVED_VIEW ? view : null);
		}
	}
    ......
}

      第二级缓存,模版缓存(TemplateCache)。绕过FreeMarkerViewResolverviewResolver的缓存后,会来到freemarker加载模版(ftl文件)的逻辑,这个过程中同样也用到了缓存。这级缓存是用时间控制的,缓存中模版加载的时间超过delay则会重新加载模版文件。想要关闭这级缓存需要将delay(配置项为template_update_delay)时间设置为0,这样相当于设置模版缓存的有效期是0s。

<bean id="freemarkerConfiguration"
    class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">    
    <property name="freemarkerSettings">
        <props>
            <!-- 配置缓存时间 -->
            <prop key="template_update_delay">0</prop>
        </props>
    </property>
</bean>

    总结一下,调试mvc要想页面实时生效,需要关闭两个缓存:

  1. FreeMarkerViewResolver的cacheLimit设置为0
  2. freemarkerSettings的template_update_delay也要设置为0(单位s)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值