自命为缓存之王的Caffeine(4)
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~
说了很多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
声明注入代码:
1 /** 2 * 声明注入代码 3 * 4 * @author 湘王 5 */ 6 @Configuration 7 @Component 8 public class WebConfiguration extends WebMvcConfigurationSupport { 9 /** 10 * 进程外缓存初始化 11 * 12 */ 13 @Bean("cache") 14 public LoadingCache<String, String> cache() { 15 return Caffeine.newBuilder() 16 .initialCapacity(1024) 17 .maximumSize(1024) 18 .expireAfterWrite(1, TimeUnit.HOURS) 19 .build(key -> { 20 return ""; 21 }); 22 } 23 }
然后在代码中调用:
/** * 功能描述 * * @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
定义一个实体类(之前用过的类):
1 /** 2 * 用户entity 3 * 4 * @author 湘王 5 */ 6 public class SysUser implements Serializable, RowMapper<SysUser> { 7 private static final long serialVersionUID = -1214743110268373599L; 8 9 private int id; 10 private int bid; 11 private String username; 12 private String password; 13 private int scope; // 0:全部,1:部门及以下,2:仅个人 14 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 15 protected Date createtime; 16 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 17 protected Date updatetime; 18 19 public int getId() { 20 return id; 21 } 22 23 public void setId(int id) { 24 this.id = id; 25 } 26 27 public int getBid() { 28 return bid; 29 } 30 31 public void setBid(int bid) { 32 this.bid = bid; 33 } 34 35 public String getUsername() { 36 return username; 37 } 38 39 public void setUsername(String username) { 40 this.username = username; 41 } 42 43 @JsonIgnore 44 public String getPassword() { 45 return password; 46 } 47 48 public void setPassword(String password) { 49 this.password = password; 50 } 51 52 public int getScope() { 53 return scope; 54 } 55 56 public void setScope(int scope) { 57 this.scope = scope; 58 } 59 60 public Date getCreatetime() { 61 return createtime; 62 } 63 64 public void setCreatetime(Date createtime) { 65 this.createtime = createtime; 66 } 67 68 public Date getUpdatetime() { 69 return updatetime; 70 } 71 72 public void setUpdatetime(Date updatetime) { 73 this.updatetime = updatetime; 74 } 75 76 @Override 77 public SysUser mapRow(ResultSet result, int i) throws SQLException { 78 SysUser user = new SysUser(); 79 80 user.setId(result.getInt("id")); 81 user.setUsername(result.getString("username")); 82 user.setPassword(result.getString("password")); 83 user.setCreatetime(result.getTimestamp("createtime")); 84 user.setUpdatetime(result.getTimestamp("updatetime")); 85 86 return user; 87 } 88 }
然后定义服务类:
1 /** 2 * 缓存服务 3 * 4 * @author 湘王 5 */ 6 @Service 7 public class CaffeineService { 8 /** 9 * 将新增的用户信息放入缓存 10 * 11 */ 12 @CachePut(value = "test", key = "#id") 13 public int addUser(int id, String username, String password) { 14 String sql = ""; 15 // TODO SOMETHING 16 return -1; 17 } 18 19 /** 20 * 从缓存读取用户信息,id作为key 21 * 22 */ 23 @Cacheable(value = "test", key = "#id") 24 public SysUser queryById(int id) { 25 System.out.println("从数据库读取:" + id); 26 String sql = ""; 27 // TODO SOMETHING 28 return new SysUser(); 29 } 30 31 /** 32 * 从缓存读取用户信息,username作为key 33 * 34 */ 35 @Cacheable(value = "test", key = "#username") 36 public SysUser queryByUsername(String username) { 37 System.out.println("从数据库读取:" + username); 38 String sql = ""; 39 // TODO SOMETHING 40 return new SysUser(); 41 } 42 }
再定义Contorller类:
1 /** 2 * 缓存COntroller 3 * 4 * @author 湘王 5 */ 6 @RestController 7 public class CacheController { 8 @Resource 9 private CaffeineService caffeineService; 10 11 /** 12 * 添加用户 13 * 14 */ 15 @PostMapping("/user/add") 16 public String add(int id, String username, String password) { 17 caffeineService.addUser(id, username, password); 18 return "添加用户成功"; 19 } 20 21 /** 22 * 查询用户 23 * 24 */ 25 @GetMapping("/user/id") 26 public String id(int id) { 27 SysUser user = caffeineService.queryById(id); 28 return "查询到用户:" + user.getUsername(); 29 } 30 31 /** 32 * 查询用户 33 * 34 */ 35 @GetMapping("/user/username") 36 public String username(String username) { 37 SysUser user = caffeineService.queryByUsername(username); 38 return "查询到用户:" + user.getUsername(); 39 } 40 }
先添加用户,再分别通过ID和用户名查询,可以看到:
1、第一次查询,会从数据库中读取;
2、第二次查询,就直接从Caffeine中读取了。
当超过设定的300s后,再次读取又会从数据中查询。
使用注解的方式简单、快速,但注解缺点是不能灵活操控,如异步存储和无法查看统计信息。
感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~