缓存方案一:EhCache

EhCache

EhCache是十分流行的开源缓存框架,解决了关系数据系统数据提取的高花费、高延时问题。
Ehcache 属于轻量级框架,内含持久化机制,保证JVM和服务器重启后数据不会丢失。
Hibernate和Liferay的默认缓存策略就是用Ehcache。

Spring Cache

Spring Cache核心就是对某个方法进行缓存,其实质就是缓存该方法的返回结果,并把方法参数和结果用键值对的方式存放到缓存中,当再次调用该方法使用相应的参数时,就会直接从缓存里面取出指定的结果进行返回。
配置方法

  • 基于注解的配置
    配置Spring对注解Cache的支持,我们需要在Spring配置文件中添加Cache命名空间,然后通过<cache:anotation-driven/>
    就可以启动Spring对注解Cache的支持。
    其中<cache:anotation-driven/>有一个mode属性,可以选择值proxy和aspectj。默认使用proxy。当mode为proxy时,只有缓存方法在外部被调用的时候才会生效。这也就意味着如果一个缓存方法在一个对象的内部被调用SpringCache是不会发生作用的。而mode为aspectj时,就不会有这种问题了。另外使用proxy的时候,只有public方法上的@Cacheable才会发生作用。如果想非public上的方法也可以使用那么就把mode改成aspectj。
  • 基于XML的配置
<!-- 指定了将findById和find方法缓存到users中 -->
<cache:advice id="cacheAdvice" cache-manager="cacheManager">  
      <cache:caching cache="users">  
         <cache:cacheable method="findById" key="#p0"/>  
         <cache:cacheable method="find" key="#user.id"/>  
         <cache:cache-evict method="deleteAll" all-entries="true"/>  
      </cache:caching>  
</cache:advice>  

Spring Boot:EhCache

依赖配置

<!-- 缓存支持 -->
<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Ehcache 2.x -->
<dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.10.6</version>
</dependency>
<!-- Ehcache 3.x:已经迁移到org-->
<dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>3.6.3</version>
</dependency>

ehcache.xml:spring boot 默认在 resources 目录下扫描到 ehcache

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd">
    <!--timeToIdleSeconds 当缓存闲置n秒后销毁 -->
    <!--timeToLiveSeconds 当缓存存活n秒后销毁 -->
    <!-- 磁盘缓存位置 -->
    <diskStore path="java.io.tmpdir" />
    <!-- 默认缓存 -->
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">

        <persistence strategy="localTempSwap" />
    </defaultCache>
    <!-- 自定义缓存 -->
    <cache name="fpcache"
           eternal="false"
           timeToIdleSeconds="2400"
           timeToLiveSeconds="2400"
           maxEntriesLocalHeap="10000"
           maxEntriesLocalDisk="10000000"
           diskExpiryThreadIntervalSeconds="120"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LRU">
    </cache>
</ehcache>

自定义缓存配置:可包含多个cache节点

 * name : 缓存的名称,可以通过指定名称获取指定的某个Cache对象
 * maxElementsInMemory :内存中允许存储的最大的元素个数,0代表无限个
 * clearOnFlush:内存数量最大时是否清除。
 * eternal :设置缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。根据存储数据的不同,例如一些静态不变的数据如省市区等可以设置为永不过时
 * timeToIdleSeconds : 设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
 * timeToLiveSeconds :缓存数据的生存时间(TTL),也就是一个元素从构建到消亡的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。
 * overflowToDisk :内存不足时,是否启用磁盘缓存。
 * maxEntriesLocalDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
 * maxElementsOnDisk:硬盘最大缓存个数。
 * diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
 * diskPersistent:是否在VM重启时存储硬盘的缓存数据。默认值是false。
 * diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。

ehcache清空缓存

  • FIFO,先进先出
  • LFU,最少被使用,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
  • LRU,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。

创建缓存管理器

InputStream in = EhCache2.class.getClassLoader().getResourceAsStream("ehcache1.xml");
CacheManager cacheManager = CacheManager.create(in);  

创建缓存实例

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

缓存与取值

//键
String key = "greeting";  
String key1 = "greeting1";
//将数据放入到缓存实例中  
cache.put(new Element(key, "Hello, World!"));  
cache.put(new Element(key1, "Hello, World1!"));
//取值  
Cache cache2 = cacheManager.getCache("helloworld1");  
final Element getGreeting = cache2.get(key); 
final Element getGreeting1 = cache2.get(key1);

Hibernate ehcache

依赖配置

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.0.2.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-ehcache</artifactId>
    <version>5.0.2.Final</version>
</dependency>

ehcache.xml
指定二级缓存存放在磁盘上的位置,可以使用磁盘目录或者Java System Property目录(user.home用户目录、user.dir用户当前工作目录、java.io.tmpdir默认临时文件路径)。

