javaweb項目搭建ehcache緩存系統

EhCache 是一個純Java的進程內緩存框架,具備快速、精幹等特色,是Hibernate中默認的CacheProvider,同時在項目開發中也被普遍使用到。接下來就以用戶緩存爲例,基於javaweb項目來搭建ehcache緩存系統。
java

主要涉及核心原理和實現要點:項目是基於spring框架來統一管理和配置bean的,因此在spring中配置緩存,定義EhCacheManagerFactoryBean,同時指向其ehcache配置文件ehcache.xml,ehcache.xml則有咱們本身根據項目狀況來定義一些緩存策略,如:cache中元素的生存時間、cache 中最多能夠存放的元素的數量和內存存儲與釋放策略等等。java代碼中則能夠定義一個統一的緩存管理類去持有net.sf.ehcache.CacheManager實例,來代理往數據庫中操做數據的行爲。關於CacheManager實例的獲取,則能夠經過實現ApplicationContextAware, DisposableBean接口,分別重寫其setApplicationContext()方法,注入ApplicationContext到靜態變量中和destroy()方法,在ApplicationContext關閉時清理靜態變量。這樣以靜態變量保存Spring ApplicationContext, 可在任何代碼任何地方任什麼時候候取出ApplicaitonContext,進而調用其getBean()方法來得到CacheManager實例。拿數據是先getByCache(),若緩存中存在數據則直接返回該數據,若緩存中不存在數據,再執行getByDb(),從數據庫中拿數據,同時將數據存進緩存中。web

一、首先從web.xml部署文件入口進行配置spring

<!-- 應用程序Spring上下文配置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath*:applicationContext*.xml,
        </param-value>
    </context-param>
<!-- 自定義監聽器 繼承自spring上下文加載監聽器 -->
        <listener>
           <listener-class>com.schoolnet.sys.listener.WebContextListener</listener-class>
        </listener>

繼承自spring上下文加載監聽器的WebContextListener類,能夠在web啓動時作一些處理數據庫

WebContextListener .java緩存

public class WebContextListener extends org.springframework.web.context.ContextLoaderListener {
    
    @Override
    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
        if (!printKeyLoadMessage()){
            return null;
        }
        return super.initWebApplicationContext(servletContext);
    }
    private static boolean printKeyLoadMessage(){
        StringBuilder sb = new StringBuilder();
        sb.append("\r\n======================================================================\r\n");
        sb.append("\r\n    歡迎使用 校園網  - EhCache緩存系統搭建\r\n");
        sb.append("\r\n======================================================================\r\n");
        System.out.println(sb.toString());
        return true;
    }
}

二、applicationContex.xml中配置ehcache緩存app

<!-- 加載配置屬性文件 -->
    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

        <property name="fileEncoding" value="UTF-8" />

        <property name="locations">
            <list>
                <value>classpath:schoolnet.properties</value>
            </list>
        </property>
    </bean>
<!-- 緩存配置 -->
    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="configLocation" value="classpath:${ehcache.configFile}" />
    </bean>

三、schoolnet.properties框架

ehcache.configFile=cache/ehcache.xml(源碼包下的cache文件夾中)

四、ehcache.xmlide

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="defaultCache">

    <diskStore path="../temp/jeesite/ehcache" />

    <!-- 默認緩存配置. -->
    <defaultCache maxEntriesLocalHeap="100" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600"
        overflowToDisk="true" maxEntriesLocalDisk="100000" />
    
    <!-- 系統緩存 -->
    <cache name="sysCache" maxEntriesLocalHeap="100" eternal="true" overflowToDisk="true"/>
    
    <!-- 用戶緩存 -->
    <cache name="userCache" maxEntriesLocalHeap="100" eternal="true" overflowToDisk="true"/>

    <!-- 系統活動會話緩存 -->
    <cache name="activeSessionsCache" maxEntriesLocalHeap="10000" overflowToDisk="true"
           eternal="true" timeToLiveSeconds="0" timeToIdleSeconds="0"
           diskPersistent="true" diskExpiryThreadIntervalSeconds="600"/>
    
    <!-- 簡單頁面緩存
    <cache name="SimplePageCachingFilter" maxEntriesLocalHeap="100" eternal="false" overflowToDisk="true"
        timeToIdleSeconds="120" timeToLiveSeconds="120" memoryStoreEvictionPolicy="LFU"/> -->
        
</ehcache>

一些配置參數的說明工具

