WebSocket实现后台向前端推送信息

什么是WebSocket?

因为 HTTP 协议有一个缺陷:通信只能由客户端发起,HTTP 协议做不到服务器主动向客户端推送信息。
WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端
在这里插入图片描述

快速上手

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

WebSocketConfig启用WebSocket的支持

/**
 * 开启WebSocket支持
 * @author zhucan
 */
@Configuration
public class WebSocketConfig {

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

}

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

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

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

集群版(多个ws节点)还需要借助mysql或者redis等进行处理,改造对应的sendMessage方法即可。

/**
 * @author
 */
@ServerEndpoint("/imserver/{userId}")
@Component
public class WebSocketService {


    /**
     * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
     */
    private static ConcurrentHashMap<String, WebSocketService> webSocketMap = new ConcurrentHashMap<>();
    /**
     * 与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    private Session session;
    /**
     * 接收userId
     */
    private String userId = "";

    /**
     * 连接建立成功调用的方法
     * <p>
     * 1.用map存 每个客户端对应的MyWebSocket对象
     */
    @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中
        }
        //服务端向客户端发送信息
        sendMessage("用户" + userId + "上线了,当前在线人数为:" + webSocketMap.size() + "。");
    }


    /**
     * 报错
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    /**
     * 实现服务器推送到对应的客户端
     */
    public void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 自定义 指定的userId服务端向客户端发送消息
     */
    public static void sendInfo(String message, String userId, String toUserId) {
        //log.info("发送消息到:"+userId+",报文:"+message);
        if (StringUtils.isNotBlank(toUserId) && webSocketMap.containsKey(toUserId)) {
            webSocketMap.get(toUserId).sendMessage(message);
        } else {
            webSocketMap.get(userId).sendMessage(toUserId + "已经下线。");
        }
    }

    /**
     * 自定义关闭
     *
     * @param userId
     */
    public static void close(String userId) {
        if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
        }
    }

    /**
     * 获取在线用户信息
     *
     * @return
     */
    public static Map getOnlineUser() {
        return webSocketMap;
    }

}

controller 对外提供发送 关闭websocket方法

@RestController
public class DemoController {



    @PostMapping("/push")
    public ResponseEntity<String> pushToWeb(String message, String toUserId,String userId) throws IOException {
        WebSocketService.sendInfo(message,userId,toUserId);
        return ResponseEntity.ok("MSG SEND SUCCESS");
    }

    @GetMapping("/close")
    public String close(String userId){
        WebSocketService.close(userId);
        return "ok";
    }


    @GetMapping("/getOnlineUser")
    public Map getOnlineUser(){
        return WebSocketService.getOnlineUser();
    }

}

html 前端页面

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>websocket通讯</title>
</head>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
    var socket;
    
    function openSocket(flag) {
        var socketUrl = "http://localhost:8449/imserver/" + $("#userId").val();
        socketUrl = socketUrl.replace("https", "ws").replace("http", "ws");
        if (socket != null) {
            socket.close();
            socket = null;
        }
        socket = new WebSocket(socketUrl);
        //打开事件
        socket.onopen = function () {
            //获得消息事件
            socket.onmessage = function (msg) {
                $('#contain').html(msg.data);
            };
            //发生了错误事件
            socket.onerror = function () {
                alert("websocket发生了错误");
            }
            $("#userId").attr("disabled", true);
        }
    }
    
    
    function sendMessage() {
        $.ajax({
            url:"http://localhost:8449/push",
            type:"POST",
            data:{
                'message':$("#contentText").val(),
                'toUserId':$("#toUserId").val(),
                'userId':$("#userId").val()
            }
        })
    }


    function closeSocket() {
        var userId =$("#userId").val()
        $.ajax({
            type:"get",
            url:"http://localhost:8449/close?userId="+userId,
            success:function(res) {
                alert('111');

            }
        });
        $("#userId").attr("disabled", false);
        $('#contain').html("下线成功!");
    }



</script>
<body>
<p>【内容】:<span id="contain"></span></p>
<p>【当前用户】:<div><input id="userId" name="userId" type="text" value="10"></div>
<p>【发送用户】:<div><input id="toUserId" name="toUserId" type="text" value="20"></div>
<p>【发送的内容】:<div><input id="contentText" name="contentText" type="text" value="hello websocket"></div>
<p>【操作】:<div><button onclick="openSocket()">登录socket</button></div>
<p>【操作】:<div><button onclick="closeSocket()">关闭socket</button></div>
<p>【操作】:<div><button onclick="sendMessage()">发送消息</button></div>
</body>

