Ehcache 初探(在項目中的簡單使用)

  最近在開發一個android項目,項目是面向在校大學生的,據說推廣起來,訪問量必將很大,針對這種情況,再看看我們現在有的後臺服務框架,竟然沒有針對高訪問量這種情況的處理,這裏必定用到緩存技術,現有的框架中也最多存在Hibernate緩存的使用,但針對數據層的緩存,必然會用到Hibernate的二級緩存,竟然框架中連Hibernate的二級緩存都沒用過,看到這些,想想也沒有在現有的基礎上做簡單擴展的必要了,於是決定針對後臺服務緩存這層進行研究使用。

         在網上看到了不少緩存技術,有些比較陌生,有些不適合現有項目,還有些使用上不是很方便,最終確定選擇了ehcache,發現Hibernate的二級緩存就是使用Ehcache實現的,但畢竟是嵌套在Hibernate框架中的,使用的靈活性就大打折扣了,例如Hibernate的二級緩存對於查詢列表只能針對固定不變的結果數據進行緩存,另外不支持對緩存的動態添加修改,Ehcache本身單獨就是很強大,於是決定單獨提出來使用。

         Ehcache 是現在最流行的純Java開源緩存框架,配置簡單、結構清晰、功能強大。

         關於Ehcache原理性的東西這邊就不做詳細的記錄了,畢竟也是剛剛接觸,理解的多會有偏差,記錄下一篇比較詳細的文章供以後參考:

         http://raychase.iteye.com/blog/1545906

         下面介紹項目中Ehcache的簡單使用。

前期準備

         項目現有環境,eclipse開發,spring4.0

1、從官網上下載Ehcache最新版本ehcache-2.8.3-distribution,解壓文件將lib下的三個jar包  拷到項目中(明顯看到所需jar包都很小)

 

2、將ehcache.xml文件考到項目src根目錄下

文件配置

ehcache.xml文件配置

增加cache節點,這裏由於項目需求,設置最大緩存數量maxElementsInMemory100000,過期設置爲永不過期,因爲過期數據需手動處理,

<cachename="jobInfoListCache"
     maxElementsInMemory="100000" //最大緩存數量
     eternal="true"                 //永不過期,手動處理過期數據
     overflowToDisk="false">       //內存超出時不放到磁盤
        <searchableallowDynamicIndexing="true">
        <searchAttributename="positionTitle"expression="value.getPositionTitle()"/>
           <searchAttributename="cityCode" expression="value.getCityCode()"/>
           <searchAttributename="distinctCode"expression="value.getDistinctCode()"/>
           <searchAttributename="positionTypeId"expression="value.getPositionTypeId()"/>
           <searchAttributename="releaseTime"expression="value.getReleaseTime()"/>
        </searchable>
</cache>

applicationContext-services.xml文件配置

<!--緩存配置 -->
    <beanid="cacheManager"
       class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
       <propertyname="configLocation"value="classpath:ehcache.xml"/>
        <propertyname="shared" value="true"/>
    </bean>
    <!-- 配置一個緩存處理接口類-->
    <beanid="jobInfoCacheManager"class="com.quangao.service.cacheManager.JobInfoCacheManager">
        <propertyname="cacheManager"ref="cacheManager"/>
        <propertyname="_dao" ref="GenericDao" />
    </bean>


 

具體使用

JobInfoCacheManager 文件具體實現

package com.quangao.service.cacheManager;
 
import java.util.ArrayList;
import java.util.List;
 
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.search.Attribute;
import net.sf.ehcache.search.Direction;
import net.sf.ehcache.search.Query;
import net.sf.ehcache.search.Result;
import net.sf.ehcache.search.Results;
 
import com.quangao.dao.generic.GenericDao;
import com.quangao.model.Enum.EnumStatusType;
import com.quangao.model.jobposition.TJobPosition;
import com.quangao.util.StringUtil;
 
public class JobInfoCacheManager {
 
    private CacheManagercacheManager;
 
    private GenericDao       _dao;
 
    private final   String          attrNames[]  = {"positionTitle", "cityCode","distinctCode","positionTypeId", "releaseTime" };
    /**
     * 獲取職位列表
     *
     * @return
     */
    public List<TJobPosition> getTJobPositions()
    {
       String hql = "fromTJobPosition where 1=1 and handleStatusId='"
              + EnumStatusType.FB.getKey() +"' order by releaseTime desc";
       return_dao.getHql(hql);
    }
 
    /**
     *
     * 初始化職位列表緩存
     *
     */
    public void initJobInfoCache()
    {
       Cache cache = cacheManager.getCache("jobInfoListCache");
       // 初始化列表數據
       List<TJobPosition> jobPositions = getTJobPositions();
       if (jobPositions !=null && jobPositions.size() > 0)
       {
           TJobPosition tJobPosition = null;
           for (int i = 0; i < jobPositions.size(); i++)
           {
              tJobPosition = jobPositions.get(i);
              Element element = new Element(tJobPosition.getId(),
                     tJobPosition);
              cache.put(element);
           }
       }
 
       // 動態註冊搜索項,不起作用,研究中
       //cache.registerDynamicAttributesExtractor(new
       //DynamicAttributesExtractor() {
       // public Map<String,Object> attributesFor(Element element) {
       // Map<String, Object> attrs= new HashMap<String, Object>();
       // TJobPosition value =(TJobPosition)element.getObjectValue();
       // attrs.put(attrNames[0],value.getPositionTitle());
       // attrs.put(attrNames[1],value.getCityCode());
       // attrs.put(attrNames[2],value.getDistinctCode());
       // attrs.put(attrNames[3],value.getPositionTypeId());
       // return attrs;
       // }
       // });
    }
 
