layim之整合WebSocket即时通讯

一. 认识LayIM即时通讯

在这里LayIM基础配置与init数据初始化等直接跳过了,开发者文档有着非常详细的说明。

已为您准备好专机 ✈ LayIM开发者文档

二. WebSocket的搭建

搭建WebSocket非常简单,无需任何配置,只需服务端一个处理类。

2.1、服务端代码

package com.cn.adonis.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;

@ServerEndpoint("/chat/socket/{username}")
public class WebSocket {
    
    
	
	private static Logger log = Logger.getLogger(WebSocket.class);
	// 在线人数
	private static int onlineCount = 0;
	// 在线用户列表
	private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();
	// 在线用户对应群聊编号集合
    private static Map<String, String> clientGroup = new ConcurrentHashMap<String, String>();
    private Session session;
    private String username;
    
    // 连接Socket触发
    @OnOpen
    public void onOpen(@PathParam("username") String username, Session session) throws IOException {
    
    
        this.username = username;
        this.session = session;
        // 在线人数+1
        addOnlineCount();
        // 把当前用户添加到在线用户列表
        clients.put(username, this);
        // 访问数据库获取该用户所有群聊编号集合
        clientGroup.put(username, "1,2,3,4,5");
        // 推送上线通知给加我为好友的在线用户
        sendMessageToFriend("online");
        log.info(username + "已上线");
    }
    
    // 离线或关闭窗口、异常关闭浏览器触发
    @OnClose
    public void onClose() throws IOException {
    
    
        // 将当前用户从在线用户列表中移除
        clients.remove(username);
        // 在线人数-1
        subOnlineCount();
        // 推送离线通知给加我为好友的在线用户
        sendMessageToFriend("offline");
        log.info(this.username + "已离线");
    }
    
    // 服务端向客户端推送消息
    @OnMessage
    public void onMessage(String messageJson) throws IOException {
    
    
        JSONObject json = JSONObject.parseObject(messageJson);
        String type = json.getString("type").toLowerCase();
        JSONObject data = json.getJSONObject("data");
        
        if(type.equals("all")){
    
     
        	// 推送给所有在线用户
        	sendMessageAll(messageJson);
        }else if(type.equals("groupMessage")){
    
    
        	// 推送给群在线用户
        	sendMessageGroup(messageJson, data.getString("fromGroupId"), false);
        }else if(type.equals("friendMessage")){
    
    
        	// 推送给固定用户
        	sendMessageTo(messageJson, String.valueOf(data.getLong("toId")));
        }
    }
    
    // 异常接收
    @OnError
    public void onError(Session session, Throwable error) {
    
    
        log.info(this.username + "发生异常");
    }
    
    /**
     * 推送给所有在线用户
     * @param message 推送信息
     */
    public void sendMessageAll(String message) throws IOException {
    
    
        for (WebSocket item : clients.values()) {
    
    
            item.session.getAsyncRemote().sendText(message);
        }
    }
    
    /**
     * 推送给固定用户
     * @param message 推送信息
     * @param To 好友编号
     */
    public void sendMessageTo(String message, String To) throws IOException {
    
    
        for (WebSocket item : clients.values()) {
    
    
            if (item.username.equals(To))
                item.session.getAsyncRemote().sendText(message);
        }
    }
    
    /**
     * 推送给群聊成员
     * @param message 推送信息
     * @param To 群聊编号
     * @param isWhole 推送状态(1推送给所有成员,0推送给非自己外的所有成员)
     */
    public void sendMessageGroup(String message, String To, boolean isWhole) throws IOException {
    
    
    	String filterId = "," + To + ",";
    	if(isWhole){
    
    
            for (WebSocket item : clients.values()) {
    
    
            	String groupIds = clientGroup.get(item.username);
            	if(groupIds.indexOf(filterId)>=0){
    
    
                    item.session.getAsyncRemote().sendText(message);
            	}
            }
    	}else{
    
    
            for (WebSocket item : clients.values()) {
    
    
            	String groupIds = clientGroup.get(item.username);
            	if(groupIds.indexOf(filterId)>=0 && !this.username.equals(item.username)){
    
    
                    item.session.getAsyncRemote().sendText(message);
            	}
            }
    	}
    }

