您的位置:首页 > 编程语言 > Java开发

Ehcache与Spring整合

2017-09-19 12:54 232 查看

一、EHCACHE介绍

 

EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。





优点:

1. 快速

2. 简单

3. 多种缓存策略

4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题

5. 缓存数据会在虚拟机重启的过程中写入磁盘

6. 可以通过RMI、可插入API等方式进行分布式缓存

7. 具有缓存和缓存管理器的侦听接口

8. 支持多缓存管理器实例,以及一个实例的多个缓存区域

9. 提供Hibernate的缓存实现

缺点

1. 使用磁盘Cache的时候非常占用磁盘空间:这是因为DiskCache的算法简单,该算法简单也导致Cache的效率非常高。它只是对元素直接追加存储。因此搜索元素的时候非常的快。如果使用DiskCache的,在很频繁的应用中,很快磁盘会满。

2. 不能保证数据的安全:当突然kill掉java的时候,可能会产生冲突,EhCache的解决方法是如果文件冲突了,则重建cache。这对于Cache 数据需要保存的时候可能不利。当然,Cache只是简单的加速,而不能保证数据的安全。如果想保证数据的存储安全,可以使用Bekeley DB Java Edition版本。这是个嵌入式数据库。可以确保存储安全和空间的利用率。

EhCache的分布式缓存有传统的RMI,1.5版的JGroups,1.6版的JMS。分布式缓存主要解决集群环境中不同的服务器间的数据的同步问题。

使用Spring的AOP进行整合,可以灵活的对方法的返回结果对象进行缓存。

参考:http://www.cnblogs.com/mxmbk/articles/5162813.html

           http://www.cnblogs.com/jianjianyang/p/4933016.html

二、与Spring整合

1. maven依赖

<dependency>
<
4000
span style="color:#0000ff;"><groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.5</version>
</dependency>

2、ehcache.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<!-- 磁盘存储:将缓存中暂时不使用的对象,转移到硬盘,类似于Windows系统的虚拟内存 path:指定在硬盘上存储对象的路径 -->
<diskStore path="java.io.tmpdir" />
<!-- defaultCache:默认的缓存配置信息,如果不加特殊说明,则所有对象按照此配置项处理 maxElementsInMemory:设置了缓存的上限,最多存储多少个记录对象
eternal:代表对象是否永不过期 timeToIdleSeconds:最大的发呆时间 timeToLiveSeconds:最大的存活时间 overflowToDisk:是否允许对象被写入到磁盘 -->
<defaultCache maxElementsInMemory="1000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" />
<!-- cache:为指定名称的对象进行缓存的特殊配置 name:指定对象的完整名 -->
<cache name="ditItemCache" maxElementsInMemory="1000" eternal="false"
timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" />
</ehcache>

3、spring-cache.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- 开启cache注解扫描 -->
<cache:annotation-driven />
<!-- encache配置 -->
<bean id="ehcacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:cache/ehcache.xml" />
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcacheManager" />
<property name="transactionAware" value="true" />
</bean>
</beans>

4、spring-basic.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<context:component-scan base-package="com.yjpal.dams">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- 缓存配置 -->
<import resource="classpath*:/cache/spring-cache.xml" />
</beans>

5、服务类实现(代码方式)

package com.yjpal.dams.common.service.impl;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.cache.Cache;

import org.springframework.cache.ehcache.EhCacheCacheManager;

import org.springframework.stereotype.Service;

 

/**

* @Description: 缓存服务类

* @author Jian Jang

* @version 1.0 2017年8月16日

*/

@Service

public class EhCacheService {

@Autowired

private EhCacheCacheManager cacheManager;

 

public EhCacheService() {

}

/**

* 根据cacheKey从缓存中获取信息

* @param cacheKey

* @return

* @throws Exception

  */

public Object getCacheElement(String cacheKey) throws Exception {

Cache cache = cacheManager.getCache("ditItemCache");

Cache.ValueWrapper e = cache.get(cacheKey);

if (null == e) {

return null;

}

return e.get();

}

 

/**

* 向缓存中添加信息

* @param cacheKey

* @param value

  */

public void addElementTocache(String cacheKey, Object value) {

Cache cache = cacheManager.getCache("ditItemCache");

cache.put(cacheKey, value);

}

}


6、示例代码(只展示逻辑,其他业务代码略)

package com.yjpal.dams.common.service.impl;

 

