Insight Spring Velocity相关配置以及缓存的设计

之前web View一直用的JSP,现在使用的velocity。

通过Insight Velocity配置,说说SpringMVC view生成的过程

......

1.Velocity 配置解析

需要配置VelocityConfigurer,这是个VelocityEngineFactory,用于初始化自定义VelocityEngine。

需要配置VelocityLayoutViewResolver,用于生成对应的VelocityView。

特别的,如果不配置ViewResolver的情况下,springmvc 会默认采用InternalResourceViewResolver,实现jsp支持


2.View 的生成过程

直接看实现:

/**
 * 委托buildView 方法来创建指定的View instance (VelocityView/FreeMarkerView/JstlView...)
 * 再经过beanFactory进行初始化处理。
 */
@Override
protected View loadView(String viewName, Locale locale) throws Exception {
    AbstractUrlBasedView view = buildView(viewName);
    // 非常重要,将View 纳入bean生命周期进行管理
    View result = applyLifecycleMethods(viewName, view);
    return (view.checkResource(locale) ? result : null);
}

/**
 * Creates a new View instance. 
 * buildView基础实现,不同View class自定义属性在subClass.buildView中实现.
 */
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
    AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass());
    // 配置的prefix + controller.viewname + suffix
    view.setUrl(getPrefix() + viewName + getSuffix());
    
    // ...
    return view;
}

@Override
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
    VelocityView view = (VelocityView) super.buildView(viewName);
    // 配置dateToolAttribute、numberToolAttribute,如果不为null,那么会在Velocity context 加入Date、Number Helper
    view.setDateToolAttribute(this.dateToolAttribute);
    view.setNumberToolAttribute(this.numberToolAttribute);
    if (this.toolboxConfigLocation != null) {
	    ((VelocityToolboxView) view).setToolboxConfigLocation(this.toolboxConfigLocation);
    }
    return view;
}
viewResolver 的统一配置会在createView过程中赋值给指定的View bean。

/**
 * 如上所见,ViewResolver.loadView过程中会进行View生命周期管理. 
 * Looks for a single VelocityConfig bean to find the relevant VelocityEngine for this factory.
 */
@Override
protected void initApplicationContext() throws BeansException {
    super.initApplicationContext();
    
    if (getVelocityEngine() == null) {
        // try to autodetect one. 工程配置的VelocityConfigurer,得到velocityEngine bean.
        setVelocityEngine(autodetectVelocityEngine());
    }
}

protected void exposeToolAttributes(Context velocityContext, HttpServletRequest request) throws Exception {
	// ...

	// 如ViewResolver配置,根据dateToolAttribute、numberToolAttribute确定是否加入Date/Number Helper
	if (this.dateToolAttribute != null || this.numberToolAttribute != null) {
		Locale locale = RequestContextUtils.getLocale(request);
		if (this.dateToolAttribute != null) {
			velocityContext.put(this.dateToolAttribute, new LocaleAwareDateTool(locale));
		}
		if (this.numberToolAttribute != null) {
			velocityContext.put(this.numberToolAttribute, new LocaleAwareNumberTool(locale));
		}
	}
}


3.设计的亮点-cache

自定义的ViewResolver 都是基于AbstractCachingViewResolver,顾名思义,有缓存功能的基类。

在这个类中,可以看到LinkedHashMap FIFO策略缓存的实现。

也可以看到双重同步锁实现多线程单例实现。上源码:

/** 直接从缓存中快速获取view 实例,非全局锁 */
private final Map
   
   
    
     viewAccessCache = new ConcurrentHashMap
    
    
     
     (DEFAULT_CACHE_LIMIT);

/** 1.view 实例创建过程Cache FIFO控制 */
private final Map
     
     
      
       viewCreationCache = new LinkedHashMap
      
      
       
       (DEFAULT_CACHE_LIMIT, 0.75f, true) {
    @Override
    protected boolean removeEldestEntry(Map.Entry
       
       
         eldest) { if (size() > getCacheLimit()) { viewAccessCache.remove(eldest.getKey()); return true; } else { return false; } } }; /** 2.双重同步锁实现view 实例多线程安全单例 */ 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); } } } } return (view != UNRESOLVED_VIEW ? view : null); } } 
       
      
      
     
     
    
    
   
   

简直就是教科书!!!


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值