|
|
@@ -30,7 +30,6 @@ import com.fdkankan.scene.vo.*;
|
|
|
import com.google.common.collect.Lists;
|
|
|
import java.util.Map.Entry;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-import net.coobird.thumbnailator.Thumbnails;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.joda.time.DateTime;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
@@ -2178,7 +2177,7 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
|
|
|
|
|
|
|
|
|
@Override
|
|
|
- public ResultData tagSave(SaveHotParamVO param) throws Exception {
|
|
|
+ public ResultData tagSave(SaveTagsParamVO param) throws Exception {
|
|
|
|
|
|
ScenePro scenePro = this.findBySceneNum(param.getNum());
|
|
|
if (scenePro == null)
|
|
|
@@ -2199,7 +2198,7 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
|
|
|
this.deleteHotData(param.getNum(), deleteSidList);
|
|
|
|
|
|
//处理新增和修改数据
|
|
|
- this.addOrUpdateHotData(param.getNum(), addOrUpdateMap);
|
|
|
+ this.addOrUpdateHotDataHandler(param.getNum(), addOrUpdateMap);
|
|
|
|
|
|
//保存数据库
|
|
|
// sceneEditInfoService.saveTagsToSceneEditInfo(param.getNum(), scenePro.getId());
|
|
|
@@ -2208,25 +2207,53 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ResultData addOrUpdateTag(SaveHotParamVO param) throws Exception {
|
|
|
+ public ResultData addOrUpdateTag(SaveTagsParamVO param) throws Exception {
|
|
|
|
|
|
ScenePro scenePro = this.findBySceneNum(param.getNum());
|
|
|
if (scenePro == null)
|
|
|
return ResultData.error(ErrorCode.FAILURE_CODE_5005);
|
|
|
|
|
|
- List<HotParamVO> hotDataList = param.getHotDataList();
|
|
|
+ this.addOrUpdateHotData(param.getNum(), param.getHotDataList());
|
|
|
+
|
|
|
+ this.addOrUpdateIcons(param.getNum(), param.getIcons());
|
|
|
+
|
|
|
+ //写入本地文件,作为备份
|
|
|
+ this.writeHotJson(param.getNum());
|
|
|
+
|
|
|
+
|
|
|
+ //保存数据库
|
|
|
+// sceneEditInfoService.saveTagsToSceneEditInfo(param.getNum(), scenePro.getId());
|
|
|
+
|
|
|
+ return ResultData.ok();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addOrUpdateHotData(String num, List<HotParamVO> hotDataList) throws Exception{
|
|
|
Map<String, String> addOrUpdateMap = new HashMap<>();
|
|
|
hotDataList.stream().forEach(hotData -> {
|
|
|
addOrUpdateMap.put(hotData.getSid(), hotData.getHotData());
|
|
|
});
|
|
|
|
|
|
+ this.syncHotFromFileToRedis(num);
|
|
|
+
|
|
|
//处理新增和修改数据
|
|
|
- this.addOrUpdateHotData(param.getNum(), addOrUpdateMap);
|
|
|
+ this.addOrUpdateHotDataHandler(num, addOrUpdateMap);
|
|
|
+ }
|
|
|
|
|
|
- //保存数据库
|
|
|
-// sceneEditInfoService.saveTagsToSceneEditInfo(param.getNum(), scenePro.getId());
|
|
|
+ private void addOrUpdateIcons(String num, List<String> icons) throws Exception{
|
|
|
|
|
|
- return ResultData.ok();
|
|
|
+ this.syncIconsFromFileToRedis(num);
|
|
|
+
|
|
|
+ String key = String.format(RedisKey.SCENE_HOT_ICONS, num);
|
|
|
+ redisUtil.sSet(key, icons.toArray());
|
|
|
+
|
|
|
+
|
|
|
+// Map<String, String> addOrUpdateMap = new HashMap<>();
|
|
|
+// hotDataList.stream().forEach(hotData -> {
|
|
|
+// addOrUpdateMap.put(hotData.getSid(), hotData.getHotData());
|
|
|
+// });
|
|
|
+
|
|
|
+ //处理新增和修改数据
|
|
|
+// this.addOrUpdateHotData(num, addOrUpdateMap);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -2238,9 +2265,13 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
|
|
|
|
|
|
List<String> deleteSidList = param.getSidList();
|
|
|
|
|
|
+
|
|
|
//处理删除状态数据
|
|
|
this.deleteHotData(param.getNum(), deleteSidList);
|
|
|
|
|
|
+ //写入本地文件,作为备份
|
|
|
+ this.writeHotJson(param.getNum());
|
|
|
+
|
|
|
//保存数据库
|
|
|
// sceneEditInfoService.saveTagsToSceneEditInfo(param.getNum(), scenePro.getId());
|
|
|
|
|
|
@@ -2248,20 +2279,52 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ResultData listTags(String num){
|
|
|
+ public ResultData deleteIcons(DeleteHotIconParamVO param) throws Exception {
|
|
|
+
|
|
|
+ ScenePro scenePro = this.findBySceneNum(param.getNum());
|
|
|
+ if (scenePro == null)
|
|
|
+ return ResultData.error(ErrorCode.FAILURE_CODE_5005);
|
|
|
+
|
|
|
+ List<String> fileNameList = param.getFileNameList();
|
|
|
+
|
|
|
+ this.syncIconsFromFileToRedis(param.getNum());
|
|
|
+
|
|
|
+ String key = String.format(RedisKey.SCENE_HOT_ICONS, param.getNum());
|
|
|
+ redisUtil.setRemove(key, fileNameList.toArray());
|
|
|
+
|
|
|
+ //写入本地文件,作为备份
|
|
|
+ this.writeHotJson(param.getNum());
|
|
|
+
|
|
|
+
|
|
|
+ return ResultData.ok();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ResultData listTags(String num) throws Exception{
|
|
|
+
|
|
|
+ this.syncHotFromFileToRedis(num);
|
|
|
+
|
|
|
+ this.syncIconsFromFileToRedis(num);
|
|
|
+
|
|
|
+ JSONObject result = new JSONObject();
|
|
|
|
|
|
//查询缓存是否包含热点数据
|
|
|
String key = String.format(RedisKey.SCENE_HOT_DATA, num);
|
|
|
Map<String, String> allTagsMap = redisUtil.hmget(key);
|
|
|
- if(CollUtil.isEmpty(allTagsMap)){
|
|
|
- return ResultData.ok();
|
|
|
+ List<JSONObject> tags = null;
|
|
|
+ if(CollUtil.isNotEmpty(allTagsMap)){
|
|
|
+ tags = allTagsMap.entrySet().parallelStream().map(entry -> {
|
|
|
+ return JSON.parseObject(entry.getValue());
|
|
|
+ }).collect(Collectors.toList());
|
|
|
}
|
|
|
+ result.put("tags", tags);
|
|
|
|
|
|
- List<JSONObject> tags = allTagsMap.entrySet().parallelStream().map(entry -> {
|
|
|
- return JSON.parseObject(entry.getValue());
|
|
|
- }).collect(Collectors.toList());
|
|
|
+ //查询缓存是否包含icons
|
|
|
+ key = String.format(RedisKey.SCENE_HOT_ICONS, num);
|
|
|
+ Set<String> icons = redisUtil.sGet(key);
|
|
|
+ result.put("icons", icons);
|
|
|
|
|
|
- return ResultData.ok(tags);
|
|
|
+ return ResultData.ok(result);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -2271,16 +2334,130 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
|
|
|
* @author dengsixing
|
|
|
* @date 2022/3/3
|
|
|
**/
|
|
|
- private void syncHotFromFileToRedis(){
|
|
|
+ private void syncHotFromFileToRedis(String num) throws Exception{
|
|
|
+
|
|
|
+ String key = String.format(RedisKey.SCENE_HOT_DATA, num);
|
|
|
+ boolean exist = redisUtil.hasKey(key);
|
|
|
+ if(exist){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String lockKey = String.format(RedisLockKey.LOCK_HOT_DATA_SYNC, num);
|
|
|
+ boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_1_MINUTE);
|
|
|
+ if(!lock){
|
|
|
+ throw new BusinessException(ErrorCode.SYSTEM_BUSY);
|
|
|
+ }
|
|
|
+ try{
|
|
|
+ exist = redisUtil.hasKey(key);
|
|
|
+ if(exist){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String tagsFilePath = String.format(ConstantFilePath.DATABUFFER_FORMAT, num);
|
|
|
+ String tagsData = FileUtils.readFile(tagsFilePath + "hot.json");
|
|
|
+ JSONObject jsonObject = JSON.parseObject(tagsData);
|
|
|
+ JSONArray tagsArr = jsonObject.getJSONArray("tags");
|
|
|
+ if(CollUtil.isEmpty(tagsArr)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Map<String, String> map = new HashMap<>();
|
|
|
+ for (Object o : tagsArr) {
|
|
|
+ JSONObject jo = (JSONObject)o;
|
|
|
+ map.put(jo.getString("sid"), jo.toJSONString());
|
|
|
+ }
|
|
|
+ redisUtil.hmset(key, map);
|
|
|
+ }finally {
|
|
|
+ redisLockUtil.unlockLua(lockKey);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * <p>
|
|
|
+ 保证icons数据安全性,当redis宕机导致icons数据丢失时,可以从文件中读取,恢复到redis
|
|
|
+ * </p>
|
|
|
+ * @author dengsixing
|
|
|
+ * @date 2022/3/3
|
|
|
+ **/
|
|
|
+ private void syncIconsFromFileToRedis(String num) throws Exception{
|
|
|
+
|
|
|
+ String key = String.format(RedisKey.SCENE_HOT_ICONS, num);
|
|
|
+ boolean exist = redisUtil.hasKey(key);
|
|
|
+ if(exist){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String lockKey = String.format(RedisLockKey.LOCK_HOT_ICONS_SYNC, num);
|
|
|
+ boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_1_MINUTE);
|
|
|
+ if(!lock){
|
|
|
+ throw new BusinessException(ErrorCode.SYSTEM_BUSY);
|
|
|
+ }
|
|
|
+ try{
|
|
|
+ exist = redisUtil.hasKey(key);
|
|
|
+ if(exist){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String tagsFilePath = String.format(ConstantFilePath.DATABUFFER_FORMAT, num);
|
|
|
+ String tagsData = FileUtils.readFile(tagsFilePath + "hot.json");
|
|
|
+ JSONObject jsonObject = JSON.parseObject(tagsData);
|
|
|
+ JSONArray iconArr = jsonObject.getJSONArray("icons");
|
|
|
+ if(CollUtil.isEmpty(iconArr)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ redisUtil.sSet(key, iconArr.toJavaList(String.class).toArray());
|
|
|
+ }finally {
|
|
|
+ redisLockUtil.unlockLua(lockKey);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * <p>
|
|
|
+ 热点数据保存
|
|
|
+
|
|
|
+ * </p>
|
|
|
+ * @author dengsixing
|
|
|
+ * @date 2022/3/3
|
|
|
+ **/
|
|
|
+ private void writeHotJson(String num) throws Exception{
|
|
|
+
|
|
|
+ String dataKey = String.format(RedisKey.SCENE_HOT_DATA, num);
|
|
|
+ Map<String, String> tagMap = redisUtil.hmget(dataKey);
|
|
|
+ List<String> tagList = Lists.newArrayList();
|
|
|
+ tagMap.entrySet().stream().forEach(entry->{
|
|
|
+ if(StrUtil.isNotEmpty(entry.getValue())){
|
|
|
+ tagList.add(entry.getValue());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ JSONArray tagJsonArr = new JSONArray();
|
|
|
+ if(CollUtil.isNotEmpty(tagList)){
|
|
|
+ tagList.stream().forEach(hot->{
|
|
|
+ tagJsonArr.add(JSONObject.parseObject(hot));
|
|
|
+ });
|
|
|
+ }
|
|
|
+ jsonObject.put("tags", tagJsonArr);
|
|
|
+
|
|
|
+ String iconsKey = String.format(RedisKey.SCENE_HOT_ICONS, num);
|
|
|
+ Set<String> iconList = redisUtil.sGet(iconsKey);
|
|
|
+ jsonObject.put("icons", iconList);
|
|
|
+
|
|
|
+ String hotJsonPath = String.format(ConstantFilePath.DATABUFFER_FORMAT, num) + "hot.json";
|
|
|
+ String lockKey = String.format(RedisLockKey.LOCK_HOT_JSON, num);
|
|
|
+ boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_1_MINUTE);
|
|
|
+ if(!lock){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try{
|
|
|
+ FileUtils.writeFile(hotJsonPath, jsonObject.toJSONString());
|
|
|
+ }finally {
|
|
|
+ redisLockUtil.unlockLua(lockKey);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
|
|
|
-// String lockKey = String.format(RedisLockKey.
|
|
|
-// )
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
- private void addOrUpdateHotData(String num, Map<String, String> addOrUpdateMap){
|
|
|
+ private void addOrUpdateHotDataHandler(String num, Map<String, String> addOrUpdateMap){
|
|
|
if(CollUtil.isEmpty(addOrUpdateMap))
|
|
|
return;
|
|
|
|
|
|
@@ -2298,7 +2475,9 @@ public class SceneProServiceImpl extends ServiceImpl<ISceneProMapper, ScenePro>
|
|
|
}
|
|
|
|
|
|
|
|
|
- private void deleteHotData(String num, List<String> deleteSidList) throws IOException {
|
|
|
+ private void deleteHotData(String num, List<String> deleteSidList) throws Exception {
|
|
|
+
|
|
|
+ this.syncHotFromFileToRedis(num);
|
|
|
|
|
|
if(CollUtil.isEmpty(deleteSidList)){
|
|
|
return;
|