1、首先在pom文件中引入Webscoekt的依赖
<!-- websocket依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
2、通过注解方式构建Websocket服务
package com.kk.server.chat.websocket; import com.kk.server.chat.service.CheckTokenService; import com.kk.server.chat.service.QueryService; import com.kk.server.chat.service.SaveMongodbService; import org.apache.log4j.Logger; import org.springframework.context.ApplicationContext; 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; /** * Created by yxl on 2018-03-19. */ @ServerEndpoint("/chat/{userId}") //关键注解,将WebSocket服务端运行在 ws://[Server端IP或域名]:[Server端口]/websockets/chat/{userId} 的访问端点,客户端浏览器已经可以对 WebSocket客户端API发起HTTP长连接了。 @Component public class ChatWebsocket { private Logger logger = Logger.getLogger(ChatWebsocket.class); private static ApplicationContext applicationContext; private SaveMongodbService saveMongodbService; private CheckTokenService checkTokenService; private QueryService queryService; //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识 private static Map<String, Session> webSocketSet = new ConcurrentHashMap<>(); //医生web //解决Websocket不能注入bean的问题 public static void setApplicationContext(ApplicationContext applicationContext) { ChatWebsocket.applicationContext = applicationContext; } /** * 连接建立成功调用的方法 * * @param userId 用户链接ID */ @OnOpen //建立连接的注解,当用户建立连接时SpringBoot会监听到,然后会调用该注解下的方法 public void onOpen(@PathParam("userId") String userId, Session session) { webSocketSet.put(userId, session); } /** * 连接关闭调用的方法 */ @OnClose public void onClose(Session session) { logger.info("进入关闭方法!"); if (session != null) { Map<String, String> pathParameters = session.getPathParameters(); String userId = pathParameters.get("userId"); //从当前关闭session中获取用户ID,前提是建立websocket连接时带有userId,即 @ServerEndpoint("/chat/{userId}") webSocketSet.remove(userId); //从map中移除用户 } } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息 * @param session 可选的参数 */ @OnMessage public void onMessage(String message, Session session) throws IOException { try { JSONObject jsonObject = JSONObject.parseObject(message); String receiver_id = jsonObject.getString("receiver_id") //接受者ID,通过该Id来获取接受者的session Session session = webSocketSet.get("receiver_id") if (session != null) { session.getBasicRemote.sendText(message); //通过session发送消息 }else { //TODO 接收方不在线,处理离线消息 } }catch(IOException e) { e.printStackTrace; } } /** * 发生错误时调用 * * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { //onClose(); if (session != null) { Map<String, String> pathParameters = session.getPathParameters(); String userId = pathParameters.get("userId"); //从当前关闭session中获取用户ID,前提是建立websocket连接时带有userId,即 @ServerEndpoint("/chat/{userId}") webSocketSet.remove(userId); //从map中移除用户 } logger.info("webscoket发生错误!"+error.getMessage()); error.printStackTrace(); } }
3、前台调用方法(js)
function WebSocketTest() { if ("WebSocket" in window) { alert("您的浏览器支持 WebSocket!"); // 打开一个 web socket var ws = new WebSocket("ws://服务器IP:端口/chat/123"); ws.onopen = function() { // Web Socket 已连接上,使用 send() 方法发送数据 ws.send('{"userId":"1555855","message" : "test"}'); ws.close("666666"); alert("数据发送中..."); }; ws.onmessage = function (evt) { console.log(evt) alert(evt.data); alert("数据已接收..."); }; ws.onclose = function(){ // 关闭 websocket alert("连接已关闭..."); }; }else { // 浏览器不支持 WebSocket alert("您的浏览器不支持 WebSocket!"); } }
4、当然,在使用websocket聊天时,可能会遇到一些数据需要查询数据库或者Redis,但是在websocket中又不能直接注入相应的Bean实例,这个时候可以看我的另一篇博客https://www.cnblogs.com/Amaris-Lin/p/9038813.html