import java.util.List;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.cache.annotation.Cacheable;

import org.springframework.stereotype.Service;

import org.springframework.util.CollectionUtils;

 

import com.yjpal.dams.common.constant.CacheDictItemEnum;

import com.yjpal.dams.common.exceptions.BizException;

import com.yjpal.dams.common.service.CommonService;

import com.yjpal.dams.common.utils.JsonUtils;

import com.yjpal.dams.dbaccess.common.dao.CommonMapper;

import com.yjpal.dams.dbaccess.common.entity.DictItem;

 

/**

* @Description: 公共服务实现类

* @author Jian Jang

* @version 1.0 2017年8月8日

*/

@Service

public class CommonServiceImpl implements CommonService {

private transient Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired

private CommonMapper commonMapper;

@Autowired

private EhCacheService ehCacheService;

 

@Override

public List<DictItem> getDictItemList(DictItem dictItem) {

try {

// 此处需要省份和城市分开,省份-level=1 城市parentCode !=null

if ("1".equals(dictItem.getLevel())) {

return getRegion(dictItem, true);

} else {

return getRegion(dictItem, false);

}

} catch (Exception e) {

logger.error("数据字典项查询失败:" + e.getMessage(), e);

}

return null;

}

 

/**

* @param dictItem

* @param flag true-省份 false-城市

* @return

* @throws Exception

  */

@SuppressWarnings("unchecked")

private List<DictItem> getRegion(DictItem dictItem, boolean flag) throws Exception {

List<DictItem> dictItemList = null;

// 先从缓存中获取

if (flag) {

dictItemList = (List<DictItem>) ehCacheService

.getCacheElement(CacheDictItemEnum.PROVINCE.getCode());

} else {

dictItemList = (List<DictItem>) ehCacheService

.getCacheElement(dictItem.getParentCode());

}

if (CollectionUtils.isEmpty(dictItemList)) {

// 缓存为空从数据库中获取

dictItemList = commonMapper.getDictItemList(dictItem);

    if (CollectionUtils.isEmpty(dictItemList)) {

throw new BizException("省份/城市信息为空,加载失败。");

} else {

        if (flag) {

// 将省份信息添加到缓存

ehCacheService.addElementTocache(CacheDictItemEnum.PROVINCE.getCode(),

dictItemList);

logger.info("从数据库中获取省份信息成功:{}", JsonUtils.list2JsonString(dictItemList));

} else {

// 将城市信息添加到缓存

ehCacheService.addElementTocache(dictItem.getParentCode(), dictItemList);

logger.info("从数据库中获取城市信息成功:{}", JsonUtils.list2JsonString(dictItemList));

}

return dictItemList;

}

} else {

    if (flag) {

logger.info("从缓存中获取省份信息成功:{}", JsonUtils.list2JsonString(dictItemList));

} else {

logger.info("从缓存中获取城市信息成功:{}", JsonUtils.list2JsonString(dictItemList));

 

}

return dictItemList;

}

}

 

@SuppressWarnings("unchecked")

@Override

public List<DictItem> getTradeTypeList(DictItem dictItem) {

List<DictItem> dictItemList = null;

try {

// 先从缓存汇总获取

dictItemList = (List<DictItem>) ehCacheService

.getCacheElement(CacheDictItemEnum.TRADE_TYPE.getCode());

    if (CollectionUtils.isEmpty(dictItemList)) {

// 从数据库中获取交易类型信息

dictItemList = commonMapper.getTradeTypeList(dictItem);

        if (CollectionUtils.isEmpty(dictItemList)) {

throw new BizException("交易类型信息为空,加载失败。");

} else {

// 将交易类型信息添加到缓存

ehCacheService.addElementTocache(CacheDictItemEnum.TRADE_TYPE.getCode(),

dictItemList);

logger.info("从数据库中获取交易类型信息成功:{}", JsonUtils.list2JsonString(dictItemList));

    return dictItemList;

}

} else {

logger.info("从缓存中获取交易类型信息成功:{}", JsonUtils.list2JsonString(dictItemList));

return dictItemList;

}

} catch (Exception e) {

logger.error("交易类型查询失败:" + e.getMessage(), e);

}

return null;

}

 

/**

* 获取响应码信息

* @param dictItem

* @return

  */

@Override

@SuppressWarnings("unchecked")

public List<DictItem> getRepCodeList(DictItem dictItem) {

List<DictItem> dictItemList = null;

try {

// 先从缓存汇总获取

dictItemList = (List<DictItem>) ehCacheService

.getCacheElement(CacheDictItemEnum.REP_CODE.getCode());

    if (CollectionUtils.isEmpty(dictItemList)) {

// 从数据库中获取响应码信息

dictItemList = commonMapper.getRepCodeList(dictItem);

        if (CollectionUtils.isEmpty(dictItemList)) {

throw new BizException("响应码信息为空,加载失败。");

} else {

// 将响应码信息放到缓存中

ehCacheService.addElementTocache(CacheDictItemEnum.REP_CODE.getCode(),

dictItemList);

logger.info("从数据库中获取响应码信息成功:{}", JsonUtils.list2JsonString(dictItemList));

    return dictItemList;

}

} else {

logger.info("从缓存中获取响应码信息成功:{}", JsonUtils.list2JsonString(dictItemList));

return dictItemList;

}

} catch (Exception e) {

logger.error("响应码查询失败:" + e.getMessage(), e);

}

return null;

}

 

@SuppressWarnings("unchecked")

@Override

public List<DictItem> getAreaList(DictItem dictItem) {

List<DictItem> dictItemList = null;

try {

    // 先从缓存中获取

dictItemList = (List<DictItem>) ehCacheService

.getCacheElement(CacheDictItemEnum.AREA_LIST.getCode());

    if (CollectionUtils.isEmpty(dictItemList)) {

// 从数据库中获取区域信息

dictItemList = commonMapper.getAreaList(dictItem);

        if (CollectionUtils.isEmpty(dictItemList)) {

throw new BizException("区域信息为空,加载失败。");

} else {

// 将区域添加到缓存

ehCacheService.addElementTocache(CacheDictItemEnum.AREA_LIST.getCode(),

dictItemList);

logger.info("从数据库中获取区域信息成功:{}", JsonUtils.list2JsonString(dictItemList));

    return dictItemList;

}

} else {

logger.info("从缓存中获取区域信息成功:{}", JsonUtils.list2JsonString(dictItemList));

return dictItemList;

}

} catch (Exception e) {

logger.error("区域信息查询失败:" + e.getMessage(), e);

}

return null;

}

 

/**

* 注解缓存测试

* @param dictItem

* @return

  */

@Cacheable(value = "ditItemCache", key = "#dictItem.code")

@Override

public List<DictItem> getCacheTest(DictItem dictItem) {

return commonMapper.getRepCodeList(dictItem);

}

}


 

