springboot搭建WebSocket服務端
阿新 • • 發佈:2019-02-08
基於springboot框架編寫一個WebSocket服務端,並通過簡單的html介面模擬客戶端驗證服務端連線。
1、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</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.4.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-web</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> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2、application.yml
spring:
thymeleaf:
prefix: classpath:/templates/
3、Server端程式碼
3.1、ServerEndpointExporter
首先要注入ServerEndpointExporter,這個bean會自動註冊使用了@ServerEndpoint註解宣告的Websocket endpoint。要注意,如果使用獨立的servlet容器,而不是直接使用springboot的內建容器,就不要注入ServerEndpointExporter,因為它將由容器自己提供和管理。
package com.example.demo.config; 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(); } }
3.2 WebSocketServer
package com.example.demo.webSocket; import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.ServerEndpoint; @ServerEndpoint("/webSocketServer") @Component public class WebSocketDemo { @OnOpen public void onOpen(Session session) { System.out.println("新開啟了一個webSocket連線" + session.getId()); } @OnMessage public String onMessage(String message, Session session) { System.out.println("收到客戶端傳送的資訊:"+message); System.out.println("當前的sessionId:"+session.getId()); return "SUCCESS"; } @OnClose public void onClose(Session session, CloseReason reason) { System.out.println("webSocket連線關閉:sessionId:"+session.getId() + "關閉原因是:"+reason.getReasonPhrase() + "code:"+reason.getCloseCode()); } @OnError public void onError(Throwable t) { t.printStackTrace(); } }
4、前端html介面
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>WebSocket 客戶端</title>
</head>
<body>
<div>
<input type="button" id="btnConnection" value="連線" />
<input type="button" id="btnClose" value="關閉" />
<input type="button" id="btnSend" value="傳送" />
</div>
<script src="/jquery-3.3.1.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
$(function(){
var socket;
if(typeof(WebSocket) == "undefined") {
alert("您的瀏覽器不支援WebSocket");
return;
}
$("#btnConnection").click(function() {
//實現化WebSocket物件,指定要連線的伺服器地址與埠
socket = new WebSocket("ws://localhost:8080/webSocketServer");
//開啟事件
socket.onopen = function() {
alert("Socket 已開啟");
//socket.send("這是來自客戶端的訊息" + location.href + new Date());
};
//獲得訊息事件
socket.onmessage = function(msg) {
alert(msg.data);
};
//關閉事件
socket.onclose = function() {
alert("Socket已關閉");
};
//發生了錯誤事件
socket.onerror = function() {
alert("發生了錯誤");
}
});
//傳送訊息
$("#btnSend").click(function() {
socket.send("這是來自客戶端的訊息" + location.href + new Date());
});
//關閉
$("#btnClose").click(function() {
socket.close();
});
});
</script>
</body>
</html>
5、跳轉介面程式碼
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloWorldController {
@GetMapping("/hello")
public String hello() {
return "/webSocketDemo";
}
}
6、目錄結構
7、當需要在websocket服務端注入Service或者Dao進行其他的業務邏輯時,常規注入是會產生空指標異常的。
我們需要在websocket中注入applilcationContext物件,從上下文物件中獲取。
方法如下:
7.1 先在main方法啟動時將application物件注入到webSocket物件中
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(RangerSocketApplication.class, args);
GatewayWebSocket.setApplicationContext(applicationContext);
}
7.2 在webSocket服務端設定注入方法,並基於上下文進行獲取
private static ApplicationContext applicationContext;
public static void setApplicationContext(ApplicationContext context) {
applicationContext = context;
}
7.3 在獲取時賦值
private GatewayDao gatewayDao;
if(gatewayDao == null) {
gatewayDao = applicationContext.getBean(GatewayDao.class);
}