推荐链接:https://blog.csdn.net/sinat_32366329/article/details/80260944
JetCache
JetCache是由阿里巴巴开源的通用缓存访问框架,相较于其他缓存框架该框架最大的特点就是将面向对象的思想应用到了缓存。
JetCache提供的核心能力包括:
提供统一的,类似jsr-107风格的API访问Cache,并可通过注解创建并配置Cache实例
通过注解实现声明式的方法缓存,支持TTL和两级缓存
分布式缓存自动刷新,分布式锁 (2.2+)
支持异步Cache API
Spring Boot支持
Key的生成策略和Value的序列化策略是可以定制的
针对所有Cache实例和方法缓存的自动统计
原文链接:https://blog.csdn.net/honger_hua/article/details/100009582
软件要求
JDK1.8
Spring Framework 4.0.8及以上(可选,支持Annotation)
Spring Boot 1.1.9及以上(可选)
Boot项目配置
maven依赖
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>2.5.3</version>
</dependency>
解决冲突
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
MySpringBootApp.java
@SpringBootApplication
@EnableMethodCache(basePackages = "com.moguhu.oc")
@EnableCreateCacheAnnotation
public class MySpringBootApp {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApp.class);
}
}
application.yml
jetcache:
statIntervalMinutes: 15
areaInCacheName: false
local:
default:
type: linkedhashmap
keyConvertor: fastjson
limit: 100
remote:
default:
type: redis
keyConvertor: fastjson
valueEncoder: java
valueDecoder: java
poolConfig:
minIdle: 5
maxIdle: 20
maxTotal: 50
host: ${redis.host}
port: ${redis.port}
方法缓存
我们可以使用@Cached用在接口方法上面。如下所示:
public interface UserService {
@Cached(expire = 3600, cacheType = CacheType.REMOTE)
User getUserById(long userId);
}
expire表示返回值User对象,将在3600秒后过期,JetCache默认使用所有入参生成缓存的key。当然我们也可以手动指定key,如下所示:
public interface UserService {
@Cached(name="userCache-", key="#userId", expire = 3600)
User getUserById(long userId);
@CacheUpdate(name="userCache-", key="#user.userId", value="#user")
void updateUser(User user);
@CacheInvalidate(name="userCache-", key="#userId")
void deleteUser(long userId);
}
上面代码中可以看出,我们可以使用SpEL(Spring Expression Language)来设置key和Value,当入参是对象时,可以使用对象中的一个字段,如 #user.userId 来设置。name属性不是必须的,但是起个名字是个好习惯,展示统计数据的使用,会使用这个名字。如果同一个area两个@CreateCache的name配置一样,它们生成的Cache将指向同一个实例。这里面需要注意的是,java代码的编辑级别必须是1.8。
自动刷新
public interface SummaryService{
@Cached(expire = 3600, cacheType = CacheType.REMOTE)
@CacheRefresh(refresh = 1800, stopRefreshAfterLastAccess = 3600, timeUnit = TimeUnit.SECONDS)
@CachePenetrationProtect
BigDecimal summaryOfToday(long catagoryId);
}
CachePenetrationProtect表示在多线程环境中同步加载数据。
缓存API
我们可以使用@CreateCache注解去创建一个Cache实例,默认超时时间是100秒:
@CreateCache(expire = 100, cacheType = CacheType.BOTH, localLimit = 50)
private Cache<Long, UserDO> userCache;
上面代码创建了一个Cache实例。其中cacheType=CacheType.BOTH定义了一个2级缓存(本地和远程),其中本地使用了LRU Cache,上线是50个,操作是可以看做是一个Map,如下所示:
UserDO user = userCache.get(12345L);
userCache.put(12345L, loadUserFromDataBase(12345L));
userCache.remove(12345L);
userCache.computeIfAbsent(1234567L, (key) -> loadUserFromDataBase(1234567L));
当然我们也可以手动的去创建Cache实例,如下:
GenericObjectPoolConfig pc = new GenericObjectPoolConfig();
pc.setMinIdle(2);
pc.setMaxIdle(10);
pc.setMaxTotal(10);
JedisPool pool = new JedisPool(pc, "localhost", 6379);
Cache<Long, UserDO> userCache = RedisCacheBuilder.createRedisCacheBuilder()
.keyConvertor(FastjsonKeyConvertor.INSTANCE)
.valueEncoder(JavaValueEncoder.INSTANCE)
.valueDecoder(JavaValueDecoder.INSTANCE)
.jedisPool(pool)
.keyPrefix("userCache-")
.expireAfterWrite(200, TimeUnit.SECONDS)
.buildCache();
高级API
异步API
CacheGetResult r = cache.GET(userId);
CompletionStage<ResultData> future = r.future();
future.thenRun(() -> {
if(r.isSuccess()){
System.out.println(r.getValue());
}
});
分布式锁
cache.tryLockAndRun("key", 60, TimeUnit.SECONDS, () -> heavyDatabaseOperation());
读取并自动刷新
@CreateCache
@CacheRefresh(timeUnit = TimeUnit.MINUTES, refresh = 60, stopRefreshAfterLastAccess = 100)
@CachePenetrationProtect
private Cache<String, Long> orderSumCache;
@PostConstruct
public void init(){
orderSumCache.config().setLoader(this::loadOrderSumFromDatabase);
}
传统项目配置
如果没有使用spring boot,可以按下面的方式配置(这里使用jedis客户端连接redis为例)。
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-anno</artifactId>
<version>2.5.4</version>
</dependency>
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-redis</artifactId>
<version>2.5.4</version>
</dependency>
配置了这个JetCacheConfig类以后,可以使用@CreateCache和@Cached注解。
import java.util.HashMap;
import java.util.Map;
import com.alicp.jetcache.anno.CacheConsts;
import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation;
import com.alicp.jetcache.anno.config.EnableMethodCache;
import com.alicp.jetcache.anno.support.GlobalCacheConfig;
import com.alicp.jetcache.anno.support.SpringConfigProvider;
import com.alicp.jetcache.embedded.EmbeddedCacheBuilder;
import com.alicp.jetcache.embedded.LinkedHashMapCacheBuilder;
import com.alicp.jetcache.redis.RedisCacheBuilder;
import com.alicp.jetcache.support.FastjsonKeyConvertor;
import com.alicp.jetcache.support.JavaValueDecoder;
import com.alicp.jetcache.support.JavaValueEncoder;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.util.Pool;
@Configuration
@EnableMethodCache(basePackages = "com.company.mypackage")
@EnableCreateCacheAnnotation
public class JetCacheConfig {
@Bean
public Pool<Jedis> pool(){
GenericObjectPoolConfig pc = new GenericObjectPoolConfig();
pc.setMinIdle(2);
pc.setMaxIdle(10);
pc.setMaxTotal(10);
return new JedisPool(pc, "localhost", 6379);
}
@Bean
public SpringConfigProvider springConfigProvider() {
return new SpringConfigProvider();
}
@Bean
public GlobalCacheConfig config(SpringConfigProvider configProvider, Pool<Jedis> pool){
Map localBuilders = new HashMap();
EmbeddedCacheBuilder localBuilder = LinkedHashMapCacheBuilder
.createLinkedHashMapCacheBuilder()
.keyConvertor(FastjsonKeyConvertor.INSTANCE);
localBuilders.put(CacheConsts.DEFAULT_AREA, localBuilder);
Map remoteBuilders = new HashMap();
RedisCacheBuilder remoteCacheBuilder = RedisCacheBuilder.createRedisCacheBuilder()
.keyConvertor(FastjsonKeyConvertor.INSTANCE)
.valueEncoder(JavaValueEncoder.INSTANCE)
.valueDecoder(JavaValueDecoder.INSTANCE)
.jedisPool(pool);
remoteBuilders.put(CacheConsts.DEFAULT_AREA, remoteCacheBuilder);
GlobalCacheConfig globalCacheConfig = new GlobalCacheConfig();
globalCacheConfig.setConfigProvider(configProvider);
globalCacheConfig.setLocalCacheBuilders(localBuilders);
globalCacheConfig.setRemoteCacheBuilders(remoteBuilders);
globalCacheConfig.setStatIntervalMinutes(15);
globalCacheConfig.setAreaInCacheName(false);
return globalCacheConfig;
}
}
spring提供的缓存方案
1、pom.xml文件引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2 使用@EnableCaching注解在主配置类开启缓存
@EnableCaching//开启缓存
@SpringBootApplication
public class SpringbootmybatisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootmybatisApplication.class, args);
}
@Bean
public UserFilter getUserFilter(){
return new UserFilter();
}
}
3、在方法前使用@Cacheable注解,将运行结果缓存
@Cacheable(value = { "sampleCache" },key="#id")
@RequestMapping("/findAllUser")
@ResponseBody
public String findAllUser(){
List<User> users = userDao.findAllUser();
List<Integer> list = new ArrayList<Integer>();
for (User user:users) {
list.add(user.getId());
}
return list.toString();
}
@Cacheable(value = { "sampleCache" },key="#id"):当调用这个方法的时候,会从一个名叫 sampleCache 的缓存(缓存本质是一个map)中查询key为id的值,如果不存在,则执行实际的方法(即查询数据库等服务逻辑),并将执行的结果存入缓存中,否则返回缓存中的对象。这里的缓存中的 key 就是参数 id,value 就是 返回的String 对象
spring catche 和 jetcache redis之间的关系
首先:
redis是存储缓存的地方,可以简单理解成数据库
spring cache和jetcache以及redis自带的redisTemplate是三种缓存放入与设置的方式,都是用redis来实际存储数据。
然后spring cache和jetcache以及redis自带的redisTemplate三种方式中jetcache更加强大,支持的语法更加简洁 丰富。