springboot集成websocket给前端推送消息

一般通常情况下,我们都是前端主动朝后端发送请求,那么有没有可能,后端主动给前端推送消息呢?这时候就可以借助websocket来实现。下面给出一个简单的实现样例。

首先创建一个websocketDemo工程,该工程的整体结构如下:

(1)修改POM文件,增加相关依赖

XML 复制代码
<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mycompany</groupId>
    <artifactId>websocketDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.18</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.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-starter-websocket</artifactId>
        </dependency>
    </dependencies>

</project>

(2)新增application.properties文件,增加端口配置信息,并设置端口为8085

XML 复制代码
server.port=8085

(3)新增socket处理器MyWebSocketHandler

java 复制代码
package com.mycompany.handler;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class MyWebSocketHandler extends TextWebSocketHandler {

    private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        System.out.println("连接建立");
        sessions.put(session.getId(), session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        System.out.println("连接关闭");
        sessions.remove(session.getId());
    }

    public void sendToAll(String message) {
        sessions.forEach((id, session) -> {
            if (session.isOpen()) {
                try {
                    session.sendMessage(new TextMessage(message));
                } catch (Exception e) {
                    System.out.println("出现异常,原因" + e);
                    sessions.remove(id);
                }
            } else {
                sessions.remove(id);
            }
        });
    }
}

(5)新增socket配置类

java 复制代码
package com.mycompany.config;

import com.mycompany.handler.MyWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebsocketConfig implements WebSocketConfigurer {

    @Autowired
    private MyWebSocketHandler myWebSocketHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myWebSocketHandler, "/ws")
                .setAllowedOrigins("*");
    }
    
}

(6)新增控制器类,我们编写了一个接口,用来触发推消息的功能,也就当调用/api/push接口时,就会给浏览器推送消息,推送的消息内容为msg字段的值

java 复制代码
package com.mycompany.controller;

import com.mycompany.handler.MyWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PushController {

    @Autowired
    private MyWebSocketHandler myWebSocketHandler;

    @GetMapping("/api/push")
    public String push(String msg) {
        myWebSocketHandler.sendToAll(msg);
        return "推送成功";
    }

}

(7)编写启动类WebsocketApplication

java 复制代码
package com.mycompany;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebsocketApplication {

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

(8)编写一个index.html页面,注意其中的端口需要和application.properties中的端口保持一致

html 复制代码
<!DOCTYPE html>
<script>
const socket = new WebSocket('ws://localhost:8085/ws');
socket.onmessage = (e) => {
    console.log('收到推送:', e.data);
    document.getElementById('msg').innerHTML += e.data + '<br>';
};
</script>
<div id="msg"></div>

(9)验证测试。首先启动项目WebsocketApplication,然后通过浏览器打开index.html页面

然后我们在浏览器地址栏输入localhost:8085/api/push?msg=你好呀,然后我们会看到浏览器中的index.html页面会显示收到推送的内容。我们可以多次刷新/api/push接口,然后会看到index.html页面也打印多次推送的信息,如下图。

相关推荐
快乐就是哈哈哈1 分钟前
被问tsconfig.json 和 tsconfig.node.json 有什么作用,我懵了……
前端
棉花糖超人18 分钟前
从【0-1的HTML】第1篇:HTML简介
前端·html
Hello-Mr.Wang24 分钟前
Vue3使用vue-web-screen-shot实现截图功能
前端·javascript·vue.js
zqx_736 分钟前
随记 配置服务器的ssl整个过程
网络·网络协议·ssl
机巧咸鱼不会受伤1 小时前
在 React Umi 项目中实现基于 SSE 的流式聊天功能
前端·react.js
白筱汐1 小时前
element plus 根据嵌套数据合并表格
前端·javascript
Mr.Liu61 小时前
小程序32-简易双向数据绑定
前端·微信小程序·小程序
BillKu1 小时前
CSS强制div单行显示不换行
前端·css
大明882 小时前
Vue 中导致 detached 元素产生的常见行为
前端·vue.js