【SpringBoot】在SpringBoot中使用Ehcache

r囧r小猫 2022-05-14 07:49 522阅读 0赞

SpringBoot提供了对缓存的支持,通过在启动类中添加@EnableCaching注解自动化配置合适的缓存管理器(CacheManager),Spring Boot根据下面的顺序去侦测缓存提供者:

  • Generic
  • JCache (JSR-107)
  • EhCache 2.x
  • Hazelcast
  • Infinispan
  • Redis
  • Guava
  • Simple

SpringBoot的缓存机制:
SpringBoot缓存是依赖于由org.springframework.cache.Cache和org.springframework.cache.CacheManager接口实现的抽象高速缓存,不提供实际的存储,SpringBoot会根据实现自动配置合适的CacheManager,只要缓存支持通过@EnableCaching注释启用即可。基于Ehcache API实现的缓存操作工具类

SpringBoot 配置 EhCache 2.x
一、在pom文件中引入Ehcache依赖
这里写图片描述
二、在resources根目录下引入配置文件 ehcache.xml,增加需要的缓存配置
这里写图片描述
Ehcache.xml 文件配置详解:

  1. diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。
  2. defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。 name:缓存名称。
  3. maxElementsInMemory:缓存最大数目 maxElementsOnDisk:硬盘最大缓存个数。
  4. eternal:对象是否永久有效,一但设置了,timeout将不起作用。 overflowToDisk:是否保存到磁盘,当系统当机时
  5. timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
  6. timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
  7. diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
  8. diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
  9. diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
  10. memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
  11. clearOnFlush:内存数量最大时是否清除。
  12. memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
  13. FIFO,first in first out,先进先出。 LFU, Less Frequently
  14. Used,一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。 LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。

三、在SpringBoot启动类中添加开启缓存的注解@EnableCaching

一般情况下,我们在Sercive层对缓存进行操作。 Ehcache 在 Spring 中的注解如下:

  1. @Cacheable
    Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。
  2. @CacheEvict
    清除缓存。
  3. @CachePut
    @CachePut也可以声明一个方法支持缓存功能。使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

参数解释:

  1. value:缓存位置名称,不能为空,如果使用EHCache,就是ehcache.xml中声明的cache的name
  2. key:缓存的key,默认为空,既表示使用方法的参数类型及参数值作为key,支持SpEL(后面会有详细的讲解)
  3. condition:触发条件,只有满足条件的情况才会加入缓存,默认为空,既表示全部都加入缓存,支持SpEL
  4. allEntries:CacheEvict参数,true表示清除value中的全部缓存,默认为false

这里写图片描述

具体的Demo示例参看本人的Github:ehcache工具类以及在springboot中使用ehcache

附录:最近在面试中一个面试官问到@Cacheable 的key生成的问题,在这里总结一下:

key属性是用来指定Spring缓存方法的返回结果时对应的key的。该属性支持SpringEL表达式。当我们没有指定该属性时,Spring将使用默认策略生成key。

自定义策略是指我们可以通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。下面是几个使用参数作为key的示例。

1、用“#参数名”或者“#p参数index”

在这里插入图片描述

  1. // key 当前类,缓存对象为返回值list
  2. 15 @Cacheable(value = {"lt.ecache"}, key = "#root.targetClass")
  3. 16 public List<Employee> getEmployees() {
  4. 17 System.out.println("*** getEmployees() 已经调用 ***");
  5. 18 List<Employee> list = new ArrayList<Employee>(5);
  6. 19 list.add(new Employee(1, "Ben", "Architect"));
  7. 20 list.add(new Employee(2, "Harley", "Programmer"));
  8. 21 list.add(new Employee(3, "Peter", "BusinessAnalyst"));
  9. 22 list.add(new Employee(4, "Sasi", "Manager"));
  10. 23 list.add(new Employee(5, "Abhi", "Designer"));
  11. 24 return list;
  12. 25 }
  13. 26
  14. 27 // key id,缓存数据为返回值Employee对象
  15. 28 @Cacheable(value = "lt.ecache", key = "#id")
  16. 29 public Employee getEmployee(int id, List<Employee> employees) {
  17. 30 System.out.println("*** getEmployee(): " + id + " ***");
  18. 31 Employee emp = null;
  19. 32 for (Employee employee : employees) {
  20. 33 if (employee.getId() == id) {
  21. 34 emp = employee;
  22. 35 }
  23. 36 }
  24. 37 return emp;
  25. 38 }
  26. 39
  27. 40 // @CachePut会去替换缓存中的Employee对象为当前id对应的对象
  28. 41 @CachePut(value = "lt.ecache", key = "#id")
  29. 42 public Employee updateEmployee(int id, String designation, List<Employee> employees) {
  30. 43 System.out.println("*** updateEmployee() " + id + " ***");
  31. 44 Employee emp = null;
  32. 45 int i = 0;
  33. 46 for (Employee employee : employees) {
  34. 47 if (employee.getId() == id) {
  35. 48 employee.setDesignation(designation);
  36. 49 emp = employee;
  37. 50 }
  38. 51 }
  39. 52 System.out.println(emp);
  40. 53 return emp;
  41. 54 }
  42. 55
  43. 56 //key为参数中Employee对象的id,缓存指定id对应的Employee对象
  44. 57 @Cacheable(value = "lt.ecache", key = "#employee.id")
  45. 58 public Employee addEmployee(Employee employee, List<Employee> employees) {
  46. 59 System.out.println("*** addEmployee() : " + employee.getId() + " ***");
  47. 60 employees.add(employee);
  48. 61 System.out.println(employee);
  49. 62 return employee;
  50. 63 }
  51. 64
  52. 65 //key为参数中的id,移除缓存,移除指定id对应的Employee对象
  53. 66 @CacheEvict(value = "lt.ecache", key = "#id")
  54. 67 public Employee removeEmployee(int id, List<Employee> employees) {
  55. 68 System.out.println("*** removeEmployee() : " + id + " ***");
  56. 69 Employee emp = null;
  57. 70 int i = 0;
  58. 71 for (Employee employee : employees) {
  59. 72 if (employee.getId() == id) {
  60. 73 emp = employee;
  61. 74 } else {
  62. 75 i++;
  63. 76 }
  64. 77 }
  65. 78 employees.remove(i);
  66. 79 return emp;
  67. 80 }
  68. 81
  69. 82 //key为当前类,移除缓存,移除employees列表对象
  70. 83 @CacheEvict(value = "lt.ecache", key = "#root.targetClass")
  71. 84 public List<Employee> removeAllEmployee(List<Employee> employees) {
  72. 85 System.out.println("*** removeAllEmployee() : ***");
  73. 86 employees.clear();
  74. 87 System.out.println(employees.size());
  75. 88 return employees;
  76. 89 }

当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。

2、如果要调用当前类里面的方法(方法必须是public):

  1. @Override
  2. @Cacheable(value={"TeacherAnalysis_public_chart"}, key="#root.target.getDictTableName() + '_' + #root.target.getFieldName()")
  3. public List<Map<String, Object>> getChartList(Map<String, Object> paramMap) {
  4. }
  5. public String getDictTableName(){
  6. return "";
  7. }
  8. public String getFieldName(){
  9. return "";
  10. }

发表评论

表情:
评论列表 (有 0 条评论,522人围观)

还没有评论,来说两句吧...

相关阅读