• 缓存初解(四)---Ibatis的缓存配置+Ehcache


    项目完结,整理一些技术方面的相关收获。
    已经记不得EhCacheController这个实现类最早来自于那里了,总之稍加修改后非常有效果,大家就这么用了,感谢最初开源的那位兄弟。这里,主要是做个记录,为以后类似扩展(譬如Memcached)做个准备。

    iBatis提供CacheController接口,用于实现第三方缓存架构的扩展。
    这里以iBatis 2.3.0,EhCache 1.2.3版本为基础,构建iBatis+EhCache实现。

    EhCacheController类:

    package com.ibatis.sqlmap.engine.cache.ehcache;
    
    import java.net.URL;
    import java.util.Properties;
    
    import net.sf.ehcache.Cache;
    import net.sf.ehcache.CacheManager;
    import net.sf.ehcache.Element;
    
    import com.ibatis.sqlmap.engine.cache.CacheController;
    import com.ibatis.sqlmap.engine.cache.CacheModel;
    
    /**
     * EhCache Implementation of the
     * {@link com.ibatis.sqlmap.engine.cache.CacheController} interface to be able
     * to use EhCache as a cache implementation in iBatis. You can configure your
     * cache model as follows, by example, in your sqlMapping files:
     * 
     * <pre>
     * <code>
     * <cacheModel id="myCache" readOnly="true" serialize="false"
     * 	type="com.ibatis.sqlmap.engine.cache.EhCacheController" > 
     * 	<property name="configLocation"
     * 		value="/path-to-ehcache.xml"/> 
     * </cacheModel> </code>
     * </pre>
     * 
     * Alternatively, you can use a type alias in your type attribute and defining
     * the class with a <code><typeAlias></code> declaration:
     * 
     * <pre>
     * <code>
     * <sqlMapConfig>
     * 	<typeAlias alias="EHCACHE" 
     * 		type="com.ibatis.sqlmap.engine.cache.ehcache.EhCacheController" />
     * </sqlMapConfig>
     * </code>
     * </pre>
     * 
     */
    public class EhCacheController implements CacheController {
    
    	/**
    	 * The EhCache CacheManager.
    	 */
    	private CacheManager cacheManager;
    
    	public static final String CONFIG_LOCATION = "configLocation";
    
    	/**
    	 * Default Configure Location
    	 */
    	public static final String DEFAULT_CONFIG_LOCATION = "/ehcache.xml";
    
    	/**
    	 * Flush a cache model.
    	 * 
    	 * @param cacheModel
    	 *            - the model to flush.
    	 */
    	public void flush(CacheModel cacheModel) {
    		getCache(cacheModel).removeAll();
    	}
    
    	/**
    	 * Get an object from a cache model.
    	 * 
    	 * @param cacheModel
    	 *            - the model.
    	 * @param key
    	 *            - the key to the object.
    	 * @return the object if in the cache, or null(?).
    	 */
    	public Object getObject(CacheModel cacheModel, Object key) {
    		Object result = null;
    		Element element = getCache(cacheModel).get(key);
    		if (element != null) {
    			result = element.getObjectValue();
    		}
    		return result;
    
    	}
    
    	/**
    	 * Put an object into a cache model.
    	 * 
    	 * @param cacheModel
    	 *            - the model to add the object to.
    	 * @param key
    	 *            - the key to the object.
    	 * @param object
    	 *            - the object to add.
    	 */
    	public void putObject(CacheModel cacheModel, Object key, Object object) {
    		getCache(cacheModel).put(new Element(key, object));
    	}
    
    	/**
    	 * Remove an object from a cache model.
    	 * 
    	 * @param cacheModel
    	 *            - the model to remove the object from.
    	 * @param key
    	 *            - the key to the object.
    	 * @return the removed object(?).
    	 */
    	public Object removeObject(CacheModel cacheModel, Object key) {
    		Object result = this.getObject(cacheModel, key);
    		getCache(cacheModel).remove(key);
    		return result;
    	}
    
    	/**
    	 * Gets an EH Cache based on an iBatis cache Model.
    	 * 
    	 * @param cacheModel
    	 *            - the cache model.
    	 * @return the EH Cache.
    	 */
    	private Cache getCache(CacheModel cacheModel) {
    		String cacheName = cacheModel.getId();
    		Cache cache = cacheManager.getCache(cacheName);
    		return cache;
    	}
    
    	/**
    	 * Shut down the EH Cache CacheManager.
    	 */
    	public void finalize() {
    		if (cacheManager != null) {
    			cacheManager.shutdown();
    		}
    	}
    
    	/**
    	 * Configure a cache controller. Initialize the EH Cache Manager as a
    	 * singleton.
    	 * 
    	 * @param props
    	 *            - the properties object continaing configuration information.
    	 */
    	@Override
    	public void configure(Properties props) {
    		String configLocation = props.getProperty(CONFIG_LOCATION);
    		// if can not found ehcache.xml from configLocaion,
    		// use default configure file.
    		if (configLocation == null) {
    			configLocation = DEFAULT_CONFIG_LOCATION;
    		}
    		URL url = getClass().getResource(configLocation);
    		cacheManager = CacheManager.create(url);
    	}
    }
    

     这里默认在根目录下获取ehcache.xml文件,可以通过cacheModel配置进行修改。

    在SqlMapConfig.xml文件中配置一个别名,作为全局变量,供其余SqlMap使用

    <typeAlias
    		alias="EHCACHE"
    		type="com.ibatis.sqlmap.engine.cache.ehcache.EhCacheController" />
    

     
    顺便提一句,要使用缓存注意SqlMapConfig.xml文件中settings节点配置cacheModelsEnabledtrue

    	<settings
    		cacheModelsEnabled="true"
    		useStatementNamespaces="true" 
    		... 
    	/>
    

     如果要变更ehcache.xml文件路径为/config/ehcache.xml,可以在上述节点中下入如下代码:

    <property name="configLocation" value="/config/ehcache.xml" /> 
    

     然后,就可以通过ehcache.xml控制ehcache缓存了!

    举例说明iBatis SqlMap & ehcahce.xml,以免有些兄弟混淆!

    以Account类为示例,在SqlMap中的配置为:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE sqlMap
        PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
        "http://ibatis.apache.org/dtd/sql-map-2.dtd">
    <sqlMap
    	namespace="Account">
    	<cacheModel
    		id="cache"
    		type="EHCACHE">
    		<flushInterval
    			hours="1" />
    		<!-- flush操作,需要指明 Namespace -->
    		<flushOnExecute
    			statement="Account.create" />
    	</cacheModel>
    	<typeAlias
    		alias="account"
    		type="org.zlex.acl.Account" />
    	<resultMap
    		id="accountMap"
    		class="account">
    		<result
    			property="accountId"
    			column="accountId" />
    		<result
    			property="accountName"
    			column="accountName" />
    		<result
    			property="mail"
    			column="mail" />
    		<result
    			property="realName"
    			column="realName" />
    		<result
    			property="status"
    			column="status" />
    		<result
    			property="lastLoginTime"
    			column="lastLoginTime" />
    	</resultMap>
    	<select
    		id="readByAccountName"
    		parameterClass="string"
    		resultMap="accountMap"
    		cacheModel="cache">
    		<![CDATA[
    			SELECT 
    				accountId,
    				accountName,
    				mail,
    				realName,
    				status,
    				lastLoginTime
    			FROM 
    				acl_account
    			WHERE 
    				accountName = #accountName# 
    		]]>
    	</select>
    	<insert
    		id="create"
    		parameterClass="account">
    		<![CDATA[
    			INSERT INTO 
    				acl_account(
    				accountName,
    				mail,
    				realName,
    				status,
    				lastLoginTime
    				) 
    			VALUES (
    					#accountName#,
    					#mail#,
    					#realName#,
    					#status#,
    					#lastLoginTime#
    				)
    		]]>
    		<selectKey
    			resultClass="long"
    			keyProperty="accountId">
    			<![CDATA[select LAST_INSERT_ID() as id ]]>
    		</selectKey>
    	</insert>
    </sqlMap>
    

     注意:

    引用
    <select
    id="readByAccountName"
    parameterClass="string"
    resultMap="accountMap"
    cacheModel="cache"> 
    

    这里的cacheModel="cache",对应的在ehcache.xml中就应该是:

    	<cache 
    		name="Account.cache" 
    		maxElementsInMemory="10000" 
    		eternal="false"
    		maxElementsOnDisk="1000" 
    		overflowToDisk="true" 
    		timeToIdleSeconds="300"
    		/>
    

     因为,我使用了useStatementNamespaces="true"

  • 相关阅读:
    springMVC源码分析
    世界近代史二
    世界近代历史
    UVA
    UVA
    UVA
    Web 前端开发学习之路(入门篇)
    01 Linux入门介绍
    2. Python基本知识
    1. 初识Python
  • 原文地址:https://www.cnblogs.com/wcyBlog/p/3949697.html
Copyright © 2020-2023  润新知