Springboot整合WebSocket经典案例
WebSocker简介
WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
案例分析
外部依赖包的导入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
application配置端口
server:
port: 9999
WebSocket配置类
package school.csu.websocketexample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WebsocketexampleApplication {
public static void main(String[] args) {
SpringApplication.run(WebsocketexampleApplication.class, args);
}
}
编写静态界面
页面内容及注释
<!DOCTYPE HTML>
<html>
<head>
<title>My WebSocket</title>
</head>
<body>
<input id="text" type="text" />
<button onclick="send()">Send</button>
<button onclick="closeWebSocket()">Close</button>
<div id="message"></div>
</body>
<script type="text/javascript">
var websocket = null;
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:9999/sendMessage/one");
} else {
alert('Not support websocket')
}
websocket.onerror = function() {
setMessageInnerHTML("error");
};
websocket.onopen = function(event) {
}
websocket.onmessage = function(event) {
setMessageInnerHTML(event.data);
}
websocket.onclose = function() {
setMessageInnerHTML("close");
}
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>
</html>
案例一:自己给自己发送消息
相关代码以及注释讲解
package school.csu.websocketexample.component;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
@ServerEndpoint("/sendMessage/one")
@Component
public class OneToOneWebSocket {
private static AtomicInteger onlineCount = new AtomicInteger(0);
@OnOpen
public void onOpen(Session session){
onlineCount.incrementAndGet();
log.info("有新连接加入:{},当前在线人数为:{}", session.getId(), onlineCount.get());
}
@OnClose
public void onClose(Session session) {
onlineCount.decrementAndGet();
log.info("有一连接关闭:{},当前在线人数为:{}", session.getId(), onlineCount.get());
}
@OnMessage
public void onMessage(String message, Session session) {
log.info("服务端收到客户端[{}]的消息:{}", session.getId(), message);
this.sendMessage("Hello, " + message, session);
}
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误");
error.printStackTrace();
}
private void sendMessage(String message, Session toSession) {
try {
log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
toSession.getBasicRemote().sendText(message);
} catch (Exception e) {
log.error("服务端发送消息给客户端失败:{}", e);
}
}
}
效果演示
案例二:群发消息(不包括自己)
package school.csu.websocketexample.component;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
@ServerEndpoint(value = "/sendMessage/oneToMany")
@Component
public class OneToManyWebSocket {
private static AtomicInteger onlineCount = new AtomicInteger(0);
private static Map<String, Session> clients = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(Session session) {
onlineCount.incrementAndGet();
clients.put(session.getId(), session);
log.info("有新连接加入:{},当前在线人数为:{}", session.getId(), onlineCount.get());
}
@OnClose
public void onClose(Session session) {
onlineCount.decrementAndGet();
clients.remove(session.getId());
log.info("有一连接关闭:{},当前在线人数为:{}", session.getId(), onlineCount.get());
}
@OnMessage
public void onMessage(String message, Session session) {
log.info("服务端收到客户端[{}]的消息:{}", session.getId(), message);
this.sendMessage(message, session);
}
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误");
error.printStackTrace();
}
private void sendMessage(String message, Session fromSession) {
for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
Session toSession = sessionEntry.getValue();
if (!fromSession.getId().equals(toSession.getId())) {
log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
toSession.getAsyncRemote().sendText(message);
}
}
}}
另外注意吧index.html的v这里也改一下
websocket = new WebSocket("ws://localhost:9999/sendMessage/oneToMany");
演示效果(同时打开三个窗口,控制台打印如下)
案例三:一对一进行发送
package school.csu.websocketexample.component;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import school.csu.websocketexample.domain.MyMessage;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
@ServerEndpoint(value = "/sendMessage/oneToAnotherOne")
@Component
public class OneToAnotherOneWebSocket {
private static AtomicInteger onlineCount = new AtomicInteger(0);
private static Map<String, Session> clients = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(Session session) {
onlineCount.incrementAndGet();
clients.put(session.getId(), session);
log.info("有新连接加入:{},当前在线人数为:{}", session.getId(), onlineCount.get());
}
@OnClose
public void onClose(Session session) {
onlineCount.decrementAndGet();
clients.remove(session.getId());
log.info("有一连接关闭:{},当前在线人数为:{}", session.getId(), onlineCount.get());
}
@OnMessage
public void onMessage(String message, Session session) {
log.info("服务端收到客户端[{}]的消息[{}]", session.getId(), message);
try {
MyMessage myMessage = JSON.parseObject(message, MyMessage.class);
if (myMessage != null) {
Session toSession = clients.get(myMessage.getUserId());
if (toSession != null) {
this.sendMessage(myMessage.getMessage(), toSession);
}
}
} catch (Exception e) {
log.error("解析失败:{}", e);
}
}
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误");
error.printStackTrace();
}
private void sendMessage(String message, Session toSession) {
try {
log.info("服务端给客户端[{}]发送消息[{}]", toSession.getId(), message);
toSession.getBasicRemote().sendText(message);
} catch (Exception e) {
log.error("服务端发送消息给客户端失败:{}", e);
}
}
}
这里记得修改一下
websocket = new WebSocket("ws://localhost:9999/sendMessage/oneToAnotherOne");
差不多就这些啦~之后要用到我们实际的项目呢之中去哦。
|