diff --git a/coolstore-partner-common/src/main/java/com/cool/store/utils/SpringUtils.java b/coolstore-partner-common/src/main/java/com/cool/store/utils/SpringUtils.java new file mode 100644 index 000000000..a8779ef50 --- /dev/null +++ b/coolstore-partner-common/src/main/java/com/cool/store/utils/SpringUtils.java @@ -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 getBean(String name) throws BeansException { + return (T) getBeanFactory().getBean(name); + } + + /** + * 获取类型为requiredType的对象 + * + * @param clz + * @return + * @throws org.springframework.beans.BeansException + * + */ + public static T getBean(Class 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); + } +} \ No newline at end of file diff --git a/coolstore-partner-service/src/main/java/com/cool/store/config/websocket/WebSocketConfig.java b/coolstore-partner-service/src/main/java/com/cool/store/config/websocket/WebSocketConfig.java new file mode 100644 index 000000000..1e54e9746 --- /dev/null +++ b/coolstore-partner-service/src/main/java/com/cool/store/config/websocket/WebSocketConfig.java @@ -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 userProperties = sec.getUserProperties(); + Map> headers = request.getHeaders(); + List mobiles = headers.get("mobiles"); + userProperties.put("mobiles", mobiles.get(0)); + } + + /** + * 初始化端点对象,也就是被@ServerEndpoint所标注的对象 + */ + @Override + public T getEndpointInstance(Class clazz) throws InstantiationException { + return super.getEndpointInstance(clazz); + } +} \ No newline at end of file diff --git a/coolstore-partner-service/src/main/java/com/cool/store/handler/WebSocketServer.java b/coolstore-partner-service/src/main/java/com/cool/store/handler/WebSocketServer.java index ef16a6cb8..15537487d 100644 --- a/coolstore-partner-service/src/main/java/com/cool/store/handler/WebSocketServer.java +++ b/coolstore-partner-service/src/main/java/com/cool/store/handler/WebSocketServer.java @@ -1,20 +1,30 @@ package com.cool.store.handler; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; 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 org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import javax.annotation.Resource; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; @Component @Slf4j -@ServerEndpoint("/websocket/{tenantId}") +@ServerEndpoint(value="/websocket/{tenantId}",configurator = WebSocketConfig.class) public class WebSocketServer { /** @@ -34,12 +44,24 @@ public class WebSocketServer { */ private String tenantId = ""; + /** + * 手机号 + */ + private List mobiles; + + private static RedisUtilPool redisUtilPool = SpringUtils.getBean(RedisUtilPool.class); /** * 连接建立成 * 功调用的方法 */ @OnOpen 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.tenantId = tenantId; if (webSocketMap.containsKey(tenantId)) { @@ -52,6 +74,9 @@ public class WebSocketServer { //在线数加1 addOnlineCount(); } + for (String mobile : this.mobiles) { + redisUtilPool.setString(mobile, tenantId, 3600); + } log.info("用户连接:" + tenantId + ",当前在线人数为:" + getOnlineCount()); sendMessage("连接成功"); } @@ -177,6 +202,39 @@ public class WebSocketServer { * @return */ public static boolean isOnline(String tenantId) { + if(StringUtils.isEmpty(tenantId)) { + return false; + } 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; + } } \ No newline at end of file diff --git a/coolstore-partner-service/src/main/java/com/cool/store/service/impl/CallServiceImpl.java b/coolstore-partner-service/src/main/java/com/cool/store/service/impl/CallServiceImpl.java index dc040ab7f..7ad1c508d 100644 --- a/coolstore-partner-service/src/main/java/com/cool/store/service/impl/CallServiceImpl.java +++ b/coolstore-partner-service/src/main/java/com/cool/store/service/impl/CallServiceImpl.java @@ -27,6 +27,7 @@ import com.cool.store.request.CallUpReq; import com.cool.store.service.CallService; import com.cool.store.service.LogService; import com.cool.store.utils.CoolDateUtils; +import com.cool.store.utils.RedisUtilPool; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; @@ -60,8 +61,9 @@ public class CallServiceImpl implements CallService { private LogService logService; @Override public String callUp(CallUpReq request) throws ApiException { + String tenantId = WebSocketServer.getTenantIdByMobile(request.getOutgoingMobile()); //校验拨出手机号APP是否在线 - boolean isOnline = WebSocketServer.isOnline(request.getOutgoingMobile()); + boolean isOnline = WebSocketServer.isOnline(tenantId); if (!isOnline) { throw new ApiException(ErrorCodeEnum.MOBILE_APP_NOT_ONLINE_ERROR); } @@ -85,7 +87,7 @@ public class CallServiceImpl implements CallService { callUpDTO.setTransNo(transNo); callUpDTO.setOutgoingMobile(request.getOutgoingMobile()); callUpDTO.setIncomingMobile(request.getIncomingMobile()); - boolean sendFlag = WebSocketServer.sendInfo(JSON.toJSONString(callUpDTO), callRecordDO.getOutgoingMobile()); + boolean sendFlag = WebSocketServer.sendInfo(JSON.toJSONString(callUpDTO), tenantId); if (!sendFlag) { throw new ApiException(ErrorCodeEnum.CREATE_CALL_REQUEST_ERROR); } diff --git a/coolstore-partner-webb/src/main/java/com/cool/store/config/WebSocketConfig.java b/coolstore-partner-webb/src/main/java/com/cool/store/config/WebSocketConfig.java deleted file mode 100644 index 9d59b0d38..000000000 --- a/coolstore-partner-webb/src/main/java/com/cool/store/config/WebSocketConfig.java +++ /dev/null @@ -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(); - } -} \ No newline at end of file