java接口的查询如何能提高性能,比每次都去数据库中查询要快的方案有了,就是下面要介绍的。
一、添加依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId></dependency>
二、启动类上添加注解
@org.springframework.cache.annotation.EnableCaching
三、配置
1、采用spring自带配置
############# 缓存配置 不推荐 建议自定义 #############
spring.cache.cache-names=USER,ADVERT
spring.cache.caffeine.spec=initialCapacity=50,maximumSize=500,expireAfterWrite=30s,refreshAfterWrite=7s
spring.cache.type=caffeine
2、自定义配置
/*** <p> 缓存名分类 </p>*/
public enum CacheNameEnum {/*** 用户*/USER(5, 20L, 60L),/*** 推荐*/ADVERT(5, 10L, 120L);private final Integer initialCapacity;private final Long maximumSize;private final Long expire;CacheNameEnum(Integer initialCapacity, Long maximumSize, Long expire) {this.initialCapacity = initialCapacity;this.maximumSize = maximumSize;this.expire = expire;}public Long getMaximumSize() {return maximumSize;}public Integer getInitialCapacity() {return initialCapacity;}public Long getExpire() {return expire;}
}
import com.coocaa.system.enums.CacheNameEnum;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.time.Duration;
import java.util.ArrayList;
import java.util.List;/*** @author songjianyong* <p> 本地缓存配置 </p>*/
@Configuration
public class CaffeineCacheConfig {private static final SimpleCacheManager SIMPLE_CACHE_MANAGER = new SimpleCacheManager();@Beanpublic CacheManager caffeineCacheManager() {List<CaffeineCache> caches = new ArrayList<>();for (CacheNameEnum value : CacheNameEnum.values()) {com.github.benmanes.caffeine.cache.Cache<Object, Object> cache = Caffeine.newBuilder().initialCapacity(value.getInitialCapacity()).maximumSize(value.getMaximumSize())//写入后失效时间.expireAfterWrite(Duration.ofSeconds(value.getExpire())).build();caches.add(new CaffeineCache(value.name(), cache));}SIMPLE_CACHE_MANAGER.setCaches(caches);return SIMPLE_CACHE_MANAGER;}}
四、使用注解
@org.springframework.cache.annotation.Cacheable(value = "USER", key="#p0.id")
五、进阶处理
自定义 CaffeineCacheManager
import com.coocaa.ops.admin.common.enums.CacheNameEnum;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;import java.util.HashMap;
import java.util.Map;/*** 自定义 CaffeineCacheManager** @author songjianyong*/
@Configuration
public class SongCaffeineCacheManager extends CaffeineCacheManager implements InitializingBean {private final Map<String, Caffeine<Object, Object>> builders = new HashMap<>();@Nullableprivate CacheLoader<Object, Object> cacheLoader;@Overridepublic void afterPropertiesSet() throws Exception {for (CacheNameEnum value : CacheNameEnum.values()) {builders.put(value.getCacheName(), Caffeine.from(value.getSpec()));}}@Override@NonNullprotected Cache<Object, Object> createNativeCaffeineCache(@NonNull String name) {Caffeine<Object, Object> builder = builders.get(name);if (builder == null) {return super.createNativeCaffeineCache(name);}if (this.cacheLoader != null) {return builder.build(this.cacheLoader);} else {return builder.build();}}@Overridepublic void setCacheLoader(@NonNull CacheLoader<Object, Object> cacheLoader) {super.setCacheLoader(cacheLoader);this.cacheLoader = cacheLoader;}
}
辅助代码
/*** 缓存名称枚举** @author songjianyong*/
public enum CacheNameEnum {/*** 接口响应结果缓存名称*/SONG_API_RESPONSE("SONG:API:RESPONSE", "initialCapacity=5,maximumSize=50,expireAfterWrite=1d"),JIAN_API_RESPONSE("JIAN:API:RESPONSE", "initialCapacity=10,maximumSize=100,expireAfterWrite=15d");/*** 缓存名称*/private final String cacheName;/*** spec*/private final String spec;CacheNameEnum(String cacheName, String spec) {this.cacheName = cacheName;this.spec = spec;}public String getCacheName() {return cacheName;}public String getSpec() {return spec;}
}
补充下注解:
- @Cacheable:表示该方法支持缓存。当调用被注解的方法时,如果对应的键已经存在缓存,则不再执行方法体,而从缓存中直接返回。当方法返回null时,将不进行缓存操作。
- @CachePut:表示执行该方法后,其值将作为最新结果更新到缓存中,每次都会执行该方法。
- @CacheEvict:表示执行该方法后,将触发缓存清除操作。
- @Caching:用于组合前三个注解,例如:
@Caching(cacheable = @Cacheable("CacheConstants.GET_USER"),evict = {@CacheEvict("CacheConstants.GET_DYNAMIC",allEntries = true)}
public User find(Integer id) {return null;
}
- cacheNames/value:缓存组件的名字,即cacheManager中缓存的名称。
- key:缓存数据时使用的key。默认使用方法参数值,也可以使用SpEL表达式进行编写。
- keyGenerator:和key二选一使用。
- cacheManager:指定使用的缓存管理器。
- condition:在方法执行开始前检查,在符合condition的情况下,进行缓存
- unless:在方法执行完成后检查,在符合unless的情况下,不进行缓存
- sync:是否使用同步模式。若使用同步模式,在多个线程同时对一个key进行load时,其他线程将被阻塞。