lyhzzz 11 月之前
父節點
當前提交
932af05a2d

+ 5 - 1
pom.xml

@@ -144,7 +144,11 @@
             <version>5.8.6</version>
         </dependency>
 
-
+        <!--websocket-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 1 - 0
src/main/java/com/fdkankan/fusion/FusionApplication.java

@@ -6,6 +6,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.transaction.annotation.EnableTransactionManagement;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
 
 @SpringBootApplication
 @EnableTransactionManagement//开启事务

+ 3 - 1
src/main/java/com/fdkankan/fusion/common/ResultCode.java

@@ -66,7 +66,9 @@ public enum ResultCode {
     SS_SCENE_DOWN_ERROR(7020,"深时点云场景下载失败"),
     FILE_NOT_EXIST(7021,"文件不存在,或已被刪除"),
 
-    HOST_ICON_LIMIT(7022,"案件图标超过上限")
+    HOST_ICON_LIMIT(7022,"案件图标超过上限"),
+
+    CASE_REMOVE_SCENE(7023,"场景被移除"),
 
     ;
 

+ 1 - 1
src/main/java/com/fdkankan/fusion/config/SaTokenConfigure.java

@@ -44,7 +44,7 @@ public class SaTokenConfigure {
     public SaServletFilter getSaServletFilter() {
         return new SaServletFilter()
                 // 指定 拦截路由 与 放行路由
-                .addInclude("/**").addExclude("/**/test/**","/**/inner/**","/**/notAuth/**")
+                .addInclude("/**").addExclude("/**/test/**","/**/inner/**","/**/notAuth/**","/**ws/**")
                 // 认证函数: 每次请求执行
                 .setAuth(obj -> {
                     String share = SaHolder.getRequest().getHeader("share");

+ 11 - 0
src/main/java/com/fdkankan/fusion/service/impl/CaseNumServiceImpl.java

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONArray;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.fdkankan.fusion.common.FilePath;
 import com.fdkankan.fusion.common.ResultCode;
+import com.fdkankan.fusion.common.ResultData;
 import com.fdkankan.fusion.common.util.*;
 import com.fdkankan.fusion.entity.CaseNumEntity;
 import com.fdkankan.fusion.entity.Model;
@@ -14,6 +15,9 @@ import com.fdkankan.fusion.mapper.ICaseNumMapper;
 import com.fdkankan.fusion.request.SceneNumParam;
 import com.fdkankan.fusion.service.*;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.fusion.websocket.SessionService;
+import com.fdkankan.fusion.websocket.enums.CommonEnum;
+import com.fdkankan.fusion.websocket.vo.WsMessage;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -56,6 +60,8 @@ public class CaseNumServiceImpl extends ServiceImpl<ICaseNumMapper, CaseNumEntit
     ICaseTagService caseTagService;
     @Autowired
     ICaseTagPointService caseTagPointService;
+    @Autowired
+    SessionService sessionService;
 
     @Override
     public List<CaseNumEntity> getByCaseId(Integer caseId) {
@@ -179,6 +185,7 @@ public class CaseNumServiceImpl extends ServiceImpl<ICaseNumMapper, CaseNumEntit
 
     private List<String> updateByNumList(Integer caseId, List<SceneNumParam> sceneNumParam) {
         List<String> addList = new ArrayList<>();
+        List<String> delMsgList = new ArrayList<>();
         for (SceneNumParam param : sceneNumParam) {
             Integer type = param.getType();
             List<String> numList = param.getNumList();
@@ -191,6 +198,7 @@ public class CaseNumServiceImpl extends ServiceImpl<ICaseNumMapper, CaseNumEntit
             for (String num : hanNumList) {
                 if(!numList.contains(num)){
                     delList.add(num);
+                    delMsgList.add(num);
                 }
             }
             for (String num : numList) {
@@ -200,6 +208,9 @@ public class CaseNumServiceImpl extends ServiceImpl<ICaseNumMapper, CaseNumEntit
             }
             this.deleteByNum(caseId,delList,param.getType());
         }
+        if(!delMsgList.isEmpty()){
+            sessionService.sendSingleByCaseId(caseId, WsMessage.okResult(CommonEnum.NOTICE, ResultData.ok(ResultCode.CASE_REMOVE_SCENE)));
+        }
 
         return addList;
     }

+ 4 - 1
src/main/java/com/fdkankan/fusion/service/impl/TmDepartmentServiceImpl.java

@@ -79,7 +79,10 @@ public class TmDepartmentServiceImpl extends ServiceImpl<ITmDepartmentMapper, Tm
         if(dept.getId().equals(dept.getParentId())){
             throw new BusinessException(ResultCode.DEPT_EDIT_ERROR);
         }
-        if(dept.getLevel() != null && dept.getLevel() >4){
+        List<TmDepartment> tmDepartments = new ArrayList<>();
+        this.getParentList(dept.getParentId(),tmDepartments);
+        List<TmDepartment> collect2 = tmDepartments.stream().filter(entity -> !entity.getId().equals("0")).collect(Collectors.toList());
+        if(collect2.size() >=4){
             throw new BusinessException(ResultCode.DEPT_ADD_ERROR);
         }
         List<TmDepartment> sonByDeptId = this.getSonByDeptId(dept.getId());

+ 99 - 0
src/main/java/com/fdkankan/fusion/websocket/MyWebSocketServer.java

@@ -0,0 +1,99 @@
+package com.fdkankan.fusion.websocket;
+
+
+import com.fdkankan.fusion.common.ResultData;
+import com.fdkankan.fusion.websocket.enums.CommonEnum;
+import com.fdkankan.fusion.websocket.service.MessageService;
+import com.fdkankan.fusion.websocket.vo.WsMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+
+@Component
+@ServerEndpoint(value = "/ws/{caseId}",configurator = WebSocketConfigurator.class)
+public class MyWebSocketServer {
+
+    private Logger webSocketLogger = LoggerFactory.getLogger("webSocketLogger");
+
+    private static SessionService sessionService;
+
+    private static MessageService messageService;
+
+    @Autowired
+    public void setWebSocketServerHandler(SessionService sessionService, MessageService messageService) {
+        MyWebSocketServer.sessionService = sessionService;
+        MyWebSocketServer.messageService = messageService;
+    }
+
+    @OnOpen
+    public void onOpen(Session session, @PathParam("caseId") Integer caseId) {
+        try {
+            Long startTime = System.currentTimeMillis();
+            session.getUserProperties().put("caseId" , caseId);
+            sessionService.onOpen(session, caseId);
+            sessionService.sendSingleBySession(WsMessage.okResult(CommonEnum.ON_OPEN, ResultData.ok("连接建立成功")),session);
+            Long endTime = System.currentTimeMillis();
+            if(endTime -startTime > 100){
+                webSocketLogger.info("WebSocketServer|onOpenStart|" + "session = [" + session.getId() + "]" +",startTime = "+ startTime);
+                webSocketLogger.info("WebSocketServer|onOpenOver|" + "session = [" + session.getId() + "]" +",endTime = "+ endTime+", totalTime = "+(endTime-startTime));
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @OnClose
+    public void onClose(Session session) {
+        try {
+            sessionService.onClose(session);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @OnError
+    public void onError(Session session, Throwable error) {
+        if (error instanceof IOException) {
+            webSocketLogger.error("错误,断开链接{},{}", session, error.getMessage());
+        } else {
+            webSocketLogger.error("错误,断开链接{}", session, error);
+        }
+        try {
+            session.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 收到客户端消息后调用的方法
+     *
+     * @param msg 客户端发送过来的消息
+     */
+    @OnMessage
+    public void onMessage(String msg, Session session) {
+        try {
+            if(StringUtils.isEmpty(msg)){
+                return;
+            }
+            Long startTime = System.currentTimeMillis();
+            messageService.onMessage(msg, session);
+            Long endTime = System.currentTimeMillis();
+            if(endTime -startTime > 100){
+                webSocketLogger.info("WebSocketServer|onMessageStart|" + "request = "+ msg + "session = [" + session.getId() + "]"+ ",startTime = "+ startTime);
+                webSocketLogger.info("WebSocketServer|onMessageOver|" + "request = "+ msg +"session = [" + session.getId() + "]" +",endTime = "+ endTime+", totalTime = "+(endTime-startTime));
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+}

+ 128 - 0
src/main/java/com/fdkankan/fusion/websocket/SessionService.java

@@ -0,0 +1,128 @@
+package com.fdkankan.fusion.websocket;
+
+import com.alibaba.druid.util.Utils;
+import com.fdkankan.fusion.entity.TmUser;
+import com.fdkankan.fusion.service.ITmUserService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.Session;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReentrantLock;
+
+@Component("sessionService")
+public class SessionService {
+    private static Logger webSocketLogger = LoggerFactory.getLogger("webSocketLogger");
+
+    public static ConcurrentHashMap<Session, Integer> sessionMap = new ConcurrentHashMap<>();
+
+
+
+
+    /**
+     * 用户注册和离开都需要这个锁
+     */
+    private final ReentrantLock lock = new ReentrantLock();
+
+
+    /**
+     * 用户链接上来
+     *
+     * @param session
+     */
+    public void onOpen(Session session, Integer caseId) {
+
+        try {
+            lock.lock();
+            sessionMap.put(session,caseId);
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            lock.unlock();
+        }
+
+    }
+
+
+    /**
+     * 关闭
+     *
+     * @param session
+     */
+    public void onClose(Session session) {
+        try {
+            lock.lock();
+            sessionMap.remove(session.getId());
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+
+    /**
+     * 服务端向 全体客户端广播消息
+     *
+     * @param message
+     */
+    public synchronized void sendALL(String message) {
+        Set<Session> keySet = sessionMap.keySet();
+        if (keySet.isEmpty()) {
+            return;
+        }
+        sessionMap.forEach((session, caseId) -> {
+            if (null != session && session.isOpen()) {
+                sendMessage(message,session);
+            }
+        });
+    }
+
+
+    /**
+     * 服务端向 通过token向客服端发送消息
+     *
+     * @param message
+     */
+    public synchronized void sendSingleByCaseId(Integer caseId, String message) {
+        Set<Session> keySet = sessionMap.keySet();
+        if (keySet.isEmpty()) {
+            return;
+        }
+        if(!sessionMap.containsValue(caseId)){
+            return;
+        }
+        sessionMap.forEach((session, caseIdMap) -> {
+            if (null != session && session.isOpen() && caseIdMap.equals(caseId)) {
+                sendMessage(message,session);
+            }
+        });
+    }
+
+    public void sendSingleBySession(String msg, Session session) {
+        sendMessage(msg, session);
+    }
+
+    private synchronized  void sendMessage(String msg, Session session) {
+
+
+        if (null == session || !session.isOpen()) {
+            return;
+        }
+        synchronized (session) {
+            try {
+                session.getBasicRemote().sendText(msg);
+            } catch(Exception e){
+                webSocketLogger.error("---------------------------------------------------->"+e.getMessage()+"\n"+ Utils.toString(e.getStackTrace()));
+            }
+        }
+    }
+
+
+}

+ 25 - 0
src/main/java/com/fdkankan/fusion/websocket/WebSocketConfig.java

@@ -0,0 +1,25 @@
+package com.fdkankan.fusion.websocket;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * SpringBoot + WebSocket 是用@ServerEndpoint注入,必须有此配置
+ *
+ */
+@Configuration
+public class WebSocketConfig {
+
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        return new ServerEndpointExporter();
+    }
+
+
+}
+

+ 85 - 0
src/main/java/com/fdkankan/fusion/websocket/WebSocketConfigurator.java

@@ -0,0 +1,85 @@
+package com.fdkankan.fusion.websocket;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.context.annotation.Configuration;
+
+import javax.servlet.http.HttpSession;
+import javax.websocket.HandshakeResponse;
+import javax.websocket.server.HandshakeRequest;
+import javax.websocket.server.ServerEndpointConfig;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Configuration
+public class WebSocketConfigurator extends ServerEndpointConfig.Configurator{
+    public static final String HTTP_SESSION_ID_ATTR_NAME = "HTTP.SESSION.ID";
+
+    @Override
+    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
+
+        Map<String, Object> attributes = sec.getUserProperties();
+        HttpSession session = (HttpSession) request.getHttpSession();
+        if (session != null) {
+            attributes.put(HTTP_SESSION_ID_ATTR_NAME, session.getId());
+            Enumeration<String> names = session.getAttributeNames();
+            while (names.hasMoreElements()) {
+                String name = names.nextElement();
+                attributes.put(name, session.getAttribute(name));
+            }
+
+        }
+
+
+        Map<String, List<String>> headerList =   request.getHeaders();
+        String ip = getIpAddr(headerList);
+        attributes.put("clientIp" , ip);
+
+    }
+
+
+    private String getIpAddr(Map<String, List<String>> headerList) {
+        String ip = null;
+        try {
+            ip = getHeader("x-forwarded-for" , headerList);
+            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+                ip = getHeader("Proxy-Client-IP" , headerList);
+            }
+            if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+                ip = getHeader("WL-Proxy-Client-IP" , headerList);
+            }
+            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+                ip = getHeader("HTTP_CLIENT_IP" , headerList);
+            }
+            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+                ip = getHeader("HTTP_X_FORWARDED_FOR" , headerList);
+            }
+            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+                ip = headerList.get("host").get(0);
+            }
+        } catch (Exception e) {
+            log.error("MyWebListener|getIpAddr|" + e.getMessage(), e);
+        }
+        // 使用代理,则获取第一个IP地址
+        if (StringUtils.isNotBlank(ip) && ip.length() > 15) {
+            if (StringUtils.contains(ip, ",")) {
+                ip = StringUtils.substringBefore(ip, ",");
+            }
+        }
+        if (StringUtils.startsWith(ip, "0:0:0:0:0:0:0")) {
+            ip = "127.0.0.1";
+        }
+        return ip;
+    }
+
+    private String getHeader(String key , Map<String, List<String>> headerList){
+        List<String> l = headerList.get(key);
+        if(null == l){
+            return null;
+        }
+
+        return l.get(0);
+    }
+}

+ 7 - 0
src/main/java/com/fdkankan/fusion/websocket/enums/CommonEnum.java

@@ -0,0 +1,7 @@
+package com.fdkankan.fusion.websocket.enums;
+
+public class CommonEnum {
+    public final static String ON_OPEN = "open";
+    public final static String PING = "ping";
+    public final static String NOTICE = "notice";
+}

+ 40 - 0
src/main/java/com/fdkankan/fusion/websocket/service/MessageService.java

@@ -0,0 +1,40 @@
+package com.fdkankan.fusion.websocket.service;
+
+import com.alibaba.fastjson.JSON;
+import com.fdkankan.fusion.common.ResultData;
+import com.fdkankan.fusion.websocket.SessionService;
+import com.fdkankan.fusion.websocket.enums.CommonEnum;
+import com.fdkankan.fusion.websocket.vo.RequestMsg;
+import com.fdkankan.fusion.websocket.vo.WsMessage;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.websocket.Session;
+
+@Service
+public class MessageService {
+
+    @Autowired
+    private SessionService sessionService;
+
+    public void onMessage(String msg, Session session) {
+        if (StringUtils.isBlank(msg)) {
+            return;
+        }
+        RequestMsg requestMsg = JSON.parseObject(msg, RequestMsg.class);
+
+        switch (requestMsg.getCommand()) {
+            case CommonEnum.PING:
+                messageByPing(requestMsg, session); //ping
+                break;
+            default:
+                break;
+        }
+    }
+
+    private void messageByPing(RequestMsg requestMsg, Session session) {
+        String msg = WsMessage.okResult(CommonEnum.PING, ResultData.ok("ping"));
+        sessionService.sendSingleBySession(msg, session);
+    }
+}

+ 45 - 0
src/main/java/com/fdkankan/fusion/websocket/vo/RequestMsg.java

@@ -0,0 +1,45 @@
+package com.fdkankan.fusion.websocket.vo;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/***
+ * 前端发来的信息结构对象
+ */
+public class RequestMsg implements Serializable {
+
+    private String command;
+    private int requestId;
+    private Map<String, Object> content;
+
+    public Object getMapValue(String key){
+        if(content != null){
+            return  content.get(key);
+        }
+        return null;
+    }
+
+    public String getCommand() {
+        return command;
+    }
+
+    public void setCommand(String command) {
+        this.command = command;
+    }
+
+    public Map<String, Object> getContent() {
+        return content;
+    }
+
+    public void setContent(Map<String, Object> content) {
+        this.content = content;
+    }
+
+    public int getRequestId() {
+        return requestId;
+    }
+
+    public void setRequestId(int requestId) {
+        this.requestId = requestId;
+    }
+}

+ 26 - 0
src/main/java/com/fdkankan/fusion/websocket/vo/WsMessage.java

@@ -0,0 +1,26 @@
+package com.fdkankan.fusion.websocket.vo;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author tang
+ */
+public class WsMessage {
+
+
+    public static String okResult(String command, Object content) {
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("command", command);
+        jsonObject.put("content", content);
+        return jsonObject.toJSONString();
+    }
+
+
+
+
+
+
+}