Java后端向前端推送消息完整代码实例

 更新时间:2026年02月02日 10:05:28   作者:recollection℡¹⁸⁶  
WebSocket是一种全双工通信协议,允许后端主动向前端推送消息,下面这篇文章主要介绍了Java后端向前端推送消息的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

1、WebSocketConfig配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

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

2、WebSocket消息发送接收

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
@ServerEndpoint(value = "/web/{id}")
public class WebSocketProcess {

    /*
     * 持有每个webSocket对象,以key-value存储到线程安全ConcurrentHashMap,
     */
    private static ConcurrentHashMap<Long, WebSocketProcess> concurrentHashMap = new ConcurrentHashMap<>(12);

    /**
     * 会话对象
     **/
    private Session session;


    /*
     * 客户端创建连接时触发
     * */
    @OnOpen
    public void onOpen(Session session, @PathParam("id") long id) {
        //每新建立一个连接,就把当前客户id为key,this为value存储到map中
        this.session = session;
        concurrentHashMap.put(id, this);
        log.info("Open a websocket. id={}", id);
    }

    /**
     * 客户端连接关闭时触发
     **/
    @OnClose
    public void onClose(Session session, @PathParam("id") long id) {
        //客户端连接关闭时,移除map中存储的键值对
        concurrentHashMap.remove(id);
        log.info("close a websocket, concurrentHashMap remove sessionId= {}", id);
    }

    /**
     * 接收到客户端消息时触发
     */
    @OnMessage
    public void onMessage(String message, @PathParam("id") String id) {
        log.info("receive a message from client id={},msg={}", id, message);
    }

    /**
     * 连接发生异常时候触发
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("Error while websocket. ", error);
    }

    /**
     * 发送消息到指定客户端
     *
     * @param id
     * @param message
     */
    public void sendMessage(long id, String message) throws Exception {
        //根据id,从map中获取存储的webSocket对象
        WebSocketProcess webSocketProcess = concurrentHashMap.get(id);
        if (!ObjectUtils.isEmpty(webSocketProcess)) {
            //当客户端是Open状态时,才能发送消息
            if (webSocketProcess.session.isOpen()) {
                webSocketProcess.session.getBasicRemote().sendText(message);
            } else {
                log.error("websocket session={} is closed ", id);
            }
        } else {
            log.error("websocket session={} is not exit ", id);
        }
    }

    /**
     * 发送消息到所有客户端
     */
    public void sendAllMessage(String msg) throws Exception {
        log.info("online client count={}", concurrentHashMap.size());
        Set<Map.Entry<Long, WebSocketProcess>> entries = concurrentHashMap.entrySet();
        for (Map.Entry<Long, WebSocketProcess> entry : entries) {
            Long cid = entry.getKey();
            WebSocketProcess webSocketProcess = entry.getValue();
            boolean sessionOpen = webSocketProcess.session.isOpen();
            if (sessionOpen) {
                webSocketProcess.session.getBasicRemote().sendText(msg);
            } else {
                log.info("cid={} is closed,ignore send text", cid);
            }
        }
    }
}

3、消息推送Controller

import com.xyl.web.controller.common.WebSocketProcess;
import com.xyl.web.controller.common.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/testws")
public class WebSocketController {

    /**
     * 注入WebSocketProcess
     **/
    @Autowired
    private  WebSocketProcess webSocketProcess;

