上篇文章介绍了Read的使用与实现。但在整合到Halo的之前的实现就感觉有点不太适用故新增一个基于AbstractStringCacheStore来实现一个Read
代码实现
/**
* @author: HeHui
* @date: 2020-07-21 11:05
* @description: 本地缓存阅读
*/
@Slf4j
public class LocalCacheRead<POST extends BasePost> extends ReadAbstract<Double,Integer> {
private final AbstractStringCacheStore stringCacheStore;
private final String cacheKey;
/**
* 本地缓存读
*
* @param maxRead 最大阅读数
* @param jobSeconds 工定时秒
* @param stringCacheStore 字符串数据缓存
* @param basePostService 基地发布服务
* @param cacheKey 缓存键
*/
public LocalCacheRead(Double maxRead, int jobSeconds, AbstractStringCacheStore stringCacheStore,BasePostService basePostService,String cacheKey) {
super(maxRead, jobSeconds, new VisitReadStorage(basePostService,cacheKey));
this.cacheKey = cacheKey;
this.stringCacheStore = stringCacheStore;
}
/**
* 增加
*
* @param id id
* @param readNumber 阅读数量
* @return {@link Optional<Double>}
*/
@Override
protected Optional<Double> increase(Integer id, Double readNumber) {
Map<Integer, Double> cache = getCache();
if(cache == null){
cache = new HashMap<>(128);
}
Double aDouble = cache.getOrDefault(id,0D);
cache.put(id,aDouble + readNumber);
stringCacheStore.putAny(cacheKey,cache);
return Optional.ofNullable(aDouble + readNumber);
}
/**
* 减少
*
* @param id id
* @param readNumber 阅读数量
*/
@Override
protected void reduce(Integer id, Double readNumber) {
Map<Integer, Double> cache = getCache();
if(MapUtil.isNotEmpty(cache)){
Double aDouble = cache.get(id);
if(aDouble == null || aDouble <= readNumber){
cache.remove(id);
}else{
cache.put(id,aDouble - readNumber);
}
stringCacheStore.putAny(cacheKey,cache);
}
}
/**
* 得到所有
*
* @return {@link Optional<Map<Integer, Double>>}
*/
@Override
protected Optional<Map<Integer, Double>> getAll() {
return Optional.ofNullable(getCache());
}
/**
* 清除
*/
@Override
protected void clear() {
stringCacheStore.delete(cacheKey);
}
/**
* 清除
*
* @param id id
* @return {@link Optional<Double>}
*/
@Override
public Optional<Double> getRead(Integer id) {
Map<Integer, Double> cache = getCache();
if(MapUtil.isNotEmpty(cache)){
return Optional.ofNullable(cache.get(id));
}
return Optional.empty();
}
/**
* 查询指定
* @param ids
* @return {@link Optional<Map<Integer, Double>>}
*/
@Override
public Optional<Map<Integer, Double>> getReads(List<Integer> ids) {
Map<Integer, Double> map = getCache();
if(MapUtil.isNotEmpty(map)){
Optional.ofNullable(map.entrySet().stream().filter(v->ids.contains(v.getKey())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
}
return Optional.empty();
}
/**
* 查询缓存
* @return
*/
private Map<Integer, Double> getCache(){
Optional<Map> optional = stringCacheStore.getAny(cacheKey, Map.class);
if(optional.isPresent()){
/**
* key适用String 是因为在测试过程中发现 getAny 转换的key就是String 如果声明Integer在获取时就会报错
*/
Map<String,Double> map = optional.get();
return map.entrySet().stream().collect(Collectors.toMap(v->Integer.valueOf(v.getKey()), Map.Entry::getValue));
}
return null;
}
/**
* 阅读数存储
*/
static class VisitReadStorage implements ReadStorage<Double,Integer>{
private BasePostService postService;
private String name;
VisitReadStorage(BasePostService basePostService,String name){
this.postService = basePostService;
this.name = name;
}
@Override
public void increase(Integer posId, Double n) {
postService.increaseVisit(n.longValue(),posId);
log.info("{} 新增阅读数:{},postId:{}",name,n,posId);
}
@Override
public void increase(Map<Integer, Double> map) {
log.info("{}: 定时清除阅读数",name);
try {
postService.increaseListVisit(map);
}catch (Exception e){
log.error("{} 定时清除阅读数异常:", name,e);
}
}
}
}
配置
特别注意:cahceKey不要重复,此处的参数可改为配置的
/**
* post 阅读器缓存
* @param stringCacheStore
* @param postService
* @return
*/
@Bean
@Primary
public LocalCacheRead<Post> postLocalCacheRead(AbstractStringCacheStore stringCacheStore, PostService postService){
return new LocalCacheRead<Post>(35D,300,stringCacheStore,postService,"post:read:cache" );
}
/**
* Sheet 阅读器缓存
* @param stringCacheStore
* @param sheetService
* @return
*/
@Bean
public LocalCacheRead<Sheet> sheetLocalCacheRead(AbstractStringCacheStore stringCacheStore, SheetService sheetService){
return new LocalCacheRead<Sheet>(12D,300,stringCacheStore,sheetService,"sheet:read:cache" );
}
使用
/**
* Visit event listener.
*
* @author johnniang
* @date 19-4-22
*/
@Component
public class PostVisitEventListener extends AbstractSmoothVisitEventListener<Post> {
public PostVisitEventListener(run.halo.app.core.LocalCacheRead<Post> read) {
super(read);
}
@Async
@EventListener
public void onPostVisitEvent(PostVisitEvent event) throws InterruptedException {
handleVisitEvent(event);
}
}
实时显示最新阅读数
实时显示最新阅读数只需要在需要显示最新阅读数的代码中加上就好Read提供Optional
getRead(ID key)和Optional<Map<ID,T>> getReads(List keys)
目前需要加的地方有
- PostController#pageBy
- PostController#pageByStatus
- PostModel#content
- PostModel#list
评论区