自学内容网 自学内容网

SpringBoot集成websocket

websocket

基于 TCP 协议的全双工通信协议,它允许客户端和服务器之间建立持久的、双向的通信连接。
相比传统的 HTTP 请求 - 响应模式,WebSocket 提供了实时、低延迟的数据传输能力。通过 WebSocket,客户端和服务器可以在任意时间点互相发送消息,实现实时更新和即时通信的功能。WebSocket 协议经过了多个浏览器和服务器的支持,成为了现代 Web 应用中常用的通信协议之一。
广泛应用于聊天应用、实时数据更新、多人游戏等场景,为 Web 应用提供了更好的用户体验和更高效的数据传输方式。

Spring Boot 中整合websocket

一、依赖

spring-boot-starter-websocket


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot-demo</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>websocket</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.40</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
</project>

二、配置文件和启动类

server:
  port: 8088
@SpringBootApplication
public class DemoApplication {

   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

三、websocket配置类

@Configuration
@EnableWebSocket
public class WebSocketConfiguration{

@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}

四、websocket服务类

四个事件:

  • @OnOpen:标注客户端打开 WebSocket 服务端点调用方法
  • @OnClose:标注客户端关闭 WebSocket 服务端点调用方法
  • @OnMessage:标注客户端发送消息,WebSocket 服务端点调用方法
  • @OnError:标注客户端请求 WebSocket 服务端点发生异常调用方法
@ServerEndpoint("/websocket/{userId}")
@Component
public class WebSocketServer{

private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);

//当前在线连接数
private static AtomicInteger onlineCount = new AtomicInteger(0);

//用来存放每个客户端对应的WebSocketServer对象
private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();

//与某个客户端的连接会话,需要通过它给客户端发送数据
private Session session;

//接收用户userId
private String userId = "";

//连接建立成功调用的方法 (标注客户端打开 WebSocket 服务端点调用方法)
@OnOpen
public void onOpen(Session session,@PathParam("userId") String userId){

this.session = session;
this.userId = userId;

if(webSocketMap.containsKey(userId)){
webSocketMap.remove(userId);
webSocketMap.put(userId, this);
}else{
webSocketMap.put(userId, this);
            addOnlineCount();
}
log.info("用户连接:" + userId + ",当前在线人数为:" + getOnlineCount());

try {
            sendMessage("连接成功!");
        } catch (IOException e) {
            log.error("用户:" + userId + ",网络异常!!!!!!");
        }
}

//连接关闭调用的方法
@OnClose
public void onClose(){
if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
            subOnlineCount();
        }
        log.info("用户退出:" + userId + ",当前在线人数为:" + getOnlineCount());
}

//收到客户端消息后调用的方法
@OnMessage
    public void onMessage(String message, Session session) {
        log.info("用户消息:" + userId + ",报文:" + message);
        if (!StringUtils.isEmpty(message)) {
            try {
                JSONObject jsonObject = JSON.parseObject(message);
                jsonObject.put("fromUserId", this.userId);
                String toUserId = jsonObject.getString("toUserId");
                if (!StringUtils.isEmpty(toUserId) && webSocketMap.containsKey(toUserId)) {
                    webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
                } else {
                    log.error("请求的 userId:" + toUserId + "不在该服务器上");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

//发生错误时调用
@OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误:" + this.userId + ",原因:" + error.getMessage());
        error.printStackTrace();
    }

/**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    public static synchronized AtomicInteger getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount.getAndIncrement();
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount.getAndDecrement();
    }
}

测试

打开postman,新建2个websocket测试连接,ws://127.0.0.1:8088/websocket/wupx
点击开启连接按钮,消息记录中会多一条由服务器端发送的连接成功!记录
在这里插入图片描述
输入ws://127.0.0.1:8088/websocket/huxy,点击开启连接按钮,然后回到第一次打开的网页在消息框中输入{“toUserId”:“huxy”,“message”:“i love you”},点击发送到服务端,第二个网页中会收到服务端推送的消息{“fromUserId”:“wupx”,“message”:“i love you”,“toUserId”:“huxy”}
在这里插入图片描述
控制台输出


2024-02-26 15:26:48.699 INFO 27848 --- [nio-8088-exec-2] c.et.websocket.channel.WebSocketServer : 用户连接:huxy,当前在线人数为:1
2024-02-26 15:26:56.581 INFO 27848 --- [nio-8088-exec-4] c.et.websocket.channel.WebSocketServer : 用户连接:wupx,当前在线人数为:2
2024-02-26 15:27:26.401 INFO 27848 --- [nio-8088-exec-5] c.et.websocket.channel.WebSocketServer : 用户消息:wupx,报文:{"toUserId":"huxy","message":"i love you"}

原文地址:https://blog.csdn.net/usa_washington/article/details/136470985

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!