Просмотр исходного кода

热点相关接口增加处理icons逻辑
增加删除icons接口

dengsixing 4 лет назад
Родитель
Сommit
16437177d3

+ 16 - 3
4dkankan-center-scene/src/main/java/com/fdkankan/scene/controller/SceneEditController.java

@@ -7,7 +7,6 @@ import com.fdkankan.scene.service.ISceneProService;
 import com.fdkankan.scene.service.ISceneUploadService;
 import com.fdkankan.scene.vo.*;
 import com.fdkankan.common.response.ResultData;
-import java.io.IOException;
 import java.util.List;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -226,7 +225,7 @@ public class SceneEditController extends BaseController {
      * @return com.fdkankan.common.response.ResultData
      **/
     @PostMapping(value = "/tagSave")
-    public ResultData tagSave(@RequestBody @Validated SaveHotParamVO param) throws Exception {
+    public ResultData tagSave(@RequestBody @Validated SaveTagsParamVO param) throws Exception {
         return sceneProService.tagSave(param);
     }
 
@@ -240,7 +239,7 @@ public class SceneEditController extends BaseController {
      * @return com.fdkankan.common.response.ResultData
      **/
     @PostMapping(value = "/tag/save")
-    public ResultData saveTag(@RequestBody @Validated SaveHotParamVO param) throws Exception {
+    public ResultData saveTag(@RequestBody @Validated SaveTagsParamVO param) throws Exception {
         return sceneProService.addOrUpdateTag(param);
     }
 
@@ -265,6 +264,20 @@ public class SceneEditController extends BaseController {
 
     /**
      * <p>
+     删除热点
+     * </p>
+     * @author dengsixing
+     * @date 2022/2/16
+     * @param param
+     * @return com.fdkankan.common.response.ResultData
+     **/
+    @PostMapping(value = "/icons/delete")
+    public ResultData deleteIcons(@RequestBody @Validated DeleteHotIconParamVO param) throws Exception {
+        return sceneProService.deleteIcons(param);
+    }
+
+    /**
+     * <p>
      保存场景热点
      * </p>
      * @author dengsixing

+ 7 - 5
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/ISceneProService.java

@@ -5,9 +5,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.fdkankan.common.response.ResultData;
 import com.fdkankan.scene.entity.ScenePro;
 import com.fdkankan.scene.entity.SceneProPO;
+import com.fdkankan.scene.vo.DeleteHotIconParamVO;
 import com.fdkankan.scene.vo.DeleteHotParamVO;
 import com.fdkankan.scene.vo.FileNameAndDataParamVO;
-import com.fdkankan.scene.vo.SaveHotParamVO;
+import com.fdkankan.scene.vo.SaveTagsParamVO;
 import com.fdkankan.scene.vo.BaseDataParamVO;
 import com.fdkankan.scene.vo.SaveTagsVisibleParamVO;
 import com.fdkankan.scene.vo.SceneEditParamVO;
@@ -15,7 +16,6 @@ import com.fdkankan.scene.vo.SceneParamVO;
 import com.fdkankan.scene.vo.SceneVO;
 import com.fdkankan.scene.vo.FileParamVO;
 import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
@@ -87,13 +87,15 @@ public interface ISceneProService extends IService<ScenePro> {
 
     ResultData uploadHotMedia(FileParamVO param, MultipartFile file) throws Exception;
 
-    ResultData tagSave(SaveHotParamVO param) throws Exception;
+    ResultData tagSave(SaveTagsParamVO param) throws Exception;
 
-    ResultData addOrUpdateTag(SaveHotParamVO param) throws Exception;
+    ResultData addOrUpdateTag(SaveTagsParamVO param) throws Exception;
 
     ResultData deleteTag(DeleteHotParamVO param) throws Exception;
 
-    ResultData listTags(String num);
+    ResultData deleteIcons(DeleteHotIconParamVO param) throws Exception;
+
+    ResultData listTags(String num) throws Exception;
 
     ResultData saveShopHot(SceneEditParamVO base) throws Exception;
 

+ 200 - 21
4dkankan-center-scene/src/main/java/com/fdkankan/scene/service/impl/SceneProServiceImpl.java

@@ -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;

+ 27 - 0
4dkankan-center-scene/src/main/java/com/fdkankan/scene/vo/DeleteHotIconParamVO.java

@@ -0,0 +1,27 @@
+package com.fdkankan.scene.vo;
+
+import java.util.List;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * <p>
+ * 删除热点icons数据参数类
+ * </p>
+ *
+ * @author dengsixing
+ * @since 2022/2/8
+ **/
+@Data
+public class DeleteHotIconParamVO {
+
+    @NotBlank(message = "场景码不能为空")
+    private String num;
+
+    @NotNull(message = "fileNameList不能为空")
+    private List<String> fileNameList;
+
+
+
+}

+ 5 - 1
4dkankan-center-scene/src/main/java/com/fdkankan/scene/vo/SaveHotParamVO.java

@@ -15,7 +15,7 @@ import lombok.Data;
  * @since 2022/2/8
  **/
 @Data
-public class SaveHotParamVO {
+public class SaveTagsParamVO {
 
     @NotBlank(message = "场景码不能为空")
     private String num;
@@ -24,6 +24,10 @@ public class SaveHotParamVO {
     @NotNull(message = "热点数据不能为空")
     private List<HotParamVO> hotDataList;
 
+    @Valid
+    @NotNull(message = "icons数据不能为空")
+    private List<String> icons;
+
 
 
 }