查看原文
其他

Spring Boot 集成 Ehcache 缓存,三步搞定!

点击上方 "程序员小乐"关注, 星标或置顶一起成长

每天凌晨00点00分, 第一时间与你相约

每日英文

Don't ask why people keep hurting you. Ask yourself why are you allowing it to happen.

不要疑惑为什么别人会一直伤害你,问问你自己为何你一直允许这种事情发生。


每日掏心

累不是一种无能,而是一种担当。累了,因为你懂了。你也知道,只要你后退,甚至彻底放弃,你就不会再累了。


来自:谭朝红 | 责编:乐乐

链接:ramostear.com/articles/spring_boot_ehcache.html

程序员小乐(ID:study_tech)第 702 次推文   图片来自网络


往日回顾:必会的44个Java性能优化细节!将性能优化一网打尽!看了都说好!



   正文   


本次内容主要介绍基于Ehcache 3.0来快速实现Spring Boot应用程序的数据缓存功能。在Spring Boot应用程序中,我们可以通过Spring Caching来快速搞定数据缓存。


接下来我们将介绍如何在三步之内搞定 Spring Boot 缓存。

1. 创建一个Spring Boot工程

你所创建的Spring Boot应用程序的maven依赖文件至少应该是下面的样子:
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  4. <modelVersion>4.0.0</modelVersion>

  5. <parent>

  6. <groupId>org.springframework.boot</groupId>

  7. <artifactId>spring-boot-starter-parent</artifactId>

  8. <version>2.1.3.RELEASE</version>

  9. <relativePath/> <!-- lookup parent from repository -->

  10. </parent>

  11. <groupId>com.ramostear</groupId>

  12. <artifactId>cache</artifactId>

  13. <version>0.0.1-SNAPSHOT</version>

  14. <name>cache</name>

  15. <description>Demo project for Spring Boot</description>


  16. <properties>

  17. <java.version>1.8</java.version>

  18. </properties>


  19. <dependencies>

  20. <dependency>

  21. <groupId>org.springframework.boot</groupId>

  22. <artifactId>spring-boot-starter-cache</artifactId>

  23. </dependency>

  24. <dependency>

  25. <groupId>org.springframework.boot</groupId>

  26. <artifactId>spring-boot-starter-web</artifactId>

  27. </dependency>

  28. <dependency>

  29. <groupId>org.ehcache</groupId>

  30. <artifactId>ehcache</artifactId>

  31. </dependency>

  32. <dependency>

  33. <groupId>javax.cache</groupId>

  34. <artifactId>cache-api</artifactId>

  35. </dependency>

  36. <dependency>

  37. <groupId>org.springframework.boot</groupId>

  38. <artifactId>spring-boot-starter-test</artifactId>

  39. <scope>test</scope>

  40. </dependency>

  41. <dependency>

  42. <groupId>org.projectlombok</groupId>

  43. <artifactId>lombok</artifactId>

  44. </dependency>

  45. </dependencies>


  46. <build>

  47. <plugins>

  48. <plugin>

  49. <groupId>org.springframework.boot</groupId>

  50. <artifactId>spring-boot-maven-plugin</artifactId>

  51. </plugin>

  52. </plugins>

  53. </build>


  54. </project>

依赖说明:

  • spring-boot-starter-cache为Spring Boot应用程序提供缓存支持

  • ehcache提供了Ehcache的缓存实现

  • cache-api 提供了基于JSR-107的缓存规范

2. 配置Ehcache缓存

现在,需要告诉Spring Boot去哪里找缓存配置文件,这需要在Spring Boot配置文件中进行设置:
  1. spring.cache.jcache.config=classpath:ehcache.xml

然后使用@EnableCaching注解开启Spring Boot应用程序缓存功能,你可以在应用主类中进行操作:

  1. package com.ramostear.cache;


  2. import org.springframework.boot.SpringApplication;

  3. import org.springframework.boot.autoconfigure.SpringBootApplication;

  4. import org.springframework.cache.annotation.EnableCaching;


  5. @SpringBootApplication

  6. @EnableCaching

  7. public class CacheApplication {


  8. public static void main(String[] args) {

  9. SpringApplication.run(CacheApplication.class, args);

  10. }

  11. }

