跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

layim框架+websocket即时通讯功能

文章目录 一、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; //群id private Integer id; //list集合接收多个群 private List list; ... getter/setter }

/**

* /群组列表信息 */ public class GroupInfo { //群id(部门id) private Integer id; //群名 private String groupname; //群头像 private String avatar; ... getter/setter }

controller层返回json数据

@RequestMapping("/findChatInfo")

@ResponseBody public ChatInfo findChatInfo(Integer currentUserId) { List 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 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{ //消息的来源id private Integer id; //消息接收方的id private 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")

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

findGroupEmps方法代码

@Override

public Map findGroupEmps(Integer groupId) { Map map = new HashMap(); map.put("owner", ""); //查询当前用户所在群成员的人数--value类型 Integer map.put("members", groupInfoDao.findGroupEmpsNum(groupId)); //查询当前用户所在群的所有人员--value类型 List 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: '' }]

//,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、创建消息处理类

//消息处理类

@Component public class MyHandler extends TextWebSocketHandler { // 在线用户列表 public static final Map userSocketSessionMap = new HashMap();

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

// 消息处理方法 @Override public 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 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 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掉,这样用户就处于离线状态了,也不会占用系统资源 @Override public 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

@EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer {

@Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/myHandler"); }

@Bean public 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的的字段必须是id if (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版本地演示

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

// 用户连接成功 就被调用

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

1.4、效果图 谷歌浏览

火狐浏览器

相关文章