package com.example.server.netty;
import com.example.server.biz.UserBiz;
import com.example.server.utils.JsonUtils;
import com.example.server.utils.SpringUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* 客户端消息处理器
*
* @author xiangLong
* @date 2019年5月31日 上午10:36:44
*/
@Slf4j
public class ChatNewHandler extends SimpleChannelInboundHandler<ByteBuf> {
// 用于记录和管理所有客户端的channle,可以用redis取代
public static ChannelGroup users = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
/**
* 当客户端连接服务端之后(打开连接)
* 获取客户端的channle,并且放到ChannelGroup中去进行管理
*/
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("add.....");
users.add(ctx.channel());
}
/**
* 处理前端传过来的数据
* 可能是连接成功通知:服务端需要将uid和channel绑定
* 具体聊天消息:服务端需要把消息转发给接收方,此时手机签收状态为未签收
* 手机签收消息成功通知(用户读没读不一定,只是手机接到消息了):服务端更改数据库记录为已签收
* 心跳通知:无需处理
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
System.out.println("read..........");
// 获取客户端传输过来的消息
String content = msg.toString(Charset.forName("GBK"));
Channel currentChannel = ctx.channel();
// 1. 获取客户端发来的消息
DataContent dataContent = JsonUtils.jsonToPojo(content, DataContent.class);
Integer action = dataContent.getAction();
// 2. 判断消息类型,根据不同的类型来处理不同的业务
if (action == MsgActionEnum.CONNECT.type) {
// 2.1当websocket 第一次open的时候,初始化channel,把用户的channel和userid关联起来
String senderId = dataContent.getChatMsg().getSenderId();
UserChannelRel.put(senderId, currentChannel);
// 测试
for (Channel c : users) {
System.out.println(c.id().asLongText());
}
UserChannelRel.output();
} else if (action == MsgActionEnum.CHAT.type) {
// 2.2 聊天类型的消息,把聊天记录保存到数据库,同时标记消息的签收状态[未签收]
ChatMsg chatMsg = dataContent.getChatMsg();
chatMsg.setFlag(0);
String msgText = chatMsg.getMsg();
String receiverId = chatMsg.getReceiverId();
String senderId = chatMsg.getSenderId();
// 保存消息到数据库,并且标记为 未签收
// 在handler中无法使用依赖注入的方式获取ioc容器中的service对象,需要直接从ioc容器中取
UserBiz userBiz = (UserBiz) SpringUtil.getBean("userBiz");
String msgId = userBiz.saveMsg(chatMsg);
chatMsg.setMsgId(msgId);
DataContent dataContentMsg = new DataContent();
dataContentMsg.setChatMsg(chatMsg);
// 发送消息
// 从全局用户Channel关系中获取接受方的channel
Channel receiverChannel = UserChannelRel.get(receiverId);
if (receiverChannel == null) {
// TODO channel为空代表用户离线,推送消息(JPush,个推,小米推送)
System.err.println("离线");
} else {
// 当receiverChannel不为空的时候,从ChannelGroup去查找对应的channel是否存在
Channel findChannel = users.find(receiverChannel.id());
if (findChannel != null) {
// 用户在线,服务端利用channel将消息发送给接收方
String result = JsonUtils.objectToJson(dataContentMsg);
ByteBuf encoded = ByteBufAllocator.DEFAULT.buffer(4 * result.length());
encoded.writeBytes(result.getBytes("GBK"));
receiverChannel.writeAndFlush(encoded);
} else {
// 用户离线 TODO 推送消息
System.err.println("离线");
}
}
} else if (action == MsgActionEnum.SIGNED.type) {
// 2.3 签收消息类型,针对具体的消息进行签收,修改数据库中对应消息的签收状态[已签收]
UserBiz userBiz = (UserBiz)SpringUtil.getBean("userBiz");
// 扩展字段在signed类型的消息中,代表需要去签收的消息id,逗号间隔
String msgIdsStr = dataContent.getExtand();
String msgIds[] = msgIdsStr.split(",");
List<String> msgIdList = new ArrayList<>();
for (String mid : msgIds) {
if (StringUtils.isNotBlank(mid)) {
msgIdList.add(mid);
}
}
System.out.println(msgIdList.toString());
if (msgIdList != null && !msgIdList.isEmpty() && msgIdList.size() > 0) {
// 批量签收
userBiz.updateMsgSigned(msgIdList);
}
} else if (action == MsgActionEnum.KEEPALIVE.type) {
// 2.4 心跳类型的消息,不需要处理。只是为了判断是否关闭channel
System.out.println("收到来自channel为[" + currentChannel + "]的心跳包...");
}
}
/**
* 当客户端断开连接之后(相当于关闭channel)
*/
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
String channelId = ctx.channel().id().asShortText();
System.out.println("客户端被移除,channelId为:" + channelId);
// 当触发handlerRemoved,ChannelGroup会自动移除对应客户端的channel
users.remove(ctx.channel());
}
/**
* 这个类的统一异常处理方法
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
// 发生异常之后关闭连接(关闭channel),随后从ChannelGroup中移除
ctx.channel().close();
users.remove(ctx.channel());
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
netty服务端、客户端代码
共68个文件
class:25个
java:22个
xml:12个
需积分: 19 1 下载量 103 浏览量
2022-07-18
08:35:28
上传
评论
收藏 1.77MB RAR 举报
温馨提示
本资源包含netty服务端和客户端代码,以及连接工具WebLisTools
资源详情
资源评论
资源推荐
收起资源包目录
netty.rar (68个子文件)
netty
client
pom.xml 3KB
target
classes
application.yml 434B
com
example
client
netty
NettyClientHandler.class 2KB
NettyClientStart$1.class 1KB
NettyClientStart$2.class 2KB
NettyClientStart.class 5KB
ClientApplication.class 743B
controller
TestController.class 2KB
utils
CtxMap.class 542B
generated-sources
annotations
client.iml 81B
src
test
java
main
resources
application.yml 434B
java
com
example
client
ClientApplication.java 336B
netty
NettyClientHandler.java 1KB
NettyClientStart.java 5KB
controller
TestController.java 998B
utils
CtxMap.java 355B
.idea
misc.xml 526B
jarRepositories.xml 864B
encodings.xml 191B
compiler.xml 709B
workspace.xml 4KB
.gitignore 230B
server
server.iml 81B
pom.xml 4KB
target
classes
application.yml 977B
com
example
server
ServerApplication.class 971B
config
RedisConfig.class 2KB
biz
UserBiz.class 3KB
netty
ChatHandler.class 4KB
WSServer.class 2KB
UserChannelRel.class 2KB
WSServerInitialzer.class 2KB
ChatNewHandler.class 7KB
MsgActionEnum.class 2KB
ChatMsg.class 3KB
DataContent.class 2KB
WSServer$SingletionWSServer.class 560B
HeartBeatHandler.class 2KB
NettyStart.class 2KB
controller
TestController.class 2KB
utils
SpringUtil.class 2KB
JsonUtils.class 2KB
MD5Utils.class 1KB
generated-sources
annotations
src
test
java
main
resources
application.yml 977B
java
com
example
server
config
RedisConfig.java 2KB
biz
UserBiz.java 1KB
netty
NettyStart.java 726B
HeartBeatHandler.java 2KB
MsgActionEnum.java 512B
ChatNewHandler.java 7KB
ChatMsg.java 459B
ChatHandler.java 6KB
WSServer.java 1KB
DataContent.java 1KB
WSServerInitialzer.java 2KB
UserChannelRel.java 765B
ServerApplication.java 529B
controller
TestController.java 1KB
utils
SpringUtil.java 1KB
JsonUtils.java 2KB
MD5Utils.java 694B
.idea
misc.xml 526B
jarRepositories.xml 864B
encodings.xml 191B
compiler.xml 709B
workspace.xml 6KB
.gitignore 230B
WebLisTools.exe 5.1MB
共 68 条
- 1
一梦无痕bzy
- 粉丝: 108
- 资源: 11
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0