SpringBoot之WebSocket服务搭建
文章目录
WebSockets 彻底改变了 Web,将笨拙、缓慢的实时交互转变为时尚、低延迟的体验,使其成为动态、用户友好型应用程序的首选。
1.创建SpringBoot工程
在Intellij IDEA工具中使用SpringBoot项目初始化向导新建一个工程,如工程名为
yuan-websocket-demo
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">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yuan-websocket-demo</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
</dependencies>
</project>
3. application.yml配置
server:
port: 2001
max-http-header-size: 8192
spring:
thymeleaf:
cache: false
4. 主启动类
主启动类中标注开启WebSoket的注解
@EnableWebSocket
package org.yuan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
/**
* <p>
* Description: <br>
* <p>
* Author:jinshengyuan <br>
* Datetime: 2020-05-29 15:00
* </p>
*
*/
@SpringBootApplication
@EnableWebSocket
@ServletComponentScan
public class MyWebSocketApplication {
public static void main(String[] args) {
SpringApplication.run(MyWebSocketApplication.class, args);
}
}
5. WebSocket配置类
配置类
WebSocketConfig .java
如下
package org.yuan.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* 用于扫描和注册所有携带ServerEndPoint注解的实例。
* <p>
* 注意:若部署到外部容器,则无需配置此类。
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
6. 编写MyWebSocket服务类
package org.yuan.mysoket;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
@Component
@ServerEndpoint("/myChat")
public class MyWebSocket {
private static int onLineCount = 0;//记录在线连接数,应该做成线程安全的
//线程安全set,用来存储每个客户的MyWebSocket对象
private static CopyOnWriteArraySet<MyWebSocket> myWebSockets = new CopyOnWriteArraySet<>();
//与某个客户端的连接会话,需要通过它来给客户发送数据
private Session session;
/**
* <p>
* Description: 连接建立成功后调用的方法<br>
* <p>
* Author:jinshengyuan <br>
* Datetime: 2020/5/28 22:25
* </p>
*
* @return
* @since 2020/5/28 22:25
*/
@OnOpen
public void onOpen(Session session) {
System.out.println("连接了哦");
this.session = session;
myWebSockets.add(this);
addOnlineCount();
System.out.println();
}
/**
* <p>
* Description: 关闭会话连接<br>
* <p>
* Author:jinshengyuan <br>
* Datetime: 2020/5/28 22:39
* </p>
*
* @param
* @param
* @return
* @since 2020/5/28 22:39
*/
@OnClose
public void onClose(Session session) {
myWebSockets.remove(this);
subOnlineCount();
}
/**
* <p>
* Description: 发送消息<br>
* <p>
* Author:jinshengyuan <br>
* Datetime: 2020/5/28 22:39
* </p>
* @since 2020/5/28 22:39
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("来自客户端的消息:" + message);
for (MyWebSocket socket : myWebSockets) {
try {
socket.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
@OnError
public void onError(Session session, Throwable error) {
System.out.println("发送消息失败");
error.printStackTrace();
}
public static synchronized void addOnlineCount() {
MyWebSocket.onLineCount++;
}
public static synchronized void subOnlineCount() {
MyWebSocket.onLineCount--;
}
public static synchronized int getOnLineCount() {
return onLineCount;
}
}
7. 编写测试页面
index.html如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket</title>
</head>
<body>
Welcome to WebSocket demo<br>
请输入消息:<input type="texarea" id="msg">
<button onclick="send()">发送消息</button>
<hr>
<button onclick="closeWebSocket()">关闭WebSocket连接</button>
<hr>
<div id="message"></div>
</body>
</html>
<script>
let webSocket = null;
if ('WebSocket' in window) {
webSocket = new WebSocket('ws://localhost:2001/myChat')
} else {
alert("当前浏览器不支持WebSocket协议");
}
//连接出错时的回调
webSocket.onerror = () => {
setMessageInnerHTML("WebSocket连接失败");
}
//连接成功建立的回调
webSocket.onopen = () => {
setMessageInnerHTML("WebSocket连接成功");
}
//接收到消息的回调方法
webSocket.onmessage = function (event) {
setMessageInnerHTML(event.data);
}
//监听窗口关闭事件
window.onbeforeunload = () => {
closeWebSocket();
}
//关闭WebSocket连接
closeWebSocket = () => {
webSocket.close();
}
const send = () => {
let message = document.getElementById("msg").value;
webSocket.send(message);
}
function setMessageInnerHTML(innerHTML) {
document.getElementById("message").innerHTML += innerHTML + '<br>';
}
</script>
启动SpringBoot应用后,浏览器中输入地址进行测试:http://localhost:2001