简介
JetCache是一个基于Java的缓存系统封装,提供统一的API和强大的注解来简化缓存的使用。原生支持TTL、两级缓存、分布式自动刷新,还提供了Cache接口用于手工缓存操作。主要是用来替代Springboot 自带的Cache服务。
添加依赖
使用jetcache,需要引入相关依赖,jetcache的远程缓存使用的是redis,同时使用的redis是jedis,因此需要在集成的redis组件里排除lettuce连接池
<!-- 添加jetcahce依赖 -->
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>2.7.0</version>
</dependency>
<!-- 引入redis,同时排除默认的lettuce连接池 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入 redis jedis 连接池 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- 引入fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
使用
配置jetcache
在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: 127.0.0.1
port: 6379
启用jetcache
在启动类中添加@EnableMethodCache
注解,其中basePackages指定启用注解的包,一般填写启动类的包名,如下:
@SpringBootApplication
@EnableMethodCache(basePackages = "com.example.cache")
public class CacheApplication {
public static void main(String[] args) {
SpringApplication.run(CacheApplication.class, args);
}
}
创建缓存
使用@Cached
方法为一个方法添加上缓存。JetCache通过Spring AOP生成代理,来支持缓存功能。注解可以加在接口方法上也可以加在类方法上,但需要保证是个归spring容器管理的SpringBean。
案例
public interface JetCacheService {
@Cached(name = "student_cache_", key = "#id", expire = 3600)
Student getStudent(Long id);
}
@Service
public class JetCacheServiceImpl implements JetCacheService {
@Override
public Student getStudent(Long id) {
Student student = new Student();
student.setId(id);
student.setAge(15);
student.setName("李四");
student.setGrade("高一");
student.setCreatedTime(LocalDateTime.now());
System.out.println("正在进行创建缓存");
return student;
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Serializable {
private Long id;
private String name;
private int age;
private String grade;
private LocalDateTime createdTime;
}
测试
@SpringBootTest
class JetCacheServiceImplTest {
@Autowired
private JetCacheService jetCacheService;
@Test
void getStudent() {
Student student = jetCacheService.getStudent(1L);
System.out.println(student);
}
}
第一次运行测试结果如下:
正在进行创建缓存
Student(id=1, name=李四, age=15, grade=高一, createdTime=2022-10-22T13:09:05.960)
第二次运行测试结果如下:
Student(id=1, name=李四, age=15, grade=高一, createdTime=2022-10-22T13:09:05.960)
从上面两次的测试运行结果可以看出,正在进行创建缓存
这行文件在第二次测试运行时并没有进行输出,则可以说明,第二次运行获取到的数是直接从缓存中获取的,并没有执行getStudent
方法里面的相关代码。
@Cached 注解解析
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Cached {
// 缓存区域,默认为default
String area() default "default";
// 缓存实例的名称,可用作显示统计信息和作为key的前缀
String name() default "$$undefined$$";
// 缓存是否生效,默认为true
boolean enabled() default true;
// 缓存时间的单位,默认为秒
TimeUnit timeUnit() default TimeUnit.SECONDS;
// 过期时间,如果未配置localExpire则本地缓存和remote缓存都使用此
int expire() default Integer.MIN_VALUE;
// 本地缓存的过期时间
int localExpire() default Integer.MIN_VALUE;
// 缓存类型,可选EMOTE(远端), LOCAL(本地), BOTH(本地与远端同时缓存)
CacheType cacheType() default CacheType.REMOTE;
// 本地缓存最大数量
int localLimit() default Integer.MIN_VALUE;
// 序列化方式,默认使用全局
String serialPolicy() default "$$undefined$$";
// 指定**转换器。用于转换复杂的**对象。JetCache内置版本keyConvertor是KeyConvertor.FASTJSON或KeyConvertor.NONE。NONE表示不转换,FASTJSON将使用fastjson将key对象转换为字符串。如果缺少属性值,请使用全局配置。
String keyConvertor() default "$$undefined$$";
// 缓存key,使用spel表达式
String key() default "$$undefined$$";
// 是否缓存null
boolean cacheNullValue() default false;
// 使用SpEL指定条件,如果表达式返回true的时候才去缓存中查询
String condition() default "$$undefined$$";
// 表达式脚本用于调节方法缓存更新,当评估结果为假时,缓存操作被否决。在实际方法调用之后进行评估,因此我们可以在脚本中引用#result。
String postCondition() default "$$undefined$$";
}
缓存更新
在方法上面添加@CacheUpdate
注解可以进行缓存更新,注解可以加在接口方法上也可以加在类方法上,案例如下:
案例
public interface JetCacheService {
@CacheUpdate(name = "student_cache_", key = "#student.id", value = "#student")
Student updateStudent(Student student);
}
@Service
public class JetCacheServiceImpl implements JetCacheService {
@Override
public Student updateStudent(Student student) {
System.out.println("update student:" + student);
return student;
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Serializable {
private Long id;
private String name;
private int age;
private String grade;
private LocalDateTime createdTime;
}
测试
@SpringBootTest
class JetCacheServiceImplTest {
@Autowired
private JetCacheService jetCacheService;
@Test
void updateStudent() {
System.out.println(jetCacheService.getStudent(1L));
Student student = new Student();
student.setId(1L);
student.setAge(18);
student.setName("李四");
student.setGrade("高三");
student.setCreatedTime(LocalDateTime.now());
jetCacheService.updateStudent(student);
System.out.println(jetCacheService.getStudent(1L));
}
}
运行测试案例,输出结果如下:
Student(id=2, name=李四, age=15, grade=高一, createdTime=2022-10-22T13:33:07.812)
update student:Student(id=2, name=李四, age=18, grade=高三, createdTime=2022-10-22T13:33:07.835)
Student(id=2, name=李四, age=18, grade=高三, createdTime=2022-10-22T13:33:07.835)
从输出结果可以看出,第一行输出是没有进行缓存更新前的数据输出,第二行是需要缓存更新的更新,第三行输出是缓存更新后,从缓存中获取出来的数据,因此可以看出缓存更新成功。
@CacheUpdate 注解解析
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface CacheUpdate {
// 缓存区域,默认default, 一般情况下不需要设置
String area() default "default";
// 缓存实例的名称,可用作显示统计信息和作为key的前缀
String name();
// 缓存key,使用spel表达式
String key() default "$$undefined$$";
// 使用spel表达式指定缓存数据
String value();
// 缓存条件,true更新缓存,false不更新缓存,使用spel指定
String condition() default "$$undefined$$";
boolean multi() default false;
}
缓存删除
在方法上面添加@CacheInvalidate
注解进行缓存删除,注解可以加在接口方法上也可以加在类方法上,案例如下:
案例
public interface JetCacheService {
@CacheInvalidate(name = "student_cache_", key = "#id")
void deleteStudent(Long id);
}
@Service
public class JetCacheServiceImpl implements JetCacheService {
@Override
public void deleteStudent(Long id) {
System.out.println("deleteStudent:" + id);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Serializable {
private Long id;
private String name;
private int age;
private String grade;
private LocalDateTime createdTime;
}
@CacheInvalidate 注解解析
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(CacheInvalidateContainer.class)
@Target({ElementType.METHOD})
public @interface CacheInvalidate {
// 缓存区域,默认为default
String area() default "default";
// 缓存实例的名称,可用作显示统计信息和作为key的前缀
String name();
// 缓存key,使用spel表达式
String key() default "$$undefined$$";
// 缓存条件,true删除缓存,false不删除缓存,使用spel指定
String condition() default "$$undefined$$";
boolean multi() default false;
}
缓存刷新
在方法上面添加@CacheRefresh
注解可以进行缓存自动刷新,即只要请求过一次缓存,后面会自动进行后台刷新,例如:
public interface JetCacheService {
@Cached(name = "student_cache_", key = "#id", expire = 3600)
@CacheRefresh(refresh = 10)
Student getStudent(Long id);
}
@Service
public class JetCacheServiceImpl implements JetCacheService {
@Override
public Student getStudent(Long id) {
Student student = new Student();
student.setId(id);
student.setAge(15);
student.setName("李四");
student.setGrade("高一");
student.setCreatedTime(LocalDateTime.now());
System.out.println(LocalDateTime.now());
System.out.println("正在进行创建缓存");
System.out.println(student);
return student;
}
}
测试
@RestController
@RequestMapping("/jetcache")
public class JetCacheController {
@Autowired
private JetCacheService jetCacheService;
@GetMapping
public Student getStudent(){
Student student = jetCacheService.getStudent(1L);
return student;
}
}
启动应用,访问URL: http://localhost:8080/jetcache,然后查看控制台输出,输出如下:
2022-10-22T21:35:55.145
正在进行创建缓存
Student(id=1, name=李四, age=15, grade=高一, createdTime=2022-10-22T21:35:55.145)
2022-10-22T21:36:05.154
正在进行创建缓存
Student(id=1, name=李四, age=15, grade=高一, createdTime=2022-10-22T21:36:05.154)
2022-10-22T21:36:15.163
正在进行创建缓存
Student(id=1, name=李四, age=15, grade=高一, createdTime=2022-10-22T21:36:15.163)
从上面可以看出,每隔10秒就会自动进行缓存刷新。
@CacheRefresh 注解解析
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface CacheRefresh {
// 隔多久进行刷新
int refresh();
// 指定该key多长时间没有访问就停止刷新,如果不指定会一直刷新
int stopRefreshAfterLastAccess() default Integer.MIN_VALUE;
// 类型为BOTH/REMOTE的缓存刷新时,同时只会有一台服务器在刷新,这台服务器会在远程缓存放置一个分布式锁,此配置指定该锁的超时时间
int refreshLockTimeout() default Integer.MIN_VALUE;
// 间隔时间单位,默认是秒
TimeUnit timeUnit() default TimeUnit.SECONDS;
}
更多信息,请查看官方文档:GitHub - alibaba/jetcache: JetCache is a Java cache framework.
原创文章,作者:jiafegn,如若转载,请注明出处:https://www.techlearn.cn/archives/505