导入依赖
<!-- https://mvnrepository.com/artifact/com.github.ben-manes.caffeine/caffeine --><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>3.1.7</version></dependency>
在Service层中调用Caffeine的接口
@Service
public class DiscussPostService {private final static Logger logger = LoggerFactory.getLogger(DiscussPostService.class);@Autowiredprivate DiscussPostMapper discussPostMapper;@Value("${caffeine.posts.max-size}")private int maxSize;@Value("${caffeine.posts.expire-seconds}")private int expireSeconds;// Caffeine's core API: Cache, LoadingCache, AsyncLoadingCache// posts list cacheprivate LoadingCache<String, List<DiscussPost>> postListCache;// posts total number cacheprivate LoadingCache<Integer, Integer> postRowsCache;@PostConstructpublic void init(){// initialize the post list cachepostListCache = Caffeine.newBuilder().maximumSize(maxSize).expireAfterWrite(expireSeconds, TimeUnit.SECONDS).build(new CacheLoader<String, List<DiscussPost>>() {@Overridepublic @Nullable List<DiscussPost> load(String key) throws Exception {if(key == null || key.length() == 0){throw new IllegalArgumentException("parameter error: key must not be null");}String[] params = key.split(":");if(params == null || params.length != 2) {throw new IllegalArgumentException("parameter error");}int offset = Integer.valueOf(params[0]);int limit = Integer.valueOf(params[1]);// in there, we can add second level cache, such as Redis// if we can't find data in the Redis, then query it in MySQLlogger.debug("load post list from DB...");return discussPostMapper.selectDiscussPosts(0, offset, limit, 1);}});// initialize the post total number cachepostRowsCache = Caffeine.newBuilder().maximumSize(maxSize).expireAfterWrite(expireSeconds, TimeUnit.SECONDS).build(new CacheLoader<Integer, Integer>() {@Overridepublic @Nullable Integer load(Integer key) throws Exception {logger.debug("load post list from DB...");return discussPostMapper.selectDiscussPostRows(key);}});}public List<DiscussPost> findDiscussPosts(int userId, int offset, int limit, int orderMode) {if(userId == 0 && orderMode == 1){return postListCache.get(offset + ":" + limit);}logger.debug("load post list from DB...");return discussPostMapper.selectDiscussPosts(userId, offset, limit, orderMode);}public int findDiscussPostRows(int userId) {if (userId == 0) {return postRowsCache.get(userId);}logger.debug("load post rows from DB...");return discussPostMapper.selectDiscussPostRows(userId);}
}
测试
@SpringBootTest
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MyCommunityApplication.class)
public class CaffeineTest {@Autowiredprivate DiscussPostService postService;@Testpublic void testCache(){System.out.println(postService.findDiscussPosts(0, 0, 10, 1));System.out.println(postService.findDiscussPosts(0, 0, 10, 1));System.out.println(postService.findDiscussPosts(0, 0, 10, 1));System.out.println(postService.findDiscussPosts(0, 0, 10, 0));}
}
结果:
可以看到,第一次记录还未加入缓存,所以是从DB中加载,而后两次访问记录都是从Caffeine中加载的;最后一次访问是强制要求从DB中访问的。