springboot整合webscoket时写了一个service,代码如下:
package com.xjc.leleservice.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xjc.common.client.WebSocketClient;
import com.xjc.common.untils.RedisUtils;
import com.xjc.entity.OrderList;
import com.xjc.leleservice.OrderListService;
import com.xjc.vo.AdminOrderManagerVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author bill
* @ClassName WebSocketService
* @Describe
* @Date 2022/4/1 15:00
**/
@ServerEndpoint(value = "/websocket/{orderId}")
@Component
public class WebSocketService {
private static final Logger log = LoggerFactory.getLogger(WebSocketService.class);
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。
private static ConcurrentHashMap<String, WebSocketClient> webSocketMap = new ConcurrentHashMap<>();
/**与某个客户端的连接会话,需要通过它来给客户端发送数据*/
private Session session;
/**接收orderId*/
private String orderId="";
@Autowired
private RedisUtils redisUtils;
/**
* 连接建立成功调用的方法*/
@OnOpen
public void onOpen(Session session, @PathParam("orderId") String orderId) {
if(!webSocketMap.containsKey(orderId))
{
addOnlineCount(); // 订单数 +1
}
this.session = session;
this.orderId= orderId;
WebSocketClient client = new WebSocketClient();
client.setSession(session);
client.setUri(session.getRequestURI().toString());
webSocketMap.put(orderId, client);
log.info("----------------------------------------------------------------------------");
log.info("订单:"+orderId+",当前订单数:" + getOnlineCount());
sendMessage("1","有新订单了");
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
log.info("你好性感");
if(webSocketMap.containsKey(orderId)){
webSocketMap.remove(orderId);
if(webSocketMap.size()>0)
{
//从set中删除
subOnlineCount();
}
}
log.info("----------------------------------------------------------------------------");
log.info(orderId+"用户退出,当前在线人数为:" + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("收到新的订单:"+orderId+",报文:"+message);
//可以群发消息
//消息保存到数据库、redis
if(StringUtils.isNotBlank(message)){
}
}
/**
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("用户错误:"+this.orderId+",原因:"+error.getMessage());
error.printStackTrace();
}
/**
* 连接服务器成功后主动推送
*/
public void sendMessage(String message) throws IOException {
System.out.println(message);
synchronized (session){
this.session.getBasicRemote().sendText(message);
}
}
/**
* 向指定客户端发送消息
* @param orderId
* @param message
*/
public void sendMessage(String orderId,String message){
try {
if (StringUtils.isEmpty(orderId)) {
throw new IOException("后台错误,请联系管理员");
}
WebSocketClient webSocketClient = webSocketMap.get(orderId);
if(webSocketClient!=null){
webSocketClient.getSession().getBasicRemote().sendText(message);
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketService.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketService.onlineCount--;
}
public static void setOnlineCount(int onlineCount) {
WebSocketService.onlineCount = onlineCount;
}
public static ConcurrentHashMap<String, WebSocketClient> getWebSocketMap() {
return webSocketMap;
}
public static void setWebSocketMap(ConcurrentHashMap<String, WebSocketClient> webSocketMap) {
WebSocketService.webSocketMap = webSocketMap;
}
public Session getSession() {
return session;
}
public void setSession(Session session) {
this.session = session;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
}
前端vue封装了一下websocket,如下
export function useWebSocket(handleMessage){
console.log(265235)
const ws = new WebSocket('ws://localhost:2000/websocket/1')
const init = () => {
bindEvent()
}
function bindEvent(){
ws.addEventListener('open',handleOpen,false)
ws.addEventListener('close',handleClose,false)
ws.addEventListener('error',handleError,false)
ws.addEventListener('message',handleMessage,false)
function handleOpen(e) {
console.log('handleOpen'+e)
}
function handleClose(e) {
console.log('handleClose'+e)
}
function handleError(e) {
console.log('handleError'+e)
}
console.log(2652321325)
init()
}
return ws
}
在页面调用如下图
第一次打开页面时没有调用onclose,但是第二次访问时onclose被调用了,这是咋回事