接下来,需要创建一个 ehcache的配置文件,该文件放置在类路径下,如resources目录下:
  1. <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  2. xmlns="http://www.ehcache.org/v3"

  3. xmlns:jsr107="http://www.ehcache.org/v3/jsr107"

  4. xsi:schemaLocation="

  5. http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd

  6. http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">

  7. <service>

  8. <jsr107:defaults enable-statistics="true"/>

  9. </service>


  10. <cache alias="person">

  11. <key-type>java.lang.Long</key-type>

  12. <value-type>com.ramostear.cache.entity.Person</value-type>

  13. <expiry>

  14. <ttl unit="minutes">1</ttl>

  15. </expiry>

  16. <listeners>

  17. <listener>

  18. <class>com.ramostear.cache.config.PersonCacheEventLogger</class>

  19. <event-firing-mode>ASYNCHRONOUS</event-firing-mode>

  20. <event-ordering-mode>UNORDERED</event-ordering-mode>

  21. <events-to-fire-on>CREATED</events-to-fire-on>

  22. <events-to-fire-on>UPDATED</events-to-fire-on>

  23. <events-to-fire-on>EXPIRED</events-to-fire-on>

  24. <events-to-fire-on>REMOVED</events-to-fire-on>

  25. <events-to-fire-on>EVICTED</events-to-fire-on>

  26. </listener>

  27. </listeners>

  28. <resources>

  29. <heap unit="entries">2000</heap>

  30. <offheap unit="MB">100</offheap>

  31. </resources>

  32. </cache>

  33. </config>

最后,还需要定义个缓存事件监听器,用于记录系统操作缓存数据的情况,最快的方法是实现CacheEventListener接口:

  1. package com.ramostear.cache.config;


  2. import org.ehcache.event.CacheEvent;

  3. import org.ehcache.event.CacheEventListener;

  4. import org.slf4j.Logger;

  5. import org.slf4j.LoggerFactory;


  6. /**

  7. * @author ramostear

  8. * @create-time 2019/4/7 0007-0:48

  9. * @modify by :

  10. * @since:

  11. */

  12. public class PersonCacheEventLogger implements CacheEventListener<Object,Object>{


  13. private static final Logger logger = LoggerFactory.getLogger(PersonCacheEventLogger.class);


  14. @Override

  15. public void onEvent(CacheEvent cacheEvent) {

  16. logger.info("person caching event {} {} {} {}",

  17. cacheEvent.getType(),

  18. cacheEvent.getKey(),

  19. cacheEvent.getOldValue(),

  20. cacheEvent.getNewValue());

  21. }

  22. }

3. 使用@Cacheable注解

要让Spring Boot能够缓存我们的数据,还需要使用@Cacheable注解对业务方法进行注释,告诉Spring Boot该方法中产生的数据需要加入到缓存中:

  1. package com.ramostear.cache.service;

  2. import com.ramostear.cache.entity.Person;

  3. import org.springframework.cache.annotation.Cacheable;

  4. import org.springframework.stereotype.Service;


  5. /**

  6. * @author ramostear

  7. * @create-time 2019/4/7 0007-0:51

  8. * @modify by :

  9. * @since:

  10. */

  11. @Service(value = "personService")

  12. public class PersonService {


  13. @Cacheable(cacheNames = "person",key = "#id")

  14. public Person getPerson(Long id){

  15. Person person = new Person(id,"ramostear","ramostear@163.com");

  16. return person;

  17. }

  18. }

通过以上三个步骤,我们就完成了Spring Boot的缓存功能。接下来,我们将测试一下缓存的实际情况。

4. 缓存测试

