【Spring Boot】Ehcache2.x缓存实战总结

最近猫哥在研究SpringBoot缓存,在这里对SpringBoot的Ehcache2.x缓存做一个总结梳理,顺便贴一下自己写的实战代码,以供参考。

SpringBoot缓存

Spring3.1中开始对缓存提供支持,核心思路是对方法的缓存,当开发者调用一个方法时,将方法的参数和返回值作为key/value缓存起来,当再次调用该方法时,如果缓存中有数据,就直接从缓存中获取,否则再去执行该方法。但是,Spring中未提供缓存的实现,而是提供了一套缓存API,开发者可以自由选择缓存的实现,目前SpringBoot支持的缓存有如下几种:

  • JCache(JSR-107)
  • EnCache2.x
  • Hazelcast
  • Infinispan
  • Couchbase
  • Redis
  • Caffeine
  • Simple

这里主要介绍目前常用的缓存实现之一:EnCache2.x。由于Spring早已将缓存领域统一,因此无论使用哪种缓存实现,不同的只是缓存配置,开发者使用的缓存注解是一致的。

EnCache2.x缓存

在SpringBoot中,EnCache2.x缓存的使用十分常见,实现也比较容易,只需一个配置文件就可以将EnCache集成到项目中。EnCache2.x的使用具体步骤如下。

  1. 创建项目,添加依赖

    创建Spring Boot项目,添加spring-boot-starter-cache依赖以及Encache依赖,代码如下:

    
    <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>

     

  2. 添加缓存配置文件

    如果Encache的依赖存在,并且在classpath下面有一个名为encache.xml的Encache的配置文件,那么EnCacheCacheManager会自动作为缓存的实现。因此,在resources目录下创建encache.xml文件作为Encache缓存的配置文件,代码如下:
     

    
    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache>
        <diskStore path="java.io.tmpdir/cache"/>
        <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            />
        <cache name="book_cache"
               maxElementsInMemory="10000"
               eternal="true"
               timeToIdleSeconds="120"
               timeToLiveSeconds="120"
               overflowToDisk="true"
               diskPersistent="true"
               diskExpiryThreadIntervalSeconds="600"
            />
    </ehcache>

    这是一个常规的Encache配置文件,提供了两个缓存策略,一个是默认的,一个是名为book_cache。另外,如果你想自定义Encache配置文件的名称和位置,可以在application.properties中添加如下配置:
     

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

     

  3. 开启缓存
    在项目的入口类上添加@EnableCaching注解开启缓存,代码如下:

    
    @SpringBootApplication
    @EnableCaching
    public class MavenprojectApplication {
        public static void main(String[] args) {
            SpringApplication.run(MarvenprojectApplication.class, args);
        }
    }

     

  4. 创建Book实体类和BookService,代码如下:
     

    
    public class BookBean implements Serializable {
    
        private Integer id;
    
        private String name;
    
        private String author;
    
        public Integer getId() {
            return id;
        }
    
        public String getName() {
            return name;
        }
    
        public String getAuthor() {
            return author;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    }
    
    @Repository
    @CacheConfig(cacheNames = "book_cache")
    public class BookDao {
        @Cacheable
        public BookBean getBookById(Integer id){
            System.out.println("getBookById");
            BookBean book = new BookBean();
            book.setId(id);
            book.setName("三国演义");
            book.setAuthor("罗贯中");
            return book;
        }
    
        @CachePut(key = "#book.id")
        public BookBean updateBookById(BookBean book){
            System.out.println("updateBookById");
            book.setName("三国演义2");
            return book;
        }
    
        @CacheEvict(key = "#id")
        public void deleteBookById(Integer id){
            System.out.println("deleteBookById");
        }
    }


    ps:相对的@CacheEvict标注在需要清除缓存元素的方法或类上。

  5. 创建测试类
    创建测试类,对Service中的方法进行测试,代码如下:

     

     

    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class CacheApplicationTests {
        @Autowired
        BookDao bookDao;
        @Test
        public void contextLoads(){
            bookDao.getBookById(1);
            bookDao.getBookById(1);
            bookDao.deleteBookById(1);
    
            BookBean b3 = bookDao.getBookById(1);
            System.out.println("b3:"+b3.getName());
    
            BookBean b = new BookBean();
            b.setName("三国演义2");
            b.setAuthor("罗贯中");
            b.setId(1);
            bookDao.updateBookById(b);
    
            BookBean b4 = bookDao.getBookById(1);
            System.out.println("b4:"+b4.getName());
        }
    }

    ps:使用注解@RunWith(SpringRunner.class),需要首先在pom中引入依赖:
     

    
    <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
    </dependency>
    <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>5.2.2.RELEASE</version>
                <scope>compile</scope>
    </dependency>

     

  6. 最后执行测试类,得到打印日志

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章