layim框架+websocket即时通讯功能

发布时间:2025-12-10 11:17:26 浏览次数:5

文章目录
一、layim即时通讯的认识
1.1、layim基础配置
1.1.1、初始化(init)
1.1.2、群员接口(members)
1.1.3、layim基础配置代码
二、WebSocket搭建
2.1、创建消息处理类
2.2、webSocket配置类
2.3、前台jsp页面建立websocket连接
四、附上完整jsp代码
1.4、效果图
那么上篇讲到spring集成websocket的简单使用,这篇则将使用layim框架实现websocket即时通讯功能
一、layim即时通讯的认识

官方文档 https://www.layui.com/doc/modules/layim.html
由于layim是官方收费的,这里不便附上layim源码

准备阶段
集成ssm框架,spring集成websocket
引入layim
1.1、layim基础配置
1.1.1、初始化(init)

需要从后台去找好友分组数据以及群的信息
需要返回的json数据格式为:

{"code": 0,"msg": "","data": {"mine": {"username": "纸飞机","id": "100000","status": "online","sign": "在深邃的编码世界,做一枚轻盈的纸飞机","avatar": "http://cdn.firstlinkapp.com/upload/2016_6/1465575923433_33812.jpg"},"friend": [{"groupname": "我心中的女神","id": 3,"online": 1,"list": [{"username": "林心如","id": "76543","avatar": "http://tp3.sinaimg.cn/1223762662/180/5741707953/0","sign": "我爱贤心"}]}}

创建ChatInfo、FriendInfo、GroupInfo类封装需要的json数据

public class ChatInfo {/*** 响应码*/private Integer code;/*** 响应消息*/private String msg;/*** 数据集合:接收mine(我的信息),friend(好友的信息)*/private Map data = new HashMap();....getter/setter} /*** 好友列表信息*/public class FriendInfo {//群名private String groupname;//群idprivate Integer id;//list集合接收多个群private List<EmpInfo> list;...getter/setter} /*** /群组列表信息*/public class GroupInfo {//群id(部门id)private Integer id;//群名private String groupname;//群头像private String avatar;...getter/setter}

controller层返回json数据

@RequestMapping("/findChatInfo")@ResponseBodypublic ChatInfo findChatInfo(Integer currentUserId) {List<FriendInfo> friendInfos = friendInfoService.findFriendInfos();EmpInfo mine = empInfoService.findOne(currentUserId);ChatInfo chatInfo = new ChatInfo();chatInfo.setCode(0);chatInfo.setMsg("ok");Map map = chatInfo.getData();map.put("mine", mine);map.put("friend", friendInfos);List<GroupInfo> list = Arrays.asList(groupInfoService.findGroupInfo(currentUserId));map.put("group", list);return chatInfo;}

显示结果为

1.1.2、群员接口(members)

需要从后台根据群id来查找群成员
返回的json数据格式如下

{"code": 0,"msg": "","data": {"owner": {"username": "贤心","id": "100001","avatar": "http://tp1.sinaimg.cn/1571889140/180/40030060651/1","sign": "这些都是测试数据,实际使用请严格按照该格式返回"},"members": 12,"list": [{"username": "贤心","id": "100001","avatar": "http://tp1.sinaimg.cn/1571889140/180/40030060651/1","sign": "这些都是测试数据,实际使用请严格按照该格式返回"}]}}

创建EmpInfo类封装群成员信息封装需要的json数据

/*** 成员信息*/public class EmpInfo{//消息的来源idprivate Integer id;//消息接收方的idprivate Integer toId;private String username;private String status;//签名private String sign;//头像private String avatar;//登陆状态private Integer isLogin;//消息内容private String content;//消息的来源类型private String type;//是否是本人private Boolean mine = false;//发送消息的时间private Date timestamp = new Date();//历史消息时间private Date historyTime = new Date();...getter/setter}

controller层返回json数据

@RequestMapping("/getMembers")@ResponseBodypublic String getMembers(Integer id) {PageTable<Map<String, Object>> pageTable = new PageTable<Map<String, Object>>();//查询当前用户所在群的所有人员Map groupEmps = groupInfoService.findGroupEmps(id);//设置codepageTable.setCode(WebConstant.PAGESUCCESSCODE);//设置msgpageTable.setMsg("获取成功");//设置datapageTable.setData(groupEmps);//转成字符串形式返回给前台return responseAPI.getJsonString(pageTable);}

findGroupEmps方法代码

@Overridepublic Map findGroupEmps(Integer groupId) {Map map = new HashMap();map.put("owner", "");//查询当前用户所在群成员的人数--value类型 Integermap.put("members", groupInfoDao.findGroupEmpsNum(groupId));//查询当前用户所在群的所有人员--value类型 List<EmpInfo>map.put("list", groupInfoDao.findGroupEmps(groupId));return map;}

效果图如下

1.1.3、layim基础配置代码

layim.config({//初始化接口init: {url: '/chatController/findChatInfo?currentUserId=' +${currentUserId} //从后台去找好友分组数据, data: {}}, min: true//查看群员接口, members: {url: '/chatController/getMembers', data: {}}//上传图片接口, uploadImage: {url: '/upload/image' //(返回的数据格式见下文), type: '' //默认post}//上传文件接口, uploadFile: {url: '/upload/file' //(返回的数据格式见下文), type: '' //默认post}, isAudio: true //开启聊天工具栏音频, isVideo: true //开启聊天工具栏视频//扩展工具栏, tool: [{alias: 'code', title: '代码', icon: '&#xe64e;'}]//,brief: true //是否简约模式(若开启则不显示主面板), title: xxx //自定义主面板最小化时的标题//,right: '100px' //主面板相对浏览器右侧距离//,minRight: '90px' //聊天面板最小化时相对浏览器右侧距离, initSkin: '5.jpg' //1-5 设置初始背景//,skin: ['aaa.jpg'] //新增皮肤// ,isfriend: false //是否开启好友//,isgroup: false //是否开启群组//,min: true //是否始终最小化主面板,默认false, notice: true //是否开启桌面消息提醒,默认false//,voice: false //声音提醒,默认开启,声音文件为:default.mp3, msgbox: layui.cache.dir + 'css/modules/layim/html/msgbox.html' //消息盒子页面地址,若不开启,剔除该项即可, find: layui.cache.dir + 'css/modules/layim/html/find.html' //发现页面地址,若不开启,剔除该项即可, chatLog: "/msg/showHistoryMsg" //聊天记录页面地址,若不开启,剔除该项即可});

二、WebSocket搭建
与前篇基本相同

2.1、创建消息处理类

//消息处理类@Componentpublic class MyHandler extends TextWebSocketHandler {// 在线用户列表public static final Map<Integer, WebSocketSession> userSocketSessionMap = new HashMap<Integer, WebSocketSession>();// 用户连接成功 就被调用@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {//获取传来的登录用户的idString idstr = session.getUri().toString().split("=")[1];int id = Integer.parseInt(idstr);System.err.println("用户连接成功");//保存对应的WebSocketSessionuserSocketSessionMap.put(id, session);}// 消息处理方法@Overridepublic void handleTextMessage(WebSocketSession session, TextMessage message) {try {ObjectMapper objectMapper = new ObjectMapper();EmpInfo friendInfo = objectMapper.readValue(message.getPayload(), EmpInfo.class);//session.sendMessage(message);//发送给当前人if(friendInfo.getType().equals("friend")) {sendMessageToUser(message,friendInfo );}else if(friendInfo.getType().equals("group")) {sendMessagesToUsers(message,friendInfo);//给所有的用户发送消息}}catch (Exception e){e.printStackTrace();}}/*** 给所有的用户发送消息*/public void sendMessagesToUsers(TextMessage message,EmpInfo friendInfo) {Set<Integer> clientIds = userSocketSessionMap.keySet();WebSocketSession session = null;for (Integer clientId : clientIds) {session = userSocketSessionMap.get(clientId);System.out.println(clientId);try {if(session.isOpen()&&!friendInfo.getId().equals(clientId)){session.sendMessage(message);}} catch (IOException e) {e.printStackTrace();}}}/*** 给所有的用户发送消息*/public void sendMessageToUser(TextMessage message,EmpInfo friendInfo) throws IOException {Set<Integer> clientIds = userSocketSessionMap.keySet();WebSocketSession session = null;for (Integer clientId : clientIds) {session = userSocketSessionMap.get(clientId);System.out.println(session);try {if(session.isOpen()&&friendInfo.getToId().equals(clientId)){System.out.println("回复消息");session.sendMessage(message);}} catch (IOException e) {e.printStackTrace();}}}//用户退出后的处理,退出之后,要将用户信息从websocket的session中remove掉,这样用户就处于离线状态了,也不会占用系统资源@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {try {if(session.isOpen()){session.close();}userSocketSessionMap.remove(session.getId());System.out.println("退出系统");}catch (Exception e){System.out.println("用户非正常关闭");}}}

2.2、webSocket配置类

@Configuration@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(myHandler(), "/myHandler");}@Beanpublic WebSocketHandler myHandler() {return new MyHandler();}}

2.3、前台jsp页面建立websocket连接

var socket = null;//连接websocket的ip地址var ip = "输入你的ip地址";//比如localhost//动态修改查var im = {init: function () {if ('WebSocket' in window) {//var socketUrl = 'ws://localhost:80/myHandler?myid=' +${currentUserId};var socketUrl = 'ws://'+ip+'/myHandler?myid='+${currentUserId};socket = new WebSocket(socketUrl);im.startListener();} else {alert('当前浏览器不支持WebSocket功能,请更换浏览器访问。');}},startListener: function () {if (socket) {// 连接发生错误的回调方法socket.onerror = function () {console.log("通讯连接失败!");};// 连接成功建立的回调方法socket.onopen = function (event) {console.log("通讯连接成功");}// 接收到消息的回调方法socket.onmessage = function (event) {console.log("通讯接收到消息");im.handleMessage(event.data);}// 连接关闭的回调方法socket.onclose = function () {console.log("通讯关闭连接!!");}}},handleMessage: function (msg) {msg = JSON.parse(msg)//如果是群消息,转换一下id,返回群id的的字段必须是idif (msg.type == "group") {var temId = msg.id;msg.id = msg.toId;msg.toId = temId;}//console.log(msg)layim.getMessage(msg);}};im.init();

四、附上完整jsp代码
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>

LayIM 3.x PC版本地演示 <link rel="stylesheet" href="/lib/layMI/css/layui.css"><style></style>

注意:必须在登录的时候传一个登录用户的id到消息处理类中作为用户列表的key

MyHandler类

// 用户连接成功 就被调用@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {//获取传来的登录用户的idString idstr = session.getUri().toString().split("=")[1];int id = Integer.parseInt(idstr);System.err.println("用户连接成功");//保存对应的WebSocketSessionuserSocketSessionMap.put(id, session);}

1.4、效果图
谷歌浏览

火狐浏览器

需要做网站?需要网络推广?欢迎咨询客户经理 13272073477