1.websocket介绍
WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
1.1注解介绍
@ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端。
注解的值将被用于监听用户连接的终端访问URL地址。
@OnMessage 前端发送消息 进行处理
@OnClose 关闭处理
@OnOpen 前端打开页面的处理
2.demo
引入依赖:
compile group: 'org.springframework.boot', name: 'spring-boot-starter-websocket', version: '2.5.5'
2.1 后端代码
package com.zqm.utils.socket;
/**
* @describe: sid 需要提前约定
* @author:zqm
*/
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
@ServerEndpoint("/websocket/{sid}")
@Component
public class WebSocketTest {
private static final ConcurrentHashMap<String, Session> SESSION_MAP = new ConcurrentHashMap();
/**
* 接受消息
* @param sid
* @param session
* @throws IOException
* @throws InterruptedException
// @OnMessage
// public void onMessage(@PathVariable("sid") String sid, Session session)
// throws IOException, InterruptedException {
// System.out.println();
// }
*/
/**
* 接受消息
*
* @param message 客户端发送的消息
* @param session
* @throws IOException
* @throws InterruptedException
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println(session.getPathParameters().get("sid"));
System.out.println(message);
}
/**
* 登记连接
*
* @param sid
* @param session
*/
@OnOpen
public void onOpen(@PathParam("sid") String sid, Session session) {
if (SESSION_MAP.containsKey(sid)) {
return;
}
SESSION_MAP.put(sid, session);
System.out.println("Client connected");
}
/**
* 注销连接
*/
c
public void onClose() {
System.out.println("Connection closed");
}
public void sendMessage(String sid, String message) throws IOException {
if (StringUtils.isNotBlank(sid)) {
Session session = SESSION_MAP.get(sid);
session.getBasicRemote().sendText(message);
}
}
}
package com.zqm.controller;
import com.zqm.utils.socket.WebSocketTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
/**
* @describe:
* @author:zqm
*/
@RestController
@RequestMapping("web-socket")
public class WebSocketController {
@Autowired
private WebSocketTest webSocketTest;
@RequestMapping("send")
public void sendMessage(String message) throws IOException {
webSocketTest.sendMessage("user000",message);
}
}
2.2 前端代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
Websocket Demo <br />
<input id="text" type="text" />
<button onclick="send()"> Send </button>
<button onclick="closeWebSocket()"> Close </button>
<div id="message"> </div>
<script type="text/javascript">
//判断当前浏览器是否支持WebSocket
if('WebSocket' in window){
websocket = new WebSocket("ws://192.168.43.12:8081/zqm/websocket/user");
console.log("link success")
}else{
alert('Not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function(){
setMessageInnerHTML("error");
};
//连接成功建立的回调方法
websocket.onopen = function(event){
setMessageInnerHTML("open");
}
console.log("-----")
//接收到消息的回调方法
websocket.onmessage = function(event){
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>
</body>
</html>
2.3 效果
1.先启动后端服务,打开html,显示连接成功
2.客户端发送消息,后台接受成功
3.后台发送消息,客户端接受成功
附录:socket地址404问题解决
@Configuration
@EnableWebSocket
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpoint() {
return new ServerEndpointExporter();
}
}
或者
@Configuration
public class WebSocketConfig extends ServerEndpointConfig.Configurator{
@Bean
public ServerEndpointExporter serverEndpoint() {
return new ServerEndpointExporter();
}
}