新增 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