|
@@ -0,0 +1,117 @@
|
|
|
+package com.phm.netty.server.handler;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
+import com.phm.netty.domain.Message;
|
|
|
+import com.phm.netty.enums.MessageEnum;
|
|
|
+import com.phm.netty.utils.ChannelMap;
|
|
|
+import io.netty.channel.Channel;
|
|
|
+import io.netty.channel.ChannelHandler;
|
|
|
+import io.netty.channel.ChannelHandlerContext;
|
|
|
+import io.netty.channel.SimpleChannelInboundHandler;
|
|
|
+import io.netty.util.AttributeKey;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import java.util.Objects;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @Description ServerListenerHandler 数据处理器,针对不同类型数据分类处理
|
|
|
+ * @Author WGK
|
|
|
+ * @Date 2023/9/14 11:45
|
|
|
+ */
|
|
|
+@ChannelHandler.Sharable
|
|
|
+@Slf4j
|
|
|
+@Component
|
|
|
+public class ServerListenerHandler extends SimpleChannelInboundHandler<Message> {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设备接入连接时处理
|
|
|
+ *
|
|
|
+ * @param ctx ctx
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void handlerAdded(ChannelHandlerContext ctx) {
|
|
|
+ log.info("有新的连接:[{}]", ctx.channel().id().asLongText());
|
|
|
+ Message msg = new Message();
|
|
|
+ msg.setContent("和服务端连接成功");
|
|
|
+ msg.setTarget("Client");
|
|
|
+ msg.setSource("Serve");
|
|
|
+ ctx.channel().writeAndFlush(msg);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 数据处理
|
|
|
+ *
|
|
|
+ * @param ctx ctx
|
|
|
+ * @param msg msg
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ protected void channelRead0(ChannelHandlerContext ctx, Message msg) throws Exception {
|
|
|
+ // 获取消息实例中的消息体
|
|
|
+ String content = msg.getContent();
|
|
|
+ msg.setId(ctx.channel().id().asLongText());
|
|
|
+ // 对不同消息类型进行处理
|
|
|
+ MessageEnum type = MessageEnum.getStructureEnum(msg);
|
|
|
+ switch (Objects.requireNonNull(type)) {
|
|
|
+ case GET_DATA_BY_ONBOARD:
|
|
|
+ // 将通道加入ChannelMap
|
|
|
+ ChannelMap.getChannelMap().put(msg.getId(), ctx.channel());
|
|
|
+ // 将客户端ID作为自定义属性加入到channel中,方便随时channel中获取用户ID
|
|
|
+ AttributeKey<String> key = AttributeKey.valueOf("id");
|
|
|
+ ctx.channel().attr(key).setIfAbsent(msg.getId());
|
|
|
+ this.channelWrite(ctx.channel(), msg);
|
|
|
+ // TODO 业务处理
|
|
|
+ case FALSE_ALARM:
|
|
|
+ // TODO 业务处理
|
|
|
+ default:
|
|
|
+ System.out.println(type.content + "消息内容: " + content);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设备下线处理
|
|
|
+ *
|
|
|
+ * @param ctx ctx
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void handlerRemoved(ChannelHandlerContext ctx) {
|
|
|
+ log.info("设备下线了:{}", ctx.channel().id().asLongText());
|
|
|
+ // map中移除channel
|
|
|
+ removeId(ctx);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设备连接异常处理
|
|
|
+ *
|
|
|
+ * @param ctx ctx
|
|
|
+ * @param cause cause
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
|
|
+ // 打印异常
|
|
|
+ log.info("异常:{}", cause.getMessage());
|
|
|
+ // map中移除channel
|
|
|
+ removeId(ctx);
|
|
|
+ // 关闭连接
|
|
|
+ ctx.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void removeId(ChannelHandlerContext ctx) {
|
|
|
+ AttributeKey<String> key = AttributeKey.valueOf("id");
|
|
|
+ // 获取channel中id
|
|
|
+ String id = ctx.channel().attr(key).get();
|
|
|
+ // map移除channel
|
|
|
+ if (CollectionUtil.isNotEmpty(ChannelMap.getChannelMap())) {
|
|
|
+ ChannelMap.getChannelMap().remove(id);
|
|
|
+ } else {
|
|
|
+ log.info("ChannelMap === 为空");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void channelWrite(Channel channel, Message message) throws Exception {
|
|
|
+ if (null == channel) {
|
|
|
+ throw new RuntimeException("客户端已离线");
|
|
|
+ }
|
|
|
+ channel.writeAndFlush(message);
|
|
|
+ }
|
|
|
+}
|