springBoot集成WebSocket,实现后台向前端推送信息

springBoot集成WebSocket,实现后台向前端推送信息

  1. 先在搭建好的springBoot项目中引入对应的websocket包。地址如下。
         <dependency>  
           <groupId>org.springframework.boot</groupId>  
                <artifactId>spring-boot-starter-websocket</artifactId>  
         </dependency>  
  1. 这里集成下thymeleaf模板,在配置文件中添加thymeleaf配置信息。
         thymeleaf:
            cache: false
            prefix: classpath:/templates/
            suffix: .html
            mode: HTML5
            encoding: UTF-8
            content-type: text/html
    
  2. 自定义WebsocketServer,使用底层的websocket方法,编写对应的onOpen()、onClose()、onMessage()、onError()方法,
    先添加webSocketConfig配置类。
  @Configuration
      public class WebSocketConfig {
       @Bean
        public ServerEndpointExporter serverEndpointExporter(){
             return new ServerEndpointExporter();
           }
       }
  1. 在Controller层创建WebSocketServer类,在里面编写逻辑代码。
       package com.dehui.info.surveyingmanagementback.controller;
       import com.alibaba.fastjson.JSON;
       import com.alibaba.fastjson.JSONObject;
       import com.dehui.info.surveyingmanagementback.utils.StringUtils;
       import org.apache.juli.logging.Log;
       import org.apache.juli.logging.LogFactory;
       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;
      @ServerEndpoint("/imserver/{userId}")
      @Component
      public class WebSocketServer {
           static Log log= LogFactory.getLog(WebSocketServer.class);
           private static int onLineCount=0;
         /**
          * concurrent包的线程安全Set,用来存放每个客户端对应的wwebsocket对象.
          */
          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();
               //调用在线人数增加方法
           }
           log.info("用户连接:"+userId+",当前在线人数为:"+ getOnlineCount());
         try{
            //将在线人数群发给所有在线用户
            for(String key:webSocketMap.keySet()){
    
                JSONObject jsonObject1= new JSONObject();
    
                jsonObject1.put("code",200);
                jsonObject1.put("type",1);
                jsonObject1.put("data",getOnlineCount());
                webSocketMap.get(key).sendMessage(jsonObject1.toJSONString());
            }
    
           }catch (IOException e){
             log.error("用户:"+userId+",网络异常!!!");
         }
       }
    
         /**
         * 关闭连接方法
         */
        @OnClose
      public void onClose(){
       if(webSocketMap.containsKey(userId)){
           webSocketMap.remove(userId);
    
           //从set中删除
           subOnlineCount();
       }
       log.info("用户退出:"+userId+",当前在线人数为:"+getOnlineCount());
       }
    
       /**
       * 收到客户端消息后调用的方法
       */
      @OnMessage
      public void onMessage(String message,Session session){
        log.info("用户消息:"+userId+",报文"+message);
        //可以进行群发消息,信息也可以保存在数据库中,或者redis中
       System.out.println("判断条件"+StringUtils.isNotBlank(message));
    
       if(StringUtils.isNotBlank(message)){
           try{
               //解析发送的报文
               JSONObject jsonObject= JSON.parseObject(message);
    
               //追加发送人防止串改
               jsonObject.put("fromUserId",this.userId);
               jsonObject.put("type",2);
               String toUserId=jsonObject.getString("toUserId");
               //向指定的userId用户发送消息
               if(StringUtils.isNotBlank(toUserId)&&webSocketMap.containsKey(toUserId)){
                     webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
               }else{
                   log.error("请求的userId:"+toUserId+"不在该服务器上");
                   //如果服务器上没有可以存在数据库中
               }
           }catch (Exception e){
               e.printStackTrace();
           }
    
          }
      }
       /**
         * 连接报错
        */
        @OnError
       public void onErrot(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+",不在线!!");
            }
      }
      public static synchronized int getOnlineCount(){
          return onLineCount;
       }
    
      public static synchronized  void addOnlineCount(){
          WebSocketServer.onLineCount++;
      }
      public static synchronized void subOnlineCount(){
         WebSocketServer.onLineCount--;
        }
       }
    

5.然后再创建WebSocketTestController层,实现登陆访问时跳转到对应的页面。

@Controller
        public class WebSocketTestController {
        @GetMapping("page")
        public ModelAndView page(){

          return new ModelAndView("page");
         }

       }

6.创建page页面,测试websocket。

  <!DOCTYPE html>
            <html lang="en">
            <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() {
          if(typeof(WebSocket)=="undefined"){
              console.log("您的浏览器不支持websocket");
          }else{
              console.log("您的浏览器支持websocket");
             //与websocket服务端建立连接
              var socketUrl="ws://localhost:8091/imserver/"+$("#userId").val();
              if(socket!=null){
                  socket.close();
                  socket=null
              }
              socket = new WebSocket(socketUrl);
              //打开事件

              socket.onopen=function () {
                    console.log("websocket已打开");

              };
              //获得消息事件
              socket.onmessage=function (msg) {
                  let data=JSON.parse(msg.data)
                     if(data.type===1){
                         document.getElementById("msg_data").innerHTML = "当前在线人数:"+ data.data;
                     }else if(data.type===2){
                         $("#info").append('<div >用户'+data.fromUserId+':'+data.contentText+'</div>');
                     }
              }
              //关闭事件
              socket.onclose=function () {
                  console.log("websocket已关闭");
              }
              //发生错误
              socket.onerror=function () {
               console.log("websocket发生了错误")
              }
          }

        }
       function sendMessage() {
          if(typeof(WebSocket)=="undefined"){
              console.log("您的浏览器不支持websocket")
          }else{
              console.log("您的浏览器支持websocket")
              console.log('{"toUserId":"'+$("#toUserId").val()+'","contentText":"'+$("#contentText").val()+'"}');
              socket.send('{"toUserId":"'+$("#toUserId").val()+'","contentText":"'+$("#contentText").val()+'"}');

          }
       }
       </script>
        <div><span>用户id:</span><input id="userId" name="userId" type="text" value="10"><span>连接-></span><span>聊天对象id:</span><input id="toUserId" name="toUserId" type="text" value="20"></div>
        <p>【信息输入框】:<div><input id="contentText" name="contentText" type="text" value="hello friend"><div><button onclick="sendMessage()">发送消息</button></div></div>
        <p>【操作】:<div><button onclick="openSocket()">开启socket</button></div>
        <p><div id="msg_data"></div></p>
        <p>【接收信息面板】:<div id="info"></div></p>
        </body>
        </html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值