環境
window7,IntelliJ IDEA 2019.2 x64
背景:利用IntelliJ來搭建springboot框架,之后來實現websocket的功能。websocket只是實現了畫面上的消息的互相推送的功能,即在不刷新網頁的情況下,把必要的消息推送到你的網頁上面。
利用IntelliJ來搭建spring的web框架。
1. 下載IntelliJ的安裝包,之后正常安裝即可
2. 打開IDE,創建一個web功能
具體操作如下
點擊finish之后,自己的springweb的工程創建完了。
構建自己的websocket程序
工程的構成如下圖
創建自己的control文件
LoginControl類是為了加載首頁,找到webSocketIndex.html文件,但此時的application.properties文件里面要引用【spring.thymeleaf.prefix=classpath:/templates/】否則找不到路徑
package com.control; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @EnableAutoConfiguration @RestController public class LoginControl { @RequestMapping("login") public ModelAndView home(Model model, HttpServletRequest request, HttpServletResponse response) throws Exception { String userName = "Jef"; int count = 100;
// 固定的寫法 ModelAndView mv = new ModelAndView("webSocketIndex"); return mv; } }
application.properties文件
spring.thymeleaf.prefix=classpath:/templates/
server.port=8081
pom文件
<?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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
WebSocketServer文件
package com.control; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; //@ServerEndpoint(value ="/WebSocket/{id}/{name}") @ServerEndpoint(value ="/WebSocket") @Component public class WebSocketServer { //靜態變量,用來記錄當前在線連接數。應該把它設計成線程安全的。 private static int onlineCount = 0; //concurrent包的線程安全Set,用來存放每個客戶端對應的MyWebSocket對象。 private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>(); private static ConcurrentHashMap<String, List<WebSocketServer>> webSocketMap = new ConcurrentHashMap<>(3); //與某個客戶端的連接會話,需要通過它來給客戶端發送數據 private Session session; private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class); @OnOpen public void onOpen(Session session) throws Exception { this.session = session; System.out.println(this.session.getId()); webSocketSet.add(this); //加入set中 addOnlineCount(); //在線數加1 System.out.println("有新連接加入!當前在線人數為" + getOnlineCount()); LOGGER.info("Open a websocket. id={}", "12"); // try { // sendMessage(CommonConstant.CURRENT_WANGING_NUMBER.toString()); // } catch (IOException e) { // System.out.println("IO異常"); // } } /** * 連接關閉調用的方法 */ @OnClose public void onClose() { webSocketSet.remove(this); //從set中刪除 subOnlineCount(); //在線數減1 System.out.println("有一連接關閉!當前在線人數為" + getOnlineCount()); LOGGER.info("Close a websocket. "); } /** * 收到客戶端消息后調用的方法 * * @param message 客戶端發送過來的消息*/ @OnMessage public void onMessage(String message, Session session) { System.out.println("來自客戶端的消息:" + message); LOGGER.info("Receive a message from client: " + message); //群發消息 for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } } /** * 發生錯誤時調用 */ @OnError public void onError(Session session, Throwable error) { System.out.println("發生錯誤"); LOGGER.error("Error while websocket. ", error); error.printStackTrace(); } public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } /** * 群發自定義消息 * */ public static void sendInfo(String message) throws IOException { for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { continue; } } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketServer.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketServer.onlineCount--; } }
html5文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> Welcome<br/> <input id="text" type="text" /> <button onclick="connect()">Connect</button> <button onclick="send()">Send</button> <button onclick="closeWebSocket()">Close</button> <div id="message"> </div> </body> <script type="text/javascript"> var websocket = null; //判斷當前瀏覽器是否支持WebSocket if('WebSocket' in window){ debugger websocket = new WebSocket("ws://localhost:8081/WebSocket"); } else{ alert('Not support websocket') } //連接發生錯誤的回調方法 websocket.onerror = function(){ debugger setMessageInnerHTML("error"); }; //連接成功建立的回調方法 websocket.onopen = function(event){ debugger setMessageInnerHTML("open"); } //接收到消息的回調方法 websocket.onmessage = function(event){ debugger setMessageInnerHTML(event.data); } //連接關閉的回調方法 websocket.onclose = function(){ setMessageInnerHTML("close"); } //監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。 window.onbeforeunload = function(){ websocket.close(); } //將消息顯示在網頁上 function setMessageInnerHTML(innerHTML){ document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //關閉連接 function closeWebSocket(){ websocket.close(); } //發送消息 function send(){ var message = document.getElementById('text').value; websocket.send(message); } </script> </html>
在做的過程中遇到的問題是【websocket = new WebSocket("ws://localhost:8081/WebSocket");】總是訪問不到,這時你要確認你的【ws://localhost:8081/WebSocket】是否寫錯
自己檢查一下即可。
運行
利用Google瀏覽器和IE瀏覽器打開網頁http://localhost:8081/login,效果如下
Google瀏覽器
IE瀏覽器
Google瀏覽器
IE瀏覽器