    /**
     * 向指定客户端发消息
     *
     * @param id

     */
    @PostMapping(value = "sendMsgToClientById")
    public void sendMsgToClientById(@RequestParam long id, @RequestParam String text) {
        try {
            webSocketProcess.sendMessage(id, text);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 发消息到所有客户端
     *
     * @param text
     */
    @PostMapping(value = "sendMsgToAllClient")
    public void sendMsgToAllClient(@RequestParam String text) {
        try {
            webSocketProcess.sendAllMessage(text);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
     /**
     * 定时向客户端推送消息
     * @throws Exception
     */
    @Scheduled(cron = "0/5 * * * * ?")
    private void configureTasks() throws Exception {
        webSocketProcess.sendAllMessage("向前端推送消息内容");
    }
}

4、测试HTML

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>websocket测试</title>
    <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
<div id="content"></div>

</body>
<script type="text/javascript">

    $(function(){
        var ws;
        //检测浏览器是否支持webSocket
        if("WebSocket" in window){
            $("#content").html("您的浏览器支持webSocket!");
            //模拟产生clientID
            let clientID = Math.ceil(Math.random()*100);

            //创建 WebSocket 对象,注意请求路径!!!!
            ws = new WebSocket("ws://127.0.0.1:9095/web/"+clientID);

            //与服务端建立连接时触发
            ws.onopen = function(){
                $("#content").append("<p>与服务端建立连接建立成功!您的客户端ID="+clientID+"</p>");

                //模拟发送数据到服务器
                ws.send("你好服务端!我是客户端 "+clientID);
            }

            //接收到服务端消息时触发
            ws.onmessage = function (evt) {
                let received_msg = evt.data;
                $("#content").append("<p>接收到服务端消息:"+received_msg+"</p>");
            };

            //服务端关闭连接时触发
            ws.onclose = function() {
                console.error("连接已经关闭.....")
            };
        }else{
            $("#content").html("您的浏览器不支持webSocket!");
        }
    })

</script>
</html>


总结 

到此这篇关于Java后端向前端推送消息完整代码的文章就介绍到这了,更多相关Java后端向前端推送消息内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 10张图总结出并发编程最佳学习路线

    10张图总结出并发编程最佳学习路线

    这篇文章主要介绍了并发编程的最佳学习路线,文中通过图片介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-08-08
  • Java生成订单号或唯一id的高并发方案(4种方法)

    Java生成订单号或唯一id的高并发方案(4种方法)

    本文主要介绍了Java生成订单号或唯一id的高并发方案,包括4种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-01-01
  • Spring Cloud Config 使用本地配置文件方式

    Spring Cloud Config 使用本地配置文件方式

    这篇文章主要介绍了Spring Cloud Config 使用本地配置文件方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Java基础语法:逻辑控制

    Java基础语法:逻辑控制

    下面小编就为大家带来一篇Java逻辑控制的基础文章。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2021-08-08
  • idea编辑XML文件出现:Tag name expected报错的解决

    idea编辑XML文件出现:Tag name expected报错的解决

    在XML中,一些特殊字符不能直接使用,因为它们被保留用于XML文档的结构和语法,如果直接使用这些保留字符,会导致解析错误,正确的做法是使用实体引用或字符引用,或者使用CDATA标记将这些字符包裹起来
    2025-01-01
  • Java基础之内部类与代理知识总结

    Java基础之内部类与代理知识总结

    今天带大家复习Java的基础知识,文中有非常详细的介绍及图文示例,对正在学习Java的小伙伴们很有帮助,需要的朋友可以参考下
    2021-06-06
  • java8的stream如何取max

    java8的stream如何取max

    这篇文章主要介绍了java8的stream如何取max问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Java实现终止线程池中正在运行的定时任务

    Java实现终止线程池中正在运行的定时任务

    本篇文章给大家分享了JAVA中实现终止线程池中正在运行的定时任务的具体步骤和方法,有需要的朋友跟着学习下。
    2018-05-05
  • java.sql.Date和java.util.Date的区别详解

    java.sql.Date和java.util.Date的区别详解

    Java中有两个Date类,一个是java.util.Date通常情况下用它获取当前时间或构造时间,另一个是java.sql.Date是针对SQL语句使用的,它只包含日期而没有时间部分,这篇文章主要给大家介绍了关于java.sql.Date和java.util.Date区别的相关资料,需要的朋友可以参考下
    2023-03-03
  • Spring StateMachine实现状态机使用示例详解

    Spring StateMachine实现状态机使用示例详解

    本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解析状态同步、事件触发与数据持久化机制,感兴趣的朋友跟随小编一起看看吧
    2025-07-07

最新评论