maxElementsInMemory :cache 中最多能夠存放的元素的數量。若是放入cache中的元素超過這個數值,有兩種狀況:一、若overflowToDisk的屬性值爲true,會將cache中多出的元素放入磁盤文件中。二、若overflowToDisk的屬性值爲false,會根據memoryStoreEvictionPolicy的策略替換cache中原有的元素。
eternal :意思是是否永駐內存。若是值是true,cache中的元素將一直保存在內存中,不會由於時間超時而丟失,因此在這個值爲true的時候,timeToIdleSeconds和timeToLiveSeconds兩個屬性的值就不起做用了。
timeToIdleSeconds :就是訪問這個cache中元素的最大間隔時間。若是超過這個時間沒有訪問這個cache中的某個元素,那麼這個元素將被從cache中清除。
timeToLiveSeconds : 這是cache中元素的生存時間。意思是從cache中的某個元素從建立到消亡的時間,從建立開始計時,當超過這個時間,這個元素將被從cache中清除。
overflowToDisk :溢出是否寫入磁盤。系統會根據標籤<diskStore path="java.io.tmpdir"/> 中path的值查找對應的屬性值,若是系統的java.io.tmpdir的值是 D:/temp,寫入磁盤的文件就會放在這個文件夾下。文件的名稱是cache的名稱,後綴名的data。如:CACHE_FUNC.data。這個屬性在解釋maxElementsInMemory的時候也已經說過了。
diskExpiryThreadIntervalSeconds  :磁盤緩存的清理線程運行間隔
memoryStoreEvictionPolicy :內存存儲與釋放策略。有三個值:
LRU -least recently used
LFU -least frequently used
FIFO-first in first out, the oldest element by creation time
diskPersistent : 是否持久化磁盤緩存。當這個屬性的值爲true時,系統在初始化的時候會在磁盤中查找文件名爲cache名稱,後綴名爲index的的文件,如CACHE_FUNC.index 。這個文件中存放了已經持久化在磁盤中的cache的index,找到後把cache加載到內存。要想把cache真正持久化到磁盤,寫程序時必須注意,在是用net.sf.ehcache.Cache的void put (Element element)方法後要使用void flush()方法。
ui

五、CacheUtils.java

/**
 * Cache工具類
 */
public class CacheUtils {
    
    private static CacheManager cacheManager = ((CacheManager)SpringContext.getBean("cacheManager"));

    private static final String SYS_CACHE = "sysCache";

    /**
     * 獲取SYS_CACHE緩存
     * @param key
     * @return
     */
    public static Object get(String key) {
        return get(SYS_CACHE, key);
    }
    
    /**
     * 寫入SYS_CACHE緩存
     * @param key
     * @return
     */
    public static void put(String key, Object value) {
        put(SYS_CACHE, key, value);
    }
    
    /**
     * 從SYS_CACHE緩存中移除
     * @param key
     * @return
     */
    public static void remove(String key) {
        remove(SYS_CACHE, key);
    }
    
    /**
     * 獲取緩存
     * @param cacheName
     * @param key
     * @return
     */
    public static Object get(String cacheName, String key) {
        Element element = getCache(cacheName).get(key);
        return element==null?null:element.getObjectValue();
    }

    /**
     * 寫入緩存
     * @param cacheName
     * @param key
     * @param value
     */
    public static void put(String cacheName, String key, Object value) {
        Element element = new Element(key, value);
        getCache(cacheName).put(element);
    }

    /**
     * 從緩存中移除
     * @param cacheName
     * @param key
     */
    public static void remove(String cacheName, String key) {
        getCache(cacheName).remove(key);
    }
    
    /**
     * 得到一個Cache,沒有則建立一個。
     * @param cacheName
     * @return
     */
    private static Cache getCache(String cacheName){
        Cache cache = cacheManager.getCache(cacheName);
        if (cache == null){
            cacheManager.addCache(cacheName);
            cache = cacheManager.getCache(cacheName);
            cache.getCacheConfiguration().setEternal(true);
        }
        return cache;
    }

    public static CacheManager getCacheManager() {
        return cacheManager;
    }
    
}
6、SpringContext.java,用類得到ApplicationContext實例

@Component
public class SpringContext implements ApplicationContextAware,DisposableBean{
    private static ApplicationContext applicationContext;
    /**
     * 取得存儲在靜態變量中的ApplicationContext.
     */
    @Override
    public void setApplicationContext(ApplicationContext context)
            throws BeansException {
        try {
            applicationContext=context;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 從靜態變量applicationContext中取得Bean, 自動轉型爲所賦值對象的類型.
     */
    public static <T> T getBean(String name){
        return (T) applicationContext.getBean(name);
    }
    public static String[] getBeanNamesForType(Class<?> type){
        return applicationContext.getBeanNamesForType(type);
    }
    /**
     * 實現DisposableBean接口, 在Context關閉時清理靜態變量.
     */
    @Override
    public void destroy() throws Exception {
        applicationContext = null;
    }
}

七、UserUtils.java

/**
 * 用戶工具類
 */
public class UserUtils {


    private static UserDao userDao = SpringContextHolder.getBean(UserDao.class);
    private static Map<String, Object> cacheMap;
    /**
     * 根據ID獲取用戶
     * @param id
     * @return 取不到返回null
     */
    public static User getUser(String id){
        User user = (User)CacheUtils.get("userCache", "id_" + id);
        if (user ==  null){
            user = userDao.get(id);
            if (user == null){
                return null;
            }
            CacheUtils.put("userCache", "id_" + user.getId(), user);
            CacheUtils.put("userCache", "ln" + user.getLoginName(), user);
        }
        return user;
    }
    
    /**
     * 根據登陸名獲取用戶
     * @param loginName
     * @return 取不到返回null
     */
    public static User getByLoginName(String loginName){
        User user = (User)CacheUtils.get("userCache", "ln" + loginName);
        if (user == null){
            user = userDao.getByLoginName(new User(null, loginName));
            if (user == null){
                return null;
            }
            CacheUtils.put("userCache", "id_" + user.getId(), user);
            CacheUtils.put("userCache", "ln" + user.getLoginName(), user);
        }
        return user;
    }
    
    
    /**
     * 清除用戶緩存
     * @param user
     */
    public static void clearCache(User user){
        CacheUtils.remove("userCache", "id_" + user.getId());
        CacheUtils.remove("userCache", "ln" + user.getLoginName());
        CacheUtils.remove("userCache", "ln" + user.getOldLoginName());
    }
}


 
相關文章
相關標籤/搜索