Spring Boot集成Ehcache

一. 概念

      Ehcache是一个纯Java实现的进程内缓存框架,具有快速、精干的特点,是Hibernate中默认的CacheProvider。它是一个内存+文件的缓存框架,当内存不足的时候,会将溢出的数据序列化到文件中,当在需要使用时,再反序列到内存中。所以,通过Ehcache管理的数据,必须实现Serializable接口。

      Ehcache是一个框架,既可以集成到本地应用中,做本地缓存,同样也可以独立架设。

      Ehcache的缓存空间实际上就是JVM虚拟机中的一个连续的存储空间,这个缓存空间的管理可以通过配置文件来决定,并且可以划分成若干个相互独立的空间。

二. 应用

     1. maven pom.xml中引入相关依赖   

<!-- Spring boot缓存支持启动器(针对于所有内存型缓存框架的启动器,类似于驱动。至于需要缓存什么技术,那就需要独立引入依赖了) -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- EHCache -->
<dependency>
	<groupId>net.sf.ehcache</groupId>
	<artifactId>ehcache</artifactId>
</dependency>

    2. EHCache配置文件

   如果不清楚EHCache配置文件的写法,我们可以找到ehcache的jar包,打开ehcache-failsafe.xml,这份文件详细的说明了ehcache该如何配置

   

   ehcache对配置文件的名称和路径都没有特殊要求,我放置在了resources/ehcache目录下。

   

   ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

    <!-- 配置序列化文件存储的目录路径 -->
    <diskStore path="java.io.temdir"/>

    <!-- 默认缓存区,在不指定使用哪一个缓存区的时候,使用默认缓存区
         maxElementsInMemory: 内存中最多缓存对象的数目
         timeToIdleSeconds: 空闲的对象缓存时长多少秒  (空闲指的是没有任务外部请求访问该对象)  超出指定秒数后,ehcache会将其从内存中序列化到文件
         timeToLiveSeconds: 缓存对象的生命周期(单位: 秒)
         maxElementsOnDisk: 文件中最多缓存对象的数目
         memoryStoreEvictionPolicy: 内存的缓存策略。 当内存不足时,ehcache通过相应的策略,决定序列化哪些对象。
               1. LRU(Least Recently Used)
                  最近最少使用。把最近(单位时间)内,使用频率最少的对象从内存中序列化存储到文件内,从内存中腾出空间供新对象缓存使用。
               2. LFU(Least Frequently Used)
                  最不经常使用 一段时间内,使用次数最少的对象从内中存序列化存储到文件内。
               3. FIFO(First In First Out)
                  先进先出
               注意,LRU和LFU的概念容易混淆。它们都会在单位时间内分析一个对象的去留,但LRU关心的是最后一次操作的时间距离当前准备时间的时长,而LFU针对的是使用次数。
               比如,通过考虑当前1小时内的执行情况,决定缓存中对象A和对象B的去留。
               若对象A在前10分钟被操作了1万次,在后50分钟没有被操作。对象B每隔10分钟就会被操作一次,并且在距离当前的前1分钟还被操作过一次。
               因此,
               若使用LRU,侧重于观察最后一次执行的时间距离当前时间的时长。显然,对象B保留,对象A序列化到文件内,并从内存中移除。
               若使用LFU,侧重于观察单位时间内的执行次数,显然,对象A保留,对象B序列化到文件内,并从内存中移除。
    -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="200"
        maxElementsOnDisk="50000"
        diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU"
    >
        <persistence strategy="localTempSwap"/>
    </defaultCache>

    <!-- 自定义缓存区,可以通过name命名指定使用的缓存区 -->
    <cache name="myCustomCache"
           maxElementsInMemory="10000"
           eternal="false"
           timeToIdleSeconds="120"
           timeToLiveSeconds="200"
           maxElementsOnDisk="50000"
           diskExpiryThreadIntervalSeconds="120"
           memoryStoreEvictionPolicy="LRU"
    >
        <persistence strategy="localTempSwap"/>
    </cache>
</ehcache>

 3. application.properties全局配置文件中添加ehcache相关配置

spring.cache.ehcache.config=classpath:ehcache/ehcache.xml

4. main启动器中配置

@SpringBootApplication
@EnableCaching //代表Spring应用是否开启缓存策略
public class AppStarter {
    public static void main(String[] args) {
        SpringApplication.run(AppStarter.class, args);
    }
}

5. 业务代码中的应用

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 缓存一般用于查询操作
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    /**
     * @Cacheable 注解
     * 描述类: 代表当前类中所有有返回值的方法,返回的数据都缓存
     * 描述方法: 代表当前方法的返回值缓存
     * 注解属性:
     *      1. value: 使用的是哪个缓存区。   缓存区的名称在ehcache配置文件中通过name属性定义。如果不定义,默认使用defaultCache
     *      2. key: 缓存区中保存缓存数据的唯一标志,默认为空。如果不定义key,EHCache有特殊的定义方式,确保不同对象的key不重复。
     *              如果方法有参数,EHCache会使用参数数据作为key,如果方法无参数,EHCache会根据方法的命名来生成一个唯一的GUID作为key
     *              赋值可以使用SpringEL表达式
     *      3. condition: 生效条件。当数据为true时,代表缓存。可以使用SpringEL表达式来赋值。
     */

    @Override
    @Cacheable(value = "myCustomCache", key = "'allUsers'") //由于是将一个固定的字符串作为key,因此要在字符串周围加上'',否则会被当成SpringEL表达式来解析
    public List<User> findAll() {
        return userDao.findAll();
    }

    @Override
    @Cacheable(value = "myCustomCache", key="#page+#size") //比如传入的是findByPage(1,3) 那么存入缓存时的key就是13   这样便保证了key的不同
    public Page<User> findByPage(int page, int size) {
        Pageable pageable = new PageRequest(page-1, size);

        return this.userDao.findAll(pageable);
    }

    @Override
    @Cacheable(value = "myCustomCache", key="'#id'", condition = "#id < 3") //当且仅当id小于3时才会缓存数据
    public User findById(Long id) {
        return this.userDao.findOne(id);
    }

    /**
     * @CacheEvict
     * 管理缓存。描述了在何时需要清理缓存的哪些对象
     * 注解属性:
     *      1. value: 指定缓存区,默认为defaultCache缓存区。
     *      2. key: 清理 哪一个缓存对象。 默认为空,代表不清理任何缓存对象
     *      3. allEntries: 是否清理缓存中的所有对象  true|false  默认为false
     *      4. condition: 满足时才清理缓存
     */
    @Override
    @CacheEvict(value= "myCustomCache", key="'allUsers'") //清理key为"allUsers"的缓存区
    public void saveOrUpdate(User user) {
        this.userDao.save(user);
    }

    @Override
    @CacheEvict(value = "myCustomCache", allEntries=true) //清理所有对象  (所以就没必要写key了)
    public void deleteById(Long id) {
        this.userDao.delete(id);
    }

}
发布了45 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/miaomiao19971215/article/details/90345904