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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章