Merge remote-tracking branch 'origin/5.X' into 5.X

This commit is contained in:
zzc 2025-03-27 23:02:07 +08:00
commit 9a1e3bfd15
11 changed files with 410 additions and 92 deletions

View File

@ -9,6 +9,7 @@ import com.alibaba.fastjson.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.LoginUser;
@ -55,6 +56,7 @@ import java.util.stream.Collectors;
* @date 2024-07-14
*/
@Validated
@Log4j2
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/device")
@ -131,6 +133,7 @@ public class EqDeviceController extends BaseController {
*/
@GetMapping("/operate")
public R<String> operate(EqDeviceCmdBo bo){
log.info("设备控制参数 userId{}, equipmentCode{}, operateType{}",bo.getUserId(),bo.getEquipmentCode(),bo.getOperateType());
if (bo.getEquipmentCode() == null) throw new ServiceException("设备编码不能为空");
if (bo.getOperateType() == 0) throw new ServiceException("操作类型不能为0");
if (bo.getUserId() == null) throw new ServiceException("用户ID不能为空");
@ -283,6 +286,8 @@ public class EqDeviceController extends BaseController {
public void saveDeviceLogs(@RequestBody EqEquipmentLogBo eqEquipmentLogBo){
String equipmentName = eqEquipmentLogBo.getEquipmentName();
Integer status = eqEquipmentLogBo.getStatus();
List<String> statusList = Arrays.asList("101", "102", "103", "104", "105", "106", "107", "108", "1", "2", "112", "113");
//设备id查询
DeviceByDeviceName deviceByNameDto = iotService.apiTenantDevicesByName(equipmentName);//无信息会抛异常 无需判断
if (deviceByNameDto==null) throw new RuntimeException("设备不存在");
@ -319,7 +324,8 @@ public class EqDeviceController extends BaseController {
eqEquipmentLogBo.setDayOfWeek(dayOfWeek - 1);// Calendar类中星期日为1星期一为2依此类推
//更新状态
if(!(status==0 ||status==108 ||status==109 ||status==110 ||status==111 ||status==112 ||status==113||status==114||status==500||status==501) )
if (statusList.contains(status.toString()) )
// if(!(status==0 ||status==108 ||status==109 ||status==110 ||status==111 ||status==112 ||status==113||status==114||status==500||status==501) )
{
logService.insertByBo(eqEquipmentLogBo);
}

View File

@ -1,49 +1,30 @@
package org.dromara.web.controller.app;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.lock.annotation.Lock4j;
import com.github.benmanes.caffeine.cache.Cache;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MessageUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.websocket.dto.WebSocketMessageDto;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.dromara.system.service.ISysDictTypeService;
import org.dromara.common.websocket.holder.WebSocketSessionHolder;
import org.dromara.web.config.LastWebSocketParamDto;
import org.dromara.web.device.iot.DeviceByDeviceName;
import org.dromara.web.domain.bo.*;
import org.dromara.web.domain.vo.*;
import org.dromara.web.service.*;
import org.dromara.web.utils.WebSocketBusinessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* app iot设备业务
@ -51,6 +32,7 @@ import java.util.stream.Collectors;
* @author Lion Li
* @date 2024-07-14
*/
@Log4j2
@Validated
@RequiredArgsConstructor
@RestController
@ -141,8 +123,10 @@ public class EqIotDeviceController extends BaseController {
*/
@SaIgnore
@PostMapping("/sendDeviceMsg2")
public void sendDeviceMsg2(@RequestBody EqEquipmentLogBo eqEquipmentLogBo){
String status = eqEquipmentLogBo.getStatus() + "";
@Lock4j(keys = {"#eqEquipmentLogBo.equipmentName"}, expire = 30000, acquireTimeout = 1000)
public void sendDeviceMsg2(@RequestBody EqEquipmentLogBo eqEquipmentLogBo) throws InterruptedException {
// Thread.sleep(1000);
/*String status = eqEquipmentLogBo.getStatus() + "";
String statusCache = tokenCache.getIfPresent("status");
if (StringUtils.isEmpty(statusCache)){
tokenCache.put("status",status);
@ -152,7 +136,7 @@ public class EqIotDeviceController extends BaseController {
}else{
return;
}
}
}*/
String equipmentName = eqEquipmentLogBo.getEquipmentName();
//设备id查询
DeviceByDeviceName deviceByNameDto = iotService.apiTenantDevicesByName(equipmentName);//无信息会抛异常 无需判断
@ -168,12 +152,28 @@ public class EqIotDeviceController extends BaseController {
Long userId = eqEquipmentVo.getUserId();
LoginUser loginUser = new LoginUser();
loginUser.setUserId(userId);
//小优化 减少不必要查询 后续可以让设备传设备id 减少iot查询 再通过初始redis来映射userId来减少数据库查询
if (!WebSocketSessionHolder.existSession(Long.valueOf("5"+userId.toString().substring(1)))&&!WebSocketSessionHolder.existSession(Long.valueOf("6"+userId.toString().substring(1)))){
log.info("app-Socket-{} 未上线",userId);
return;
}
LastWebSocketParamDto dto = RedisUtils.getCacheObject(Constants.WEBSOCKET_METHOD+loginUser.getUserId());
String param = JSONObject.toJSONString(dto.getBo());
if (Constants.METHOD_EQ_DETAIL.equals(dto.getMethod())){
webSocketBusinessHandler.dealWithDetailMsg(loginUser,param);
String redisKey = Constants.METHOD_EQ_DETAIL + userId;
Boolean isSent = RedisUtils.setObjectIfAbsent(redisKey, Constants.METHOD_EQ_DETAIL, Duration.ofMillis(1000));
if (Boolean.TRUE.equals(isSent)) {
webSocketBusinessHandler.dealWithDetailMsg2(loginUser,param,2);
}
}else if (Constants.METHOD_EQ_LIST.equals(dto.getMethod())){
webSocketBusinessHandler.dealWithListMsg(loginUser,param);
String redisKey = Constants.METHOD_EQ_LIST + userId;
Boolean isSent = RedisUtils.setObjectIfAbsent(redisKey, Constants.METHOD_EQ_LIST, Duration.ofMillis(1000));
if (Boolean.TRUE.equals(isSent)) {
webSocketBusinessHandler.dealWithListMsg2(loginUser,param,2);
}
}else{
System.out.println("无设备信息最新参数");
}

View File

@ -74,19 +74,19 @@ public class EqEquipmentLogBo extends BaseEntity {
* 13.电机维护故障 motorMaintainException
* 14.设备故障 deviceException
*
* 101.烟雾报警
* 102.红外触发报警
* 103.电机运行报警
* 104.电机维修报警
* 105.非APP开门提醒
* 106.非APP关门提醒
* 107.关门故障报警
* 108.开门故障报警
* 109.开门运行提醒
* 110.关门运行提醒
* 101.烟雾报警
* 102.红外触发报警
* 103.电机运行报警
* 104.电机维修报警
* 105.非APP开门提醒
* 106.非APP关门提醒
* 107.关门故障报警
* 108.开门故障报警
* 109.开门运行提醒 使用1
* 110.关门运行提醒 使用2
* 111.忘记关门提醒
* 112.门体手动开启提醒
* 113.半开门运行提醒
* 112.门体手动开启提醒
* 113.半开门运行提醒
* 114.门体停止运行提醒
*
* 500.设备离线 offline

View File

@ -0,0 +1,140 @@
package org.dromara.web.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import java.io.Serial;
import java.io.Serializable;
/**
* 设备信息视图对象 eq_equipment
*
* @author zzc
* @date 2024-07-19
*/
@Data
public class EqEquipmentListVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long equipmentId;
/**
* 分布id
*/
@ExcelProperty(value = "分布id")
private Long areaId;
/**
* 设备类型
*/
@ExcelProperty(value = "设备类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "eq_equipment_type")
private Integer type;
/**
* 登录账号
*/
@ExcelProperty(value = "登录账号ID")
private Long userId;
/**
* 设备编码
*/
@ExcelProperty(value = "设备编码")
private String equipmentCode;
/**
* 设备名称
*/
@ExcelProperty(value = "设备名称")
private String equipmentName;
/**
* 离线状态
*/
@ExcelProperty(value = "离线状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "eq_line_status")
private Integer lineStatus;
/**
* //半开门功能开关 false
* //半开门功能开关 true
*/
private Boolean PartOpenSwitch;
/**
* 排序
*/
@ExcelProperty(value = "排序")
private Integer orderNum;
/**
* 设备状态(开合度)
* 0.已关闭
* 10.打开10%
* 20.打开20%
* 30.打开30%
* 40.打开40%
* 50.打开50%
* 60.打开60%
* 70.打开70%
* 80.打开80%
* 90.打开90%
* 100.打开100%
*/
@ExcelProperty(value = "设备状态 设备的打开状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "eq_status_type")
private Integer openStatus;
/**
* 设备状态(开合度)
* 0.已关闭
* 10.打开10%
* 20.打开20%
* 30.打开30%
* 40.打开40%
* 50.打开50%
* 60.打开60%
* 70.打开70%
* 80.打开80%
* 90.打开90%
* 100.打开100%
* 故障状态
*/
private String openStatusText;
/**
* 设备运行状态
* 0.停止中 stop
* 1.关闭中 closing
* 2.开启中 opening
* 11.红外故障 irException
* 12.电机运转故障 motorRunException
* 13.电机维护故障 motorMaintainException
* 14.设备故障 deviceException
*/
@ExcelProperty(value = "设备状态 设备的打开状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "eq_run_status_type")
private Integer runStatus;
/**
* 设备运行状态文本
* 0.停止中 stop
* 1.关闭中 closing
* 2.开启中 openning
* 11.红外故障 irException
* 12.电机运转故障 motorRunException
* 13.电机维护故障 motorMaintainException
* 14.设备故障 deviceException
*/
private String runStatusText;
}

View File

@ -117,7 +117,7 @@ public class EqEquipmentServiceImpl implements IEqEquipmentService {
record.setOpenStatusText(
telemetryMsg.getOpenPercentage()==0
?MessageUtils.message("openStatus.name0")
:MessageUtils.message("openStatus.name1")+ telemetryMsg.getOpenPercentage()+"%");
:MessageUtils.message("openStatus.name1"));
//运行状态
record.setRunStatus(garageException ==10?telemetryMsg.getWorkState(): garageException);
@ -321,7 +321,7 @@ public class EqEquipmentServiceImpl implements IEqEquipmentService {
result.setOpenStatusText(
telemetryMsg.getOpenPercentage()==0
?MessageUtils.message("openStatus.name0")
:MessageUtils.message("openStatus.name1")+ telemetryMsg.getOpenPercentage()+"%");
:MessageUtils.message("openStatus.name1"));
//运行状态
result.setRunStatus(telemetryMsg.getGarageException()==10?telemetryMsg.getWorkState():telemetryMsg.getGarageException());
@ -476,7 +476,8 @@ public class EqEquipmentServiceImpl implements IEqEquipmentService {
eqVersionBo.setCurrentVersion(currentVersion);
eqVersionBo.setLatestVersion(null);
}else{
eqVersionBo.setNeedUpdate(true);
if (StringUtils.isBlank(currentVersion)) throw new RuntimeException("设备无当前OTA版本");
eqVersionBo.setNeedUpdate(!currentVersion.equals(lastOtaPackage.getVersion()));
eqVersionBo.setCurrentVersion(currentVersion);
eqVersionBo.setLatestVersion(lastOtaPackage.getVersion());
}

View File

@ -1,6 +1,8 @@
package org.dromara.web.utils;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.lock.annotation.Lock4j;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.domain.R;
@ -18,6 +20,7 @@ import org.dromara.web.controller.app.EqHomeController;
import org.dromara.web.domain.bo.EqAppHomeBo;
import org.dromara.web.domain.bo.EqUserConfigBo;
import org.dromara.web.domain.vo.EqEquipmentDetailVo;
import org.dromara.web.domain.vo.EqEquipmentListVo;
import org.dromara.web.domain.vo.EqEquipmentVo;
import org.dromara.web.domain.vo.EqUserConfigVo;
import org.dromara.web.service.IEqUserConfigService;
@ -25,6 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@ -78,21 +82,62 @@ public class WebSocketBusinessHandler implements WebSocketApi {
// EqEquipmentDetailVo data = deviceMsg.getData();
sendMsg = JsonUtils.toJsonString(deviceMsg);
log.info("socket详情发送{}",sendMsg);
sendMsg(sendMsg, userId);
// sendMsg(sendMsg, userId);
sendMsg(sendMsg, Long.valueOf("5"+userId.toString().substring(1)));
}
@Lock4j(keys = {"#loginUser.userId"}, expire = 2000, acquireTimeout = 1000)
@Override
public void dealWithDetailMsg2(LoginUser loginUser, String msg,int type) {
EqAppHomeBo bo = null;
String sendMsg = "";
R<EqEquipmentDetailVo> deviceMsg = null;
boolean isTrue = true;
Long userId = loginUser.getUserId();
try {
initLanguage(userId);
bo = JSON.parseObject(msg, EqAppHomeBo.class);
LastWebSocketParamDto dto = new LastWebSocketParamDto();
dto.setMethod(Constants.METHOD_EQ_DETAIL);
dto.setBo(bo);
RedisUtils.setCacheObject(Constants.WEBSOCKET_METHOD+ userId,dto);
} catch (Exception e) {
log.error("参数错误");
isTrue = false;
deviceMsg = R.fail("参数错误:"+e.getMessage());
}
if (isTrue){
try {
deviceMsg = controller.getDeviceMsg(bo);
} catch (Exception e) {
deviceMsg = R.fail("设备详情获取失败:"+e.getMessage());
log.error("设备详情获取失败");
}
}
// EqEquipmentDetailVo data = deviceMsg.getData();
sendMsg = JsonUtils.toJsonString(deviceMsg);
log.info("socket详情发送{}",sendMsg);
// sendMsg(sendMsg, userId);
sendMsg(sendMsg, Long.valueOf("5"+userId.toString().substring(1)));
}
private void initLanguage(Long userId) {
EqUserConfigBo userConfigBo = new EqUserConfigBo();
userConfigBo.setUserId(userId);
List<EqUserConfigVo> eqUserConfigVos = userConfigService.queryList(userConfigBo);
if(!eqUserConfigVos.isEmpty()){
EqUserConfigVo eqUserConfigVo = eqUserConfigVos.get(0);
String languageType = eqUserConfigVo.getLanguageType();
String[] languages = languageType.split("_");
LocaleContextHolder.setDefaultLocale(new Locale(languages[0], languages[1]));
synchronized (this){
EqUserConfigBo userConfigBo = new EqUserConfigBo();
userConfigBo.setUserId(userId);
List<EqUserConfigVo> eqUserConfigVos = userConfigService.queryList(userConfigBo);
if(!eqUserConfigVos.isEmpty()){
EqUserConfigVo eqUserConfigVo = eqUserConfigVos.get(0);
String languageType = eqUserConfigVo.getLanguageType();
String[] languages = languageType.split("_");
// LocaleContextHolder.setDefaultLocale(new Locale(languages[0], languages[1]));
LocaleContextHolder.setLocale(new Locale(languages[0], languages[1]));
// 从HTTP请求中获取Locale
}
}
}
@Override
public void dealWithListMsg(LoginUser loginUser, String msg) {
EqAppHomeBo bo = null;
@ -126,7 +171,93 @@ public class WebSocketBusinessHandler implements WebSocketApi {
}
sendMsg = isTure? JsonUtils.toJsonString(list):sendMsg;
log.info("socket列表发送{}",sendMsg);
sendMsg(sendMsg, userId);
// sendMsg(sendMsg, userId);
sendMsg(sendMsg, Long.valueOf("6"+userId.toString().substring(1)));
}
@Lock4j(keys = {"#loginUser.userId"}, expire = 2000, acquireTimeout = 1000)
@Override
public void dealWithListMsg2(LoginUser loginUser, String msg, int type) {
EqAppHomeBo bo = null;
String sendMsg = "";
boolean isTure = true;
Long userId = loginUser.getUserId();
try {
initLanguage(userId);
bo = JSON.parseObject(msg, EqAppHomeBo.class);
LastWebSocketParamDto dto = new LastWebSocketParamDto();
dto.setMethod(Constants.METHOD_EQ_LIST);
dto.setBo(bo);
RedisUtils.setCacheObject(Constants.WEBSOCKET_METHOD + userId,dto);
} catch (Exception e) {
log.error("参数错误");
sendMsg = "参数错误";
isTure = false;
}
TableDataInfo<EqEquipmentVo> list = null;
boolean canSendFlag = false;
if (isTure){
PageQuery pageQuery = new PageQuery();
pageQuery.setPageNum(0);
pageQuery.setPageSize(100);
try {
list = homeController.listForWebSocket(bo, pageQuery,loginUser);
canSendFlag = true;
/* zc 去除去重
if (type == 1){
canSendFlag = true;
}else{
String key = userId + "_" + Constants.METHOD_EQ_LIST;
List<EqEquipmentVo> rows = list.getRows();
List<EqEquipmentListVo> currentVoList = new ArrayList<>();
if (rows !=null && !rows.isEmpty()){
currentVoList = BeanUtil.copyToList(rows, EqEquipmentListVo.class);
if (RedisUtils.hasKey(key)){
List<EqEquipmentListVo> cacheList = RedisUtils.getCacheList(key);
for (EqEquipmentListVo cacheVo : cacheList) {
for (EqEquipmentListVo currentVo : currentVoList) {
if (cacheVo.getEquipmentId().equals(currentVo.getEquipmentId())){
if (
!cacheVo.getLineStatus().equals(currentVo.getLineStatus())||
!cacheVo.getAreaId().equals(currentVo.getAreaId())||
!cacheVo.getOpenStatus().equals(currentVo.getOpenStatus())||
!cacheVo.getRunStatus().equals(currentVo.getRunStatus())||
!cacheVo.getPartOpenSwitch().equals(currentVo.getPartOpenSwitch())||
!cacheVo.getEquipmentCode().equals(currentVo.getEquipmentCode())||
!cacheVo.getEquipmentName().equals(currentVo.getEquipmentName())||
!cacheVo.getUserId().equals(currentVo.getUserId())||
!cacheVo.getOrderNum().equals(currentVo.getOrderNum())
){
canSendFlag = true;
}
}
}
}
if (canSendFlag) RedisUtils.setCacheList(key,currentVoList);
}else{
RedisUtils.setCacheList(key,currentVoList);
canSendFlag = true;
}
}else{
canSendFlag = true;
}
}*/
} catch (Exception e) {
isTure = false;
sendMsg = "获取设备列表失败"+e.getMessage();
log.error("获取设备列表失败:{}",e.getMessage());
}
}
if (canSendFlag){
sendMsg = isTure? JsonUtils.toJsonString(list):sendMsg;
log.info("socket列表发送{}",sendMsg);
// sendMsg(sendMsg, userId);
sendMsg(sendMsg, Long.valueOf("6"+userId.toString().substring(1)));
}
}

View File

@ -332,19 +332,19 @@ logStatus.name13=电机维护故障
logStatus.name14=设备故障
## 《故障状态》
logStatus.name101=烟雾报警
logStatus.name102=红外触发报警
logStatus.name103=电机运报警
logStatus.name102=红外保护被触发
logStatus.name103=电机运报警
logStatus.name104=电机维修报警
logStatus.name105=非APP开门提醒
logStatus.name106=非APP关门提醒
logStatus.name107=关门故障报警
logStatus.name108=开门故障报警
logStatus.name109=开门运行提醒
logStatus.name110=关门运行提醒
logStatus.name111=忘记关门提醒
logStatus.name112=体手动开启提醒
logStatus.name113=半开门运行提醒
logStatus.name114=门体停止运行提醒
logStatus.name105=非APP开门
logStatus.name106=非APP关门
logStatus.name107=关门故障
logStatus.name108=开门故障
logStatus.name109=开门运行
logStatus.name110=关门运行
logStatus.name111=忘记关门
logStatus.name112=被手动打开
logStatus.name113=半开门
logStatus.name114=门体停止
logStatus.name500=离线
logStatus.name501=在线

View File

@ -30,6 +30,7 @@ public class MessageUtils {
public static String message(String code, Object... args) {
try {
Locale locale = LocaleContextHolder.getLocale();
log.info("获取国际化资源文件: {}~{}", locale.toLanguageTag(), code);
// if (locale.toLanguageTag().equals("en")) locale = Locale.CHINA;//zc change with userid because socket I18n
return MESSAGE_SOURCE.getMessage(code, args, locale);
} catch (NoSuchMessageException e) {

View File

@ -1,8 +1,6 @@
package org.dromara.common.websocket.handler;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.websocket.constant.WebSocketConstants;
@ -10,11 +8,13 @@ import org.dromara.common.websocket.dto.WebSocketMessageDto;
import org.dromara.common.websocket.holder.WebSocketSessionHolder;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USER_KEY;
@ -24,8 +24,10 @@ import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USE
* @author zendwang
*/
@Slf4j
@Service
public class PlusWebSocketHandler extends AbstractWebSocketHandler {
@Autowired
WebSocketApi webSocketApi;
/**
* 连接成功后
*/
@ -37,12 +39,21 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
log.info("[connect] invalid token received. sessionId: {}", session.getId());
return;
}
WebSocketSessionHolder.addSession(loginUser.getUserId(), session);
log.info("[connect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType());
String currentPath = Objects.requireNonNull(session.getUri()).getPath();
Long userId = loginUser.getUserId();
if (currentPath.contains(WebSocketConstants.detail)){
WebSocketSessionHolder.addSession(Long.valueOf("5"+userId.toString().substring(1) ), session);
}else if (currentPath.contains(WebSocketConstants.list)){
WebSocketSessionHolder.addSession(Long.valueOf("6"+userId.toString().substring(1)), session);
}else{
WebSocketSessionHolder.addSession(userId, session);
}
log.info("[connect] sessionId: {},userId:{},userType:{}", session.getId(), userId, loginUser.getUserType());
}
@Autowired
WebSocketApi webSocketApi;
/**
* 处理接收到的文本消息
@ -56,17 +67,17 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
// 从WebSocket会话中获取登录用户信息
log.info("socket接受到消息 {}", message.getPayload());
LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY);
String currentPath = session.getUri().getPath();
String lastPath = WebSocketSessionHolder.getSessions(loginUser.getUserId()).getUri().getPath();
String currentPath = Objects.requireNonNull(session.getUri()).getPath();
/*String lastPath = WebSocketSessionHolder.getSessions(loginUser.getUserId()).getUri().getPath();
if (!currentPath.equals(lastPath)){
WebSocketSessionHolder.addSession(loginUser.getUserId(), session);
}
}*/
String payload = message.getPayload();
if (currentPath.contains(WebSocketConstants.detail)){
webSocketApi.dealWithDetailMsg(loginUser, payload);
webSocketApi.dealWithDetailMsg2(loginUser, payload,1);
} else if (currentPath.contains(WebSocketConstants.list)) {
webSocketApi.dealWithListMsg(loginUser, payload);
webSocketApi.dealWithListMsg2(loginUser, payload,1);
} else {
// 创建WebSocket消息DTO对象
@ -111,7 +122,11 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
*/
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
// 当WebSocket发生传输错误时调用比如网络问题导致连接断开
// 这里可以认为是客户端断开连接因为服务端无法主动抛出传输错误
log.info("websocket连接-网络-客户端断开连接,错误信息:" + exception.getMessage());
log.error("[transport error] sessionId: {} , exception:{}", session.getId(), exception.getMessage());
super.handleTransportError(session, exception);
}
/**
@ -121,14 +136,33 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
* @param status 关闭状态信息
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY);
if (ObjectUtil.isNull(loginUser)) {
log.info("[disconnect] invalid token received. sessionId: {}", session.getId());
return;
}
WebSocketSessionHolder.removeSession(loginUser.getUserId());
log.info("[disconnect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType());
// 当WebSocket连接关闭时调用
if (status.equals(CloseStatus.SERVER_ERROR)) {
// 服务端断开连接比如服务端代码中调用了session.close()
log.info("websocket连接-服务端-断开连接,关闭状态:" + status);
} else {
// 客户端断开连接比如客户端调用了close方法
log.info("websocket连接-客户端-断开连接,关闭状态:" + status);
}
super.afterConnectionClosed(session, status);
String currentPath = session.getUri().getPath();
Long userId = loginUser.getUserId();
if (currentPath.contains(WebSocketConstants.detail)){
WebSocketSessionHolder.removeSession(Long.valueOf("5"+userId.toString().substring(1)));
}else if (currentPath.contains(WebSocketConstants.list)){
WebSocketSessionHolder.removeSession(Long.valueOf("6"+userId.toString().substring(1)));
}else{
WebSocketSessionHolder.removeSession(userId);
}
// WebSocketSessionHolder.removeSession(loginUser.getUserId());
log.info("[disconnect] sessionId: {},userId:{},userType:{}", session.getId(), userId, loginUser.getUserType());
}
/**
@ -141,4 +175,5 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
return false;
}
}

View File

@ -2,7 +2,6 @@ package org.dromara.common.websocket.handler;
import org.dromara.common.core.domain.model.LoginUser;
import org.springframework.stereotype.Service;
/**
* @ClassName : WebSocketApi
@ -10,8 +9,10 @@ import org.springframework.stereotype.Service;
* @Date : 2024/11/16 19:06
* @Description :
**/
@Service
//@Service
public interface WebSocketApi {
void dealWithDetailMsg(LoginUser loginUser, String msg);
void dealWithDetailMsg2(LoginUser loginUser, String msg,int type);
void dealWithListMsg(LoginUser loginUser, String msg);
void dealWithListMsg2(LoginUser loginUser, String msg,int type);
}

View File

@ -106,7 +106,7 @@ public class WebSocketUtils {
public static void sendMessage(WebSocketSession session, String message) {
sendMessage(session, new TextMessage(message));
}
private static final Object sessionLock = new Object();
/**
* 向指定的WebSocket会话发送WebSocket消息对象
*
@ -114,14 +114,17 @@ public class WebSocketUtils {
* @param message 要发送的WebSocket消息对象
*/
private static void sendMessage(WebSocketSession session, WebSocketMessage<?> message) {
if (session == null || !session.isOpen()) {
log.warn("[send] session会话已经关闭");
} else {
try {
session.sendMessage(message);
} catch (IOException e) {
log.error("[send] session({}) 发送消息({}) 异常", session, message, e);
synchronized (sessionLock) {
if (session == null || !session.isOpen()) {
log.warn("[send] session会话已经关闭");
} else {
try {
session.sendMessage(message);
} catch (IOException e) {
log.error("[send] session({}) 发送消息({}) 异常", session, message, e);
}
}
}
}
}