huang
2025-07-25 cf4622df137c26d238730316651f214fd29ca65f
修改最新websocket
8个文件已修改
2个文件已添加
1个文件已删除
529 ■■■■ 已修改文件
JiuMuMesParent/common/servicebase/src/main/java/com/mes/tools/WebSocketServer.java 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/common/servicebase/src/main/java/com/mes/websocket/WebSocketServer.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/common/servicebase/src/main/java/com/mes/websocket/WebSocketUtils.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/impl/EnergyConsumptionServiceImpl.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/job/AddTask.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/job/MachineTask.java 64 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/job/PLCCleaning.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/mechanicalMonitor/controller/MechanicalMonitorController.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/mechanicalMonitor/service/impl/MechanicalMonitorServiceImpl.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/plannedAmount/service/impl/PlannedAmountImpl.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/yield/service/impl/YieldServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/common/servicebase/src/main/java/com/mes/tools/WebSocketServer.java
File was deleted
JiuMuMesParent/common/servicebase/src/main/java/com/mes/websocket/WebSocketServer.java
New file
@@ -0,0 +1,170 @@
package com.mes.websocket;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Semaphore;
/**
 * WebSocketServer class
 *
 * @author zsh
 * @date 2025/07/04
 */
@ServerEndpoint(value = "/api/talk/{webSocketName}")
@Component
public class WebSocketServer {
    /** 日志记录器,记录 WebSocketServer 类运行时日志信息 */
    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    /** 单次消息允许的最大字符数(超出则进行分块) */
    private static final int MAX_MESSAGE_SIZE = 50000;
    /** 用于限制并发连接数量的信号量,控制最大并发数为 100 */
    private static final Semaphore SEMAPHORE = new Semaphore(100);
    /**
     * 用户名与 WebSocket 实例映射表,支持一个用户对应多个连接。
     * 使用线程安全的 ConcurrentHashMap 存储,保证高并发下的数据一致性。
     */
    public static final Map<String, List<WebSocketServer>> SESSIONMAP = new ConcurrentHashMap<>();
//    public static final Map<String, ArrayList<WebSocketServer>> sessionMap = new ConcurrentHashMap<>();
    /** 当前连接对应的用户名 */
    private String webSocketName;
    /** 当前连接的 WebSocket 会话对象 */
    private Session session;
    /** 线程安全的消息缓存,用于记录当前连接收到的所有消息 */
    private final List<String> messages = new CopyOnWriteArrayList<>();
    /**
     * 连接建立
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("webSocketName") String webSocketName) {
        this.webSocketName = webSocketName;
        this.session = session;
        SESSIONMAP.computeIfAbsent(webSocketName, k -> new CopyOnWriteArrayList<>())
                .add(this);
        log.info("用户连接: webSocketName={}, 当前会话数: {}", webSocketName,
                SESSIONMAP.getOrDefault(webSocketName, Collections.emptyList()).size());
    }
    /**
     * 连接关闭
     */
    @OnClose
    public void onClose() {
        List<WebSocketServer> sessions = SESSIONMAP.get(webSocketName);
        if (sessions != null) {
            sessions.remove(this);
            if (sessions.isEmpty()) {
                SESSIONMAP.remove(webSocketName);
            }
            log.info("用户断开: webSocketName={}, 剩余会话数: {}", webSocketName,
                    SESSIONMAP.getOrDefault(webSocketName, Collections.emptyList()).size());
        }
    }
    /**
     * 接收消息
     */
    @OnMessage
    public void onMessage(String message) {
        log.info("收到消息: webSocketName={}, content={}", webSocketName, message);
        JSONObject obj = JSONUtil.parseObj(message);
        // 存储消息历史
        messages.add(obj.getStr("data"));
    }
    /**
     * 错误处理
     */
    @OnError
    public void onError(Throwable error) {
        log.error("WebSocket错误: webSocketName={}", webSocketName, error);
    }
    /**
     * 向当前用户的所有会话发送消息
     */
    public void sendToWeb(String webSocketName, String message) {
        List<WebSocketServer> sessions = SESSIONMAP.get(webSocketName);
        if (sessions == null) {
            return;
        }
        sessions.forEach(ws -> {
            try {
                SEMAPHORE.acquire();
                ws.sendChunkedMessage(message);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } catch (Exception e) {
                log.error("推送失败: webSocketName={}", webSocketName, e);
            } finally {
                SEMAPHORE.release();
            }
        });
    }
    /**
     * 分块发送大消息
     */
    private void sendChunkedMessage(String message) {
        if (!session.isOpen()) {
            return;
        }
        try {
            if (message.length() <= MAX_MESSAGE_SIZE) {
                session.getBasicRemote().sendText(message);
                return;
            }
            // 分块发送
            int chunks = (int) Math.ceil((double) message.length() / MAX_MESSAGE_SIZE);
            for (int i = 0; i < chunks; i++) {
                int start = i * MAX_MESSAGE_SIZE;
                int end = Math.min(start + MAX_MESSAGE_SIZE, message.length());
                String chunk = message.substring(start, end) + (i == chunks - 1 ? "<END>" : "");
                session.getBasicRemote().sendText(chunk);
            }
        } catch (IOException e) {
            log.error("消息发送失败: webSocketName={}", webSocketName, e);
        }
    }
    public List<WebSocketServer> getWebSocketServer(String name) {
        return SESSIONMAP.get(name);
    }
    public static Set<String> getOnlineUsers() {
        return SESSIONMAP.keySet();
    }
    public List<String> getMessages() {
        return Collections.unmodifiableList(messages);
    }
    public void clearMessages() {
        messages.clear();
    }
}
JiuMuMesParent/common/servicebase/src/main/java/com/mes/websocket/WebSocketUtils.java
New file
@@ -0,0 +1,31 @@
package com.mes.websocket;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
 * @Author : zhoush
 * @Date: 2025/6/27 10:01
 * @Description:
 */
