目录
前言
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
WebSocket 协议本质上是一个基于 TCP 的协议。
为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息"Upgrade: WebSocket"表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。
实现
1、pom文件引入包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
2、WebSocketConfig.java
package com.hahashujia.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
/**
* @author hahashujia
* @describe
* @createTime 2020-06-05 10:09
*/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
//客户端接收服务端消息的地址的前缀信息
config.enableSimpleBroker("/topic","/user");
//客户端给服务端发消息的地址的前缀
config.setApplicationDestinationPrefixes("/app");
//给指定用户发送一对一的消息前缀是/users/。
config.setUserDestinationPrefix("/users/");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
//添加了一个/socket端点,客户端就可以通过这个端点来进行连接
registry.addEndpoint("/hahashujia-websocket")
.setAllowedOrigins("*")
.withSockJS();
}
}
3、后端给前端发送系统信息
@Autowired
private SimpMessageSendingOperations simpMessageSendingOperations;
// receiveUser 接收者,content 接收内容
simpMessageSendingOperations.convertAndSend("/topic/" + receiveUser, content);
4、发消息接口
package com.hahashujia.controller;
import com.hahashujia.sso.interfaces.LoginRequired;
import com.hahashujia.config.Swagger2Config;
import com.hahashujia.config.aop.annotation.ApiType;
import io.swagger.annotations.Api;
import org.apache.ibatis.annotations.Param;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.web.bind.annotation.RestController;
/**
* @author hahashujia
*/
@ApiType(apiTypeValue = Swagger2Config.FunctionGroup.HOME_STATISTICS)
@Api(description = "消息长连接")
@RestController
@LoginRequired
public class WebSocketTestController {
@MessageMapping("/{ldap}")
@SendTo("/topic/{ldap}")
public String greeting(@Param("ldap") @DestinationVariable String ldap, String name) {
return ldap + " Hello, " + name + "!";
}
}
5、前端接收/发送消息
//1、引入js
//sockjs.min.js
//stomp.min.js
var stompClient = null;
var ldap = "hahashujia";
//2、初始化连接
// url里的hahashujia-websocket要和配置的socket端点一致
// '/topic/' + ldap 和后端发送连接一致
function connect() {
var url = 'http://127.0.0.1:8045/hahashujia/hahashujia-websocket/';
var socket = new SockJS(url);
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/' + ldap, function (massage) {
showGreeting(massage.body);
});
});
}
// 断开连接
function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
// 前端发送消息,前缀是app可配置
function sendName() {
stompClient.send("/app/" + ldap, {}, JSON.stringify({'name': $("#name").val()}));
}