最近在开发一个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节点,这里由于项目需求,设置最大缓存数量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; } }
版权声明:本文为博主原创文章,未经博主允许不得转载。