springboot2集成ehcache3
POM.XML增加依赖
<!-- springboot EhCache3 --> <dependency> <groupId>javax.cache</groupId> <artifactId>cache-api</artifactId> </dependency> <dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> <version>3.7.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
配置文件,放在resource根目录下
<?xml version="1.0" encoding="UTF-8" ?> <eh:config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:eh='http://www.ehcache.org/v3' xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.3.xsd"> <!--指定缓存目录 --> <eh:persistence directory="${java.io.tmpdir}/cache-data" /> <!--缓存模板 --> <eh:cache-template name="default"> <eh:expiry> <eh:ttl unit="seconds">600</eh:ttl> </eh:expiry> <eh:resources> <!--堆内内存可以放2000个条目,超出部分堆外100MB --> <eh:heap unit="entries">2000</eh:heap> <eh:offheap unit="MB">10</eh:offheap> </eh:resources> </eh:cache-template> <!--实际的缓存区间,继承了default缓存模板,sample完全使用模板默认 --> <!-- <eh:cache alias="sample" uses-template="default"></eh:cache> --> <!--下面两个继承了default缓存模板,但覆盖了缓存的过期时间 --> <!-- <eh:cache alias="authority_service" uses-template="default"> <eh:expiry> <eh:ttl unit="hours">1</eh:ttl> </eh:expiry> </eh:cache> --> <eh:cache alias="article_detail" uses-template="default"> <eh:expiry> <eh:ttl unit="hours">12</eh:ttl> </eh:expiry> </eh:cache> <eh:cache alias="article_list" uses-template="default"> <eh:expiry> <eh:ttl unit="hours">24</eh:ttl> </eh:expiry> </eh:cache> </eh:config>
application.properties配置
# 可选,配置了spring.cache.jcache.config属性会自动装配JCacheCacheManager spring.cache.type=jcache # 指定ehcache的配置文件所在的位置 spring.cache.jcache.config=classpath:ehcache-3.x.xml
key值生成
根据类名、方法名、参数信息自动生成key和匹配
CustomKeyGenerator.java
package com.daimeng.ehcache; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Configuration; import com.alibaba.fastjson.JSONObject; import java.io.Serializable; import java.lang.reflect.Method; import java.util.Arrays; @Configuration public class CustomKeyGenerator implements KeyGenerator { @Override public Object generate(Object target, Method method, Object... params) { return new CustomKey(target.getClass(), method.getName(), params); } /** * Like {@link org.springframework.cache.interceptor.SimpleKey} but considers the method. */ static final class CustomKey implements Serializable{ private static final long serialVersionUID = 1L; private final Class<?> clazz; private final String methodName; private final Object[] params; private final int hashCode; /** * Initialize a key. * * @param clazz the receiver class * @param methodName the method name * @param params the method parameters */ CustomKey(Class<?> clazz, String methodName, Object[] params) { this.clazz = clazz; this.methodName = methodName; this.params = params; //int code = Arrays.deepHashCode(params); int code = Arrays.deepHashCode(getStringCode(params)); code = 31 * code + clazz.hashCode(); code = 31 * code + methodName.hashCode(); this.hashCode = code; } @Override public int hashCode() { return this.hashCode; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof CustomKey)) { return false; } CustomKey other = (CustomKey) obj; if (this.hashCode != other.hashCode) { return false; } return this.clazz.equals(other.clazz) && this.methodName.equals(other.methodName) && Arrays.deepEquals(getStringCode(this.params), getStringCode(other.params)); //&& Arrays.deepEquals(this.params, other.params) } public String[] getStringCode(Object[] params) { String[] s = new String[params.length]; for(int i = 0; i < params.length; i ++) { String json = JSONObject.toJSONString(params[i]); s[i] = json; } return s; } } }
CustomCachingConfig
package com.daimeng.ehcache; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Configuration; @Configuration public class CustomCachingConfig extends CachingConfigurerSupport { @Override public KeyGenerator keyGenerator() { return new CustomKeyGenerator(); } }
service增加注解
/** * * @功能描述: TODO * @Cacheable Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素, * 如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中 * @CachePut 标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中 * @CacheEvict 是用来标注在需要清除缓存元素的方法或类上的 * 可以指定的属性有value、key、condition、allEntries和beforeInvocation * allEntries:是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。 * 当指定了allEntries为true时,Spring Cache将忽略指定的key。有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率 * beforeInvocation:清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。 * 使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素 * @名称: ArticleServiceImpl.java * @路径 com.daimeng.web.article.service.impl * @作者 daimeng.fun * @E-Mail sephy9527@qq.com * @创建时间 2020年8月29日 上午12:19:15 * @version V1.0 */ @Service @EnableCaching public class ArticleServiceImpl implements ArticleService{ ...... //value:使用叫做'shop_service'的缓存器 //key: 缓存的key等于#type,即传入的key值 //condition:缓存的条件,当#type等于phone时,才进行缓存 //@Cacheable(cacheNames = "shop_service", key = "#typeId", condition = "#type == 'phone'") @Override @Cacheable(value = "article_detail", key = "#id") public ArticleInfo findArticleInfoById(Integer id) { ..... } @Override @Cacheable(value = "article_list") public Page<ArticleInfo> findAllBySpecification(final ArticleInfo info, int page) { ..... } @Override @Caching(evict= { @CacheEvict(value = "article_list", allEntries = true), @CacheEvict(value = "article_detail", key = "#info.id") }) public ArticleInfo addArticle(ArticleInfo info) { ..... } @Override @Caching(evict= { @CacheEvict(value = "article_list", allEntries = true), @CacheEvict(value = "article_detail", key = "#info.id") }) public ArticleInfo updateArticle(ArticleInfo info) { ..... } @Override @CacheEvict(value = "article_list", allEntries = true) public ArticleInfo deleteArticle(ArticleInfo info) { ..... } }