即时通讯-客户端格式(三)


前言

完成了服务端和客户端的部分展示,开始就行具体的功能实现,根据LayIM返回的信息格式进行代码编写,以及数据库的设计。

这是我成功后的页面

具体的实体类展示

  1. ResultJson.java(响应信息的格式)
  2. Mine.java(个人信息)
  3. FriendOrGroup.java(群组消息)
  4. ChatMsgBody.java(服务端发送至客户端的消息格式)

    代码的展示

    ResultJson.java返回格式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    /**
    * 响应信息
    */
    public class ResultJson {
    private static final long serialVersionUID = 1L;

    /**
    * 成功
    */
    private static final int SUCCESS_COCE = 0;
    /**
    * 失败
    */
    private static final int FAIL_COCE = 1;

    /**
    * 返回状态
    */
    @Getter
    @Setter
    private Integer code;

    /**
    * 返回的消息
    */
    @Getter
    @Setter
    private String msg;

    /**
    * 返回封装的数据
    */
    @Getter
    @Setter
    private Object data;


    /**
    * 失败结果
    * @param msg
    */
    public ResultJson (String msg){
    this(FAIL_COCE,msg,null);
    }

    /**
    * 成功结果,有返回值,无返回信息
    * @param data
    */
    public ResultJson(Object data){
    this(SUCCESS_COCE,"",data);
    }

    /**
    * 成功结果,有返回值,有返回信息
    * @param data
    */
    public ResultJson(String msg,Object data){
    this(SUCCESS_COCE,msg,data);
    }


    public ResultJson(Integer code, String msg, Object data){
    this.data = data;
    this.code = code;
    this.msg = msg;
    }




    /**
    * 成功结果,有返回值,有返回信息
    * */
    public static ResultJson success(String msg,Object data){
    return new ResultJson(msg,data);
    }
    /**
    * 成功结果,有返回值,无返回信息
    * */
    public static ResultJson success(Object data){
    return new ResultJson(data);
    }

    /**
    * 成功结果无返回值
    * */
    public static ResultJson success(){
    return success(null);
    }
    /**
    * 失败结果
    * */
    public static ResultJson error(String msg){
    return new ResultJson(msg);
    }
    /**
    * 失败结果
    * */
    public static ResultJson error(String msg,Object data){
    return new ResultJson(FAIL_COCE,msg, data);
    }

    }

Mine.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* 我的信息
*/

public class Mine extends BaseEntity<Mine> {
private static final long serialVersionUID = 1L;

/**
* 我的昵称
*/
@Getter
@Setter
private String username;
/**
* 在线状态
*/
@Getter
@Setter
private String status;
/**
* 签名
*/
@Getter
@Setter
private String sign;
/**
* 头像
*/
@Getter
@Setter
private String avatar;


/**
* 好友列表
*/
@Getter
@Setter
private FriendOrGroup friendOrGroup;

/**
* 用户表
*/
@Getter
@Setter
private User user;

}

FriendOrGroup.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
* 好友or群组
*/
public class FriendOrGroup extends BaseEntity<FriendOrGroup> {
private static final long serialVersionUID = 1L;
/**好友分组名
*
*/
@Getter
@Setter
private String groupname;
/**分组下的好友列表
*
*/
@Getter
@Setter
private List list;

/**
* 群组头像
*/
@Getter
@Setter
private String avatar;

/**
* 好友的父级编号
*/
@Getter
@Setter
private String parentIds;
/**
* 类型("0"为好友,"1"为群组)
*/
@Getter
@Setter
private String type;

@Getter
@Setter
private Mine mine;

@Getter
@Setter
private ImData imData;

public FriendOrGroup(){

}
public FriendOrGroup(Mine mine,String type){
this.mine=mine;
this.type=type;
}




}

ChatMsgBody.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* 服务端发送消息格式
*/
public class ChatMsgBody extends BaseBody {

/**
* 消息来源用户名
*/
@Getter
@Setter
private String username;

/**
* 消息来源用户头像
*/
@Getter
@Setter
private String avatar;

/**
* 消息的来源ID(如果是私聊,则是用户id,如果是群聊,则是群组id)
*/
@Getter
@Setter
private String id;
/**
* 聊天窗口来源类型,从发送消息传递的to里面获取
*/
@Getter
@Setter
private String type;

/**
* 消息id,可不传。除非你要对消息进行一些操作(如撤回)
*/
@Getter
@Setter
private String cid;
/**
* 是否我发送的消息,如果为true,则会显示在右方
*/
@Getter
@Setter
private boolean mine;
/**
* 消息的发送者id(比如群组中的某个消息发送者),可用于自动解决浏览器多窗口时的一些问题
*/
@Getter
@Setter
private String fromid;

}

