websocket
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
package com.cool.store.request;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: young.yu
|
||||
* @Date: 2023-08-10 19:24
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
@ApiModel
|
||||
public class CallUpReq {
|
||||
@ApiModelProperty(value = "线索id", required = true)
|
||||
private String lineId;
|
||||
|
||||
@ApiModelProperty(value = "呼出人用户id", required = true)
|
||||
private String outgoingUserId;
|
||||
|
||||
@ApiModelProperty(value = "呼出人手机号", required = true)
|
||||
private String outgoingMobile;
|
||||
|
||||
@ApiModelProperty(value = "接听人用户id", required = true)
|
||||
private String incomingUserId;
|
||||
|
||||
@ApiModelProperty(value = "接听人手机号", required = true)
|
||||
private String incomingMobile;
|
||||
}
|
||||
@@ -85,6 +85,11 @@
|
||||
<artifactId>dysmsapi20170525</artifactId>
|
||||
<version>2.0.1</version>
|
||||
</dependency>
|
||||
<!--websocket作为服务端-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,166 @@
|
||||
package com.cool.store.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.websocket.*;
|
||||
import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@ServerEndpoint("/websocket/{tenantId}")
|
||||
public class WebSocketServer {
|
||||
|
||||
/**
|
||||
* 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
|
||||
*/
|
||||
private static int onlineCount = 0;
|
||||
/**
|
||||
* concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。
|
||||
*/
|
||||
private static final ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* 与某个客户端的连接会话,需要通过它来给客户端发送数据
|
||||
*/
|
||||
private Session session;
|
||||
/**
|
||||
* 接收userId
|
||||
*/
|
||||
private String tenantId = "";
|
||||
|
||||
/**
|
||||
* 连接建立成
|
||||
* 功调用的方法
|
||||
*/
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("tenantId") String tenantId) {
|
||||
this.session = session;
|
||||
this.tenantId = tenantId;
|
||||
if (webSocketMap.containsKey(tenantId)) {
|
||||
webSocketMap.remove(tenantId);
|
||||
//加入set中
|
||||
webSocketMap.put(tenantId, this);
|
||||
} else {
|
||||
//加入set中
|
||||
webSocketMap.put(tenantId, this);
|
||||
//在线数加1
|
||||
addOnlineCount();
|
||||
}
|
||||
log.info("用户连接:" + tenantId + ",当前在线人数为:" + getOnlineCount());
|
||||
sendMessage("连接成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接关闭
|
||||
* 调用的方法
|
||||
*/
|
||||
@OnClose
|
||||
public void onClose() {
|
||||
if (webSocketMap.containsKey(tenantId)) {
|
||||
webSocketMap.remove(tenantId);
|
||||
//从set中删除
|
||||
subOnlineCount();
|
||||
}
|
||||
log.info("用户退出:" + tenantId + ",当前在线人数为:" + getOnlineCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到客户端消
|
||||
* 息后调用的方法
|
||||
*
|
||||
* @param message 客户端发送过来的消息
|
||||
**/
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) {
|
||||
log.info("用户消息:" + tenantId + ",报文:" + message);
|
||||
//可以群发消息
|
||||
//消息保存到数据库、redis
|
||||
if (StringUtils.isNotBlank(message)) {
|
||||
try {
|
||||
//解析发送的报文
|
||||
JSONObject jsonObject = JSON.parseObject(message);
|
||||
//追加发送人(防止串改)
|
||||
jsonObject.put("fromUserId", this.tenantId);
|
||||
String toUserId = jsonObject.getString("toUserId");
|
||||
//传送给对应toUserId用户的websocket
|
||||
if (StringUtils.isNotBlank(toUserId) && webSocketMap.containsKey(toUserId)) {
|
||||
webSocketMap.get(toUserId).sendMessage(message);
|
||||
} else {
|
||||
//否则不在这个服务器上,发送到mysql或者redis
|
||||
log.error("请求的userId:" + toUserId + "不在该服务器上");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param session Session
|
||||
* @param error Throwable
|
||||
*/
|
||||
@OnError
|
||||
public void onError(Session session, Throwable error) {
|
||||
|
||||
log.error("用户错误:" + this.tenantId + ",原因:" + error.getMessage());
|
||||
error.printStackTrace();
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现服务
|
||||
* 器主动推送
|
||||
*/
|
||||
public void sendMessage(String message) {
|
||||
try {
|
||||
this.session.getBasicRemote().sendText(message);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送自定
|
||||
* 义消息
|
||||
**/
|
||||
public static void sendInfo(String message, String tenantId) {
|
||||
log.info("发送消息到:" + tenantId + ",报文:" + message);
|
||||
if (StringUtils.isNotBlank(tenantId) && webSocketMap.containsKey(tenantId)) {
|
||||
webSocketMap.get(tenantId).sendMessage(message);
|
||||
} else {
|
||||
log.error("用户" + tenantId + ",不在线!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得此时的
|
||||
* 在线人数
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static synchronized int getOnlineCount() {
|
||||
return onlineCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在线人
|
||||
* 数加1
|
||||
*/
|
||||
public static synchronized void addOnlineCount() {
|
||||
WebSocketServer.onlineCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在线人
|
||||
* 数减1
|
||||
*/
|
||||
public static synchronized void subOnlineCount() {
|
||||
WebSocketServer.onlineCount--;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.cool.store.service;
|
||||
|
||||
import com.cool.store.exception.ApiException;
|
||||
import com.cool.store.request.CallUpReq;
|
||||
|
||||
/**
|
||||
* @Author: young.yu
|
||||
* @Date: 2023-08-10 18:56
|
||||
* @Description:
|
||||
*/
|
||||
public interface CallService {
|
||||
void callUp(CallUpReq request) throws ApiException;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.cool.store.service.impl;
|
||||
|
||||
import com.cool.store.exception.ApiException;
|
||||
import com.cool.store.request.CallUpReq;
|
||||
import com.cool.store.service.CallService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @Author: young.yu
|
||||
* @Date: 2023-08-10 18:58
|
||||
* @Description:
|
||||
*/
|
||||
@Service
|
||||
public class CallServiceImpl implements CallService {
|
||||
|
||||
@Override
|
||||
public void callUp(CallUpReq request) throws ApiException {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,9 @@ public class TokenValidateFilter implements Filter {
|
||||
//腾讯音视频回调,单独做验签
|
||||
"/partner/pc/video/**",
|
||||
//TODO 800回调地址暂时不做验证
|
||||
"/partner/pc/flow/qualificationReview/callback","/**/ecSync/ecToApplet/**");
|
||||
"/partner/pc/flow/qualificationReview/callback",
|
||||
"/**/ecSync/ecToApplet/**",
|
||||
"/partner/pc/websocket/**");
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.cool.store.controller;
|
||||
|
||||
import com.cool.store.exception.ApiException;
|
||||
import com.cool.store.request.CallUpReq;
|
||||
import com.cool.store.request.GetTipsInfoReq;
|
||||
import com.cool.store.response.ResponseResult;
|
||||
import com.cool.store.service.CallService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @Author: young.yu
|
||||
* @Date: 2023-08-10 18:05
|
||||
* @Description:
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("call")
|
||||
@Api(tags = "通话")
|
||||
@Slf4j
|
||||
public class CallController {
|
||||
|
||||
@Autowired
|
||||
private CallService callService;
|
||||
|
||||
@PostMapping("/callUp")
|
||||
@ApiOperation("呼出电话")
|
||||
public ResponseResult callUp(@RequestBody CallUpReq request) throws ApiException {
|
||||
callService.callUp(request);
|
||||
return ResponseResult.success();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user