问诊大厅代码提交

dev_2.0.0
liu 1 year ago
parent 25450fc781
commit 24d943fe43

@ -43,6 +43,7 @@
<freemarker.version>2.3.31</freemarker.version>
<mysql-connector-java.version>8.0.26</mysql-connector-java.version>
<io-swagger.version>1.5.22</io-swagger.version>
<lock4j.version>2.2.5</lock4j.version>
</properties>
<dependencyManagement>

@ -38,6 +38,12 @@
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!--redis分布式锁 https://gitee.com/baomidou/lock4j -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>lock4j-redis-template-spring-boot-starter</artifactId>
<version>${lock4j.version}</version>
</dependency>
<!-- 其他依赖 -->
<dependency>

@ -1,7 +1,8 @@
package com.supervision.constant;
public interface UserTokenConstant {
String USER_ID_CACHE = "USER:ID:CACHE";
String USER_WEBSOCKET_CACHE = "USER:ID:CACHE";
String KICK_CHANNEL = "USER:KICK:CHANNEL";
}

@ -58,6 +58,7 @@
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>
<build>

@ -2,12 +2,11 @@ package com.supervision.controller;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.supervision.constant.UserTokenConstant;
import com.supervision.usermanage.UserWebSocketDTO;
import lombok.RequiredArgsConstructor;
import com.supervision.usermanage.UserResourceCheck;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@ -28,16 +27,19 @@ public class WebSocketServer {
//concurrent包的线程安全Set用来存放每个客户端对应的WebSocketServer对象。
private static final ConcurrentHashMap<String, Session> SESSION_POOL = new ConcurrentHashMap<>();
@Value("${human.resourceMaxNumber}")
private String resourceNumber;
@Autowired
private UserResourceCheck userResourceCheck;
/**
*
*/
@OnOpen
public void onOpen(Session session, @PathParam(value = "uid") String uid) throws IOException {
log.info("用户:{}登录,缓存到Redis", uid);
// 链接之前先把之前的用户踢下线(ignoreSessionId防止把当前用户踢下线)
redisTemplate.convertAndSend(UserTokenConstant.KICK_CHANNEL, JSONUtil.toJsonStr(new UserWebSocketDTO(uid, session.getId())));
public void onOpen(Session session, @PathParam(value = "uid") String uid) {
userResourceCheck.achieveDiagnoseResourceAndOpenConnection(uid, session);
SESSION_POOL.put(uid, session);
redisTemplate.opsForHash().put(UserTokenConstant.USER_ID_CACHE, uid, session.getId());
}
/**
@ -45,9 +47,9 @@ public class WebSocketServer {
*/
@OnClose
public void onClose(Session session, @PathParam(value = "uid") String uid) {
redisTemplate.opsForHash().delete(UserTokenConstant.USER_ID_CACHE, uid, session.getId());
redisTemplate.opsForHash().delete(UserTokenConstant.USER_WEBSOCKET_CACHE, uid, session.getId());
SESSION_POOL.remove(uid);
log.info("用户:{}关闭从Redis中移除,当前连接数为:{}", uid, redisTemplate.opsForHash().size(UserTokenConstant.USER_ID_CACHE));
log.info("用户:{}关闭从Redis中移除,当前连接数为:{}", uid, redisTemplate.opsForHash().size(UserTokenConstant.USER_WEBSOCKET_CACHE));
}
/**
@ -55,9 +57,9 @@ public class WebSocketServer {
*/
@OnError
public void onError(Session session, @PathParam(value = "uid") String uid, Throwable throwable) {
redisTemplate.opsForHash().delete(UserTokenConstant.USER_ID_CACHE, uid, session.getId());
redisTemplate.opsForHash().delete(UserTokenConstant.USER_WEBSOCKET_CACHE, uid, session.getId());
SESSION_POOL.remove(uid);
log.error("用户:{}发生错误从Redis中移除,当前连接数为:{}", uid, redisTemplate.opsForHash().size(UserTokenConstant.USER_ID_CACHE), throwable);
log.error("用户:{}发生错误从Redis中移除,当前连接数为:{}", uid, redisTemplate.opsForHash().size(UserTokenConstant.USER_WEBSOCKET_CACHE), throwable);
}
// 实现一个方法用于踢下线用户,走的是Redis的消息队列

@ -18,7 +18,6 @@ public class AskPhysicalResultReqVO {
private String locationCode;
@ApiModelProperty("初步诊断ID")
@NotBlank(message = "初步诊断ID不能为空")
private String primaryId;
@NotBlank(message = "流程ID不能为空")

@ -1,8 +1,9 @@
package com.supervision.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.lock.annotation.Lock4j;
import com.supervision.constant.UserTokenConstant;
import com.supervision.service.DiagnoseHallService;
import com.supervision.usermanage.UserResourceCheck;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@ -14,17 +15,13 @@ import org.springframework.stereotype.Service;
@Slf4j
public class DiagnoseHallServiceImpl implements DiagnoseHallService {
private final RedisTemplate<String,String> redisTemplate;
@Value("${human.resourceMaxNumber}")
private String resourceNumber;
private final UserResourceCheck userResourceCheck;
@Lock4j(name = "achieveDiagnoseResource")
@Override
public boolean achieveDiagnoseResource() {
long humanMaxNumber = Long.parseLong(resourceNumber);
long currentUserNum = redisTemplate.opsForHash().size(UserTokenConstant.USER_ID_CACHE);
// 如果小于数字人最大连接数,则可以连接
return currentUserNum <= humanMaxNumber;
return userResourceCheck.achieveDiagnoseResource();
}
}

@ -0,0 +1,45 @@
package com.supervision.usermanage;
import cn.hutool.json.JSONUtil;
import com.baomidou.lock.annotation.Lock4j;
import com.supervision.constant.UserTokenConstant;
import com.supervision.exception.BusinessException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import javax.websocket.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@RequiredArgsConstructor
public class UserResourceCheck {
@Value("${human.resourceMaxNumber}")
private String resourceNumber;
private final RedisTemplate<String, String> redisTemplate;
@Lock4j(name = "achieveDiagnoseResource")
public boolean achieveDiagnoseResource() {
long humanMaxNumber = Long.parseLong(resourceNumber);
long currentSize = redisTemplate.opsForHash().size(UserTokenConstant.USER_WEBSOCKET_CACHE);
// 如果小于数字人最大连接数,则可以连接
return currentSize < humanMaxNumber;
}
@Lock4j(name = "achieveDiagnoseResourceAndOpenConnection")
public void achieveDiagnoseResourceAndOpenConnection(String uid, Session session){
// 如果小于数字人最大连接数,则可以连接
if (!achieveDiagnoseResource()) {
throw new BusinessException("暂时没有资源,建立连接失败");
}
log.info("用户:{}登录,缓存到Redis", uid);
// 链接之前先把之前的用户踢下线(ignoreSessionId防止把当前用户踢下线)
// 注意,这里如果用户没有进到问诊页面,只是在问诊大厅时,是不会被踢掉的.(因为这时没有建立websocket连接)
redisTemplate.convertAndSend(UserTokenConstant.KICK_CHANNEL, JSONUtil.toJsonStr(new UserWebSocketDTO(uid, session.getId())));
redisTemplate.opsForHash().put(UserTokenConstant.USER_WEBSOCKET_CACHE, uid, session.getId());
}
}

@ -13,4 +13,5 @@ public class UserWebSocketDTO {
* ID
*/
private String ignoreSessionId;
}

Loading…
Cancel
Save