数据格式的基础实体类就是以上这些,其中ChatMsgBody.java暂时可以不用管,因为它牵扯到数据的发送,暂时还未到那一步。
下面为Controller

ImController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
* LayIM基础信息
*/
@Controller
@RequestMapping("/im")
public class ImController {
@Autowired
private MineService mineService;
@Autowired
private FriendOrGroupService friendOrGroupService;
@Autowired
WebSocketProperties websocketProperties;
@Autowired
ImDataService imDataService;

/**
* 初始化数据
*/
@RequestMapping(value = "/getInit",method = RequestMethod.GET)
@ResponseBody
private ResultJson getInit() {
Mine mymine = this.getMineInfo(new Mine());
//将当前登录人员信息进行缓存,key为当前用户的id
CacheUtils.put(mymine.getId(),mymine);
//好友
List<FriendOrGroup> friends = this.getFriend(new FriendOrGroup(mymine,"0"));
//群组
List<FriendOrGroup> groups = this.getGroupInfo(mymine.getId());
Map map = new HashMap();
//当前登录人信息
map.put("mine", mymine);
//好友
map.put("friend", friends);
//群组
map.put("group",groups);
return ResultJson.success(map);

}

/**
* 获得个人信息
*/
private Mine getMineInfo(Mine mine){
User user= UserUtils.getUser();
Mine minea=mineService.getUserid(user.getId());
return minea;
}

/**
* 获得好友信息
*/
private List<FriendOrGroup> getFriend(FriendOrGroup friendOrGroup){
//获得当前登录用户的好友
List<FriendOrGroup> friendOrGroupList=friendOrGroupService.getMind(friendOrGroup);
//根据当前登录人员的id获得好友列表id
for(int i=0;i<friendOrGroupList.size();i++){
//获得当前用户好友列表的成员信息
friendOrGroupList.get(i).setList(getMineList(friendOrGroupList.get(i).getId()));
}
return friendOrGroupList;

}

/**
* 获得分组
* @param mid
* @return
*/
private List<FriendOrGroup> getGroupInfo(String mid){
//获得自己所创建的群
// List<FriendOrGroup> friendOrGroupList=friendOrGroupService.getMind(friendOrGroup);
//获得自己创建的群以及自己所加入的群
List<FriendOrGroup> GroupList=friendOrGroupService.getExistence(mid);
return GroupList;
}

/**
* 根据好友列表的id获得好友信息
* @return
* @throws Exception
*/
public List getMineList(String parentId){
List list=imDataService.getStringList(parentId);
List<Mine> mineList=mineService.getEntity(list);
return mineList;
}

/**
* 获得websocket的配置信息
* @return
* @throws Exception
*/
@RequestMapping(value = "/getImConfig",method = RequestMethod.GET)
@ResponseBody
public JsonResult getImConfig() {
String url;
User user= UserUtils.getUser();
String uid=user.getId();
String token = AESUtil.encrypt(uid);
Map map=new HashMap();

if(!websocketProperties.isDeploy()==true){
url=websocketProperties.getIp()+":"+websocketProperties.getPort();
}else {
url=websocketProperties.getProurl();
}
map.put("url",url);
map.put("token",token);

return JsonResult.success(map);
}

}

至此后端代码完成,下面就行前端页面的
chat.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html>
<head>
<meta charset="UTF-8">
<title>LayIM</title>
<link th:href="@{static/layui/css/layui.css}" rel="stylesheet" />
</head>
<body>
<div style=" position: absolute;right: 16px;">
<button type="button" value="退出" id="out">退出</button>
</div>

<script th:src="@{static/layui/layui.js}"></script>
<script th:src="@{static/js/jquery.min.js}"></script>
<script th:src="@{static/websocket/socket.js}"></script>
<script>

$('#out').on('click',function () {
$.ajax({
type:"POST",
url:"/logOut",
success: function (result) {
location.href = '/login';
},
error: function (error) {
}

})
});

