1.客戶端: HTML
<!DOCTYPE html> <html> <head> <title>Java后端WebSocket的Tomcat實現</title> </head> <body> Welcome<br/><input id="text" type="text"/> <button onclick="send()">發送消息</button> <hr/> <!--userno:發送消息人的編號--> <div id="userno">1234</div> <button onclick="closeWebSocket()">關閉WebSocket連接</button> <hr/> <div id="message"></div> </body> <script type="text/javascript"> var websocket = null; var userno=document.getElementById('userno').innerHTML; //判斷當前瀏覽器是否支持WebSocket if ('WebSocket' in window) { websocket = new WebSocket("ws://localhost:8899/websocket/"+userno); } else { alert('當前瀏覽器 Not support websocket') } //連接發生錯誤的回調方法 websocket.onerror = function () { setMessageInnerHTML("WebSocket連接發生錯誤"); }; //連接成功建立的回調方法 websocket.onopen = function () { setMessageInnerHTML("WebSocket連接成功"); } //接收到消息的回調方法 websocket.onmessage = function (event) { setMessageInnerHTML(event.data); } //連接關閉的回調方法 websocket.onclose = function () { setMessageInnerHTML("WebSocket連接關閉"); } //監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。 window.onbeforeunload = function () { closeWebSocket(); } //將消息顯示在網頁上 function setMessageInnerHTML(sendMessage) { document.getElementById('message').innerHTML += sendMessage + '<br/>'; } //關閉WebSocket連接 function closeWebSocket() { websocket.close(); } //發送消息 function send() { var message = document.getElementById('text').value;//要發送的消息內容 var now=getNowFormatDate();//獲取當前時間 document.getElementById('message').innerHTML += (now+"發送人:"+userno+'<br/>'+"---"+message) + '<br/>'; document.getElementById('message').style.color="red"; var ToSendUserno="4567";//接收人編號:4567 message=message+"|"+ToSendUserno//將要發送的信息和內容拼起來,以便於服務端知道消息要發給誰 websocket.send(message); } //獲取當前時間 function getNowFormatDate() { var date = new Date(); var seperator1 = "-"; var seperator2 = ":"; var month = date.getMonth() + 1; var strDate = date.getDate(); if (month >= 1 && month <= 9) { month = "0" + month; } if (strDate >= 0 && strDate <= 9) { strDate = "0" + strDate; } var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate + " " + date.getHours() + seperator2 + date.getMinutes() + seperator2 + date.getSeconds(); return currentdate; } </script> </html>
2.服務端:
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example.websocket</groupId> <artifactId>websocketdemo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>websocketdemo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> </dependency> <!--添加websocket依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> <version>1.3.5.RELEASE</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
java實體類:
WebSocketTest
package com.example.websocket.websocketdemo; import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.ConcurrentHashMap; /** * @ServerEndpoint 注解是一個類層次的注解,它的功能主要是將目前的類定義成一個websocket服務器端, * 注解的值將被用於監聽用戶連接的終端訪問URL地址,客戶端可以通過這個URL來連接到WebSocket服務器端 * @ServerEndpoint 可以把當前類變成websocket服務類 */ @ServerEndpoint("/websocket/{userno}") @Component public class WebSocketTest { //靜態變量,用來記錄當前在線連接數。應該把它設計成線程安全的。 private static int onlineCount = 0; //concurrent包的線程安全Set,用來存放每個客戶端對應的MyWebSocket對象。若要實現服務端與單一客戶端通信的話,可以使用Map來存放,其中Key可以為用戶標識 private static ConcurrentHashMap<String, WebSocketTest> webSocketSet = new ConcurrentHashMap<String, WebSocketTest>(); //與某個客戶端的連接會話,需要通過它來給客戶端發送數據 private Session session; //當前發消息的人員編號 private String userno = ""; /** * 連接建立成功調用的方法 * * @param session 可選的參數。session為與某個客戶端的連接會話,需要通過它來給客戶端發送數據 */ @OnOpen public void onOpen(@PathParam(value = "userno") String param, Session session, EndpointConfig config) { System.out.println(param); userno = param;//接收到發送消息的人員編號 this.session = session; webSocketSet.put(param, this);//加入map中 addOnlineCount(); //在線數加1 System.out.println("有新連接加入!當前在線人數為" + getOnlineCount()); } /** * 連接關閉調用的方法 */ @OnClose public void onClose() { if (!userno.equals("")) { webSocketSet.remove(userno); //從set中刪除 subOnlineCount(); //在線數減1 System.out.println("有一連接關閉!當前在線人數為" + getOnlineCount()); } } /** * 收到客戶端消息后調用的方法 * * @param message 客戶端發送過來的消息 * @param session 可選的參數 */ @OnMessage public void onMessage(String message, Session session) { System.out.println("來自客戶端的消息:" + message); // session.get //群發消息 if (1 < 2) { sendAll(message); } else { //給指定的人發消息 sendToUser(message); } } /** * 給指定的人發送消息 * @param message */ private void sendToUser(String message) { String sendUserno = message.split("[|]")[1]; String sendMessage = message.split("[|]")[0]; String now = getNowTime(); try { if (webSocketSet.get(sendUserno) != null) { webSocketSet.get(sendUserno).sendMessage(now + "用戶" + userno + "發來消息:" + " <br/> " + sendMessage); } else { System.out.println("當前用戶不在線"); } } catch (IOException e) { e.printStackTrace(); } } /** * 給所有人發消息 * @param message */ private void sendAll(String message) { String now = getNowTime(); String sendMessage = message.split("[|]")[0]; //遍歷HashMap for (String key : webSocketSet.keySet()) { try { //判斷接收用戶是否是當前發消息的用戶 if (!userno.equals(key)) { webSocketSet.get(key).sendMessage(now + "用戶" + userno + "發來消息:" + " <br/> " + sendMessage); System.out.println("key = " + key); } } catch (IOException e) { e.printStackTrace(); } } } /** * 獲取當前時間 * * @return */ private String getNowTime() { Date date = new Date(); DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time = format.format(date); return time; } /** * 發生錯誤時調用 * * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { System.out.println("發生錯誤"); error.printStackTrace(); } /** * 這個方法與上面幾個方法不一樣。沒有用注解,是根據自己需要添加的方法。 * * @param message * @throws IOException */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketTest.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketTest.onlineCount--; } }
WebSocketConfig
package com.example.websocket.websocketdemo; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
SpringBoot啟動類:
package com.example.websocket.websocketdemo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; import org.springframework.boot.web.support.SpringBootServletInitializer; @SpringBootApplication public class WebsocketdemoApplication extends SpringBootServletInitializer implements EmbeddedServletContainerCustomizer { public static void main(String[] args) { SpringApplication.run(WebsocketdemoApplication.class, args); } @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.setPort(8899);//設置服務端口為8899 } }
源碼下載地址:http://download.csdn.net/download/zb18829224773/10121298(導入直接可以跑)