为了测试我们的应用程序,创建一个简单的Restful端点,它将调用PersonService返回一个Person对象:
  1. package com.ramostear.cache.controller;


  2. import com.ramostear.cache.entity.Person;

  3. import com.ramostear.cache.service.PersonService;

  4. import org.springframework.beans.factory.annotation.Autowired;

  5. import org.springframework.http.HttpStatus;

  6. import org.springframework.http.ResponseEntity;

  7. import org.springframework.web.bind.annotation.GetMapping;

  8. import org.springframework.web.bind.annotation.PathVariable;

  9. import org.springframework.web.bind.annotation.RequestMapping;

  10. import org.springframework.web.bind.annotation.RestController;



  11. /**

  12. * @author ramostear

  13. * @create-time 2019/4/7 0007-0:54

  14. * @modify by :

  15. * @since:

  16. */

  17. @RestController

  18. @RequestMapping("/persons")

  19. public class PersonController {


  20. @Autowired

  21. private PersonService personService;


  22. @GetMapping("/{id}")

  23. public ResponseEntity<Person> person(@PathVariable(value = "id") Long id){

  24. return new ResponseEntity<>(personService.getPerson(id), HttpStatus.OK);

  25. }

  26. }

Person是一个简单的POJO类:
  1. package com.ramostear.cache.entity;



  2. import lombok.AllArgsConstructor;

  3. import lombok.Getter;

  4. import lombok.NoArgsConstructor;

  5. import lombok.Setter;


  6. import java.io.Serializable;


  7. /**

  8. * @author ramostear

  9. * @create-time 2019/4/7 0007-0:45

  10. * @modify by :

  11. * @since:

  12. */

  13. @Getter

  14. @Setter

  15. @AllArgsConstructor

  16. @NoArgsConstructor

  17. public class Person implements Serializable{


  18. private Long id;


  19. private String username;


  20. private String email;

  21. }

以上准备工作都完成后,让我们编译并运行应用程序。项目成功启动后,使用浏览器打开:http://localhost:8080/persons/1 ,你将在浏览器页面中看到如下的信息:

  1. {"id":1,"username":"ramostear","email":"ramostear@163.com"}

此时在观察控制台输出的日志信息:

  1. 2019-04-07 01:08:01.001 INFO 6704 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 5 ms

  2. 2019-04-07 01:08:01.054 INFO 6704 --- [e [_default_]-0] c.r.cache.config.PersonCacheEventLogger : person caching event CREATED 1 null com.ramostear.cache.entity.Person@ba8a729

由于我们是第一次请求API,没有任何缓存数据。因此,Ehcache创建了一条缓存数据,可以通过CREATED看一了解到。
我们在ehcache.xml文件中将缓存过期时间设置成了1分钟(1),因此在一分钟之内我们刷新浏览器,不会看到有新的日志输出,一分钟之后,缓存过期,我们再次刷新浏览器,将看到如下的日志输出:
  1. 2019-04-07 01:09:28.612 INFO 6704 --- [e [_default_]-1] c.r.cache.config.PersonCacheEventLogger : person caching event EXPIRED 1 com.ramostear.cache.entity.Person@a9f3c57 null

  2. 2019-04-07 01:09:28.612 INFO 6704 --- [e [_default_]-1] c.r.cache.config.PersonCacheEventLogger : person caching event CREATED 1 null com.ramostear.cache.entity.Person@416900ce

第一条日志提示缓存已经过期,第二条日志提示Ehcache重新创建了一条缓存数据。

结束语


在本次案例中,通过简单的三个步骤,讲解了基于 Ehcache 的 Spring Boot 应用程序缓存实现。文章内容重在缓存实现的基本步骤与方法,简化了具体的业务代码,有兴趣的朋友可以自行扩展,期间遇到问题也可以随时与我联系。

欢迎在留言区留下你的观点,一起讨论提高。如果今天的文章让你有新的启发,学习能力的提升上有新的认识,欢迎转发分享给更多人。

欢迎各位读者加入程序员小乐技术群,在公众号后台回复“加群”或者“学习”即可。

猜你还想看


阿里、腾讯、百度、华为、京东最新面试题汇集

假如有人把支付宝存储服务器炸了(物理炸),大众在支付宝里的钱是不是就都没有了呢?

7 个显著提升编码效率的 IntelliJ IDEA 必备插件

推荐 33 个 IDEA 最牛配置,让你的IDEA有飞一般的感觉!


关注「程序员小乐」,收看更多精彩内容
嘿,你在看吗?
视频 小程序 ,轻点两下取消赞 在看 ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存