版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Wyx_wx/article/details/83480263
WebSocket 协议是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信--允许服务器主动发送信息给客户端,实现客户端之间的交互。
WebSocket 是从 Html5 中演化而出,但是相对于 HTTP的 不支持持久性连接,WebSocket 是一个持久化的协议。
实现 WebSocket 协议后,服务端只要与客户端进行过一次连接之后,就不需要再次连接,并且可以一直向客户端发送信息,即服务端主动向客户端发送消息。
由于 WebSocket 协议在握手阶段采用了 HTTP 协议,能通过各种 HTTP 代理服务器。
目前并不是所有的浏览器都实现了 WebSocket,对于没有实现该协议的浏览器,还需要通过 STOMP 协议来完成兼容。
要想在 Spring Boot 项目中应用 WebSocket,首先要在 pom.xml 中加入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
<!-- Spring security 主要为了点对点时的安全登录,可以不使用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
下面开发一个简单的 WebSocket 服务
· 创建 java 配置文件
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();
}
}
· 定义 WebSocket 服务端站点
import org.springframework.stereotype.Service;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArrayList;
//创建 WebSocket 服务站点, 参数: 请求地址
@ServerEndpoint("/ws")
@Service
public class WebSocketServiceImpl {
//用来记录当前在线连接数,应该设置为线程安全
private static int onlineCount = 0;
//保证线程安全的 WebSocketServiceImpl 对象的 Set
private static CopyOnWriteArrayList<WebSocketServiceImpl> webSocketServices = new CopyOnWriteArrayList<>();
//与客户端的连接会话
private Session session;
public Session getSession() {
return session;
}
/**
* 连接建立成功调用的方法
* @param session
*/
@OnOpen
public void onOpen(Session session){
this.session = session;
webSocketServices.add(this);
addOnlineCount();
System.out.println("有新连接加入, 当前在线人数: " + getOnlineCount());
try {
sendMessage("有新连接加入了");
}catch (IOException e){
e.printStackTrace();
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(){
webSocketServices.remove(this);
subOnlineCount();
System.out.println("有一个连接关闭, 当前在线人数: " + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送来的消息
* @param session
*/
@OnMessage
public void onMessage(String message, Session session){
System.out.println("收到客户端消息: " + message);
//群发消息
for(WebSocketServiceImpl service : webSocketServices){
try {
//获取当前用户名称
String userName = service.getSession().getUserPrincipal().getName();
System.out.println(userName);
service.sendMessage(message);
}catch (IOException e){
e.printStackTrace();
}
}
}
/**
*发生错误时调用
*/
@OnError
public void onError(Session session, Throwable error){
System.out.println("发生错误");
error.printStackTrace();
}
/**
* 发送消息
* @param message 客户端消息
* @throws IOException
*/
private void sendMessage(String message) throws IOException{
this.session.getBasicRemote().sendText(message);
}
//返回在线数
private static synchronized int getOnlineCount(){
return onlineCount;
}
//增加连接人数
private static synchronized void addOnlineCount(){
WebSocketServiceImpl.onlineCount++;
}
//减少连接人数
private static synchronized void subOnlineCount(){
WebSocketServiceImpl.onlineCount--;
}
}
· WebSocket 页面(websocket.jsp)
若是资源路径出问题,报404错误时,请移步此篇文章
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>My WebSocket</title>
<script type="text/javascript" src="/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="/websocket.js"></script>
</head>
<body>
测试 WebSocket 站点
<br>
<input id = "message" type="text">
<button onclick="sendMessage()">发送消息</button>
<button onclick="closeWebSocket()">关闭 WebSocket 连接</button>
<div id="context"></div>
</body>
</html>
· WebSocket 客户端脚本(websocket.js)
var websocket = null;
//判断当前浏览器是否支持 WebSocket
if('WebSocket' in window){
//创建 WebSocket 对象,连接服务器端点
websocket = new WebSocket("ws://localhost:8080/ws");
}else{
alert('Not support webSocket')
}
//连接发生错误的回调方法
websocket.onerror = function () {
appendMessage("error");
};
//连接成功建立的回调方法
websocket.onopen = function (event) {
appendMessage("open");
};
//接收到消息的回调方法
websocket.onmessage = function (event) {
appendMessage(event.data);
};
//连接关闭的回调方法
websocket.onclose = function () {
appendMessage("close");
};
//监听窗口关闭事件,当窗口关闭时,主动关闭 websocket 连接
//防止连接还没断开就关闭窗口, server 端会抛异常
window.onbeforeunload = function () {
websocket.close();
};
//将消息显示在网页上
function appendMessage(message) {
var context = $("#context").html() + "<br/>" + message;
$("#context").html(context);
};
//关闭连接
function closeWebSocket() {
websocket.close();
}
//发送消息
function sendMessage() {
var message = $("#message").val();
websocket.send(message);
}
· WebSocket 控制器
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping(value = "/websocket")
@RestController
public class WebSocketController {
@GetMapping(value = "/index")
public String websocket(){
return "websocket";
}
}