WebSocket实现消息推送

WebSocket实现消息推送

WebSocket的工作流程是这 样的:浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 TCP连接传输数据。因为WebSocket连接本质上是TCP连接,不需要每次传输都带上重复的头部数据,所以它的数据传输量比轮询和Comet技术小 了很多。本文不详细地介绍WebSocket规范,主要介绍下WebSocket在Java Web中的实现。

服务端代码

@ServerEndpoint(value = "/ws_chatroom/fh", configurator = HttpSessionConfigurator.class)
public class WSServer {

    private static Logger logger = LoggerFactory.getLogger(WSServer.class);

    // 已登录的所有的session。一个用户账号可以在多个地方登录,所以此处用list来存储
    private static final ConcurrentMap<String, List<WSServer>> map = Maps.newConcurrentMap();

    // 与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    // 当前会话的httpsession
    private HttpSession httpSession;


    /**
     * 建立连接
     */
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {

        try {
            // 得到httpSession
            List<WSServer> clients = map.get("-1");
            if (clients == null) {
                clients = new CopyOnWriteArrayList<>();
            }
            clients.add(this);
            map.put("-1", clients);
            this.session = session;
            logger.info("建立连接时,从session中获取当前用户信息为空,可能是session已过期");
        } catch (Exception e) {
            logger.info("什么时候会走到这里来啊");
            // 长时间不操作,session过期了。需要用户刷新页面重新建立连接
        } finally {
            // 连接数+1
            addOnlineCount();
            logger.debug("有新的连接,当前连接数为:" + getOnlineCount());
        }

    }


    /**
     * 关闭连接
     */
    @OnClose
    public void onClose() {

        try {
            // 这个session可能会过期
            UserInfo userInfo = (UserInfo) this.httpSession.getAttribute("currentUser");

            if (userInfo != null) {
                List<WSServer> clients = map.get(userInfo.getUserCode());
                if (clients != null && clients.size() > 0) {
                    clients.remove(this);// 要判断对象是不是同一个
                }
            } else {
                logger.info("关闭连接时,从session中获取当前用户信息为空,可能是session已过期");
            }
        } catch (Exception e) {
            // 关闭连接时,session可能已经过期
            // session过期后,拿不到usercode了,放在map中的wsserver就无法被移除了,等它自动过期吧
        } finally {
            // 连接数-1
            subOnlineCount();
            logger.debug("有一连接断开,当前连接数为:" + getOnlineCount());
        }
    }


    /**
     * websocket系统异常处理
     * 
     * @param t 异常
     */
    @OnError
    public void onError(Throwable t) {
        logger.error("websocket系统异常处理", t);
    }

    public static void sendMsg(String userid, WebSocketBean data) {
        // 通过用户ID获取当前用户登录的所有session
        // 给所有的这些session发消息
        List<WSServer> clients = map.get(userid);

        if (clients != null) {
            // 群发
            Iterator<WSServer> it = clients.iterator();
            while (it.hasNext()) {
                WSServer client = it.next();
                try {
                    if (!client.session.isOpen()) {
                        clients.remove(client);
                        continue;
                    }
                    if (client.session != null) {
                        client.session.getBasicRemote().sendText(JSON.toJSONString(data));
                    }
                } catch (IOException e) {
                    logger.error("发送消息异常", e);
                }
            }
        }
    }


    // 获取连接数
    private static synchronized int getOnlineCount() {
        return MessageConstant.onlineCount;
    }

    // 增加连接数
    private static synchronized void addOnlineCount() {
        MessageConstant.onlineCount++;
    }

    // 减少连接数
    private static synchronized void subOnlineCount() {
        MessageConstant.onlineCount--;
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        WSServer that = (WSServer) o;
        if (that.session.getId().equals(this.session.getId())) {
            return true;
        }
        return false;
    }

    @Override
    public int hashCode() {
        int result = session != null ? session.hashCode() : 0;
        result = 31 * result + (httpSession != null ? httpSession.hashCode() : 0);
        return result;
    }
}

 

**
 * 
 * 消息内容JAVABEAN
 *
 *
 *
 */
public class MessageDto {

    /**
     * 消息ID
     */
    private String id;
    /**
     * 发送用户ID
     */
    private String sender;
    /**
     * 接收用户ID
     */
    private String[] receivers;

    /**
     * 聊天内容
     */
    private String chatContent;

    /**
     * 发送时间
     */
    private String time;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getSender() {
        return sender;
    }

    public void setSender(String sender) {
        this.sender = sender;
    }

    public String[] getReceivers() {
        return receivers;
    }

    public void setReceivers(String[] receivers) {
        this.receivers = receivers;
    }

    public String getChatContent() {
        return chatContent;
    }

    public void setChatContent(String chatContent) {
        this.chatContent = chatContent;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值