新增 CORS 跨域配置和 Socket 连接管理器,支持 JTT808 设备的连接管理与指令下发

This commit is contained in:
syruan 2025-12-24 09:32:57 +08:00
parent 1a7aa385f1
commit e5347567d7
2 changed files with 208 additions and 0 deletions

View File

@ -0,0 +1,30 @@
package com.bonus.sgzb.material.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* CORS跨域配置
*
* @author system
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
// 允许所有来源开发环境
.allowedOriginPatterns("*")
// 允许的请求方法
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH")
// 允许的请求头
.allowedHeaders("*")
// 允许携带凭证
.allowCredentials(true)
// 预检请求的有效期
.maxAge(3600);
}
}

View File

@ -0,0 +1,178 @@
package com.bonus.sgzb.material.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Socket 连接管理器
* 用于管理 JTT808 设备的 Socket 连接支持主动下发指令
*
* @author system
* @date 2025-12-23
*/
@Slf4j
@Component
public class SocketConnectionManager {
/**
* 终端手机号 -> Socket 连接的映射
*/
private final Map<String, Socket> connectionMap = new ConcurrentHashMap<>();
/**
* 添加连接
*
* @param phoneNumber 终端手机号
* @param socket Socket 连接
* @return 是否添加成功
*/
public boolean addConnection(String phoneNumber, Socket socket) {
if (phoneNumber == null || socket == null) {
log.warn("添加连接失败: phoneNumber 或 socket 为 null");
return false;
}
// 如果已存在连接关闭旧连接
Socket oldSocket = connectionMap.get(phoneNumber);
if (oldSocket != null && !oldSocket.isClosed()) {
log.info("终端 {} 已有连接,关闭旧连接", phoneNumber);
try {
oldSocket.close();
} catch (IOException e) {
log.error("关闭旧连接异常: {}", e.getMessage());
}
}
connectionMap.put(phoneNumber, socket);
log.info("添加连接: {} -> {}", phoneNumber, socket.getRemoteSocketAddress());
return true;
}
/**
* 移除连接
*
* @param phoneNumber 终端手机号
* @return 是否移除成功
*/
public boolean removeConnection(String phoneNumber) {
if (phoneNumber == null) {
return false;
}
Socket socket = connectionMap.remove(phoneNumber);
if (socket != null) {
log.info("移除连接: {}", phoneNumber);
return true;
}
return false;
}
/**
* 获取连接
*
* @param phoneNumber 终端手机号
* @return Socket 连接如果不存在或已关闭则返回 null
*/
public Socket getConnection(String phoneNumber) {
if (phoneNumber == null) {
return null;
}
Socket socket = connectionMap.get(phoneNumber);
if (socket != null && socket.isClosed()) {
// 连接已关闭从映射中移除
connectionMap.remove(phoneNumber);
return null;
}
return socket;
}
/**
* 检查终端是否在线有活跃的 Socket 连接
*
* @param phoneNumber 终端手机号
* @return 是否在线
*/
public boolean isOnline(String phoneNumber) {
Socket socket = getConnection(phoneNumber);
return socket != null && socket.isConnected() && !socket.isClosed();
}
/**
* 向终端发送数据
*
* @param phoneNumber 终端手机号
* @param data 要发送的数据
* @return 是否发送成功
*/
public boolean sendData(String phoneNumber, byte[] data) {
if (phoneNumber == null || data == null || data.length == 0) {
log.warn("发送数据失败: phoneNumber 或 data 为空");
return false;
}
Socket socket = getConnection(phoneNumber);
if (socket == null) {
log.warn("发送数据失败: 终端 {} 不在线", phoneNumber);
return false;
}
try {
OutputStream outputStream = socket.getOutputStream();
outputStream.write(data);
outputStream.flush();
log.info("向终端 {} 发送数据成功: {} 字节", phoneNumber, data.length);
return true;
} catch (IOException e) {
log.error("向终端 {} 发送数据失败: {}", phoneNumber, e.getMessage());
// 发送失败移除连接
removeConnection(phoneNumber);
return false;
}
}
/**
* 获取当前在线终端数量
*
* @return 在线终端数量
*/
public int getOnlineCount() {
// 清理已关闭的连接
connectionMap.entrySet().removeIf(entry -> entry.getValue().isClosed());
return connectionMap.size();
}
/**
* 根据 Socket 查找终端手机号
*
* @param socket Socket 连接
* @return 终端手机号如果未找到则返回 null
*/
public String getPhoneNumberBySocket(Socket socket) {
if (socket == null) {
return null;
}
for (Map.Entry<String, Socket> entry : connectionMap.entrySet()) {
if (entry.getValue() == socket) {
return entry.getKey();
}
}
return null;
}
/**
* 清空所有连接
*/
public void clearAll() {
connectionMap.clear();
log.info("清空所有连接");
}
}