调整类名称,新增websocket状态与处理逻辑

This commit is contained in:
WenG 2021-09-14 13:59:57 +08:00
parent 9753f9f737
commit baa200761a
10 changed files with 117 additions and 162 deletions

View File

@ -15,30 +15,37 @@ public enum ClientSocketTypeEnum {
REGISTER(1000, "注册消息body 为 RegisterBody 的 JSON 字符串"),
MESSAGE(2001, "文本消息"),
GROUP_MESSAGE(2002, "群发文本消息"),
MESSAGE_HREF(2002, "链接消息"),
MESSAGE_IMAGE(2003, "图片消息"),
MESSAGE_FILE(2004, "文件消息"),
MESSAGE_AUDIO(2005, "音频消息"),
MESSAGE_VIDEO(2006, "视频消息"),
SYSTEM_MESSAGE(3001, "系统消息"),
SYSTEM_GROUP_MESSAGE(3002, "系统群发问呢消息"),
SYSTEM_TARGET_MESSAGE(3003, "系统目标消息"),
MESSAGE_GROUP(2101, "群发文本消息"),
MESSAGE_GROUP_HREF(2102, "群发链接消息"),
MESSAGE_GROUP_IMAGE(2103, "群发图片消息"),
MESSAGE_GROUP_FILE(2104, "群发文件消息"),
MESSAGE_GROUP_AUDIO(2105, "群发音频消息"),
MESSAGE_GROUP_VIDEO(2106, "群发视频消息"),
LAYIM_HREF_MESSAGE(4001, "LAYIM 连接消息"),
LAYIM_IMAGE_MESSAGE(4002, "LAYIM 图片消息"),
LAYIM_FILE_MESSAGE(4003, "LAYIM 文件消息"),
LAYIM_AUDIO_MESSAGE(4004, "LAYIM 音频消息"),
LAYIM_VIDEO_MESSAGE(4005, "LAYIM 视频消息"),
MESSAGE_SYSTEM(2201, "系统消息"),
MESSAGE_SYSTEM_GROUP(2202, "系统群发消息"),
MESSAGE_SYSTEM_TARGET(2203, "系统目标消息"),
NOTICE(5001, "通知"),
NOTICE_GROUP_MESSAGE(5002, "群通知"),
NOTICE_TARGET_MESSAGE(5003, "目标通知用于APP打开特定页面"),
UPDATE_SERVICE_HANDLE_STATUS(5004, "更新业务的处理状态"),
NOTICE(3001, "通知"),
NOTICE_GROUP_MESSAGE(3002, "群通知"),
NOTICE_TARGET_MESSAGE(3003, "目标通知用于APP打开特定页面"),
UPDATE_SERVICE_HANDLE_STATUS(3004, "更新业务的处理状态"),
SEARCH_ONLINE_USER(6001, "查询全部在线用户body 为查询用户的 userId"),
SEARCH_ONLINE_USER_FRIEND(6002, "查询朋友在线用户body 为查询用户的 userId"),
SEARCH_COUNT_NEED_TO_DEALT_WITH(6003, "查询全部待办总数"),
SEARCH_ONLINE_USER(4001, "查询全部在线用户body 为查询用户的 userId"),
SEARCH_ONLINE_USER_FRIEND(4002, "查询朋友在线用户body 为查询用户的 userId"),
SEARCH_COUNT_NEED_TO_DEALT_WITH(4003, "查询全部待办总数"),
SEND_STATUS(1100, "消息发送状态body 为 BaseResult 的 JSON 字符串"),
SEND_STATUS_ONLINE(1101, "发送在线状态body 为 在线用户的ID JSONArray 字符串"),
SEND_STATUS_OFFLINE(1102, "发送离线状态body 为 离线用户的ID JSONArray 字符串");
STATUS_SEND(9001, "消息发送状态body 为 BaseResult 的 JSON 字符串"),
STATUS_SEND_ONLINE(9002, "发送在线状态body 为 在线用户的ID JSONArray 字符串"),
STATUS_SEND_OFFLINE(9003, "发送离线状态body 为 离线用户的ID JSONArray 字符串"),
STATUS_RECEIVED(9101,"消息接受状态");
private int value;
private String summary;

View File

@ -10,22 +10,22 @@ package ink.wgink.module.instantmessage.websocket.enums;
* @Date: 2021/1/14 12:59 下午
* @Version: 1.0
*/
public enum SendStatusEnum {
public enum StatusEnum {
SUCCESS(200, "成功"),
FAILED(400, "失败"),
MESSAGE_ERROR(401, "消息错误"),
SESSION_ERROR(402, "会话错误"),
CLIENT_SESSION_ERROR(403, "客户端会话错误"),
TYPE_ERROR(405, "类型错误"),
BODY_ERROR(406, "消息体错误"),
FROM_ERROR(407, "来源错误"),
TO_ERROR(408, "接受用户错误");
TYPE_ERROR(404, "类型错误"),
BODY_ERROR(405, "消息体错误"),
FROM_ERROR(406, "来源错误"),
TO_ERROR(407, "接受用户错误"),
RECEIVE_ERROR(408, "接收错误");
private int value;
private String summary;
SendStatusEnum(int value, String summary) {
StatusEnum(int value, String summary) {
this.value = value;
this.summary = summary;
}

View File

@ -1,33 +0,0 @@
package ink.wgink.module.instantmessage.websocket.exception;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: AppException
* @Description: App异常
* @Author: wanggeng
* @Date: 2021/1/14 12:23 下午
* @Version: 1.0
*/
public class AppSessionException extends SessionException {
public AppSessionException() {
}
public AppSessionException(String message) {
super(message);
}
public AppSessionException(String message, Throwable cause) {
super(message, cause);
}
public AppSessionException(Throwable cause) {
super(cause);
}
public AppSessionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -10,23 +10,23 @@ package ink.wgink.module.instantmessage.websocket.exception;
* @Date: 2021/1/14 12:14 下午
* @Version: 1.0
*/
public class TypeErrorException extends BaseSocketException {
public TypeErrorException() {
public class TypeException extends BaseSocketException {
public TypeException() {
}
public TypeErrorException(String message) {
public TypeException(String message) {
super(message);
}
public TypeErrorException(String message, Throwable cause) {
public TypeException(String message, Throwable cause) {
super(message, cause);
}
public TypeErrorException(Throwable cause) {
public TypeException(Throwable cause) {
super(cause);
}
public TypeErrorException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
public TypeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -10,24 +10,24 @@ package ink.wgink.module.instantmessage.websocket.exception;
* @Date: 2021/1/14 12:51 下午
* @Version: 1.0
*/
public class UserErrorException extends BaseSocketException {
public class UserException extends BaseSocketException {
public UserErrorException() {
public UserException() {
}
public UserErrorException(String message) {
public UserException(String message) {
super(message);
}
public UserErrorException(String message, Throwable cause) {
public UserException(String message, Throwable cause) {
super(message, cause);
}
public UserErrorException(Throwable cause) {
public UserException(Throwable cause) {
super(cause);
}
public UserErrorException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
public UserException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -1,33 +0,0 @@
package ink.wgink.module.instantmessage.websocket.exception;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: UserException
* @Description: 用户异常
* @Author: wanggeng
* @Date: 2021/1/14 12:21 下午
* @Version: 1.0
*/
public class UserSessionException extends SessionException {
public UserSessionException() {
}
public UserSessionException(String message) {
super(message);
}
public UserSessionException(String message, Throwable cause) {
super(message, cause);
}
public UserSessionException(Throwable cause) {
super(cause);
}
public UserSessionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -3,14 +3,14 @@ package ink.wgink.module.instantmessage.websocket.handler.text;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import ink.wgink.module.instantmessage.websocket.enums.ClientSocketTypeEnum;
import ink.wgink.module.instantmessage.websocket.enums.SendStatusEnum;
import ink.wgink.module.instantmessage.websocket.enums.StatusEnum;
import ink.wgink.module.instantmessage.websocket.exception.*;
import ink.wgink.module.instantmessage.websocket.manager.WebSocketChannelManager;
import ink.wgink.module.instantmessage.websocket.pojo.WebSocketClientMessage;
import ink.wgink.module.instantmessage.websocket.pojo.WebSocketSession;
import ink.wgink.module.instantmessage.websocket.pojo.body.IdsBody;
import ink.wgink.module.instantmessage.websocket.pojo.body.RegisterBody;
import ink.wgink.module.instantmessage.websocket.pojo.body.SendStatusBody;
import ink.wgink.module.instantmessage.websocket.pojo.body.StatusBody;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
@ -33,49 +33,53 @@ public class WebSocketTextHandler {
public void handler(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) {
WebSocketClientMessage clientSocketMessage = null;
SendStatusBody sendStatusBody = null;
StatusBody statusBody = null;
try {
clientSocketMessage = JSONObject.parseObject(textWebSocketFrame.text(), WebSocketClientMessage.class);
if (clientSocketMessage.getType() == null) {
throw new TypeErrorException("Type类型不能为空");
throw new TypeException("Type类型不能为空");
}
if (StringUtils.isBlank(clientSocketMessage.getBody())) {
throw new BodyException("Body主体不能为空");
}
if (ClientSocketTypeEnum.REGISTER.getValue() == clientSocketMessage.getType()) {
// 客户端注册消息
sendStatusBody = clientRegisterSession(ctx.channel(), clientSocketMessage);
statusBody = clientRegisterSession(ctx.channel(), clientSocketMessage);
} else if (ClientSocketTypeEnum.MESSAGE.getValue() == clientSocketMessage.getType()) {
// 文本消息
sendText(ctx.channel(), clientSocketMessage);
} else if (ClientSocketTypeEnum.GROUP_MESSAGE.getValue() == clientSocketMessage.getType()) {
} else if (ClientSocketTypeEnum.MESSAGE_GROUP.getValue() == clientSocketMessage.getType()) {
// 群发消息
sendGroupText(ctx.channel(), clientSocketMessage);
} else if (ClientSocketTypeEnum.SEARCH_ONLINE_USER.getValue() == clientSocketMessage.getType()) {
// 用户在线状态
listOnlineUser(ctx.channel(), clientSocketMessage);
} else if (ClientSocketTypeEnum.STATUS_RECEIVED.getValue() == clientSocketMessage.getType()) {
// 消息接收状态
} else {
throw new TypeException("请求类型错误");
}
} catch (SessionException e) {
// 没有登录时返回内容关闭连接
sendStatusBody = new SendStatusBody(SendStatusEnum.SESSION_ERROR.getValue(), SendStatusEnum.SESSION_ERROR, e.getMessage());
clientSocketMessage.setBody(JSONObject.toJSONString(sendStatusBody));
statusBody = new StatusBody(StatusEnum.SESSION_ERROR.getValue(), StatusEnum.SESSION_ERROR, e.getMessage());
clientSocketMessage.setBody(JSONObject.toJSONString(statusBody));
WebSocketChannelManager.getInstance().sendText(ctx.channel(), clientSocketMessage);
ctx.close();
} catch (TypeErrorException e) {
sendStatusBody = new SendStatusBody(SendStatusEnum.SESSION_ERROR.getValue(), SendStatusEnum.SESSION_ERROR, e.getMessage());
} catch (TypeException e) {
statusBody = new StatusBody(StatusEnum.TYPE_ERROR.getValue(), StatusEnum.SESSION_ERROR, e.getMessage());
} catch (BodyException e) {
sendStatusBody = new SendStatusBody(SendStatusEnum.SESSION_ERROR.getValue(), SendStatusEnum.SESSION_ERROR, e.getMessage());
} catch (UserErrorException e) {
sendStatusBody = new SendStatusBody(SendStatusEnum.SESSION_ERROR.getValue(), SendStatusEnum.SESSION_ERROR, e.getMessage());
statusBody = new StatusBody(StatusEnum.BODY_ERROR.getValue(), StatusEnum.SESSION_ERROR, e.getMessage());
} catch (UserException e) {
statusBody = new StatusBody(StatusEnum.SESSION_ERROR.getValue(), StatusEnum.SESSION_ERROR, e.getMessage());
} catch (JSONException e) {
clientSocketMessage = new WebSocketClientMessage();
clientSocketMessage.setSystem(true);
clientSocketMessage.setType(ClientSocketTypeEnum.SYSTEM_MESSAGE.getValue());
clientSocketMessage.setType(ClientSocketTypeEnum.MESSAGE_SYSTEM.getValue());
clientSocketMessage.setFrom(WebSocketChannelManager.FORM_SYSTEM);
sendStatusBody = new SendStatusBody(SendStatusEnum.TO_ERROR.getValue(), SendStatusEnum.MESSAGE_ERROR, e.getMessage());
statusBody = new StatusBody(StatusEnum.TO_ERROR.getValue(), StatusEnum.MESSAGE_ERROR, e.getMessage());
} finally {
if (sendStatusBody != null && ctx.channel().isOpen()) {
clientSocketMessage.setBody(JSONObject.toJSONString(sendStatusBody));
if (statusBody != null && ctx.channel().isOpen()) {
clientSocketMessage.setBody(JSONObject.toJSONString(statusBody));
WebSocketChannelManager.getInstance().sendText(ctx.channel(), clientSocketMessage);
}
}
@ -89,11 +93,11 @@ public class WebSocketTextHandler {
* @return
* @throws SessionException
*/
private SendStatusBody clientRegisterSession(Channel channel, WebSocketClientMessage clientSocketMessage) throws SessionException {
private StatusBody clientRegisterSession(Channel channel, WebSocketClientMessage clientSocketMessage) throws SessionException {
RegisterBody registerBody = JSONObject.parseObject(clientSocketMessage.getBody(), RegisterBody.class);
// 更新通道
WebSocketChannelManager.getInstance().addChannel(registerBody.getSessionId(), clientSocketMessage.getFrom(), channel);
return new SendStatusBody(SendStatusEnum.SUCCESS.getValue(), SendStatusEnum.SUCCESS, "OK");
return new StatusBody(StatusEnum.SUCCESS.getValue(), StatusEnum.SUCCESS, "OK");
}
/**
@ -101,11 +105,11 @@ public class WebSocketTextHandler {
*
* @param channel 通道
* @param webSocketClientMessage 客户端消息
* @throws UserErrorException
* @throws UserException
*/
private void sendText(Channel channel, WebSocketClientMessage webSocketClientMessage) throws UserErrorException, UserSessionException {
private void sendText(Channel channel, WebSocketClientMessage webSocketClientMessage) throws UserException {
if (StringUtils.isBlank(webSocketClientMessage.getTo())) {
throw new UserErrorException("To 值不能为空");
throw new UserException("To 值不能为空");
}
webSocketClientMessage.setSystem(false);
List<WebSocketSession> webSocketSessions = WebSocketChannelManager.getInstance().listOnlineUser(webSocketClientMessage.getTo());
@ -123,21 +127,20 @@ public class WebSocketTextHandler {
/**
* 群发文字消息
*
* @param channel 通道
* @param fromChannel 发送通道
* @param webSocketClientMessage 客户端消息
* @throws UserErrorException
* @throws UserSessionException
* @throws UserException
*/
private void sendGroupText(Channel channel, WebSocketClientMessage webSocketClientMessage) throws UserErrorException, UserSessionException {
private void sendGroupText(Channel fromChannel, WebSocketClientMessage webSocketClientMessage) throws UserException {
if (StringUtils.isBlank(webSocketClientMessage.getTo())) {
throw new UserErrorException("To 值不能为空");
throw new UserException("To 值不能为空");
}
webSocketClientMessage.setSystem(false);
List<String> toUserIds = new ArrayList<>(Sets.newHashSet(webSocketClientMessage.getTo().split(",")));
List<WebSocketSession> webSocketSessions = WebSocketChannelManager.getInstance().listOnlineUser(toUserIds);
// 返回失败结果
if (webSocketSessions.isEmpty()) {
sendTextFailed(channel, webSocketClientMessage, "无用户在线");
sendTextFailed(fromChannel, webSocketClientMessage, "无用户在线");
return;
}
// 发送消息
@ -149,17 +152,16 @@ public class WebSocketTextHandler {
/**
* 在线用户列表
*
* @param channel 通道
* @param fromChannel 通道
* @param webSocketClientMessage 消息体
* @throws UserSessionException
* @throws UserErrorException
* @throws UserException
*/
private void listOnlineUser(Channel channel, WebSocketClientMessage webSocketClientMessage) throws UserSessionException, UserErrorException {
private void listOnlineUser(Channel fromChannel, WebSocketClientMessage webSocketClientMessage) throws UserException {
webSocketClientMessage.setSystem(true);
webSocketClientMessage.setTo(webSocketClientMessage.getFrom());
IdsBody idsBody = JSONObject.parseObject(webSocketClientMessage.getBody(), IdsBody.class);
if (idsBody.getIds() == null || idsBody.getIds().isEmpty()) {
sendTextFailed(channel, webSocketClientMessage, "用户ID列表为空");
sendTextFailed(fromChannel, webSocketClientMessage, "用户ID列表为空");
return;
}
List<WebSocketSession> webSocketSessions = WebSocketChannelManager.getInstance().listOnlineUser(idsBody.getIds());
@ -169,21 +171,21 @@ public class WebSocketTextHandler {
}
idsBody = new IdsBody();
idsBody.setIds(new ArrayList<>(idSets));
webSocketClientMessage.setType(ClientSocketTypeEnum.SEND_STATUS_ONLINE.getValue());
webSocketClientMessage.setType(ClientSocketTypeEnum.STATUS_SEND_ONLINE.getValue());
webSocketClientMessage.setBody(JSONObject.toJSONString(idsBody));
sendText(channel, webSocketClientMessage);
sendText(fromChannel, webSocketClientMessage);
}
/**
* 发送文本失败
* 发送失败内容
*
* @param fromChannel 来源通道
* @param webSocketClientMessage webSocket客户端消息
* @param msg
*/
public static void sendTextFailed(Channel fromChannel, WebSocketClientMessage webSocketClientMessage, String msg) {
webSocketClientMessage.setType(ClientSocketTypeEnum.SEND_STATUS.getValue());
webSocketClientMessage.setBody(JSONObject.toJSONString(new SendStatusBody(SendStatusEnum.FAILED.getValue(), SendStatusEnum.FAILED, msg)));
webSocketClientMessage.setType(ClientSocketTypeEnum.STATUS_SEND.getValue());
webSocketClientMessage.setBody(JSONObject.toJSONString(new StatusBody(StatusEnum.FAILED.getValue(), StatusEnum.FAILED, msg)));
WebSocketChannelManager.getInstance().sendText(fromChannel, webSocketClientMessage);
}

View File

@ -229,15 +229,15 @@ public class WebSocketChannelManager {
/**
* 单发
*
* @param channel
* @param webSocketClientMessage
* @param toChannel 接收人通道
* @param webSocketClientMessage 发送内容
*/
public void sendText(Channel channel, WebSocketClientMessage webSocketClientMessage) {
if (channel == null || !channel.isOpen() || !channel.isActive()) {
public void sendText(Channel toChannel, WebSocketClientMessage webSocketClientMessage) {
if (toChannel == null || !toChannel.isOpen() || !toChannel.isActive()) {
return;
}
TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(JSONObject.toJSONString(webSocketClientMessage));
channel.writeAndFlush(textWebSocketFrame);
toChannel.writeAndFlush(textWebSocketFrame);
}
/**

View File

@ -1,6 +1,6 @@
package ink.wgink.module.instantmessage.websocket.pojo.body;
import ink.wgink.module.instantmessage.websocket.enums.SendStatusEnum;
import ink.wgink.module.instantmessage.websocket.enums.StatusEnum;
/**
* @ClassName: SendStatusBody
@ -9,15 +9,15 @@ import ink.wgink.module.instantmessage.websocket.enums.SendStatusEnum;
* @Date: 2021/9/12 10:08 下午
* @Version: 1.0
*/
public class SendStatusBody {
public class StatusBody {
private Integer code;
private SendStatusEnum status;
private StatusEnum status;
private String msg;
public SendStatusBody() {
public StatusBody() {
}
public SendStatusBody(int code, SendStatusEnum status, String msg) {
public StatusBody(int code, StatusEnum status, String msg) {
this.code = code;
this.status = status;
this.msg = msg;
@ -31,11 +31,11 @@ public class SendStatusBody {
this.code = code;
}
public SendStatusEnum getStatus() {
public StatusEnum getStatus() {
return status;
}
public void setStatus(SendStatusEnum status) {
public void setStatus(StatusEnum status) {
this.status = status;
}

View File

@ -30,7 +30,7 @@
<input id="currentUserId" class="websocket-input" type="hidden" th:value="${currentUserId}"/>
</div>
<div class="websocket-line">
接收用户ID <input id="toUserId" class="websocket-input" type="text" style="width: 198px;" placeholder="输入接收用户ID"/>
接收用户ID <input id="toUserId" class="websocket-input" type="text" style="width: 196px;" placeholder="输入接收用户ID"/>
</div>
<div class="websocket-line">
<input id="clientName" class="websocket-input" type="text" placeholder="请输入客户端名称"/>
@ -41,12 +41,14 @@
状态:<span id="loginStatus">未登录</span>
</div>
<div id="websocketHistoryBox" class="websocket-history-box">
<!--
<div class="receive-msg-box">
<div class="message receive-msg">收到</div>
</div>
<div class="send-msg-box">
<span class="send-status" title="用户不存在">!</span> <div class="message send-msg">发送</div>
</div>
-->
</div>
<div id="sendBox" class="websocket-box" style="display: none;">
<input type="text" id="message" class="websocket-input" placeholder="请输入发送内容"/>
@ -62,7 +64,7 @@
function register(sessionId) {
var registBody = {
id: new Date().getTime(),
type: 100,
type: 1000,
from: $('#currentUserId').val(),
to: $('#currentUserId').val(),
body: {
@ -93,21 +95,31 @@
//接收到消息的回调方法
websocket.onmessage = function (event) {
var data = JSON.parse(event.data);
// 注册
if(data.type === 100) {
if(data.type === 1000) {
// 注册
var body = JSON.parse(data.body);
if(body.code === 200) {
$('#loginStatus').html('已连接');
} else {
$('#loginStatus').html(body.msg);
}
} else if(data.type === 101) {
} else if(data.type === 2001) {
// 文本消息
var body = data.body;
$('#websocketHistoryBox').append('<div class="receive-msg-box"><div class="message receive-msg">'+ body +'</div></div>');
autoScrollBottom();
} else if(data.type === 1100) {
} else if(data.type === 9001) {
// 发送状态
var body = JSON.parse(data.body);
$('#'+ data.id).before('<span class="send-status" title="'+ body.msg +'">!</span> ')
if(body.code != 200) {
$('#'+ data.id).before('<span class="send-status" title="'+ body.msg +'">!</span> ')
}
} else if(data.type === 9101) {
// 接收状态
var body = JSON.parse(data.body);
if(body.code != 200) {
$('#'+ data.id).before('<span class="send-status" title="'+ body.msg +'">!</span> ')
}
}
}
//连接关闭的回调方法
@ -154,7 +166,7 @@
var sendId = new Date().getTime();
var sendBody = {
id: sendId,
type: 101,
type: 2001,
from: $('#currentUserId').val(),
to: $('#toUserId').val(),
body: $('#message').val()