websocket实现消息推送(亲测有效)

一、websocket原理和背景

摘自:WebSocket介绍和Socket的区别

二、使用javax的websocket实现消息推送

1.依赖注入


        
            javax.websocket
            javax.websocket-api
            1.1
            provided
        
        
            javax
            javaee-api
            7.0
        

2.建立前后端连接

前端代码:



    
    


websocket Demo---- user000 

后端测试代码:这个类充当websocket服务端的角色,当有请求到来时,会调用onMessage()方法进行处理,并通过session.getAsyncRemote().sendText()方法推送给前端。


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 12450
 * 简书demo:https://www.jianshu.com/p/d79bf8174196
 */
@ServerEndpoint(value = "/websocketTest/{userId}")
@Component
public class DemoWebsocket {
    private static Logger logger = LoggerFactory.getLogger(DemoWebsocket.class);

    private String userId;
    /**
     * 会话
     */
    private Session session;

    /**
     * 以用户的姓名为key,websocket为对象保存起来
     */
    private static Map clients = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(@PathParam("userId") String userId, Session session) {
        logger.debug("新连接:{}", userId);
        //首先要判断该ID是否已经加入,如果已经加入不重复加入
        if (!isEmpty(userId)) {
            this.userId = userId;
            this.session = session;
            clients.put(userId, this);
            logger.info("现在连接的客户编码为:" + userId);
        }
    }

    /**
     * 关闭时执行
     */
    @OnClose
    public void onClose() {
        logger.debug("连接:{} 关闭", this.userId);
    }

    /**
     * 收到消息时执行
     *
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.debug("收到用户{}的消息{}", this.userId, message);
        //回复用户
        session.getAsyncRemote().sendText("收到 " + this.userId + " 的消息:" + message);
    }

    /**
     * 连接错误时执行
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.debug("用户id为:{}的连接发送错误", this.userId);
        error.printStackTrace();
    }

    /**
     * 消息点对点推送
     *
     * @param clientId
     * @param message
     */
    public static void sendMessageToUser(String clientId, String message) {

        DemoWebsocket session = clients.get(clientId);
        if (session != null) {
            if (session.session.isOpen()) {
                session.session.getAsyncRemote().sendText("收到 " + clientId + " 的消息:" + message);
            } else {
                logger.info("用户session关闭");
            }
        } else {
            logger.info("用户session不存在");
        }
    }

    private static boolean isEmpty(String s) {
        return s == null || s.length() == 0 || "".equals(s)
                || "null".equalsIgnoreCase(s)
                || "undefined".equalsIgnoreCase(s);
    }

}

测试类:我们通过调用后台接口的方式可以模拟纯后台向前台不定期推送数据的情况。


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import xin.shenwan.websocket.DemoWebsocket;

/**
 * websocket后端主动向前端推送消息demo
 * @author gongyunlong
 */
@Controller
@RequestMapping(value = "/queue")
public class Test {


    @RequestMapping(value="/websocket")
    @ResponseBody
    public void websocket(String message){
        DemoWebsocket.sendMessageToUser("user000",message);
    }


}

那么当你一进入前端页面,连接已经建立了,你所发送的请求都会在同一个连接中传输,而不是再次新建请求。

 

实测

一、“传统的”前台发出请求,后台响应

在测试框输入消息,关注后台返回结果,可以看到后台做出了响应

websocket实现消息推送(亲测有效)_第1张图片

二、模拟纯后端推送

  • 我们打开一个浏览器来请求后端,填写请求的url和参数;
  • 当我们点击回车后,当前页面是没有任何反应的,因为我没有编写返回的页面代码,哈哈
  • 但是当我们回到第一步打开的,和后端服务器建立连接的页面我们就会看到,消息此时已经被推送到了前端页面;

websocket实现消息推送(亲测有效)_第2张图片

仅仅是入门分享,希望大家可以一块讨论,共同进步。

你可能感兴趣的:(websocket)