</html>
  • 5
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 可以使用 websocket 在前后端进行实时通信。要在 Java 中实现 websocket,可以使用 Java API for WebSocket(JSR 356)。 要在 Vue 中使用 websocket,可以使用第三方库,例如 vue-socket.io。 示例代码: Java 服务端: ```java import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; @ServerEndpoint("/websocket") public class WebSocketServer { @OnOpen public void onOpen(Session session) { System.out.println("Open a new session: " + session.getId()); } @OnMessage public void onMessage(String message, Session session) { System.out.println("Receive a message: " + message); } @OnClose public void onClose(Session session) { System.out.println("Close a session: " + session.getId()); } } ``` Vue 客户端: ```javascript import Vue from 'vue'; import VueSocketIO from 'vue-socket.io'; Vue.use(new VueSocketIO({ debug: true, connection: 'http://localhost:8080/websocket', })); new Vue({ el: '#app', data: { message: '', }, methods: { sendMessage() { this.$socket.emit('send message', this.message); this.message = ''; }, }, }); ``` 在这个示例中,Java 服务端会监听 `/websocket` 路径,Vue 客户端会连接到这个路径。当 Vue 客户端调用 `sendMessage` 方法时,会向服务端发送 `send message` 事件,服务端会收到并打印消息。 ### 回答2: 使用WebSocket可以实现实时消息推送功能。下面是使用Java和Vue实现后台消息推送的简单流程: 1. 后台Java实现: 首先,需要创建一个WebSocket处理器类,可以使用Java中的WebSocket API或开源库(如Spring WebSocket)来简化实现。 在WebSocket处理器类中,需要定义连接建立、断开和接收消息等方法,并添加注解以映射监听的消息路径,并处理相应的业务逻辑。 2. 前端Vue实现: 在Vue中,可以使用WebSocket对象来与后台建立连接,并监听消息的到达。 需要在Vue的钩子函数中创建WebSocket对象,并注册回调函数处理后台发送的消息。 当收到消息时,可以将其展示在前端页面的相应位置。 3. 后台推送消息: 在后台的相关业务逻辑中,可以通过WebSocket的连接向前端发送消息。 可以在需要推送消息的地方,通过获取对应的WebSocket连接,并使用WebSocket对象的send方法将消息发送至前端。 需要注意的是,WebSocket是基于TCP协议的全双工通信协议,所以需要确保后台服务器和前端浏览器都支持WebSocket。 以上是一个简单的实现示例,实际项目中还需要根据具体需求进行扩展和优化。希望能帮到你! ### 回答3: 要使用WebSocket实现后台消息推送,需要进行以下步骤: 1. 在后台使用Java语言创建WebSocket服务器。可以使用Java内置的WebSocket API或者第三方库,如Tomcat的WebSocket实现等。具体方式可以通过搜索相关教程了解。 2. 在Vue前端应用中,使用WebSocket连接到后台服务器。可以使用Vue插件,如vue-native-websocket或者自己编写相关逻辑。具体方式可以通过搜索相关教程了解。 3. 后台服务器接收Vue前端应用的WebSocket连接请求,并处理连接逻辑。 4. 在后台服务器向Vue前端应用发送消息时,通过WebSocket向已连接的Vue客户端发送消息后台服务器可以根据消息类型和接收者,选择性地发送消息给指定的客户端。 5. Vue前端应用接收到后台服务器发送的消息后,进行逻辑处理,如显示消息内容或者执行其他相应操作。 需要注意以下几点: 1. 后台服务器需要保持WebSocket连接的活跃性,以便随时向前端应用发送消息。可以使用定时任务或者其他方式来检测和维持连接。 2. Vue前端应用需要在合适的时机关闭WebSocket连接,以释放资源。可以在Vue组件的生命周期钩子函数中处理关闭连接的逻辑。 总之,通过WebSocket实现后台消息推送,涉及到后台服务器的建立和维护,以及前端应用的连接和消息处理。可以根据实际需求选择合适的技术和工具,完成消息推送功能。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值