电话呼出连接逻辑修改,增加多手机号兼容

This commit is contained in:
俞扬
2023-08-26 13:44:17 +08:00
parent e1361e0b86
commit 3e93ad3fb3
5 changed files with 201 additions and 20 deletions

View File

@@ -0,0 +1,96 @@
package com.cool.store.utils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Repository;
/**
**/
@Repository
public class SpringUtils implements BeanFactoryPostProcessor {
//Spring应用上下文环境
private static ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
SpringUtils.beanFactory = beanFactory;
}
public static ConfigurableListableBeanFactory getBeanFactory() {
return beanFactory;
}
/**
* 获取对象
*
* @param name
* @return Object 一个以所给名字注册的bean的实例
* @throws org.springframework.beans.BeansException
*
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
return (T) getBeanFactory().getBean(name);
}
/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*
*/
public static <T> T getBean(Class<T> clz) throws BeansException {
T result = (T) getBeanFactory().getBean(clz);
return result;
}
/**
* 如果BeanFactory包含一个与所给名称匹配的bean定义则返回true
*
* @param name
* @return boolean
*/
public static boolean containsBean(String name) {
return getBeanFactory().containsBean(name);
}
/**
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到将会抛出一个异常NoSuchBeanDefinitionException
*
* @param name
* @return boolean
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return getBeanFactory().isSingleton(name);
}
/**
* @param name
* @return Class 注册对象的类型
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return getBeanFactory().getType(name);
}
/**
* 如果给定的bean名字在bean定义中有别名则返回这些别名
*
* @param name
* @return
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
return getBeanFactory().getAliases(name);
}
}

View File

@@ -0,0 +1,42 @@
package com.cool.store.config.websocket;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import java.util.List;
import java.util.Map;
@Configuration
public class WebSocketConfig extends ServerEndpointConfig.Configurator {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
/**
* 建立握手时,连接前的操作
*/
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
// 这个userProperties 可以通过 session.getUserProperties()获取
final Map<String, Object> userProperties = sec.getUserProperties();
Map<String, List<String>> headers = request.getHeaders();
List<String> mobiles = headers.get("mobiles");
userProperties.put("mobiles", mobiles.get(0));
}
/**
* 初始化端点对象,也就是被@ServerEndpoint所标注的对象
*/
@Override
public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
return super.getEndpointInstance(clazz);
}
}

View File