    /**
     * 增加職位緩存
     *
     * @param tJobPosition
     */
    public void addJobInfoCache(TJobPosition tJobPosition)
    {
       Cache cache = cacheManager.getCache("jobInfoListCache");
       if (tJobPosition !=null)
       {
           Element element = new Element(tJobPosition.getId(), tJobPosition);
           cache.put(element);
       }
    }
 
    /**
     * 修改職位緩存
     *
     * @param tJobPosition
     */
    public void updateJobInfoCache(TJobPosition tJobPosition)
    {
       Cache cache = cacheManager.getCache("jobInfoListCache");
       if (tJobPosition !=null)
       {
           // 相同key值,內容會被覆蓋
           Element element = new Element(tJobPosition.getId(), tJobPosition);
           cache.put(element);
       }
    }
 
    /**
     * 移除職位緩存
     *
     * @param tJobPosition
     */
    public void removeJobInfoCache(TJobPosition tJobPosition)
    {
       Cache cache = cacheManager.getCache("jobInfoListCache");
       if (tJobPosition !=null)
       {
           cache.remove(tJobPosition.getId());
       }
    }
 
    /**
     * 根據條件查詢緩存列表
     *
     * @param cityCode
     * @param areaCode
     * @param typeCode
     * @param firstResult
     * @param maxResult
     * @return
     */
    public List<TJobPosition>getJobPositionsByCondition(String positionTitle,
           String cityCode, String areaCode, String typeCode,
           Integer firstResult, Integer maxResult)
    {
       Cache cache = cacheManager.getCache("jobInfoListCache");
       List<TJobPosition> listTJobPositions = newArrayList<TJobPosition>();
 
      
       /**
        *
        * 這是新版本的強大之處,可以根據緩存值對象進行條件查詢,前提是在ehcache.xml文件中對值對象查詢字段進行定義搜索項
        *<searchableallowDynamicIndexing="true">
            <searchAttributename="positionTitle"expression="value.getPositionTitle()"/>
              <searchAttribute name="cityCode"expression="value.getCityCode()"/>
              <searchAttribute name="distinctCode"expression="value.getDistinctCode()"/>
              <searchAttribute name="positionTypeId"expression="value.getPositionTypeId()"/>
              <searchAttribute name="releaseTime"expression="value.getReleaseTime()"/>
      </searchable>
        */
       Attribute<String> positionTitlet = cache
              .getSearchAttribute(attrNames[0]);
       Attribute<String> cityCodet = cache.getSearchAttribute(attrNames[1]);
       Attribute<String> areaCodet = cache.getSearchAttribute(attrNames[2]);
       Attribute<String> typeCodet = cache.getSearchAttribute(attrNames[3]);
       Attribute<String> releaseTime =cache.getSearchAttribute(attrNames[4]);
       // 查詢結果集
       Results results = null;
       // 新建緩存值查詢
       Query query = cache.createQuery().includeValues();
       // 根據條件索引
       if (StringUtil.isNotBlankOrNull(positionTitle))
       {
           query.addCriteria(positionTitlet.ilike("*" +positionTitle +"*"));
       }
       if (StringUtil.isNotBlankOrNull(cityCode))
       {
           query.addCriteria(cityCodet.eq(cityCode));
       }
       if (StringUtil.isNotBlankOrNull(areaCode))
       {
           query.addCriteria(areaCodet.eq(areaCode));
       }
       if (StringUtil.isNotBlankOrNull(typeCode))
       {
           query.addCriteria(typeCodet.eq(typeCode));
       }
       // 查詢結果排序
       query.addOrderBy(releaseTime, Direction.DESCENDING).end();
       results = query.execute();
       // 分頁查找
       // List<Result>listreResults = results.all();
       List<Result> listreResults = results.range(firstResult,maxResult);
 
       // 將結果封裝成需要的數據格式
       if (listreResults !=null && listreResults.size() > 0)
       {
           Result result = null;
           for (int i = 0; i < listreResults.size(); i++)
           {
              result = listreResults.get(i);
 
              System.out.println("+++++++++++" + result.toString());
 
              listTJobPositions.add((TJobPosition)result.getValue());
           }
       }
       System.out.println("===============" + results.size());
       return listTJobPositions;
    }
 
    public GenericDao get_dao()
    {
       return_dao;
    }
 
    public void set_dao(GenericDao dao)
    {
       _dao = dao;
    }
 
    public CacheManager getCacheManager()
    {
       returncacheManager;
    }
 
    public void setCacheManager(CacheManager cacheManager)
    {
       this.cacheManager = cacheManager;
    }
}


 

總結

         看了Ehcache的相關文檔後,發現其非常強大,而且使用起來非常簡單,這裏只是真對項目中的特定需求做了簡單的使用,關於性能參數調優還有待優化完善,後期可能會用到分佈式,集羣等應用,使用的時候再進行總結學習。
發佈了26 篇原創文章 · 獲贊 10 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章