@Slf4j
@Component
public class WebSocketUtils {
    @Resource
    WebSocketServer webSocketServer;
    @Resource
    ObjectMapper objectMapper;
    public <T> void sendToWeb(String webSocketName, T t) {
        try {
            String message = objectMapper.writeValueAsString(t);
            webSocketServer.sendToWeb(webSocketName, message);
        } catch (JsonProcessingException ex) {
            log.info("{}发送数据失败:{}", "rawGlassStorage", ex.getMessage());
        }
    }
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/energy/service/impl/EnergyConsumptionServiceImpl.java
@@ -1,14 +1,14 @@
package com.mes.energy.service.impl;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mes.energy.entity.EnergyConsumption;
import com.mes.energy.mapper.EnergyConsumptionMapper;
import com.mes.energy.service.EnergyConsumptionService;
import com.mes.tools.WebSocketServer;
import cn.hutool.json.JSONObject;
import com.mes.websocket.WebSocketServer;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class EnergyConsumptionServiceImpl extends ServiceImpl<EnergyConsumptionMapper, EnergyConsumption> implements EnergyConsumptionService {
@@ -19,10 +19,10 @@
        message.set("type", "energy_update");
        message.set("data", consumption);
        ArrayList<WebSocketServer> servers = WebSocketServer.sessionMap.get("energy");
        List<WebSocketServer> servers = WebSocketServer.SESSIONMAP.get("energy");
        if (servers != null) {
            for (WebSocketServer server : servers) {
                server.sendMessage(message.toString());
                server.sendToWeb("",message.toString());
            }
        }
    }
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/job/AddTask.java
@@ -1,25 +1,22 @@
package com.mes.job;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.mes.md.entity.*;
import com.mes.md.mapper.MachineMapper;
import com.mes.md.entity.KBBTJPDrawingBP;
import com.mes.md.entity.Tasking;
import com.mes.md.mapper.TaskingMapper;
import com.mes.md.service.*;
import com.mes.service.ModbusTcp;
import com.mes.service.PlcAgreement;
import com.mes.service.PlcParameter;
import com.mes.tools.WebSocketServer;
import com.mes.utils.HexUtil;
import com.mes.utils.Result;
import com.mes.md.service.KBBTJPDrawingBPService;
import com.mes.md.service.ProjectService;
import com.mes.md.service.TaskingLogService;
import com.mes.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
 * @author SNG-010
@@ -69,12 +66,12 @@
        JSONObject jsonObject = new JSONObject();
        List<KBBTJPDrawingBP> list =kBBTJPDrawingBPService.notReceiveKBBTJPDrawingBP();
        jsonObject.append("content", list);
        ArrayList<WebSocketServer> sendwServer = WebSocketServer.sessionMap.get("notReceiveTask");
        List<WebSocketServer> sendwServer = WebSocketServer.SESSIONMAP.get("notReceiveTask");
        if (sendwServer != null) {
            for (WebSocketServer webserver : sendwServer) {
                if (webserver != null) {
                    try {
                        webserver.sendMessage(jsonObject.toString());
                        webserver.sendToWeb("",jsonObject.toString());
                        List<String> messages = webserver.getMessages();
                        if (!messages.isEmpty()) {
                            // // 将最后一个消息转换为整数类型的列表
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/job/MachineTask.java
@@ -2,24 +2,19 @@
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.mes.common.S7objectFlipSlice;
import com.mes.common.S7objectMachine;
import com.mes.common.S7objectMarking;
import com.mes.device.PlcParameterInfo;
import com.mes.device.PlcParameterObject;
import com.mes.md.entity.*;
import com.mes.md.mapper.GlassInfoMapper;
import com.mes.md.mapper.MachineMapper;
import com.mes.md.mapper.TaskingMapper;
import com.mes.md.service.*;
import com.mes.tools.WebSocketServer;
import com.mes.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -50,6 +45,8 @@
    KBBTJPDrawingBPService kBBTJPDrawingBPService;
    @Autowired
    LineConfigurationService lineConfigurationService;
    @Resource
    WebSocketServer webSocketServer;
    @Autowired
    private GlassInfoMapper glassInfoMapper;
    public List<Map> sendRecords = new ArrayList<>();
@@ -241,33 +238,42 @@
        this.webSocketServer(jsonObject);
    }
    public void webSocketServer(JSONObject jsonObject) {
        try {
            String sessionMapName=jsonObject.getJSONArray("sessionMapName").get(0).toString();
            ArrayList<WebSocketServer> sendwServer = WebSocketServer.sessionMap.get(sessionMapName);
            if (sendwServer != null) {
                for (WebSocketServer webserver : sendwServer) {
                    if (webserver != null) {
                        try {
                            webserver.sendMessage(jsonObject.toString());
                            List<String> messages = webserver.getMessages();
                            if (!messages.isEmpty()) {
                                // // 将最后一个消息转换为整数类型的列表
                                webserver.clearMessages();
                            }
                        }catch (Exception e) {
                        }
                    } else {
                        log.info("Home is closed");
                    }
                }
            }
        }catch (Exception e) {
            webSocketServer.sendToWeb(sessionMapName, jsonObject.toString());
        } catch (Exception ex) {
            log.info("{}发送数据失败:{}", "rawGlassStorage", ex.getMessage());
        }
    }
//    public void webSocketServer(JSONObject jsonObject) {
//        try {
//            String sessionMapName=jsonObject.getJSONArray("sessionMapName").get(0).toString();
//            ArrayList<WebSocketServer> sendwServer = WebSocketServer.sessionMap.get(sessionMapName);
//            if (sendwServer != null) {
//                for (WebSocketServer webserver : sendwServer) {
//                    try {
//                        webserver.sendMessage(jsonObject.toString());
//                        List<String> messages = webserver.getMessages();
//                        if (!messages.isEmpty()) {
//                            // // 将最后一个消息转换为整数类型的列表
//                            webserver.clearMessages();
//                        }
//                    }catch (Exception e) {
//                        if (webserver != null) {
//
//                        } else {
//                            log.info("Home is closed");
//                        }
//                    }
//
//                }
//            }
//        }catch (Exception e) {
//
//        }
//
//    }
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/job/PLCCleaning.java
@@ -2,25 +2,20 @@
import cn.hutool.json.JSONObject;
import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
import com.mes.common.S7object;
import com.mes.common.S7objectCleaning;
import com.mes.common.S7objectMachine;
import com.mes.common.S7objectMarking;
import com.mes.device.PlcParameterInfo;
import com.mes.device.PlcParameterObject;
import com.mes.md.entity.Machine;
import com.mes.md.entity.Tasking;
import com.mes.md.mapper.MachineMapper;
import com.mes.md.service.TaskingService;
import com.mes.tools.WebSocketServer;
import com.mes.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
 * @author SNG-010
@@ -67,12 +62,12 @@
        List<Tasking> taskingList=taskingService.findMachineTask(machine);
        jsonObject.append("taskingList", taskingList);
        jsonObject.append("machine", machine);
        ArrayList<WebSocketServer> sendwServer = WebSocketServer.sessionMap.get("cleaning");
        List<WebSocketServer> sendwServer = WebSocketServer.SESSIONMAP.get("cleaning");
        if (sendwServer != null) {
            for (WebSocketServer webserver : sendwServer) {
                if (webserver != null) {
                    try {
                        webserver.sendMessage(jsonObject.toString());
                        webserver.sendToWeb("",jsonObject.toString());
                        List<String> messages = webserver.getMessages();
                        if (!messages.isEmpty()) {
                            // // 将最后一个消息转换为整数类型的列表
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/mechanicalMonitor/controller/MechanicalMonitorController.java
@@ -1,17 +1,17 @@
package com.mes.mechanicalMonitor.controller;
import cn.hutool.json.JSONObject;
import com.mes.mechanicalMonitor.entity.MechanicalMonitor;
import com.mes.mechanicalMonitor.service.MechanicalMonitorService;
import com.mes.tools.WebSocketServer;
import com.mes.utils.Result;
import com.mes.websocket.WebSocketServer;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import cn.hutool.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Api(tags = "设备状态监控")
@@ -42,10 +42,10 @@
    @ResponseBody
    public Result updateMechanicalStatus(@RequestBody JSONObject status) {
        try {
            ArrayList<WebSocketServer> servers = WebSocketServer.sessionMap.get("mechanicalMonitor");
            List<WebSocketServer> servers = WebSocketServer.SESSIONMAP.get("mechanicalMonitor");
            if (servers != null) {
                for (WebSocketServer server : servers) {
                    server.sendMessage(status.toString());
                    server.sendToWeb("",status.toString());
                }
            }
            return Result.build(200, "状态更新成功", null);
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/mechanicalMonitor/service/impl/MechanicalMonitorServiceImpl.java
@@ -1,15 +1,15 @@
package com.mes.mechanicalMonitor.service.impl;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mes.mechanicalMonitor.entity.MechanicalMonitor;
import com.mes.mechanicalMonitor.mapper.MechanicalMonitorMapper;
import com.mes.mechanicalMonitor.service.MechanicalMonitorService;
import com.mes.tools.WebSocketServer;
import cn.hutool.json.JSONObject;
import com.mes.websocket.WebSocketServer;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Date;
import java.util.ArrayList;
import java.util.List;
@Service
public class MechanicalMonitorServiceImpl extends ServiceImpl<MechanicalMonitorMapper, MechanicalMonitor> 
@@ -52,10 +52,10 @@
        message.set("type", "status_change");
        message.set("data", monitor);
        
        ArrayList<WebSocketServer> servers = WebSocketServer.sessionMap.get("mechanicalMonitor");
        List<WebSocketServer> servers = WebSocketServer.SESSIONMAP.get("mechanicalMonitor");
        if (servers != null) {
            for (WebSocketServer server : servers) {
                server.sendMessage(message.toString());
                server.sendToWeb("",message.toString());
            }
        }
    }
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/plannedAmount/service/impl/PlannedAmountImpl.java
@@ -5,10 +5,10 @@
import com.mes.plannedAmount.entity.PlannedAmount;
import com.mes.plannedAmount.mapper.PlannedAmountMapper;
import com.mes.plannedAmount.service.PlannedAmountService;
import com.mes.tools.WebSocketServer;
import com.mes.websocket.WebSocketServer;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class PlannedAmountImpl extends ServiceImpl<PlannedAmountMapper, PlannedAmount> implements PlannedAmountService {
@@ -19,10 +19,10 @@
        message.set("type", "planned_update");
        message.set("data", value);
        ArrayList<WebSocketServer> servers = WebSocketServer.sessionMap.get("value");
        List<WebSocketServer> servers = WebSocketServer.SESSIONMAP.get("value");
        if (servers != null) {
            for (WebSocketServer server : servers) {
                server.sendMessage(message.toString());
                server.sendToWeb("",message.toString());
            }
        }
    }
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/yield/service/impl/YieldServiceImpl.java
@@ -1,18 +1,14 @@
package com.mes.yield.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mes.websocket.WebSocketServer;
import com.mes.yield.entity.Yield;
import com.mes.yield.mapper.YieldMapper;
import com.mes.yield.service.YieldService;
import com.mes.tools.WebSocketServer;
import cn.hutool.json.JSONObject;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class YieldServiceImpl extends ServiceImpl<YieldMapper, Yield> implements YieldService {
@@ -23,10 +19,10 @@
        message.set("type", "yield_update");
        message.set("data", yield);
        ArrayList<WebSocketServer> servers = WebSocketServer.sessionMap.get("yield");
        List<WebSocketServer> servers = WebSocketServer.SESSIONMAP.get("yield");
        if (servers != null) {
            for (WebSocketServer server : servers) {
                server.sendMessage(message.toString());
                server.sendToWeb("",message.toString());
            }
        }
    }