redis+redisson/setnx/synchronized具体用法
原创一、controller输入代码,获取目录信息。
@ResponseBody
@GetMapping("/index/catalog.json")
public Map> getCatalogJson(){
Map> catalogJson = categoryService.getCatalogJson();
return catalogJson;
}

二、service层

三、serviceImpl层
@Override
public Map> getCatalogJson() {
//注意:将其放入缓存中。json串,取出json字符串也会反转为可以使用的对象类型(即序列化和反序列化过程)。
//1,加入缓存逻辑,缓存中存储的数据是json字符串。json优点是跨语言、跨平台的兼容性。
String catalogJSON = stringRedisTemplate.opsForValue().get("catalogJSON");
if (StringUtils.isEmpty(catalogJSON)) {
//2如果不在缓存中,请检查数据库
Map> catalogJsonFromDB = this.getCatalogJsonFromDBWithRedissonLock();//使用redisson分布式锁
//Map> catalogJsonFromDB = this.getCatalogJsonFromDBWithRedisLock();//使用本机redis的setnx添加分布式锁
//Map> catalogJsonFromDB = this.getCatalogJsonFromDBWithLocalLock();//在单个实例下使用synchronized加锁即可
//3找到的数据在缓存中,转动找到的对象json放入缓存 --重要提示:这不是原子操作。应将其放入检查数据库的方法中,以便由锁控制。因此,下面的代码被注释掉,并放入检查数据库的方法中。
// String s = JSON.toJSONString(catalogJsonFromDB);
// stringRedisTemplate.opsForValue().set("catalogJSON",s);
// return catalogJsonFromDB;
}
Map> result = JSON.parseObject(catalogJSON, new TypeReference
" +
"then
" +
" return redis.call("del",KEYS[1])
" +
"else
" +
" return 0
" +
"end";
stringRedisTemplate.execute(new DefaultRedisScript
}
}
//上面方法的再次进化:查询并封装数据库中的分类数据。 --使用redisson执行分布式锁
public Map> getCatalogJsonFromDBWithRedissonLock() {
RLock lock = redisson.getLock("CatalogJson-lock");
lock.lock();
Map> dataFromDB;
try{
dataFromDB = getDataFromDB();
}finally{
lock.unlock();
}
return dataFromDB;
}
//查找数据库并将其放入缓存的方法。
private Map> getDataFromDB() {
//查出所有1级分类
List level1Categorys = this.getLevel1Categorys();
//封装数据
Map> parent_cid = level1Categorys.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> {
//每个初级分类,找到该初级分类的次级分类。
List categoryEntities = baseMapper.selectList(new QueryWrapper().eq("parent_cid", v.getCatId()));
//封装上述结果
List category2Vos = null;
if (categoryEntities != null) {
category2Vos = categoryEntities.stream().map(l2 -> {
Category2Vo category2Vo = new Category2Vo(v.getCatId().toString(), null, l2.getCatId().toString(), l2.getName());
//查找三级分类包的当前二级分类。vo
List level3Catelog = baseMapper.selectList(new QueryWrapper().eq("parent_cid", l2.getCatId()));
if (level3Catelog != null) {
List collect = level3Catelog.stream().map(l3 -> {
//以指定格式封装
Category2Vo.Catelog3Vo catelog3Vo = new Category2Vo.Catelog3Vo(l2.getCatId().toString(), l3.getCatId().toString(), l3.getName());
return catelog3Vo;
}).collect(Collectors.toList());
category2Vo.setCatelog3List(collect);
}
return category2Vo;
}).collect(Collectors.toList());
}
return category2Vos;
}));
//3找到的数据在缓存中,转动找到的对象json放入缓存 --重要提示:这不是原子操作,应该放置getCatalogJsonFromDB方法,让它成为主题synic..管制
String s = JSON.toJSONString(parent_cid);
stringRedisTemplate.opsForValue().set("catalogJSON", s);
return parent_cid;
} 版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除
上一篇:建立FastDFS的client 下一篇:进程池实战讲解+完整内容
itfan123