	/**
	 * 推送给加我为好友的用户
	 * @param lineState 在线状态(在线:online,离线:offline
	 */
    public void sendMessageToFriend(String lineState) throws IOException {
    
    
    	String userId = username;
    	// 登录用户信息,实际应用请根据userId查用户信息
    	Map<String, Object> user = new HashMap<String, Object>();
    	user.put("id", userId);
    	user.put("username", "小升");
    	// 获取加我为好友的在线用户集合
    	String userIds = "1,2,5,12,22,23,43,44";
    	Map<String, Object> revertMap = new HashMap<String, Object>();
    	revertMap.put("type", "chatLineState");
    	revertMap.put("state", lineState);
    	revertMap.put("mine", user);
    	String message = JSON.toJSONString(revertMap, SerializerFeature.WriteMapNullValue);
    	 for (WebSocket item : clients.values()) {
    
    
    		 if(userIds.indexOf("," + item.username + ",")>=0){
    
    
    			 item.session.getAsyncRemote().sendText(message);
    		 }
        }
    }
      
    public static synchronized int getOnlineCount() {
    
    
        return onlineCount;
    }
    public static synchronized void addOnlineCount() {
    
    
        WebSocket.onlineCount++;
    }
    public static synchronized void subOnlineCount() {
    
    
        WebSocket.onlineCount--;
    }
    public static synchronized Map<String, WebSocket> getClients() {
    
    
        return clients;
    }
}

2.2、客户端代码

(1). 首先引入Sockjs插件

<!-- 加载Sockjs -->
<script src="https://cdn.bootcss.com/sockjs-client/1.4.0/sockjs.min.js"></script>

(2). 在监听LayIM建立就绪事件里初始化Socket

// 监听layim建立就绪
layim.on('ready', function(res){
    
    
	// 服务端WebSocket的访问路径。(注意:路径前缀务必添加websocket的“ws://”。username为登录用户,与服务端WebSocket的username一致。)
	var action = 'ws://localhost/chat/socket/' + username;
	// 初始化Socket
	if('WebSocket' in window) {
    
    
		websocket = new WebSocket(action);  
	} else if('MozWebSocket' in window) {
    
    
		websocket = new MozWebSocket(action);
	} else {
    
    
		websocket = new SockJS(action);
	}
	// 连接成功建立的回调方法  
	websocket.onopen = function () {
    
    
	    layer.msg('WebSocket连接成功!');
	}
	// 接收到消息的回调方法 
    websocket.onmessage = function (event) {
    
    
       	//获取返回数据
       	var json = JSON.parse(event.data);
   		console.log(json)
      	// 获取消息类型
      	var messageType = json.type;
	    if(messageType === "chatLineState"){
    
    
       		// -----#开始----------- 上线通知、离线通知 ----------------
       		// 上线通知: {"type":"chatLineState","state":"online","mine":{"id":"2","username":"小焕"}}
       		// 下线通知: {"type":"chatLineState","state":"offline","mine":{"id":"2","username":"小焕"}}
       		var layimSendTo = json.mine;
       		// 更新好友列表在线离线状态
       		layim.setFriendStatus(layimSendTo.id, json.state);
       		// 提示一条信息
       		var msgHint = json.state==="online" ? "已上线" : "已离开";
       		layer.msg(layimSendTo.username+msgHint);
       		// -----#结束----------- 上线通知、离线通知 ----------------
       	}else if(messageType === "chatMessage"){
    
    
       		// -----#开始----------- 好友消息 ----------------
       		// 好友消息: {"type":"friendMessage","data":{"mine":{"username":"小升","avatar":"456.jpg","id":"1","mine":true,"content":"爱你"},"to":{"avatar":"123.jpg","id":"2","read":2,"sign":"我是签名","status":"online","username":"小焕","name":"小焕","type":"friend"}}}
       		var layimSendTo = json.data.mine;
           	// 设置消息
           	var obj = {
    
    
   					username: layimSendTo.username
   					,avatar: layimSendTo.avatar
   					,id: layimSendTo.id
   					,type: json.data.to.type
   					,content: layimSendTo.content
   				};
       		setTimeout(function(){
    
    
           		// 绑定一条消息
       			layim.getMessage(obj);
       		}, 1000);
       		// -----#结束----------- 好友消息 ----------------
       	}
	});
	/**
	 * 更多的消息类型,根据实际需要扩展(如)
	 * 上线通知、离线通知
	 * 好友消息、群聊消息
	 * 添加好友、添加群聊、回复申请好友、回复申请群聊、邀请群聊
	 * 删除好友、踢出群聊、退出群聊、解散群聊
	 */
});

(3). 测试发送消息,监听LayIM发送消息

// 监听发送消息
layim.on('sendMessage', function(data){
    
    
	// 推送一个消息
	websocket.send(JSON.stringify({
    
    
		    	type: '	friendMessage' // 随便定义,用于在服务端区分消息类型
		    	,data: data
		  }));
});

最后看看效果图

好友上线效果图
在这里插入图片描述
发送消息接收消息效果图
在这里插入图片描述

赠人玫瑰手留余香,若对您有帮助,来 点个赞呗!

猜你喜欢

转载自blog.csdn.net/ii950606/article/details/106276844