websocket介绍:

WebSocket是一种在单个TCP连接上进行全双工通信的协议,允许服务端和客户端之间进行实时、双向的数据传输。

长连接:WebSocket建立连接后,只要不关闭,会一直保持连接状态,使得服务器可以主动向客户端推送数据。双向通信:与HTTP请求-响应模式不同,WebSocket支持双向通信,即客户端和服务端都可以发送或接收数据。

使用场景:

在需要实时交互的场景中使用,例如聊天应用,实时数据推送,内容流式输出等。可实现实时向客户端进行数据推送。

1、SpringBoot集成websocket作为服务端

在前后端分离的项目中,前端作为websocket的客户端,后端服务作为websocket的服务端。

实现步骤:

添加websocket整合包

org.springframework.boot

spring-boot-starter-websocket

编写websocket配置类,暴露WebSocket @Configuration

public class WebSocketConfig {

@Bean

public ServerEndpointExporter serverEndpointExporter() {

return new ServerEndpointExporter();

}

}

编写websocket服务监听程序及处理逻辑 package com.houdehong.wsserver.controller;

import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Component;

import javax.websocket.*;

import javax.websocket.server.PathParam;

import javax.websocket.server.ServerEndpoint;

import java.io.IOException;

import java.util.concurrent.ConcurrentHashMap;

/**

* @Author houdehong

* @Date 2024/3/21 14:16

* @Description

**/

@Component

@ServerEndpoint("/api/ws/{sid}")

@Slf4j

public class WebSocketServer {

private String sid;

private static final ConcurrentHashMap SESSION_MAP = new ConcurrentHashMap<>();

/**

* 连接成功

*/

@OnOpen

public void onOpen(Session session, @PathParam("sid") String sid) {

this.sid = sid;

SESSION_MAP.put(sid, session);

log.info("有新连接:sid:{},sessionId:{},当前连接数:{}", sid, session.getId(), SESSION_MAP.size());

}

/**

* 连接关闭

*/

@OnClose

public void onClose(Session session) {

SESSION_MAP.remove(this.sid);

log.info("连接关闭,sid:{},session id:{}!当前连接数:{}", this.sid, session.getId(), SESSION_MAP.size());

}

/**

* 收到消息

*/

@OnMessage

public void onMessage(String message, Session session) {

log.info("收到消息:{},内容:{}", sid, message);

if("ping".equals(message)){

try {

session.getBasicRemote().sendText("pong");

} catch (IOException e) {

log.error("onMessage 推送消息失败:{},内容:{}", sid, message);

}

}else{

// 排除自己

// sendMeasureDataInfoExcludeSelf(message, sid);

// 发给所有客户端包括自己

sendMeasureDataInfo(message);

}

}

/**

* 连接错误

*/

@OnError

public void onError(Session session, Throwable error) {

log.error("{} 发生错误", session.getId(), error);

}

/**

* 群发消息

*/

public void sendMeasureDataInfo(String message) {

for (String sid : SESSION_MAP.keySet()) {

Session session = SESSION_MAP.get(sid);

try {

session.getBasicRemote().sendText(message);

} catch (IOException e) {

log.error("推送消息失败:{},内容:{}", sid, message);

}

log.info("推送消息:{},内容:{}", sid, message);

}

}

/**

* 群发消息,排除消息发起者

* @param message

* @param sidSelf

*/

private void sendMeasureDataInfoExcludeSelf(String message, String sidSelf){

for(String sid : SESSION_MAP.keySet()){

if(sidSelf.equals(sid)){

continue;

}

Session session = SESSION_MAP.get(sid);

try {

session.getBasicRemote().sendText(message);

} catch (IOException e) {

log.error("sendMeasureDataInfoExcludeSelf 推送消息失败:{},内容:{}", sid, message);

}

log.info("sendMeasureDataInfoExcludeSelf 推送消息:{},内容:{}", sid, message);

}

}

}

测试 至此,springboot整合websocket作为服务就搭建完成了,我们可以随便百度打开一个在线的websocket测试工具,请求一下试试,请求地址是ws://ip:port/api/ws/{sid}, 其中sid可以随便指定一个字符串,这里的sid主要是用来区分客户端,实际场景下可以在前端生成全局唯一的标识。 图片: 控制台打印信息:

2、SpringBoot集成websocket作为客户端

有时,我们需要调用第三方的websocket服务,然后将接收到的数据处理之后,或持久化到数据库,或是需要解析数据重新封装为前端需要的数据结构,这个时候我们就需要作为客户端来进行使用。

实现步骤:

添加springboot服务作为客户端的依赖

org.java-websocket

Java-WebSocket

1.3.8

继承WebSocketClient,重写方法,加入自己的逻辑 @Slf4j

public class MyWebSocketClient extends WebSocketClient {

public MyWebSocketClient(URI serverUri) {

super(serverUri);

}

@Override

public void onOpen(ServerHandshake arg0) {

log.info("------ WebSocketClient onOpen ------");

}

@Override

public void onClose(int arg0, String arg1, boolean arg2) {

log.info("------ WebSocket onClose ------{}",arg1);

}

@Override

public void onError(Exception arg0) {

log.error("------ WebSocket onError ------{}",arg0);

}

@Override

public void onMessage(String response) {

log.info("-------- 接收到服务端数据: " + response + "--------");

}

}

获取websocketClient实例 在这里我写的wsServerUrl即为上面websocket作为服务端的地址 @Component

public class WebSocketClientConfigurer {

private final String wsServerUrl = "ws://127.0.0.1:8081/api/ws/123wer";

@Bean

public WebSocketClient webSocketClient() {

try {

MyWebSocketClient webSocketClient =

new MyWebSocketClient(new URI(wsServerUrl));

webSocketClient.connect();

return webSocketClient;

} catch (URISyntaxException e) {

e.printStackTrace();

}

return null;

}

}

为了好演示我加了一个controller来进行调用 @RestController

@RequestMapping("ws-client")

public class WebsocketClient {

@Resource

private MyWebSocketClient webSocketClient;

@GetMapping("send/{message}")

public void sendRequest(@PathVariable String message){

webSocketClient.send(message);

}

}

3. 测试

至此,我们已经搭好了一个websocket的服务器和一个websocket的客户端,我们可以同时把这两个服务跑起来,做一个调用。 注意:需要先启动服务端,再启动客户端,客户端会无法创建连接,报空指针异常。 服务端启动: 客户端启动: 现在我们向客户端的controller请求一个消息: 你可以用postman或者其他api工具,我现在图简单直接在浏览器发起:

客户端控制台日志:

服务端控制台日志: OK,大功告成。 整套源码包地址

参考阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: