Springboot 集成 websocket
1.介绍
WebSocket是HTML5新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道。实时推送数据/通知到浏览器
方法一
1、引入WebSocket依赖包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
2、编写 WebSocket 实现方法
@ServerEndpoint(value = "/websocket/{id}")
@Component
public class WebSocketServer {
/**
* 静态常量,记录连接个数,线程安全
*/
private static int onlineCount = 0;
/**
* 存放客户端对应的WebSocket对象
*/
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
/**
* 会话信息
*/
private Session session;
@OnOpen
public void onOpen(Session session){
this.session = session;
webSocketSet.add(this);
addOnlineCount();
try {
sendMessage("连接成功");
}catch (IOException ex){
System.out.println(ex.getMessage());
}
}
@OnMessage
public void onMessage(String message, Session session, @PathParam("id")String id){
System.out.println("来自客户端的消息:" + message);
//群发消息
for (WebSocketServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@OnClose
public void onClass(){
webSocketSet.remove(this);
subOnlineCount();
System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
}
@OnError
public void onError(Session session,Exception ex){
ex.printStackTrace();
}
/**
* 发送消息
* @param message
* @throws IOException
*/
private void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
private void sendInfo(String message){
System.out.println(message );
for (WebSocketServer item:webSocketSet ) {
try{
item.sendMessage(message);
}catch (IOException ex){
System.out.println(ex.getMessage());
}
}
}
private synchronized void addOnlineCount(){
WebSocketServer.onlineCount ++;
}
private synchronized void subOnlineCount(){
WebSocketServer.onlineCount --;
}
public static synchronized long getOnlineCount(){
return WebSocketServer.onlineCount;
}
}
3、 添加配置文件
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
方法二
- 编写消息处理类
public class WebSocketMessageHandler extends TextWebSocketHandler {
/**
* 静态常量,保存连接数量,线程安全
*/
private static long onlineCount = 0;
/**
* 保存客户端信息
*/
private static CopyOnWriteArraySet<WebSocketSession> webSocketSet = new CopyOnWriteArraySet();
/**
* 会话信息
*/
private WebSocketSession session;
public WebSocketMessageHandler(){
super();
}
/**
* 连接建立之后
* @param session
* @throws Exception
*/
public void afterConnectionEstablished(WebSocketSession session) throws Exception{
this.session = session;
webSocketSet.add(session);
addOnlineCount();
System.out.println("连接成功,当前连接数:"+getOnlineCount());
}
/**
* 处理收到的websocket信息
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String payload = message.getPayload();
System.out.println("sadddddd");
sendMessage(payload);
}
public void handleTransportError(WebSocketSession session, Throwable var2) throws Exception{
}
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception{
webSocketSet.remove(session);
subOnlineCount();
System.out.println("连接断开,当前连接数:"+getOnlineCount());
}
private void sendMessage(String message) throws IOException {
for (WebSocketSession session: webSocketSet ) {
session.sendMessage(new TextMessage( message));
}
}
///////
private synchronized void addOnlineCount(){
onlineCount++;
}
private synchronized void subOnlineCount(){
onlineCount--;
}
private synchronized long getOnlineCount(){
return this.onlineCount;
}
}
2、位置文件
@Configuration
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
webSocketHandlerRegistry.addHandler(handler(),"/notice/{id}")//访问地址
.setAllowedOrigins("*");///解决跨域问题
}
public WebSocketHandler handler(){
return new WebSocketMessageHandler();
}
}
总结
1、网上找资料按照第一种实现,结果总是报错,比较靠谱的解释是aop拦截问题,使得ServerEndpointExporter
注册不进去;
2、第二种方法有效,一定不要忘记加依赖文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
测试页面
<!DOCTYPE HTML>
<html>
<head>
<meta charset="">
<title>WebSocket</title>
<script type="text/javascript">
var ws = null;
function WebSocketTest()
{
if ("WebSocket" in window)
{
console.log("您的浏览器支持 WebSocket!");
if(ws == null)
// 打开一个 web socket
ws = new WebSocket("ws://localhost:8001/voice/aass");
ws.onopen = function()
{
// Web Socket 已连接上,使用 send() 方法发送数据
ws.send("00000000000000000000000");
console.log("数据发送中...");
};
ws.onmessage = function (evt)
{
var received_msg = evt.data;
console.log("数据已接收...");
console.log(received_msg);
};
ws.onclose = function()
{
// 关闭 websocket
console.log("连接已关闭...");
closeWS();
};
}
else
{
// 浏览器不支持 WebSocket
console.log("您的浏览器不支持 WebSocket!");
}
}
function closeWS(){
if(ws !=null){
ws.close();
ws = null;
}
}
function sendMsg(){
ws.send("00000000000000000000000");
console.log("数据发送中...");
}
</script>
</head>
<body>
<div id="sse">
<a href="javascript:WebSocketTest()">运行 WebSocket</a>
<a href="javascript:closeWS()">关闭 WebSocket</a>
<br/>
<a href="javascript:sendMsg()">发送消息</a>
</div>
</body>
</html>