<ehcache>  
   <diskStore path="java.io.tmpdir/cache"/>

  <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true" />

  <!--可以给每个实体类指定一个配置文件,name属性指定并使用类全名-->
    <cache name="com.test.entity.User"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true" />

    <cache name="example"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"/>
</ehcache>

Hibernate二级缓存

  • Hibernate缓存首先根据entity实体的region到ehcache的缓存区域查找缓存(region对应ehcache配置中name字段);如果找不到,继续使用entity的全类名来查找缓存;如果还找不到,则使用default设置。
  • Hibernate的二级缓存默认只根据ID进行缓存,也就是使用get/load方法会将查询对象缓存,如果需要对HQL或SQL进行缓存,则需要在代码中指定setCacheable(true)。
  • 查询缓存所缓存的key值就是查询所使用的HQL或SQL语句,需要注意的是:查询缓存不仅要求所使用的HQL语句、SQL语句相同,甚至是要求所传入的参数也相同,Hibernate才能从缓存中查去数据。
  • 在query中设置query.setCacheable(true)之后,所有被标记为可缓存的对象都会被缓存下来,所以在第二次查询User时,可直接命中二级缓存,无需发出SQL查询。

Hibernate缓存配置
xml配置或者properties配置。

<!-- 开启二级缓存 -->
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<!-- 开启查询缓存 -->
<prop key="hibernate.cache.use_query_cache">true</prop>
<!-- 高速缓存提供程序 -->
<!-- Hibernate4.0 以前使用该设置<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop>-->
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>
#Spring Boot + Hibernate基于JpaRepository的查询缓存配置
#打开hibernate统计信息
spring.jpa.properties.hibernate.generate_statistics = true

#打开二级缓存
spring.jpa.properties.hibernate.cache.use_second_level_cache = true

#打开查询缓存
spring.jpa.properties.hibernate.cache.use_query_cache = true

#指定缓存provider
spring.jpa.properties.hibernate.cache.region.factory_class = org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory

#配置shared-cache-mode
spring.jpa.properties.javax.persistence.sharedCache.mode = ENABLE_SELECTIVE

接口方法加上@QueryHints注解

@Query("from UserAddress where receiveAddress like %:receiveAddress%")
@QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value ="true") })  // 使用查询缓存
public List<UserAddress> findList(@Param("receiveAddress") String receiveAddress);

EhCache注解

@Cacheable

  • 标记在方法时,表示该方法是支持缓存的。
  • 标记在类时,表示该类所有的方法都支持缓存。
  • @Cacheable可以指定三个属性,value(缓存的名称,与 ehcache.xml 中的缓存名称一致)、key(指定Spring缓存方法的返回结果所对应的key)和condition(指定发生的条件)。
// 根据条件判断是否缓存 返回值存在 user.id中,但只有当 user.id 是 2 的倍数才会缓存
@Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")
public User find(User user) {
    System.out.println("find user by user " + user);
    return user;
}

@CachePut
@CachePut 可以标注在类上或方法上,只要标注了 @CachePut ,表示每次都会自行此方法,而不管是否已经有缓存存在。参数同@Cacheable一样。

@CacheEvict
@CacheEvict用于清除缓存。
@CacheEvict 可以指定的属性有value、key、condition、allEntries 和beforeInvocation。
allEntries=true 表示清除所有的对象,不管有没有指定 key 属性。
beforeInvocation=true在调用方法前清除所有缓存。

@Caching
@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解,其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。

@CacheConfig
通过@CacheConfig统一指定缓存的名字。
所有的@Cacheable()里面都有一个value=“xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完 那就省事了

小结

使用EhCache缓存,有两种添加缓存的方式,即基于CacheManagerh缓存管理器和注解。我们要成功使用注解,基本流程为:添加依赖->创建ehcache.xml文件,配置缓存位置和缓存策略->配置缓存,如是否启动二级缓存->基于注解,可创建通用缓存service实现类,重写增删改查方法,方法上面使用注解->基于CacheManagerh,除开通用的增删改查方法,一些独特的接口也需要操作缓存,可以封装缓存操作方法,如getCache,setCache,clearCache,exist方法等。

@Autowired
CacheManager cacheManager;
Cache cache = cacheManager.getCache(cacheName);		//根据缓存名称获取缓存
ValueWrapper e = cache.get(id);						//根据键值如id,获取值。ValueWrapper 为List集合
cache.put(id, content);								//根据缓存名称和id,设置缓存
cache.evict(id);									//根据缓存名称和id,删除缓存
cache.clear();									 	//根绝缓存名称,清空缓存

参考:
GO
GO
GO
GO

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值