package com.ruoyi.demo.controller; import cn.hutool.json.JSONString; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.demo.constant.RedisContant; import com.ruoyi.demo.entity.WdInfo; import com.ruoyi.demo.entity.bo.PointBo; import com.ruoyi.demo.entity.vo.TopologicalWdAceeptVo; import com.ruoyi.demo.service.TopologicalCommonService; import com.ruoyi.demo.service.WdInfoService; import io.swagger.v3.oas.models.security.SecurityScheme; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.geo.Point; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; /** * 点位评估-基本功能 */ @RestController @RequestMapping("/poi/common") @Slf4j public class TopologicalCommonController { @Autowired TopologicalCommonService topologicalCommonService; @Autowired WdInfoService wdInfoService; @Autowired RedisTemplate redisTemplate; /** * SSE连接传输 */ private static Map sseCache = new ConcurrentHashMap<>(); /** * 搜索栏——前缀查询 * @param searchText 搜索关键字 * @param size 返回数量 * @return */ @RequestMapping("/prefixSearch") public R prefixSearch(String searchText,Integer size){ List wdInfos = topologicalCommonService.prefixSearch(searchText,size); return R.ok(wdInfos); } /** * 获取半径范围下拉框 * @return */ @RequestMapping("/range") public R range(){ HashMap hashMap = new HashMap<>(); hashMap.put("500m",500); hashMap.put("1km",1000); hashMap.put("2km",2000); return R.ok(hashMap); } /** * 获取中心点相邻点坐标(使用SSE连接) * @param topologicalWdAceeptVo 周边网点接受体 * @return * @throws IOException */ @RequestMapping(path = "/map",produces = {MediaType.TEXT_EVENT_STREAM_VALUE}) public SseEmitter map(TopologicalWdAceeptVo topologicalWdAceeptVo) throws IOException { String md5 = topologicalWdAceeptVo.getHash(); //2.查看redis中是否存在有缓存 List wdCount = (List) redisTemplate.boundHashOps(RedisContant.TOPOLOGICAL_COMMON_MAP).get(md5); if (wdCount != null) { SseEmitter sseEmitter = getSseEmitter(LoginHelper.getUserId()); sendFragment(sseEmitter,wdCount); return sseEmitter; } List map = topologicalCommonService.map(topologicalWdAceeptVo); redisTemplate.boundHashOps(RedisContant.TOPOLOGICAL_COMMON_MAP).put(md5,map); redisTemplate.expire(RedisContant.TOPOLOGICAL_COMMON_MAP,RedisContant.TOPOLOGICAL_COMMON_MAP_TIME, TimeUnit.MINUTES); //30分钟 SseEmitter sseEmitter = getSseEmitter(LoginHelper.getUserId()); sendFragment(sseEmitter,map); return sseEmitter; } /** * SSE连接:获取连接实体类SseEmitter * @param uId 用户Id * @return */ public SseEmitter getSseEmitter(Long uId){ SseEmitter sseEmitter = sseCache.get(uId); if (sseEmitter != null) { return sseEmitter; } // 超时时间设置为3s,用于演示客户端自动重连 // 设置前端的重试时间为1s SseEmitter sseEmitter1 = new SseEmitter(30000L); sseCache.put(uId, sseEmitter1); sseEmitter1.onTimeout(() -> { log.info(uId + "超时"); sseCache.remove(uId); }); //sseEmitter.onCompletion(() -> System.out.println("完成!!!")); return sseEmitter1; } /** * SSE连接:发送信息 * @param sseEmitter * @param wdCount 点位信息 */ public void sendFragment(SseEmitter sseEmitter,List wdCount){ int size = 1000; int pages = wdCount.size()%size == 0 ? wdCount.size()/size:wdCount.size()/size+1; int p1 = 0,p2 = size; for (int i=0;i wdCount.size()) p2 = wdCount.size(); try { sseEmitter.send(SseEmitter.event().name("map").data(JsonUtils.toJsonString(wdCount.subList(p1,p2)))); p1 = p2; p2+=size; } catch (IOException e) { throw new RuntimeException(e); } } } }