springboot?使用websocket技术主动给前端发送消息的

目录使用websocket技术主动给前端发送消息WebSocketConfigWebSocketServerwebsocket基础入门-前端发送消息项目结构如下图

使用websocket技术主动给前端发送消息

springBoot2.0对WebSocket的支持简直太棒了,直接就有包可以引入

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

WebSocketConfig

启用WebSocket的支持也是很简单

package com.spark.common.config; import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * @Author Lxq * @Date 2021-06-12 17:11 * @Version 1.0 * 开启websocket支持 */@Configurationpublic class WebSocketConfig {     @Bean    public ServerEndpointExporter serverEndpointExporter() {        return new ServerEndpointExporter();    }}  

WebSocketServer

这就是重点了,核心都在这里。

因为WebSocket是类似客户端服务端的形式(采用ws协议),那么这里的WebSocketServer其实就相当于一个ws协议的Controller

直接@ServerEndpoint(“/socketServer/{userId}”) 、@Component启用即可,然后在里面实现@OnOpen开启连接,@onClose关闭连接,@onMessage接收消息等方法。

新建一个ConcurrentHashMap webSocketMap 用于接收当前userId的WebSocket,方便IM之间对userId进行推送消息。单机版实现到这里就可以。

package com.spark.common.utils.websocket; import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.spark.common.utils.StringUtils;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 Lxq * @Date 2021-06-12 17:13 * @Version 1.0 */@ServerEndpoint("/socketServer/{userId}")@Component@Slf4jpublic class WebSocketServer {     /**     * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。     */    private static int onlineCount = 0;    /**     * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。     */    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();    /**     * 与某个客户端的连接会话,需要通过它来给客户端发送数据     */    private Session session;    /**     * 接收userId     */    private String userId = "";     /**     * 连接建立成功调用的方法     */    @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);            //加入set中        } else {            webSocketMap.put(userId, this);            //加入set中            addOnlineCount();            //在线数加1        }         log.info("用户连接:" + userId + ",当前在线人数为:" + getOnlineCount());         try {            sendMessage("连接成功");        } catch (IOException e) {            log.error("用户:" + userId + ",网络异常!");        }    }      /**     * 连接关闭调用的方法     */    @OnClose    public void onClose() {        if (webSocketMap.containsKey(userId)) {            webSocketMap.remove(userId);            //从set中删除            subOnlineCount();        }        log.info("用户退出:" + userId + ",当前在线人数为:" + getOnlineCount());    }      /**     * 收到客户端消息后调用的方法     *     * @param message 客户端发送过来的消息     */    @OnMessage    public void onMessage(String message, Session session) {        log.info("用户消息:" + userId + ",报文:" + message);        //可以群发消息        //消息保存到数据库、redis        if (StringUtils.isNotBlank(message)) {            try {                //解析发送的报文                JSONObject jsonObject = JSON.parseObject(message);                //追加发送人(防止串改)                jsonObject.put("fromUserId", this.userId);                String toUserId = jsonObject.getString("toUserId");                //传送给对应toUserId用户的websocket                if (StringUtils.isNotBlank(toUserId) && webSocketMap.containsKey(toUserId)) {                    webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());                } else {                    log.error("请求的userId:" + toUserId + "不在该服务器上");                    //否则不在这个服务器上,发送到mysql或者redis                }            } catch (Exception e) {                e.printStackTrace();            }        }    }     /**     * @param session     * @param error     */    @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 void sendInfo(String message, @PathParam("userId") String userId) throws IOException {        log.info("发送消息到:" + userId + ",报文:" + message);        if (StringUtils.isNotBlank(userId) && webSocketMap.containsKey(userId)) {            webSocketMap.get(userId).sendMessage(message);        } else {            log.error("用户" + userId + ",不在线!");        }    }     /**     * 获取当前在线人数     *     * @return     */    public static synchronized int getOnlineCount() {        return onlineCount;    }     /**     * 添加人数     */    public static synchronized void addOnlineCount() {        WebSocketServer.onlineCount++;    }     /**     * 减少人数     */    public static synchronized void subOnlineCount() {        WebSocketServer.onlineCount--;    } }

websocket基础入门-前端发送消息

项目结构如下图

TestSocket.java

package com.charles.socket; import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.ServerEndpoint; @ServerEndpoint(value = "/helloSocket")public class TestSocket {     /***     * 当建立链接时,调用的方法.     * @param session     */    @OnOpen    public void open(Session session) {                System.out.println("开始建立了链接...");        System.out.println("当前session的id是:" + session.getId());    }        /***     * 处理消息的方法.     * @param session     */    @OnMessage    public void message(Session session, String data) {                System.out.println("开始处理消息...");        System.out.println("当前session的id是:" + session.getId());        System.out.println("从前端页面传过来的数据是:" + data);    }}

index.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Charles-WebSocket</title> <script type="text/javascript">        var websocket = null;    var target = "ws://localhost:8080/websocket/helloSocket";        function buildConnection() {                if('WebSocket' in window) {            websocket = new WebSocket(target);                } else if('MozWebSocket' in window) {            websocket = MozWebSocket(target);        } else {            window.alert("浏览器不支持WebSocket");        }    }        // 往后台服务器发送消息.    function sendMessage() {                var sendmsg = document.getElementById("sendMsg").value;        console.log("发送的消息:" + sendmsg);                // 发送至后台服务器中.        websocket.send(sendmsg);    }    </script></head><body>        <button onclick="buildConnection();">开始建立链接</button>    <hr>    <input id="sendMsg" /> <button onclick="sendMessage();">消息发送</button> </body></html>

注意:

和后台交互的时候,一定要先点击:开始建立连接。你懂的…没有建立连接的话,是不能发送消息的。

先点击,开始建立连接,然后在文本框中输入内容:我是Charles,点击消息发送,在看后台日志。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

终究还是会从指缝中一滴一滴流淌干净。

springboot?使用websocket技术主动给前端发送消息的

相关文章:

你感兴趣的文章:

标签云: