程序陆头像
关注

Springboot实现websocket通信

目录

前言

一、websockt是什么?

Websockt与 HTTP协议的核心区别

二、后端代码实现

三、前端代码实现

总结


前言

本文目标springboot实现websocket通信并且实现聊天功能。


一、websockt是什么?

WebSocket 是一种在单个 TCP 连接上实现全双工通信的网络协议,旨在解决传统 HTTP 协议在实时通信场景中的局限性。

Websockt与 HTTP协议的核心区别

HTTP 是单向、无状态的请求 - 响应协议:

  • 客户端必须主动发起请求,服务端才能响应,服务端无法主动向客户端推送数据;
  • 每次请求都需要建立新的 TCP 连接(HTTP/1.1 虽支持长连接,但仍需客户端主动发起请求)。

而 WebSocket 实现了双向、持久的实时通信:

  • 一旦连接建立,客户端和服务端可随时互相发送数据,无需频繁发起请求;
  • 连接建立后保持持久,直到某一方主动关闭,大幅降低了连接开销。

二、后端代码实现

编写websocket配置类。                                                  

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

编写websocket实现类。

@Component
@ServerEndpoint("/ws/{id}")
public class WebSocket {
    private static Map<String, Session> sessionMap = new HashMap<>();

    @OnOpen
    public void onOpen(Session session){
        Map<String, List<String>> parameters = session.getRequestParameterMap();
        String token = parameters.get("token").get(0);
        String id = TokenUtil.webSocketGetUser(token).getId().toString();
        sessionMap.put(id,session);
        System.err.println(id);
    }

    @OnMessage
    public void onMessage(String message,@PathParam("id") String id,Session session){
        Map<String, List<String>> parameters = session.getRequestParameterMap(); //获取用户连接集合
        String token = parameters.get("token").get(0); //通过路径携带参数获取接收者id
        Integer id1 = TokenUtil.webSocketGetUser(token).getId(); //通过token获取用户id

        System.out.println("收到来自客户端"+"的信息"+message+"发给"+id);
        sendToOneClient(id,message);
    }

    @OnClose
    public void onClose(Session session){
        Map<String, List<String>> parameters = session.getRequestParameterMap();
        String token = parameters.get("token").get(0);
        String id = TokenUtil.webSocketGetUser(token).getId().toString();
        sessionMap.remove(id);
    }


    public void sendToOneClient(String id,String message) {
        Session session1 = sessionMap.get(id);
        try {

            session1.getBasicRemote().sendText(message);

        } catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void sendToAllClient(String message) {
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (Exception e){
                e.printStackTrace();
            }
        }
    }

}

该实现类中接口地址:ws://xxx/ws/{id},xxx是服务(后端)的地址加上端口号,前端连接时url 参数带上 token,如:ws://127.0.0.1:8080/ws/接收方id?token=xxx。其中,id可以是任何用于区分接收方的值。

接下来介绍该实现类中的主要部分:

首先,sessionMap是静态 Map,该实例全局共享。其中,key = 用户 id 字符串,value = 当前用户的 webSocket 会话 session。它的作用是保存所有在线用户,并用来定向发消息。

接下来是几个方法的详细讲解:

@OnOpen注解的函数在客户端建立连接时触发。当客户端和该服务建立连接时,先获取客户端带过来的用户token,通过token解析用户信息(这里获取用户id,在用户登录时生成token需要使用用户id生成),随后把可以识别用户唯一标识的信息存入sessionMap。即表示该用户在线。

@OnMessage注解的函数在收到客户端消息时触发。形参中的 message 为消息内容,因此可以获取到发送人id、接收人id以及发送消息内容三样东西,可以形成一个两人聊天的闭环。其中,@PathParam("id") String id 用来获取路径中所传递的接收方id。

@OnClose注解的函数在客户端断开连接时触发。当客户端关闭 ws 连接时,解析当前用户会话的session和对应的token,并拿到用户 id,从 sessionMap 移除该 session,表示该用户下线。

最后,就是两个发送消息的函数:

第一个是 sendToOneClient,接收的参数分别为接收方id和消息内容。使用接收方id便可以在 sessionMap 中找到接收方的会话 session。调用该session的getBasicRemote().sendText() 方法就可以实现把消息发送给接收方。但是在这一步,如果接收方不在线,即 sessionMap 中没有该用户的 session,那么消息将无法送达。因此,可以在这一步之前添加其它业务的代码,如将对应的消息内容、发送方id、接收方id以及发送时间保存至数据库,实现接收方用户登录时可以查看到所收到的所有消息。

第二个是 sendToAllClient,接收的参数为消息内容。该函数会先遍历 sessionMap,随后对sessionMap 中所有的 session (所有在线用户)发送对应的消息内容。

以上是websocket的后端实现,更多的玩法,如群聊等等都可以在这些基础功能函数上进行拓展。

三、前端代码实现

代码如下:

// 替换成你的后端地址,200是接收方id 
const ws = new WebSocket('ws://127.0.0.1:8080/ws/200?token=xxx');

//连接创建时调用的函数
ws.onopen = function() {
    console.log('连接成功');
}

//收到消息时调用的函数
ws.onmessage = function(e) {
    console.log('收到消息:', e.data);
}

//连接关闭时调用的函数
ws.onclose = function() {
    console.log('连接关闭');
}

// 捕获连接过程中的异常
ws.onerror = function(err) {
    console.error('错误', err);
}

//向接收方发送消息时调用的函数
function send() {
    const val = document.getElementById('msg').value;
    ws.send(val);
}

这段 JS 代码创建 WebSocket 实例,连接地址中指定接收方 id与身份 token。ws.onopen在 WebSocket 成功建立连接时触发,打印连接成功日志;ws.onmessage用于监听后端推送过来的消息;ws.onclose在连接关闭时执行,输出关闭日志;ws.onerror捕获连接过程中的异常并打印错误信息;自定义 send 函数读取输入框内容,通过 ws.send 把消息内容发送给后端。


总结

本文实现了前后端的 websocket 通信。希望对未来的架构师们有帮助~

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/lwj123456789123/article/details/155895068

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--