add: 添加设备端口远程同步任务

This commit is contained in:
republicline 2024-11-06 17:44:38 +08:00
parent 8cce42dd53
commit 23ccbbad12
20 changed files with 682 additions and 92 deletions

View File

@ -2,6 +2,7 @@ package com.rax.auth.endpoint;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.captcha.generator.RandomGenerator;
import com.rax.common.core.constant.CacheConstants;
import com.rax.common.core.constant.SecurityConstants;
import com.rax.common.security.annotation.Inner;
@ -43,6 +44,7 @@ public class ImageCodeEndpoint {
@SneakyThrows
@GetMapping("/image")
public void image(String randomStr, HttpServletResponse response) {
System.out.println("randomStr = " + randomStr);
ArithmeticCaptcha captcha = new ArithmeticCaptcha(DEFAULT_IMAGE_WIDTH, DEFAULT_IMAGE_HEIGHT);
String result = captcha.text();
@ -55,7 +57,10 @@ public class ImageCodeEndpoint {
@SneakyThrows
@GetMapping("/textImage")
public void textImage(String randomStr, HttpServletResponse response) {
CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 50);
RandomGenerator randomGenerator = new RandomGenerator("0123456789", 4);
// CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 50);
CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100);
captcha.setGenerator(randomGenerator);
String code = captcha.getCode();
redisTemplate.opsForValue().set(CacheConstants.DEFAULT_CODE_KEY + randomStr, code, SecurityConstants.CODE_TIME, TimeUnit.SECONDS);
BufferedImage image = captcha.getImage();

View File

@ -8,7 +8,9 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* @author lengleng
@ -23,11 +25,12 @@ public class RedisTemplateConfiguration {
@Primary
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setHashKeySerializer(RedisSerializer.string());
redisTemplate.setValueSerializer(RedisSerializer.java());
redisTemplate.setHashValueSerializer(RedisSerializer.java());
redisTemplate.setConnectionFactory(factory);
// redisTemplate.setKeySerializer(new StringRedisSerializer());
// redisTemplate.setHashKeySerializer(new StringRedisSerializer());
// redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}

View File

@ -15,8 +15,9 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@EnableRaxDoc(value = "admin")
@EnableRaxResourceServer
@EnableScheduling // 开启定时任务 -> 清除日志相关内容
// 一期下面解注, 二期注释掉
// 一期下面解注
@SpringBootApplication(exclude = MongoAutoConfiguration.class)
// 二期下面解注
//@SpringBootApplication
@ComponentScan(
basePackages = {"com.rax"},
@ -27,6 +28,7 @@ public class RaxAdminApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(RaxAdminApplication.class, args);
}
/**

View File

@ -1,4 +1,4 @@
package com.rax.admin.immu;
package com.rax.admin.constants;
/**
* project_name:remote-control-backend

View File

@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rax.admin.api.dto.HospitalDTO;
import com.rax.admin.api.entity.SysHospital;
import com.rax.admin.immu.RoleRecord;
import com.rax.admin.constants.RoleRecord;
import com.rax.admin.mapper.SysHospitalMapper;
import com.rax.admin.service.SysHospitalService;
import com.rax.admin.utils.AuthUtils;

View File

@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rax.admin.api.dto.SysLogDTO;
import com.rax.admin.api.entity.SysLog;
import com.rax.admin.api.entity.SysUser;
import com.rax.admin.immu.RoleRecord;
import com.rax.admin.constants.RoleRecord;
import com.rax.admin.mapper.SysLogMapper;
import com.rax.admin.mapper.SysUserMapper;
import com.rax.admin.service.SysLogService;

View File

@ -0,0 +1,132 @@
package com.rax.admin.timmer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.io.File;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* @project_name: rax-remote-v2
* @time: 2024/10/8 10:57
* @author: republicline
* @description: mysql定时备份
*/
@Component
@Slf4j
public class MySqlTimer {
public static void main(String[] args) throws Exception {
backup();
}
@Scheduled(cron = "0 0 0 * * 0")
public static void backup() throws Exception {
String connectionUrl = "jdbc:mysql://110.41.142.124:3306";
String ip = "110.41.142.124";
String port = "3306";
String username = "root";
String password = "Xg137839";
Connection connection = DriverManager.getConnection(connectionUrl, username, password);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SHOW DATABASES");
// System.out.println("MySQL服务器上的数据库列表:");
while (resultSet.next()) {
String databaseName = resultSet.getString(1);
System.out.println(databaseName);
if ("sys".equals(databaseName)) {
continue;
}
dbBackUpMysql(
ip,
port,
username,
password,
"/RuiAx/mysql_backup",
databaseName);
}
resultSet.close();
statement.close();
connection.close();
}
/**
* 备份mysql数据库
*
* @param username 账号
* @param pwd 密码
* @param ip 地址
* @param port 端口
* @param path 路径
* @param dbName 数据库名
* @throws Exception
*/
public static void dbBackUpMysql(String ip, String port, String username, String pwd, String path, String dbName) throws Exception {
//mysqldump -uroot -pldeSpQEL0Pbz5A61dCNb --host=123.56.234.243 --port=3309 edc > /opt/2024-10-08/edc.sql
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String time = simpleDateFormat.format(new Date());
path = path + File.separator + time + File.separator;
String pathSql = path + dbName + ".sql";
File filePath = new File(path);
File fileSql = new File(pathSql);
//创建备份sql文件
if (!filePath.exists()) {
filePath.mkdirs();
}
if (!fileSql.exists()) {
fileSql.createNewFile();
}
//mysqldump -uroot -pldeSpQEL0Pbz5A61dCNb --host=123.56.234.243 --port=3309 edc > /opt/2024-10-08/edc.sql
StringBuffer sb = new StringBuffer();
sb.append("mysqldump");
sb.append(" -u" + username);
sb.append(" -p" + pwd);
sb.append(" --host=" + ip);
sb.append(" --port=" + port);
sb.append(" " + dbName + " >");
sb.append(pathSql);
System.out.println("cmd命令为" + sb.toString());
System.out.println("开始备份:" + dbName);
Process process = null;
//判断操作系统 windwos与linux使用的语句不一样
if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) {
process = Runtime.getRuntime().exec("cmd /c" + sb);
} else if (System.getProperty("os.name").toLowerCase().indexOf("linux") > -1) {
process = Runtime.getRuntime().exec("/bin/sh -c" + sb);
} else {
log.error("暂不支持该操作系统,进行数据库备份或还原!");
throw new Exception("暂不支持该操作系统,进行数据库备份或还原!");
}
//设置超时五分钟
process.waitFor(300, TimeUnit.SECONDS);
//输出返回的错误信息
// StringBuffer mes = new StringBuffer();
// String tmp = "";
// BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
// while ((tmp = error.readLine()) != null) {
// mes.append(tmp + "\n");
// }
// if (mes != null || !"".equals(mes)) {
// System.out.println("备份成功!==>" + mes);
// }
// error.close();
}
}

View File

@ -1,7 +1,7 @@
package com.rax.admin.utils;
import cn.hutool.core.convert.Convert;
import com.rax.admin.immu.RoleRecord;
import com.rax.admin.constants.RoleRecord;
import com.rax.common.core.constant.CacheConstants;
import com.rax.common.core.util.RedisUtils;
import com.rax.common.security.service.RaxUser;

View File

@ -0,0 +1,58 @@
package com.rax.admin.utils;
import java.sql.*;
import java.util.ResourceBundle;
/**
* 适应mysql不同数据源
*
* @author republicline
*/
public class JDBCUtil {
private static final String driverClassName = "com.mysql.jdbc.Driver";
private static final String username = "root";
private static final String password = "Xg137839";
private static final String url = "jdbc:mysql://110.41.142.124:3306/";
private JDBCUtil() {
}
//注册驱动
static {
try {
Class.forName(driverClassName);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
//jdbc工具类,获取连接
public static Connection getConnection(String databaseName) throws Exception {
return DriverManager.getConnection(
url + databaseName,
username,
password);
}
//jdbc工具类,关闭连接
public static void close(Connection connection, Statement statement, ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,46 @@
package com.rax.vital.common.datasource;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class DynamicDataSource {
private HikariDataSource dataSource;
// 动态创建连接池
public void createDataSource(String databaseName) {
HikariConfig config = new HikariConfig();
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
config.setJdbcUrl("jdbc:mysql://110.41.142.124:3306/" + databaseName + "?useUnicode=true&characterEncoding=utf-8&useSSL=false");
config.setUsername("root");
config.setPassword("Xg137839");
// 配置连接池参数
config.setMinimumIdle(1);
config.setMaximumPoolSize(5);
config.setIdleTimeout(1000 * 60 * 3); // 空闲超时时间
config.setConnectionTimeout(1000 * 60 * 3); // 连接超时时间
config.setMaxLifetime(1000 * 60 * 3); // 最大连接寿命
this.dataSource = new HikariDataSource(config);
}
// 获取连接
public Connection getConnection() throws SQLException {
if (dataSource == null) {
throw new IllegalStateException("DataSource is not initialized. Call createDataSource() first.");
}
return dataSource.getConnection();
}
// 关闭数据源
public void closeDataSource() {
if (dataSource != null) {
dataSource.close();
}
}
}

View File

@ -35,7 +35,7 @@ public class MySQLSource extends CustomDataSource {
this.database = database;
}
@SneakyThrows
public boolean open() {
boolean status = true;
try {

View File

@ -0,0 +1,130 @@
package com.rax.vital.controller;
import com.rax.common.core.util.R;
import com.rax.common.security.annotation.Inner;
import com.rax.vital.common.datasource.DynamicDataSource;
import com.rax.vital.entity.VisualBody;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.concurrent.*;
/**
* @project_name: rax-remote-v2
* @time: 2024/11/5 11:05
* @author: republicline
* @description: 仪器端和服务端通信接口
*/
@RestController
@RequestMapping("/machine")
public class MachineController {
// 生命体征表名
private static final String FEATURE_TABLE_NAME = "featuretable";
// 异步入库
private ExecutorService executorService = Executors.newFixedThreadPool(5);
// 动态数据源
private ConcurrentHashMap<String, DynamicDataSource> dynamicDataSources = new ConcurrentHashMap<>();
// 仪器端生命体征数据入库
@PostMapping("/save")
@Inner(value = false)
public R<Object> saveVitalBodyData(VisualBody visualBody) {
System.out.println("visualBody = " + visualBody);
for (String key : dynamicDataSources.keySet()) System.out.println("key = " + key);
// 校验
if (visualBody == null) return R.failed("参数不能为空");
if (visualBody.getDatabaseName() == null ||
visualBody.getPhase() == null || visualBody.getBIS() == null ||
visualBody.getHR() == null || visualBody.getSBP() == null ||
visualBody.getDBP() == null || visualBody.getST() == null ||
visualBody.getTEMP() == null || visualBody.getSP02() == null ||
visualBody.getEtCO2() == null || visualBody.getPPG() == null ||
visualBody.getABG() == null || visualBody.getTOF() == null ||
visualBody.getTIME() == null) {
return R.failed("参数含有空值");
}
saveVitalBodyDataAsync(visualBody);
return R.ok("success");
}
// 关闭数据源
@PostMapping("/close")
@Inner(value = false)
public R<Object> closeDataSource(String databaseName) {
if (databaseName == null) {
return R.failed("参数不能为空");
}
dynamicDataSources.remove(databaseName);
DynamicDataSource dynamicDataSource = dynamicDataSources.get(databaseName);
if (dynamicDataSource == null) {
return R.failed("数据源不存在");
}
dynamicDataSource.closeDataSource();
return R.ok("success");
}
private void saveVitalBodyDataAsync(VisualBody visualBody) {
executorService.execute(() -> {
try {
String databaseName = visualBody.getDatabaseName();
if (!dynamicDataSources.containsKey(databaseName)) {
// 创建动态数据源
System.out.println("连接池创建数据源");
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.createDataSource(databaseName);
dynamicDataSources.put(databaseName, dynamicDataSource);
}
if (dynamicDataSources.get(databaseName) == null) {
dynamicDataSources.remove(databaseName);
throw new RuntimeException("数据源不存在");
}
// 获取连接
Connection connection = dynamicDataSources.get(databaseName).getConnection();
if (connection == null) {
throw new RuntimeException("数据库连接失败");
}
// 数据库操作
String sql = String.format("""
INSERT INTO %s
(Phase, BIS, HR, SBP, DBP, ST, TEMP, SPO2, EtCO2, PPG, ABG, TOF, `TIME`)
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?);
""", FEATURE_TABLE_NAME);
PreparedStatement ps = connection.prepareStatement(sql);
ps.setInt(1, visualBody.getPhase());
ps.setDouble(2, visualBody.getBIS());
ps.setDouble(3, visualBody.getHR());
ps.setDouble(4, visualBody.getSBP());
ps.setDouble(5, visualBody.getDBP());
ps.setDouble(6, visualBody.getST());
ps.setDouble(7, visualBody.getTEMP());
ps.setDouble(8, visualBody.getSP02());
ps.setDouble(9, visualBody.getEtCO2());
ps.setDouble(10, visualBody.getPPG());
ps.setDouble(11, visualBody.getABG());
ps.setDouble(12, visualBody.getTOF());
ps.setTimestamp(13, visualBody.getTIME());
ps.execute();
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
}

View File

@ -0,0 +1,162 @@
package com.rax.vital.entity;
import java.sql.Timestamp;
/**
* @project_name: rax-remote-v2
* @time: 2024/11/5 11:10
* @author: republicline
* @description: 生命体征实体类
*/
public class VisualBody {
private String databaseName;
private Integer Phase;
private Double BIS;
private Double HR;
private Double SBP;
private Double DBP;
private Double ST;
private Double TEMP;
private Double SP02;
private Double EtCO2;
private Double PPG;
private Double ABG;
private Double TOF;
private Timestamp TIME;
public String getDatabaseName() {
return databaseName;
}
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
public Integer getPhase() {
return Phase;
}
public void setPhase(Integer phase) {
Phase = phase;
}
public Double getBIS() {
return BIS;
}
public void setBIS(Double BIS) {
this.BIS = BIS;
}
public Double getHR() {
return HR;
}
public void setHR(Double HR) {
this.HR = HR;
}
public Double getSBP() {
return SBP;
}
public void setSBP(Double SBP) {
this.SBP = SBP;
}
public Double getST() {
return ST;
}
public void setST(Double ST) {
this.ST = ST;
}
public Double getTEMP() {
return TEMP;
}
public void setTEMP(Double TEMP) {
this.TEMP = TEMP;
}
public Double getSP02() {
return SP02;
}
public void setSP02(Double SP02) {
this.SP02 = SP02;
}
public Double getEtCO2() {
return EtCO2;
}
public void setEtCO2(Double etCO2) {
EtCO2 = etCO2;
}
public Double getPPG() {
return PPG;
}
public void setPPG(Double PPG) {
this.PPG = PPG;
}
public Double getABG() {
return ABG;
}
public void setABG(Double ABG) {
this.ABG = ABG;
}
public Double getTOF() {
return TOF;
}
public void setTOF(Double TOF) {
this.TOF = TOF;
}
public Timestamp getTIME() {
return TIME;
}
public void setTIME(Timestamp TIME) {
this.TIME = TIME;
}
public Double getDBP() {
return DBP;
}
public void setDBP(Double DBP) {
this.DBP = DBP;
}
@Override
public String toString() {
return "VisualBody{" +
"databaseName='" + databaseName + '\'' +
", Phase=" + Phase +
", BIS=" + BIS +
", DBP=" + DBP +
", HR=" + HR +
", SBP=" + SBP +
", ST=" + ST +
", TEMP=" + TEMP +
", SP02=" + SP02 +
", EtCO2=" + EtCO2 +
", PPG=" + PPG +
", ABG=" + ABG +
", TOF=" + TOF +
", TIME=" + TIME +
'}';
}
}

View File

@ -9,6 +9,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.HandshakeInterceptor;
@ -22,8 +23,8 @@ public class WebSocketConfig implements WebSocketConfigurer {
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(medicineHandler(), "/rax/vitalSignsMedicine")
.addHandler(chatHandler(), "/rax/chatRoom")
.addHandler(addMedicineHandler(), "/rax/addMedicine")
.addHandler(machineFeedbackHandler(),"/rax/getMedicine")
// .addHandler(addMedicineHandler(), "/rax/addMedicine")
// .addHandler(machineFeedbackHandler(),"/rax/getMedicine")
// .addInterceptors(new HttpSessionHandshakeInterceptor())
// .addInterceptors(webSocketInterceptors())
.setAllowedOrigins("*");
@ -39,15 +40,15 @@ public class WebSocketConfig implements WebSocketConfigurer {
return new ChatHandler();
}
@Bean
public WebSocketHandler addMedicineHandler() {
return new AddMedicineHandler();
}
// @Bean
// public WebSocketHandler addMedicineHandler() {
// return new AddMedicineHandler();
// }
@Bean
public WebSocketHandler machineFeedbackHandler() {
return new MachineFeedbackHandler();
}
// @Bean
// public WebSocketHandler machineFeedbackHandler() {
// return new MachineFeedbackHandler();
// }
@Bean
public HandshakeInterceptor webSocketInterceptors() {

View File

@ -36,7 +36,6 @@ public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {
/**
* stomp未登录验证
*
* @param registration
*/
@Override

View File

@ -1,9 +1,13 @@
package com.rax.vital.v1.handler;
import com.alibaba.fastjson.JSONObject;
import com.rax.common.core.util.RedisUtils;
import com.rax.vital.common.util.GetHttpParamUtil;
import com.rax.vital.v1.medicine.service.ChatService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
@ -11,6 +15,7 @@ import org.springframework.web.socket.*;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -25,6 +30,9 @@ public class ChatHandler implements WebSocketHandler {
@Resource
private ChatService chatService;
@Autowired
private RedisTemplate redisTemplate;
private Map<String, ScheduledExecutorService> timerTaskMap = new ConcurrentHashMap();
// dbName -> sessionList
@ -52,9 +60,18 @@ public class ChatHandler implements WebSocketHandler {
if ("heartbeat".equals(jsonObject.getString("msgType"))) {
// session.sendMessage(new TextMessage(""));
}else if ("init".equals(jsonObject.getString("msgType"))) {
} else if ("init".equals(jsonObject.getString("msgType"))) {
// 初始化, 将session信息保存起来
String dbName = jsonObject.getString("idNum");
String dbName = 'a' + jsonObject.getString("idNum");
// if (RedisUtils.hasKey("chat_" + dbName)) {
// List<WebSocketSession> sessionList = RedisUtils.get("chat_" + dbName);
//
// dbNameSessionList.put(dbName, sessionList);
// HashMap<String, String> map = new HashMap<>();
// map = RedisUtils.get("chat_sessionId_" + dbName);
// sessionDbMap.putAll(map);
// return;
// }
if (!dbNameSessionList.containsKey(dbName)) {
ArrayList<WebSocketSession> sessionArrayList = new ArrayList<>();
dbNameSessionList.put(dbName, sessionArrayList);
@ -62,16 +79,29 @@ public class ChatHandler implements WebSocketHandler {
}
List<WebSocketSession> webSocketSessions = dbNameSessionList.get(dbName);
webSocketSessions.add(session);
// ArrayList<String> sessionIDList = new ArrayList<>();
// for (WebSocketSession webSocketSession : webSocketSessions) {
// if (webSocketSession.isOpen()) {
// String id = session.getId();
// sessionIDList.add(id);
// }
// }
//
// // 保存到redis
// redisTemplate.opsForValue().set("chat_" + dbName, sessionIDList);
// redisTemplate.expire("chat_" + dbName, 60 * 60, TimeUnit.SECONDS);
// redisTemplate.opsForHash().putAll("chat_sessionId_" + dbName, sessionDbMap);
// redisTemplate.expire("chat_" + dbName, 60 * 60, TimeUnit.SECONDS);
} else {
String patientName = jsonObject.getString("patientName");
String idNum = jsonObject.getString("idNum");
String dbName = 'a' + jsonObject.getString("idNum");
String date = jsonObject.getString("date");
// 消息内容
String msg = jsonObject.getString("msg");
List<WebSocketSession> webSocketSessions = dbNameSessionList.get(idNum);
chatService.sendMessageMysql(username, patientName, idNum, date, session, msg, webSocketSessions);
List<WebSocketSession> webSocketSessions = dbNameSessionList.get(dbName);
chatService.sendMessageMysql(username, patientName, dbName, date, session, msg, webSocketSessions);
}
}else {
} else {
String msgContent = "token无效,认证失败";
JSONObject msg = new JSONObject();
msg.put("msgType", "msg");
@ -129,7 +159,9 @@ public class ChatHandler implements WebSocketHandler {
private void stopMap(WebSocketSession session) {
String dbName = sessionDbMap.get(session.getId());
dbNameSessionList.remove(dbName);
if (dbName != null) {
dbNameSessionList.remove(dbName);
}
sessionDbMap.remove(session.getId());
}

View File

@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
import com.rax.vital.common.util.GetHttpParamUtil;
import com.rax.vital.v1.timer.VitalSignTimerWS;
import jakarta.annotation.Resource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
@ -12,9 +13,6 @@ import org.springframework.web.socket.*;
import java.net.URLDecoder;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class MedicineHandler implements WebSocketHandler {
@ -24,11 +22,13 @@ public class MedicineHandler implements WebSocketHandler {
@Resource
private OAuth2AuthorizationService authorizationService;
private Map<String, ScheduledExecutorService> timerTaskMap = new ConcurrentHashMap();
private Map<String, WebSocketSession> sessionMap = new ConcurrentHashMap();
@Override
public void afterConnectionEstablished(WebSocketSession session) {
startHeartbeat(session);
sessionMap.put(session.getId(), session);
}
@Override
@ -45,23 +45,24 @@ public class MedicineHandler implements WebSocketHandler {
if ("heartbeat".equals(jsonObject.getString("msgType"))) {
// session.sendMessage(new TextMessage(""));
} else {
String patientName = jsonObject.getString("patientName");
// String patientName = jsonObject.getString("patientName");
String idNum = jsonObject.getString("idNum");
String databaseName = idNum;
String databaseName = 'a' + idNum;
vitalSignTimerWS.createAndSendMessageMySQL(databaseName, username, session);
}
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
sessionMap.remove(session.getId());
System.out.println("Error: " + exception.getMessage());
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
System.out.println("MedicineHandler Connection closed:" + closeStatus.getReason());
stopHeartbeat(session);
vitalSignTimerWS.stopTimerTask(session.getId());
// stopHeartbeat(session);
sessionMap.remove(session.getId());
}
@Override
@ -69,32 +70,44 @@ public class MedicineHandler implements WebSocketHandler {
return false;
}
private void startHeartbeat(WebSocketSession session) {
if (!timerTaskMap.containsKey(session.getId())) {
ScheduledExecutorService heartbeatExecutor = Executors.newScheduledThreadPool(1);
heartbeatExecutor.scheduleAtFixedRate(() -> {
@Scheduled(fixedRate = 30000)
private void sendHeartbeat() {
// if (!timerTaskMap.containsKey(session.getId())) {
// ScheduledExecutorService heartbeatExecutor = Executors.newScheduledThreadPool(1);
// heartbeatExecutor.scheduleAtFixedRate(() -> {
// try {
// if (session.isOpen()) {
// JSONObject jsonObject = new JSONObject();
// jsonObject.put("msgType", "heartbeat");
// session.sendMessage(new TextMessage(jsonObject.toJSONString().getBytes()));
// } else {
// session.close();
// stopHeartbeat(session);
// vitalSignTimerWS.stopTimerTask(session.getId());
// }
// } catch (Exception e) {
// e.printStackTrace();
// stopHeartbeat(session);
// }
// }, 0, 10, TimeUnit.SECONDS);
// timerTaskMap.put(session.getId(), heartbeatExecutor);
// }
for (WebSocketSession session : sessionMap.values()) {
if (session.isOpen()) {
try {
if (session.isOpen()) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("msgType", "heartbeat");
session.sendMessage(new TextMessage(jsonObject.toJSONString().getBytes()));
} else {
session.close();
stopHeartbeat(session);
vitalSignTimerWS.stopTimerTask(session.getId());
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("msgType", "heartbeat");
session.sendMessage(new TextMessage(jsonObject.toJSONString().getBytes()));
} catch (Exception e) {
e.printStackTrace();
stopHeartbeat(session);
}
}, 0, 10, TimeUnit.SECONDS);
timerTaskMap.put(session.getId(), heartbeatExecutor);
}else {
sessionMap.remove(session.getId());
vitalSignTimerWS.stopTimerTask(session.getId());
}
}
}
private void stopHeartbeat(WebSocketSession session) {
ScheduledExecutorService heartbeatExecutor = timerTaskMap.get(session.getId());
heartbeatExecutor.shutdownNow();
}
}

View File

@ -16,6 +16,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.TextMessage;
@ -57,17 +58,16 @@ public class ChatServiceImpl implements ChatService {
@Override
@Async
public void sendMessageMysql(String username, String patientName, String idNum, String date, WebSocketSession session, String msg, List<WebSocketSession> webSocketSessionList) throws SQLException, IOException {
CustomDataSource dataSource = datasourceMap.get(session.getId());
String databaseName = idNum;
System.out.println("databaseName = " + databaseName);
ArrayList<Map> history = new ArrayList<>();
// 获取连接
if (dataSource == null) {
dataSource = new MySQLSource(mysqlHost, mysqlPassword, mysqlUsername, databaseName);
boolean status = dataSource.open();
System.out.println("status = " + status);
// 查询历史消息
if (status) {
datasourceMap.put(session.getId(), dataSource);
@ -89,20 +89,24 @@ public class ChatServiceImpl implements ChatService {
String sql = "select content, create_time \"creatTime\", create_user \"createUser\", create_name \"createName\" from t_chat where deleted = 0 and revoked = 0 order by create_time asc ";
if (tablesx.next()) {
try {
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
Map map = new HashMap();
map.put("content", resultSet.getString("content"));
map.put("creatTime", resultSet.getString("creatTime"));
map.put("createUser", resultSet.getString("createUser"));
map.put("createName", resultSet.getString("createName"));
history.add(map);
}
JSONObject param = new JSONObject();
param.put("history", history);
param.put("msgType", "msg");
session.sendMessage(new TextMessage(param.toJSONString().getBytes()));
//
// Statement statement = connection.createStatement();
// ResultSet resultSet = statement.executeQuery(sql);
// while (resultSet.next()) {
// Map map = new HashMap();
// map.put("content", resultSet.getString("content"));
// map.put("creatTime", resultSet.getString("creatTime"));
// map.put("createUser", resultSet.getString("createUser"));
// map.put("createName", resultSet.getString("createName"));
// history.add(map);
// }
// JSONObject param = new JSONObject();
// param.put("history", history);
// param.put("msgType", "msg");
//// session.sendMessage(new TextMessage(param.toJSONString().getBytes()));
// for (WebSocketSession webSocketSession : webSocketSessionList) {
// webSocketSession.sendMessage(new TextMessage(param.toJSONString().getBytes()));
// }
} catch (Exception e) {
e.printStackTrace();
}
@ -150,11 +154,14 @@ public class ChatServiceImpl implements ChatService {
param.put("createTime", now);
param.put("content", msg);
System.out.println("param = " + param);
System.out.println("webSocketSessionList = " + webSocketSessionList);
// 广播消息
for (WebSocketSession webSocketSession : webSocketSessionList) {
webSocketSession.sendMessage(new TextMessage(param.toJSONString().getBytes()));
}
//
// 入库
Connection connection = dataSource.getConnection();
@ -172,15 +179,15 @@ public class ChatServiceImpl implements ChatService {
} catch (SQLException e) {
e.printStackTrace();
}
// Map<String, WebSocketSession> sessionMap1 = databaseSessionMap.get(databaseName);
// for (Map.Entry<String, WebSocketSession> entry : sessionMap1.entrySet()) {
// WebSocketSession value = entry.getValue();
// try {
// value.sendMessage(new TextMessage(param.toJSONString().getBytes()));
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//// Map<String, WebSocketSession> sessionMap1 = databaseSessionMap.get(databaseName);
//// for (Map.Entry<String, WebSocketSession> entry : sessionMap1.entrySet()) {
//// WebSocketSession value = entry.getValue();
//// try {
//// value.sendMessage(new TextMessage(param.toJSONString().getBytes()));
//// } catch (IOException e) {
//// e.printStackTrace();
//// }
//// }
}
}

View File

@ -139,11 +139,11 @@ public class VitalSignTimerWS {
}
public void createAndSendMessageMySQL(String database, String username, WebSocketSession session) {
synchronized (username) {
if (!masterControlMap.containsKey(database)) {
masterControlMap.put(database, username);
}
// synchronized (username) {
if (!masterControlMap.containsKey(database)) {
masterControlMap.put(database, username);
}
// }
String sessionId = session.getId();
@ -181,7 +181,7 @@ public class VitalSignTimerWS {
Connection connection = finalDataSource.getConnection();
JSONObject jsonObject = new JSONObject();
// List<Map> vitalSignsList = vitalSignsService.getVitalSignsList(connection);
Map vitalSignsList = vitalSignsService.getVitalSignsList(connection,username,database);
Map vitalSignsList = vitalSignsService.getVitalSignsList(connection, username, database);
jsonObject.put("vitalSignsList", vitalSignsList);
List<Map> aiMedicineList = aiMedicineService.getAIMedicine(connection);
jsonObject.put("aiMedicineList", aiMedicineList);

View File

@ -172,8 +172,8 @@ public class VitalSignTimerV2 {
if (masterControlMap.containsKey(database) && masterControlMap.get(database).equals(username)) {
// 给药到unity
WebSocketSession unitySession = aiMedicineTimer.getUnitySession(database);
result.put("medicine",medicine);
result.put("value",value);
result.put("medicine", medicine);
result.put("value", value);
result.put("flag", flag);
result.put("msgType", "addMedicine");
unitySession.sendMessage(new TextMessage(result.toJSONString().getBytes()));