【SpringBoot】在SpringBoot中使用Ehcache
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 文件配置详解:
- diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。
- defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。 name:缓存名称。
- maxElementsInMemory:缓存最大数目 maxElementsOnDisk:硬盘最大缓存个数。
- eternal:对象是否永久有效,一但设置了,timeout将不起作用。 overflowToDisk:是否保存到磁盘,当系统当机时
- timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
- timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
- diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
- diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
- diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
- memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
- clearOnFlush:内存数量最大时是否清除。
- memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
- FIFO,first in first out,先进先出。 LFU, Less Frequently
- Used,一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。 LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
三、在SpringBoot启动类中添加开启缓存的注解@EnableCaching
一般情况下,我们在Sercive层对缓存进行操作。 Ehcache 在 Spring 中的注解如下:
- @Cacheable
Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。 - @CacheEvict
清除缓存。 - @CachePut
@CachePut也可以声明一个方法支持缓存功能。使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
参数解释:
- value:缓存位置名称,不能为空,如果使用EHCache,就是ehcache.xml中声明的cache的name
- key:缓存的key,默认为空,既表示使用方法的参数类型及参数值作为key,支持SpEL(后面会有详细的讲解)
- condition:触发条件,只有满足条件的情况才会加入缓存,默认为空,既表示全部都加入缓存,支持SpEL
- 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”
// key 当前类,缓存对象为返回值list
15 @Cacheable(value = {"lt.ecache"}, key = "#root.targetClass")
16 public List<Employee> getEmployees() {
17 System.out.println("*** getEmployees() 已经调用 ***");
18 List<Employee> list = new ArrayList<Employee>(5);
19 list.add(new Employee(1, "Ben", "Architect"));
20 list.add(new Employee(2, "Harley", "Programmer"));
21 list.add(new Employee(3, "Peter", "BusinessAnalyst"));
22 list.add(new Employee(4, "Sasi", "Manager"));
23 list.add(new Employee(5, "Abhi", "Designer"));
24 return list;
25 }
26
27 // key id,缓存数据为返回值Employee对象
28 @Cacheable(value = "lt.ecache", key = "#id")
29 public Employee getEmployee(int id, List<Employee> employees) {
30 System.out.println("*** getEmployee(): " + id + " ***");
31 Employee emp = null;
32 for (Employee employee : employees) {
33 if (employee.getId() == id) {
34 emp = employee;
35 }
36 }
37 return emp;
38 }
39
40 // @CachePut会去替换缓存中的Employee对象为当前id对应的对象
41 @CachePut(value = "lt.ecache", key = "#id")
42 public Employee updateEmployee(int id, String designation, List<Employee> employees) {
43 System.out.println("*** updateEmployee() " + id + " ***");
44 Employee emp = null;
45 int i = 0;
46 for (Employee employee : employees) {
47 if (employee.getId() == id) {
48 employee.setDesignation(designation);
49 emp = employee;
50 }
51 }
52 System.out.println(emp);
53 return emp;
54 }
55
56 //key为参数中Employee对象的id,缓存指定id对应的Employee对象
57 @Cacheable(value = "lt.ecache", key = "#employee.id")
58 public Employee addEmployee(Employee employee, List<Employee> employees) {
59 System.out.println("*** addEmployee() : " + employee.getId() + " ***");
60 employees.add(employee);
61 System.out.println(employee);
62 return employee;
63 }
64
65 //key为参数中的id,移除缓存,移除指定id对应的Employee对象
66 @CacheEvict(value = "lt.ecache", key = "#id")
67 public Employee removeEmployee(int id, List<Employee> employees) {
68 System.out.println("*** removeEmployee() : " + id + " ***");
69 Employee emp = null;
70 int i = 0;
71 for (Employee employee : employees) {
72 if (employee.getId() == id) {
73 emp = employee;
74 } else {
75 i++;
76 }
77 }
78 employees.remove(i);
79 return emp;
80 }
81
82 //key为当前类,移除缓存,移除employees列表对象
83 @CacheEvict(value = "lt.ecache", key = "#root.targetClass")
84 public List<Employee> removeAllEmployee(List<Employee> employees) {
85 System.out.println("*** removeAllEmployee() : ***");
86 employees.clear();
87 System.out.println(employees.size());
88 return employees;
89 }
当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。
2、如果要调用当前类里面的方法(方法必须是public):
@Override
@Cacheable(value={"TeacherAnalysis_public_chart"}, key="#root.target.getDictTableName() + '_' + #root.target.getFieldName()")
public List<Map<String, Object>> getChartList(Map<String, Object> paramMap) {
}
public String getDictTableName(){
return "";
}
public String getFieldName(){
return "";
}
还没有评论,来说两句吧...