7.测试

package com.yjpal.dams.common.service.impl;

 

import java.util.List;

 

import org.junit.Test;

import org.springframework.beans.factory.annotation.Autowired;

 

import com.yjpal.dams.common.service.CommonService;

import com.yjpal.dams.common.utils.JsonUtils;

import com.yjpal.dams.dbaccess.common.entity.DictItem;

import com.yjpal.dams.test.support.AbstractSpringContextTestSupport;

 

/**

* @Description: 数据字典缓存测试

* @author Jian Jang

* @version 1.0 2017年8月16日

*/

public class CommonServiceImplTest extends AbstractSpringContextTestSupport {

@Autowired

private CommonService commonService;

 

/**

* Test method for

* {@link com.yjpal.dams.common.service.impl.CommonServiceImpl#getDictItemList(com.yjpal.dams.dbaccess.common.entity.DictItem)}

* .

  */

@Test

public void testGetDictItemList() {

try {

DictItem dictItem = new DictItem();

dictItem.setLevel("1");

// dictItem.setParentCode("3300");

List<DictItem> list = commonService.getDictItemList(dictItem);

System.out.println(JsonUtils.list2JsonString(list));

list = commonService.getDictItemList(dictItem);

System.out.println(JsonUtils.list2JsonString(list));

} catch (Exception e) {

e.printStackTrace();

}

}

 

/**

* Test method for

* {@link com.yjpal.dams.common.service.impl.CommonServiceImpl#getCacheTest(com.yjpal.dams.dbaccess.common.entity.DictItem)}

* .

  */

@Test

public void testgetCacheTest() {

DictItem dictItem = new DictItem();

dictItem.setCode("cacheTest");

for (int i = 0; i < 5; i++) {

List<DictItem> list = commonService.getCacheTest(dictItem);

System.out.println(JsonUtils.list2JsonString(list));

}

 

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: