一. 认识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
}));
});
最后看看效果图
好友上线效果图
发送消息接收消息效果图
赠人玫瑰手留余香,若对您有帮助,来
点个赞
呗!