您好,我是湘王,这是我的51CTO博客,欢迎您来,欢迎您再来~
说了很多Caffeine的基本特性,但是骡子是马,终归还是要看能不能拉磨。SpringBoot有两种使用Caffeine的方式:
1、直接引入Caffeine依赖,然后使用Caffeine方法实现缓存;
2、引入Caffeine和Spring Cache依赖,使用注解方式实现缓存。
先实现第一种方式(之前已实现过,整合到SpringBoot),这种方式比较灵活。再使用第二种方式(用注解实现Caffeine缓存功能),这种方式比较方便。
先引入依赖:
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
在配置文件中加入(这是可选的):
## CAFFEINE
customer.caffeine.initialCapacity=50
customer.caffeine.maximumSize=500
customer.caffeine.expireAfterWrite=86400
声明注入代码:
/**
* 声明注入代码
*
* @author 湘王
*/
@Configuration
@Component
public class WebConfiguration extends WebMvcConfigurationSupport {
/**
* 进程外缓存初始化
*
*/
@Bean("cache")
public LoadingCache<String, String> cache() {
return Caffeine.newBuilder()
.initialCapacity(1024)
.maximumSize(1024)
.expireAfterWrite(1, TimeUnit.HOURS)
.build(key -> {
return "";
});
}
}
然后在代码中调用:
/**
* 功能描述
*
* @author 湘王
*/
public class CaffeineTest {
@Resource
private LoadingCache<String, String> cache;
/**
* 保存缓存数据
*
*/
public void setCache(final String key, final String value) {
cache.put(key, value);
}
/**
* 读取缓存数据
*
*/
public String getCache(final String key) {
return cache.get(key);
}
/**
* 清除缓存数据
*
*/
public void clearCache(final String key) {
cache.invalidate(key);
}
}
然后再来看看第二种方式。先引入依赖:
<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>
在属性文件中加入配置:
## CAFFEINE
spring.cache.cache-names=test
spring.cache.type=caffeine
spring.cache.caffeine.spec=initialCapacity=50,maximumSize=500,expireAfterWrite=300s
定义一个实体类(之前用过的类):
/**
* 用户entity
*
* @author 湘王
*/
public class SysUser implements Serializable, RowMapper<SysUser> {
private static final long serialVersionUID = -1214743110268373599L;
private int id;
private int bid;
private String username;
private String password;
private int scope; // 0:全部,1:部门及以下,2:仅个人
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
protected Date createtime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
protected Date updatetime;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getBid() {
return bid;
}
public void setBid(int bid) {
this.bid = bid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@JsonIgnore
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getScope() {
return scope;
}
public void setScope(int scope) {
this.scope = scope;
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public Date getUpdatetime() {
return updatetime;
}
public void setUpdatetime(Date updatetime) {
this.updatetime = updatetime;
}
@Override
public SysUser mapRow(ResultSet result, int i) throws SQLException {
SysUser user = new SysUser();
user.setId(result.getInt("id"));
user.setUsername(result.getString("username"));
user.setPassword(result.getString("password"));
user.setCreatetime(result.getTimestamp("createtime"));
user.setUpdatetime(result.getTimestamp("updatetime"));
return user;
}
}
然后定义服务类:
/**
* 缓存服务
*
* @author 湘王
*/
@Service
public class CaffeineService {
/**
* 将新增的用户信息放入缓存
*
*/
@CachePut(value = "test", key = "#id")
public int addUser(int id, String username, String password) {
String sql = "";
// TODO SOMETHING
return -1;
}
/**
* 从缓存读取用户信息,id作为key
*
*/
@Cacheable(value = "test", key = "#id")
public SysUser queryById(int id) {
System.out.println("从数据库读取:" + id);
String sql = "";
// TODO SOMETHING
return new SysUser();
}
/**
* 从缓存读取用户信息,username作为key
*
*/
@Cacheable(value = "test", key = "#username")
public SysUser queryByUsername(String username) {
System.out.println("从数据库读取:" + username);
String sql = "";
// TODO SOMETHING
return new SysUser();
}
}
再定义Contorller类:
/**
* 缓存COntroller
*
* @author 湘王
*/
@RestController
public class CacheController {
@Resource
private CaffeineService caffeineService;
/**
* 添加用户
*
*/
@PostMapping("/user/add")
public String add(int id, String username, String password) {
caffeineService.addUser(id, username, password);
return "添加用户成功";
}
/**
* 查询用户
*
*/
@GetMapping("/user/id")
public String id(int id) {
SysUser user = caffeineService.queryById(id);
return "查询到用户:" + user.getUsername();
}
/**
* 查询用户
*
*/
@GetMapping("/user/username")
public String username(String username) {
SysUser user = caffeineService.queryByUsername(username);
return "查询到用户:" + user.getUsername();
}
}
先添加用户,再分别通过ID和用户名查询,可以看到:
1、第一次查询,会从数据库中读取;
2、第二次查询,就直接从Caffeine中读取了。
当超过设定的300s后,再次读取又会从数据中查询。
使用注解的方式简单、快速,但注解缺点是不能灵活操控,如异步存储和无法查看统计信息。
感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~