spring boot 集成 ehCache

说明

       今天在作统计报表的时候,考虑到数据比较多,因此在项目中集成ehCache减轻数据库请求压力。看似简单,网上参考也比较多,可是还遇到了几处坑,在此记录一下。 ⊙﹏⊙bjava

随手笔记,比较简单,想要具体了解的能够网上看看大神的博客spring

问题

    (1)、springboot集成了ehcache,配置了过时时间timeToIdleSeconds,发现就是不生效,问度娘后才知道须要在properties文件中指定缓存类型,否则spring boot 使用默认SimpleCacheConfiguration,不是用的ehcache。数据库

   (2)、测试的时候第一次请求接口返回正常数据,第二次查询缓存的时候会报java.io.Serializable这个错,是由于我返回的实体类没作序列化。缓存

               解决方案在下面springboot

一、首先引入依赖在pom.xml文件中

<!--开启 cache 缓存-->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-cache</artifactId>
      </dependency>
      <!-- ehcache 缓存 -->
      <dependency>
          <groupId>net.sf.ehcache</groupId>
          <artifactId>ehcache</artifactId>
      </dependency>

二、引入配置文件 ehcache.xml(本身手残名字写错ehcach,致使启动报错,加载不到配置,懵逼。。。。。)

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
    <diskStore path="java.io.tmpdir"/>
  <!--defaultCache:echcache的默认缓存策略  -->
  <!--
        缓存配置
           diskStore:指定数据在磁盘中的存储位置。
           name:缓存名称。
           defaultCache:当借助CacheManager.add("demoCache")建立Cache时,EhCache便会采用<defalutCache/>指定的的管理策略,如下属性是必须的:
           maxElementsInMemory:缓存最大个数。
           eternal:对象是否永久有效,一但设置了,timeout将不起做用。
           timeToIdleSeconds:设置对象在失效前的容许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
           timeToLiveSeconds:设置对象在失效前容许存活时间(单位:秒)。最大时间介于建立时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
           overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
           diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每一个Cache都应该有本身的一个缓冲区。
           maxElementsOnDisk:硬盘最大缓存个数。
           diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
           diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
           memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你能够设置为FIFO(先进先出)或是LFU(较少使用)。
           clearOnFlush:内存数量最大时是否清除。
    -->
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </defaultCache>
    <cache name="userCache"
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </cache>
</ehcache>

三、在properties文件中指定缓存类型和加载xml,也就是我上面说的问题 ”(1)“。xml也能够用@ImportResource注解直接在spring boot启动类配置。

spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:META-INF/mybatis/ehcache.xml

四、在spring boot 启动类也要开启缓存注解@EnableCaching,不然缓存不生效。以下

 

五、以上集成工做已经完成,那如何在代码中使用呢? 以下mybatis

/**
	 * 查询请求记录数据统计
	 * 
	 * @param docNos
	 * @return
	 */
	@Cacheable(key = "#startDate+'-'+#endDate+'-'+#type",value="userCache")
	public ResponseMessage<List<Map<String, Object>>> selectReport(String startDate, String endDate, String docTemplateCode,String type) {
		ResponseMessage<List<Map<String, Object>>> rsdto = new ResponseMessage<>();
		List<Map<String, Object>> list=new ArrayList<>();
		if(StringUtils.isBlank(startDate) || StringUtils.isBlank(endDate)) {
			ResponseUtil.setResult(rsdto, null, ErrorCodeEnum.PARAMERROR, false);
			return rsdto;
		}
		/*if(StringUtils.isBlank(docTemplateCode)) {
			ResponseUtil.setResult(rsdto, null, ErrorCodeEnum.PARAMERROR, false);
			return rsdto;
		}*/
		if(StringUtils.isBlank(type)) {
			ResponseUtil.setResult(rsdto, null, ErrorCodeEnum.PARAMERROR, false);
			return rsdto;
		}
		Integer length=0;
		try {
		    length= ReportTypeEnum.getEnum(type).getValue();
		    list=docRecordTunnel.selectReportByDateTime(startDate, endDate, docTemplateCode, length);
			ResponseUtil.setResult(rsdto, list, ErrorCodeEnum.SUCCESS,true);
		} catch (Exception e) {
			log.error("DocRecordController.selectReport查询失败", e);
			ResponseUtil.setResult(rsdto, null, ErrorCodeEnum.ERROR, false);
		}
		return rsdto;
	}

 

注: 返回的实体类须要作序列化,不然查询缓存的时候会报错。以下图spring-boot

 

通常状况下,咱们在Sercive层进行对缓存的操做。先介绍 Ehcache 在 Spring 中的注解:
* @Cacheable : Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,若是存在就再也不执行该方法,而是直接从缓存中获取结果进行返回,不然才会执行并将返回结果存入指定的缓存中。
* @CacheEvict : 清除缓存。 
* @CachePut : @CachePut也能够声明一个方法支持缓存功能。使用@CachePut标注的方法在执行前不会去检查缓存中是否存在以前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。 测试

简单来讲,Cacheable 通常用于查询,CacheEvict 用于新增清除缓存,CachePut 用于更新;其中,value 指的是 ehcache.xml 中的缓存策略空间;key 指的是缓存的标识,同时能够用 # 来引用参数。上面代码引用参数为多个组合做为缓存key 。spa

五、启动项目,测试结果。具体代码我就再也不贴了。