diff --git a/lab-67/lab-67-netty-demo/lab-67-netty-demo-client/pom.xml b/lab-67/lab-67-netty-demo/lab-67-netty-demo-client/pom.xml
new file mode 100644
index 00000000..5904c2d1
--- /dev/null
+++ b/lab-67/lab-67-netty-demo/lab-67-netty-demo-client/pom.xml
@@ -0,0 +1,56 @@
+
+
+
+ lab-67-netty-demo
+ cn.iocoder.springboot.labs
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ lab-67-netty-demo-client
+
+
+
+ 2.2.4.RELEASE
+
+ 1.8
+ 1.8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ ${spring.boot.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ io.netty
+ netty-all
+ 4.1.50.Final
+
+
+
+
+ cn.iocoder.springboot.labs
+ lab-67-netty-demo-common
+ 1.0-SNAPSHOT
+
+
+
+
diff --git a/lab-67/lab-67-netty-demo/lab-67-netty-demo-client/src/main/java/cn/iocoder/springboot/lab67/nettyclientdemo/NettyClientApplication.java b/lab-67/lab-67-netty-demo/lab-67-netty-demo-client/src/main/java/cn/iocoder/springboot/lab67/nettyclientdemo/NettyClientApplication.java
new file mode 100644
index 00000000..13d4254c
--- /dev/null
+++ b/lab-67/lab-67-netty-demo/lab-67-netty-demo-client/src/main/java/cn/iocoder/springboot/lab67/nettyclientdemo/NettyClientApplication.java
@@ -0,0 +1,4 @@
+package cn.iocoder.springboot.lab67.nettyclientdemo;
+
+public class NettyClientApplication {
+}
diff --git a/lab-67/lab-67-netty-demo/lab-67-netty-demo-client/src/main/java/cn/iocoder/springboot/lab67/nettyclientdemo/config/NettyClientConfig.java b/lab-67/lab-67-netty-demo/lab-67-netty-demo-client/src/main/java/cn/iocoder/springboot/lab67/nettyclientdemo/config/NettyClientConfig.java
new file mode 100644
index 00000000..54a83d0e
--- /dev/null
+++ b/lab-67/lab-67-netty-demo/lab-67-netty-demo-client/src/main/java/cn/iocoder/springboot/lab67/nettyclientdemo/config/NettyClientConfig.java
@@ -0,0 +1,21 @@
+package cn.iocoder.springboot.lab67.nettyclientdemo.config;
+
+import cn.iocoder.springboot.lab67.nettycommondemo.dispacher.MessageDispatcher;
+import cn.iocoder.springboot.lab67.nettycommondemo.dispacher.MessageHandlerContainer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class NettyClientConfig {
+
+ @Bean
+ public MessageDispatcher messageDispatcher() {
+ return new MessageDispatcher();
+ }
+
+ @Bean
+ public MessageHandlerContainer messageHandlerContainer() {
+ return new MessageHandlerContainer();
+ }
+
+}
diff --git a/lab-67/lab-67-netty-demo/lab-67-netty-demo-common/pom.xml b/lab-67/lab-67-netty-demo/lab-67-netty-demo-common/pom.xml
new file mode 100644
index 00000000..503b3b40
--- /dev/null
+++ b/lab-67/lab-67-netty-demo/lab-67-netty-demo-common/pom.xml
@@ -0,0 +1,55 @@
+
+
+
+ lab-67-netty-demo
+ cn.iocoder.springboot.labs
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ lab-67-netty-demo-common
+
+
+
+ 1.8
+ 1.8
+
+
+
+
+
+ io.netty
+ netty-all
+ 4.1.50.Final
+
+
+
+
+ com.alibaba
+ fastjson
+ 1.2.71
+
+
+
+
+ org.springframework
+ spring-aop
+ 5.2.5.RELEASE
+
+
+ org.springframework
+ spring-context
+ 5.2.5.RELEASE
+
+
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.30
+
+
+
+
diff --git a/lab-67/lab-67-netty-demo/lab-67-netty-demo-common/src/main/java/cn/iocoder/springboot/lab67/nettycommondemo/codec/Invocation.java b/lab-67/lab-67-netty-demo/lab-67-netty-demo-common/src/main/java/cn/iocoder/springboot/lab67/nettycommondemo/codec/Invocation.java
new file mode 100644
index 00000000..537be159
--- /dev/null
+++ b/lab-67/lab-67-netty-demo/lab-67-netty-demo-common/src/main/java/cn/iocoder/springboot/lab67/nettycommondemo/codec/Invocation.java
@@ -0,0 +1,41 @@
+package cn.iocoder.springboot.lab67.nettycommondemo.codec;
+
+public class Invocation {
+
+ /**
+ * 类型 - 心跳请求
+ */
+ public static final String TYPE_HEARTBEAT_REQUEST = "HEARTBEAT_REQUEST";
+ /**
+ * 类型 - 心跳响应
+ */
+ public static final String TYPE_HEARTBEAT_RESPONSE = "HEARTBEAT_RESPONSE";
+
+ /**
+ * 类型
+ */
+ private String type;
+ /**
+ * 消息
+ */
+ private String message;
+
+ public String getType() {
+ return type;
+ }
+
+ public Invocation setType(String type) {
+ this.type = type;
+ return this;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public Invocation setMessage(String message) {
+ this.message = message;
+ return this;
+ }
+
+}
diff --git a/lab-67/lab-67-netty-demo/lab-67-netty-demo-common/src/main/java/cn/iocoder/springboot/lab67/nettycommondemo/codec/InvocationDecoder.java b/lab-67/lab-67-netty-demo/lab-67-netty-demo-common/src/main/java/cn/iocoder/springboot/lab67/nettycommondemo/codec/InvocationDecoder.java
new file mode 100644
index 00000000..a097f746
--- /dev/null
+++ b/lab-67/lab-67-netty-demo/lab-67-netty-demo-common/src/main/java/cn/iocoder/springboot/lab67/nettycommondemo/codec/InvocationDecoder.java
@@ -0,0 +1,39 @@
+package cn.iocoder.springboot.lab67.nettycommondemo.codec;
+
+import com.alibaba.fastjson.JSON;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+import io.netty.handler.codec.CorruptedFrameException;
+
+import java.util.List;
+
+public class InvocationDecoder extends ByteToMessageDecoder {
+
+ @Override
+ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List