新增 CORS 跨域配置和 Socket 连接管理器,支持 JTT808 设备的连接管理与指令下发
This commit is contained in:
parent
1a7aa385f1
commit
e5347567d7
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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("清空所有连接");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue