最近在開發一個android項目,項目是面向在校大學生的,聽說推廣起來,訪問量必將很大,針對這種狀況,再看看咱們如今有的後臺服務框架,居然沒有針對高訪問量這種狀況的處理,這裏一定用到緩存技術,現有的框架中也最多存在Hibernate緩存的使用,但針對數據層的緩存,必然會用到Hibernate的二級緩存,居然框架中連Hibernate的二級緩存都沒用過,看到這些,想一想也沒有在現有的基礎上作簡單擴展的必要了,因而決定針對後臺服務緩存這層進行研究使用。html
在網上看到了很多緩存技術,有些比較陌生,有些不適合現有項目,還有些使用上不是很方便,最終肯定選擇了ehcache,發現Hibernate的二級緩存就是使用Ehcache實現的,但畢竟是嵌套在Hibernate框架中的,使用的靈活性就大打折扣了,例如Hibernate的二級緩存對於查詢列表只能針對固定不變的結果數據進行緩存,另外不支持對緩存的動態添加修改,Ehcache自己單獨就是很強大,因而決定單獨提出來使用。java
Ehcache 是如今最流行的純Java開源緩存框架,配置簡單、結構清晰、功能強大。android
關於Ehcache原理性的東西這邊就不作詳細的記錄了,畢竟也是剛剛接觸,理解的多會有誤差,記錄下一篇比較詳細的文章供之後參考:spring
http://raychase.iteye.com/blog/1545906express
下面介紹項目中Ehcache的簡單使用。緩存
項目現有環境,eclipse開發,spring4.0app
一、從官網上下載Ehcache最新版本ehcache-2.8.3-distribution,解壓文件將lib下的三個jar包 拷到項目中(明顯看到所需jar包都很小)框架
二、將ehcache.xml文件考到項目src根目錄下eclipse
ehcache.xml文件配置分佈式
增長cache節點,這裏因爲項目需求,設置最大緩存數量maxElementsInMemory爲100000,過時設置爲永不過時,由於過時數據需手動處理,
<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; } }