1.實際效果
2.添加一個WebSocketConfig
package com.llltony.springboot.config; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Component public class WebSocketConfig { /** * ServerEndpointExporter 作用 * * 這個Bean會自動注冊使用@ServerEndpoint注解聲明的websocket endpoint * * @return */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
3.添加WebSocket類
package com.llltony.springboot.socket; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.util.concurrent.ConcurrentHashMap; /** * @ServerEndpoint 這個注解有什么作用? * <p> * 這個注解用於標識作用在類上,它的主要功能是把當前類標識成一個WebSocket的服務端 * 注解的值用戶客戶端連接訪問的URL地址 */ @Slf4j @Component @ServerEndpoint("/websocket/{name}") public class WebSocket { /** * 與某個客戶端的連接對話,需要通過它來給客戶端發送消息 */ private Session session; /** * 標識當前連接客戶端的用戶名 */ private String name; /** * 用於存所有的連接服務的客戶端,這個對象存儲是安全的 */ private static ConcurrentHashMap<String, WebSocket> webSocketSet = new ConcurrentHashMap<>(); @OnOpen public void OnOpen(Session session, @PathParam(value = "name") String name) { this.session = session; this.name = name; // name是用來表示唯一客戶端,如果需要指定發送,需要指定發送通過name來區分 webSocketSet.put(name, this); log.info(name+"[WebSocket] 連接成功,當前連接人數為:={}", webSocketSet.size()); } @OnClose public void OnClose() { webSocketSet.remove(this.name); log.info(name+"[WebSocket] 退出成功,當前連接人數為:={}", webSocketSet.size()); } @OnMessage public void OnMessage(String message) { log.info("[WebSocket] 收到消息:{}", message); //根據用戶名判斷知道發送 JSONObject json = JSONObject.parseObject(message); String name=json.get("username").toString(); String content=json.get("content").toString(); if (!name.equals("") && name!= null) { AppointSending(name, content); } else { GroupSending(message); } } /** * 群發 * * @param message */ public void GroupSending(String message) { for (String name : webSocketSet.keySet()) { try { webSocketSet.get(name).session.getBasicRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } } /** * 指定發送 * * @param name * @param message */ public void AppointSending(String name, String message) { try { webSocketSet.get(name).session.getBasicRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } }
4.添加pom依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency>
5.添加html頁面進行調用測試
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>websocket_Test</title> <script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script> <meta content="no-cache" http-equiv="pragma"> <meta content="no-cache" http-equiv="cache-control"> <meta content="0" http-equiv="expires"> <meta content="keyword1,keyword2,keyword3" http-equiv="keywords"> <meta content="This is my page" http-equiv="description"> </head> <body> <div> <h3>testing...</h3> <div id="msgtext"> </div> <div> <input id="username" name="username" type="text" placeholder="請輸入用戶名"/> <button onclick="connectWebSocket();">連接WebSocket</button> <br> <input id="msg" name="msg" type="text" placeholder="請輸入發生信息"/> <button onclick="sendmsg();">發送</button> </div> </div> </body> <script type="text/javascript"> var ws; function connectWebSocket(){ if('WebSocket' in window){ var url="ws://localhost:8080/websocket/"; var username=$('#username').val(); if(username=="" || username==null){ alert("請輸入用戶名"); return; }else{ url=url+username; } ws = new WebSocket(url); }else{ alert("不支持 websocket"); } ws.onopen = function(evt){ //alert("op"); } ws.onclose =function(evt){ alert("close"); } ws.onmessage = function(evt){ var msg = evt.data; if("[object Blob]" != msg){ var msgdiv = document.getElementById("msgtext"); var span = document.createElement("span"); span.innerHTML = msg+"<br />"; msgdiv.appendChild(span); }else{ var msgdiv = document.getElementById("msgtext"); var span = document.createElement("span"); var br = document.createElement("br"); var can = document.createElement("canvas"); var context = can.getContext("2d"); var image = new Image(); image.onload = function () { //image.height context.clearRect(0, 0, can.width, can.height); context.drawImage(image, 0, 0, can.width, can.height); } image.src = URL.createObjectURL(msg); span.appendChild(can); span.appendChild(br); msgdiv.appendChild(span); } } ws.onerror = function(evt){ alert("error"); } } function sendmsg(){ var message={}; message.content="("+new Date().toLocaleTimeString()+")<br />"+document.getElementById("msg").value; message.username=$('#username').val(); ws.send(JSON.stringify(message)); } </script> </html>
6.后端代碼里的調用websocket發送消息
7.源碼:https://github.com/CodingPandaLLL/tsl.git(在dev_webSocket分支中)