(十八)Spring Boot 缓存【Ehcache 2.x 缓存】


     Ehcache 缓存在 Java 开发领域己是久负盛吗名,在 Spring Boot 中,只需要一个配置文 就可以将 Ehcache 集成到项目中。
  1. 创建项目,添加缓存依赖
<dependency>
 	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>
  1. 添加缓存配置文件
<ehcache>
    <diskStore path="java.io.tmpdir/cache"/>
        <defaultCache
                maxElementsInMemory="1000"
                eternal="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                overflowToDisk="false"
                diskPersistent="false"
                diskExpiryThreadIntervalSeconds="600"
        />
    <cache name="book cache"
           maxElementsInMemory="1000"
           eternal="true"
           timeToIdleSeconds="120"
           timeToLiveSeconds="120"
           overflowToDisk="true"
           diskPersistent="true"
           diskExpiryThreadIntervalSeconds="600"/>
</ehcache>

     这是一个常规的 Ehcache 配置文件,提供了两个缓存策略, 一个是默认的,另一个名为 book_cache 。

  • name 表示缓存名称;
  • maxElementsInMemory 表示缓存最大个数;
  • eternal 表示缓存对象是否永久有效,一旦设置了永久有效,timeout 不起作用
  • timeToIdleSeconds 表示缓存对象在失效前的允许闲置时间(单位 :秒),当 eternal=false 对象不是永久有效时,该属性才生效;
  • timeToLiveSeconds 表示缓存对象在失效前允许存活的时间(单位 :秒),当 eternal=false 对象不是永久有效时,该属性才生效;
  • overflowToDisk 表示当内存中的对象数量达到 maxElementsInMemory 时, Ehcache 是否将对象写到磁盘中;
  • diskExpiryThreadIntervalSeconds 表示磁盘失效线程运行时间间隔。

如果开发者想自定义 Ehcache 配置文件的名称和位置,可以在 application.properties 中添加如下配置:

spring.cache.ehcache.config=classpath:config/another_config.xml
  1. 开启缓存
@SpringBootApplication
@EnableCaching
public class EhcacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(EhcacheApplication.class, args);
    }
}
  1. 创建 实体类、BookDao
public class Book implements Serializable {
    private Integer id;
    private String name;
    private String author;
	//省略get/set方法
}
@Repository
//指明使用的缓存的名字 这个配直可选,若不使用 @CacheConfig 注解,则直接在 @Cacheable 注解中指明缓存名字
@CacheConfig(cacheNames = {"book_cache" })
public class BookDao {

    @Cacheable
    public Book getBookById(Integer id) {
        System.out.println("getBookById");
        Book book = new Book();
        book.setId(id);
        book.setName("三国演义");
        book.setAuthor("罗贯中");
        return book;
    }

    @CachePut(key = "#book.id")
    public Book updateBookById(Book book) {
        System.out.println("updateBookById");
        book.setName("三国演义2");
        return book;
    }

    @CacheEvict(key = "#id")
    public void deleteBookById(Integer id) {
        System.out.println("deleteBookById");
    }
}
  • @Cacheable:表示对该方法进行缓存,默认情况 ,缓存的 key 是方法的参数,缓存的 value 是方法的返回值当开发者在其他类中调用该方法时,首先会根据调用参数查看缓存中是否有相关数据,若有,则直接使用缓存数据,该方法不会执行,否则执行该方法,执行成功后将返回值缓存起来,但若是在当前类中调用该方法,则缓存不会生效。
  • @Cacheable 注解中还有一个属性 condition 用来描述缓存的执行时机,例如
    @Cacheable(condition ="#id%2=0") 表示当 id 对2 取模为 0 时才进行缓存,否则不缓存。
  • 如果开发者不想使用默认的 key ,也可以像 @CachePut(key = "#book.id")@CacheEvict(key = "#id")一样自定义 key ,@CachePut(key = "#book.id")表示存的 key 为参数 book 对象中 id 的值,@CacheEvict(key = "#id")表示缓存 key 为参数 id。除了这种使用参数定义 key 的方式之外,Spring 还提供了 root 对象用来生成 key ,如表所示:
    在这里插入图片描述
  • 如果这些 key 不能够满足开发需求, 开发者也可以自定义缓存 key 的生成器 KeyGenerator。
@Component
public class MyKeyGenerator implements KeyGenerator {
    @Override
    public Object generate(Object o, Method method, Object... objects) {
        return Arrays.toString(objects);
    }
}
@Repository
//指明使用的缓存的名字 这个配直可选,若不使用 @CacheConfig 注解,则直接在 @Cacheable 注解中指明缓存名字
@CacheConfig(cacheNames = {"book_cache" })
public class BookDao {

    @Autowired
    MyKeyGenerator myKeyGenerator;

    @Cacheable(keyGenerator = "myKeyGenerator")
    public Book getBookById(Integer id) {
        System.out.println("getBookById");
        Book book = new Book();
        book.setId(id);
        book.setName("三国演义");
        book.setAuthor("罗贯中");
        return book;
    }
}

自定义 MyKeyGenerator 实现 KeyGenerator 接口,然后实现该接口中的 generate 方法,该方法的三个参数分别是当前对象、当前请求的方法以及方法的参数,开发者可根据这些信息组成一个新的 key 返回,返回值就是缓存的 key ,然后在 @Cacheable 注解中引用 MyKeyGenerator 实例即可。

  • @CachePut 注解一般用于数据更新方法上,与@Cacheable 解不同,添加了@CachePut 注解的方法每次在执行时都不去检查缓存中是否有数据,而是直接执行方法,然后将方法的执行结果缓存起来,如果该 key 对应的数据已经被缓存起来了,就会覆盖之前的数据,这样可以避免再次加载数据时获取到脏数据,同时,@CachePut 具有和@Cacheable 似的属性。
  • @CacheEvict 注解一般用于删除方法上,表示移除一个key对应的缓存。@CacheEvict 注解有两个特殊的属性: allEntries 和 beforelnvocation ,其中 allEntries 表示是否将所有的缓存数据都移除, 默认为 false,beforelnvocation 表示是否在方法执行之前移除缓存中的数据,默认为 false ,即在方法执行之后移除缓存中的数据。
  1. 创建测试类
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class EhcacheApplicationTest {

    @Autowired
    BookDao bookDao;

    @Test
    public void contextLoads() {
        bookDao.getBookById(1);
        bookDao.getBookById(1);
        bookDao.deleteBookById(1);
        Book b3 = bookDao.getBookById(1);
        System.out.println("b3: " + b3);
        Book b = new Book();
        b.setName("三国演义");
        b.setAuthor("罗贯中");
        b.setId(1);
        bookDao.updateBookById(b);
        Book b4 = bookDao.getBookById(1);
        System.out.println("b4: " + b4);
    }
}

在这里插入图片描述
     一开始执行了两个查询,但是查询方法只打印了一次,因为第二次使用了缓存。接下来执行了删除方法,删除方法执行完之后再次执行查询, 询方法又被执行了,因为在删除方法中缓存己经被删除了 。再接下来执行更新方法,更新方法中不仅更新数据,也更新了缓存,所以在最后的查询方法中,查询方法的日志没打印,说明该方法没执行,而是使用了缓存中的数据,而缓存中的数据已经被更新了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值