WebSocket 实战
配置 WebSocketConfig
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
创建 WebSocket 服务端
/**
* @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
* 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
*/
@Log4j2
@Component
@ServerEndpoint(value = "/api/websocket/queue/{userId}")
public class WebSocketQueue {
// 当前会话(与某个客户端的连接会话,需要通过它来给客户端发送数据)
private Session session;
// 总会话集合:key:userId value:Session
private static Map<String,Session> sessionPool = new HashMap<>();
// session 与 userId 关系集合:key:sessionId value:userId
private static Map<String,String> sessionIds = new HashMap<>();
/**
* 连接建立成功调用的方法
* @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") String userId){
this.session = session;
sessionPool.put(userId,session);
sessionIds.put(session.getId(),userId);
log.info("Queue-用户:{},新连接加入!当前在线人数为:{}",userId,getOnlineNum());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(){
log.info("【webSocket-onClose】关闭连接调用session:{}",sessionIds);
sessionPool.remove(sessionIds.get(session.getId())); //断开连接,移除用户
sessionIds.remove(session.getId()); //断开连接移除用户
log.info("Queue-有一连接关闭!当前在线人数为" + getOnlineNum());
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
* @param session 可选的参数
*/
@OnMessage
public void onMessage(String message, Session session) {
if("ping".equals(message)){ log.info("Queue-定时请求,防止掉线;心跳sessionId:{},sessionName:{}",session.getId(),sessionIds.get(session.getId())); return;}
log.info("Queue-来自客户端的消息:{}" , message);
sendMessage(message,sessionIds.get(session.getId()));
}
/**
* 发生错误时调用
* @param session
* @param error
*/
@OnError
public void one rror(Session session, Throwable error){
log.info("【webSocket-onError】发生错误时调用 session:{}",session);
log.info("Queue-webSocket发生错误:session:{}-{}",session.getId(),error.getMessage());
error.printStackTrace();
throw new BaseErrorException("TOPIC-onError发送客户信息失败,错误:"+error.getMessage());
}
/**
* 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
* @param message
* @throws IOException
*/
public static void sendMessage(String message,String userId) throws BaseErrorException{
log.info("【webSocket消息发送】发送号:{}-发送消息:{}",userId,message);
Session s = sessionPool.get(userId);
if (s!=null){
try {
s.getBasicRemote().sendText(message);
} catch (IOException e) {
log.info("【webSocket发送接口】Queue-发送客户信息失败,错误:"+e.getMessage());
}
}
}
/**
* 获取在线人数
* @return
*/
public synchronized int getOnlineNum() {
return sessionPool.size();
}
/**
* 获取所有在线用户
*/
public synchronized void getOnlineUsers() {
for (String key : sessionIds.keySet()){
log.info("Queue-所有在线用户:{}",sessionIds.get(key));
}
}
/**
* 向所有客户端发送消息
*/
public synchronized void sendAll(String msg) {
for (String key : sessionIds.keySet()){
sendMessage(msg,sessionIds.get(key));
}
}
}
服务器给客户端发送消息
// 伪代码
WebSocketQueue.sendMessage(message, userId);
客户端
<body >
<h5>webSocket demo</h5>
<input id="msg" /><button onclick="sendMsg()">发送消息</button>
<script>
var ws;
var url = 'ws://localhost:9999/webSocketDemo/api/websocket/queue/06B31906230093';
$(function(){
if ('WebSocket' in window) {
ws = new WebSocket(url);
} else if ('MozWebSocket' in window) {
ws = new MozWebSocket(url);
} else {
alert('WebSocket is not supported by this browser.');
return;
}
ws.onmessage=function(event){
alert(event.data);
}
});
function sendMsg(){
var msg = $("#msg").val();
if(msg){
ws.send(msg);
$("#msg").val("")
}
}
</script>
</body>