layui.use('layim', function(layim){
var $ = layui.$
,admin = layui.admin
,element = layui.element
,layim = layui.layim
,router = layui.router();
//服务端的WebSocket链接信息
$.ajax({
url: '/im/getImConfig',
type: 'get',
success: function (result) {
var url=result.data.url;
var token=result.data.token;
createWebSocket("ws://"+url+"/"+token+"",eventHandle);
},
error: function ( errorThrown) {
}
});
//基础配置
layim.config({
//初始化接口
init: {
url: '/im/getInit'
,data: {}
},
title:"我的IM"
,notice:true
//查看群员接口
,members: {
url: ''
,data: {}
}
,uploadImage: {
url: 'upload/file' //(返回的数据格式见下文)
,type: '' //默认post
}
,uploadFile: {
url: 'upload/file' //(返回的数据格式见下文)
,type: '' //默认post
}
,isAudio: true //开启聊天工具栏音频
,isVideo: true //开启聊天工具栏视频

//扩展工具栏
,tool: [{
alias: 'code'
,title: '代码'
,icon: '&#xe64e;'
}]

//,brief: true //是否简约模式(若开启则不显示主面板)

//,title: 'WebIM' //自定义主面板最小化时的标题
//,right: '100px' //主面板相对浏览器右侧距离
//,minRight: '90px' //聊天面板最小化时相对浏览器右侧距离
,initSkin: '3.jpg' //1-5 设置初始背景
//,skin: ['aaa.jpg'] //新增皮肤
//,isfriend: false //是否开启好友
//,isgroup: false //是否开启群组
//,min: true //是否始终最小化主面板,默认false
//,notice: true //是否开启桌面消息提醒,默认false
//,voice: false //声音提醒,默认开启,声音文件为:default.mp3

,msgbox: '/layim/demo/msgbox.html' //消息盒子页面地址,若不开启,剔除该项即可
,find: '/layim/demo/find.html' //发现页面地址,若不开启,剔除该项即可
,chatLog: '/layim/demo/chatlog.html' //聊天记录页面地址,若不开启,剔除该项即可

});

var eventHandle = function (event) {
console.log("连接开启!");
};
socket.onopen = function(event) {
console.log("连接开启!");
};
socket.onclose = function(event) {
console.log("连接关闭!");
};
};
//监听在线状态的切换事件
layim.on('online', function(status){
layer.msg(status);
});

//监听签名修改
layim.on('sign', function(value){
layer.msg(value);
});
//监听自定义工具栏点击,以添加代码为例
layim.on('tool(code)', function(insert){
layer.prompt({
title: '插入代码 - 工具栏扩展示例'
,formType: 2
,shade: 0
}, function(text, index){
layer.close(index);
insert('[pre class=layui-code]' + text + '[/pre]'); //将内容插入到编辑器
});
});


//监听layim建立就绪
layim.on('ready', function(res){
console.log(res.mine);
layim.msgbox(5); //模拟消息盒子有新消息,实际使用时,一般是动态获得
});
//监听发送消息
layim.on('sendMessage', function(data){
console.log(data);
console.log("消息的发送");



});
//监听查看群员
layim.on('members', function(data){
console.log("监听查看群员");
});

//监听聊天窗口的切换
layim.on('chatChange', function(res){
var type = res.data.type;
console.log("监听聊天窗口的切换");

});



});
</script>
</body>
</html>

说明

关于socket.js网上有多,这是自己整理的仅供参考。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
var socket;
var reconnectflag = false;//避免重复连接
function createWebSocket(url,callbak) {
try {
if (!window.WebSocket) {
window.WebSocket = window.MozWebSocket;
}
if (window.WebSocket) {
socket = new WebSocket(url);
socket.binaryType = "arraybuffer";
callbak();
} else {
//当浏览器不支持websocket时 降级为http模式
var isClose =false;
window.onbeforeunload =function() {
if(!isClose){
return "";
}else{
return "";
}
}
window.onunload =function() {
if(!isClose){
Imwebserver.closeconnect();
}
}
dwr.engine.setActiveReverseAjax(true);
dwr.engine.setNotifyServerOnPageUnload(true);
dwr.engine.setErrorHandler(function(){
});
dwr.engine._errorHandler = function(message, ex) {
};
Imwebserver.serverconnect();

}
} catch (e) {
reconnect(url,callbak);
}
}


function reconnect(url,callbak) {
if(reconnectflag) return;
reconnectflag = true;
//没连接上会一直重连,设置延迟避免请求过多
setTimeout(function () {
createWebSocket(url,callbak);
reconnectflag = false;
}, 2000);
}

结束

-------------本文结束感谢您的阅读-------------