@@ -1,20 +1,30 @@
package com.cool.store.handler; package com.cool.store.handler;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.cool.store.config.websocket.WebSocketConfig;
import com.cool.store.utils.RedisUtil;
import com.cool.store.utils.RedisUtilPool;
import com.cool.store.utils.SpringUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.websocket.*; import javax.websocket.*;
import javax.websocket.server.PathParam; import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint; import javax.websocket.server.ServerEndpoint;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@Component @Component
@Slf4j @Slf4j
@ServerEndpoint("/websocket/{tenantId}") @ServerEndpoint(value="/websocket/{tenantId}",configurator = WebSocketConfig.class)
public class WebSocketServer { public class WebSocketServer {
/** /**
@@ -34,12 +44,24 @@ public class WebSocketServer {
*/ */
private String tenantId = ""; private String tenantId = "";
/**
* 手机号
*/
private List<String> mobiles;
private static RedisUtilPool redisUtilPool = SpringUtils.getBean(RedisUtilPool.class);
/** /**
* 连接建立成 * 连接建立成
* 功调用的方法 * 功调用的方法
*/ */
@OnOpen @OnOpen
public void onOpen(Session session, @PathParam("tenantId") String tenantId) { public void onOpen(Session session, @PathParam("tenantId") String tenantId) {
String mobiles = getHeader(session, "mobiles");
if(StringUtils.isEmpty(mobiles)){
return;
}
this.mobiles = Arrays.asList(mobiles.split(","));
this.session = session; this.session = session;
this.tenantId = tenantId; this.tenantId = tenantId;
if (webSocketMap.containsKey(tenantId)) { if (webSocketMap.containsKey(tenantId)) {
@@ -52,6 +74,9 @@ public class WebSocketServer {
//在线数加1 //在线数加1
addOnlineCount(); addOnlineCount();
} }
for (String mobile : this.mobiles) {
redisUtilPool.setString(mobile, tenantId, 3600);
}
log.info("用户连接:" + tenantId + ",当前在线人数为:" + getOnlineCount()); log.info("用户连接:" + tenantId + ",当前在线人数为:" + getOnlineCount());
sendMessage("连接成功"); sendMessage("连接成功");
} }
@@ -177,6 +202,39 @@ public class WebSocketServer {
* @return * @return
*/ */
public static boolean isOnline(String tenantId) { public static boolean isOnline(String tenantId) {
if(StringUtils.isEmpty(tenantId)) {
return false;
}
return webSocketMap.containsKey(tenantId); return webSocketMap.containsKey(tenantId);
} }
public static String getHeader(Session session, String headerName) {
final String header = (String) session.getUserProperties().get(headerName);
if (StrUtil.isBlank(header)) {
log.error("获取header失败不安全的链接即将关闭");
try {
session.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return header;
}
public static String getTenantIdByMobile(String mobile){
String jsonStr = redisUtilPool.getString(mobile);
if (StringUtils.isNotEmpty(jsonStr)){
return jsonStr;
}
//如果redis中没有循环webSocketMap找到对应的tenantId
for (String key : webSocketMap.keySet()) {
WebSocketServer webSocketServer = webSocketMap.get(key);
if (webSocketServer.mobiles.contains(mobile)){
return webSocketServer.tenantId;
}
}
return null;
}
} }

View File

@@ -27,6 +27,7 @@ import com.cool.store.request.CallUpReq;
import com.cool.store.service.CallService; import com.cool.store.service.CallService;
import com.cool.store.service.LogService; import com.cool.store.service.LogService;
import com.cool.store.utils.CoolDateUtils; import com.cool.store.utils.CoolDateUtils;
import com.cool.store.utils.RedisUtilPool;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
@@ -60,8 +61,9 @@ public class CallServiceImpl implements CallService {
private LogService logService; private LogService logService;
@Override @Override
public String callUp(CallUpReq request) throws ApiException { public String callUp(CallUpReq request) throws ApiException {
String tenantId = WebSocketServer.getTenantIdByMobile(request.getOutgoingMobile());
//校验拨出手机号APP是否在线 //校验拨出手机号APP是否在线
boolean isOnline = WebSocketServer.isOnline(request.getOutgoingMobile()); boolean isOnline = WebSocketServer.isOnline(tenantId);
if (!isOnline) { if (!isOnline) {
throw new ApiException(ErrorCodeEnum.MOBILE_APP_NOT_ONLINE_ERROR); throw new ApiException(ErrorCodeEnum.MOBILE_APP_NOT_ONLINE_ERROR);
} }
@@ -85,7 +87,7 @@ public class CallServiceImpl implements CallService {
callUpDTO.setTransNo(transNo); callUpDTO.setTransNo(transNo);
callUpDTO.setOutgoingMobile(request.getOutgoingMobile()); callUpDTO.setOutgoingMobile(request.getOutgoingMobile());
callUpDTO.setIncomingMobile(request.getIncomingMobile()); callUpDTO.setIncomingMobile(request.getIncomingMobile());
boolean sendFlag = WebSocketServer.sendInfo(JSON.toJSONString(callUpDTO), callRecordDO.getOutgoingMobile()); boolean sendFlag = WebSocketServer.sendInfo(JSON.toJSONString(callUpDTO), tenantId);
if (!sendFlag) { if (!sendFlag) {
throw new ApiException(ErrorCodeEnum.CREATE_CALL_REQUEST_ERROR); throw new ApiException(ErrorCodeEnum.CREATE_CALL_REQUEST_ERROR);
} }

View File

@@ -1,17 +0,0 @@
package com.cool.store.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* WebSocket的配置信息
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}