Browse Source

新增消息proto

zhangming 2 years ago
parent
commit
c6f022eab6
37 changed files with 4305 additions and 247 deletions
  1. 2 1
      .gitignore
  2. 0 0
      logs/2022-05-05_chat-server.0.log
  3. 0 0
      logs/2022-05-05_chat-server_error.0.log
  4. 0 0
      logs/2022-05-05_chat-server_warn.0.log
  5. 478 0
      logs/cms.2022-05-05.0.log
  6. 14 18
      pom.xml
  7. 2 2
      src/main/java/cn/com/zyjblogs/chat/ChatServerApplication.java
  8. 21 0
      src/main/java/cn/com/zyjblogs/chat/common/ChatException.java
  9. 23 0
      src/main/java/cn/com/zyjblogs/chat/common/ResponseCode.java
  10. 0 2
      src/main/java/cn/com/zyjblogs/chat/config/rest/RestTemplateConfig.java
  11. 3 3
      src/main/java/cn/com/zyjblogs/chat/config/threadpool/ExecutorConfig.java
  12. 27 17
      src/main/java/cn/com/zyjblogs/chat/netty/ChatServer.java
  13. 46 0
      src/main/java/cn/com/zyjblogs/chat/netty/ChatServerInitializer.java
  14. 0 37
      src/main/java/cn/com/zyjblogs/chat/netty/MessageProtocol.java
  15. 0 26
      src/main/java/cn/com/zyjblogs/chat/netty/MyMessageDecoder.java
  16. 0 16
      src/main/java/cn/com/zyjblogs/chat/netty/MyMessageEncoder.java
  17. 0 36
      src/main/java/cn/com/zyjblogs/chat/netty/MyServerHandler.java
  18. 0 57
      src/main/java/cn/com/zyjblogs/chat/netty/SocketHandler.java
  19. 0 23
      src/main/java/cn/com/zyjblogs/chat/netty/SocketInitializer.java
  20. 75 0
      src/main/java/cn/com/zyjblogs/chat/netty/channel/UserChannelContext.java
  21. 36 0
      src/main/java/cn/com/zyjblogs/chat/netty/factory/MessageHandleFactory.java
  22. 35 0
      src/main/java/cn/com/zyjblogs/chat/netty/factory/content/MessageContent.java
  23. 7 0
      src/main/java/cn/com/zyjblogs/chat/netty/factory/strategy/data/DataActionHandler.java
  24. 15 0
      src/main/java/cn/com/zyjblogs/chat/netty/factory/strategy/message/GeneralMessageHandler.java
  25. 15 0
      src/main/java/cn/com/zyjblogs/chat/netty/factory/strategy/message/GroupMessageHandler.java
  26. 12 0
      src/main/java/cn/com/zyjblogs/chat/netty/factory/strategy/message/MessageHandler.java
  27. 12 0
      src/main/java/cn/com/zyjblogs/chat/netty/factory/strategy/message/SystemMessageHandler.java
  28. 83 0
      src/main/java/cn/com/zyjblogs/chat/netty/handler/ChatServerHandler.java
  29. 30 0
      src/main/java/cn/com/zyjblogs/chat/netty/handler/ClientManageHandler.java
  30. 50 0
      src/main/java/cn/com/zyjblogs/chat/netty/handler/FreeClientHandler.java
  31. 3 2
      src/main/java/cn/com/zyjblogs/chat/netty/listener/NettyStartListener.java
  32. 56 0
      src/main/java/cn/com/zyjblogs/chat/netty/po/Message.proto
  33. 3198 0
      src/main/java/cn/com/zyjblogs/chat/netty/po/Msg.java
  34. 5 3
      src/main/resources/application.yml
  35. 17 3
      src/main/resources/banner.txt
  36. 39 0
      src/main/resources/logback-spring.xml
  37. 1 1
      src/test/java/cn/com/zyjblogs/chat/ChatServerApplicationTests.java

+ 2 - 1
.gitignore

@@ -28,6 +28,7 @@ target/
 build/
 !**/src/main/**/build/
 !**/src/test/**/build/
-
+logs/
 ### VS Code ###
+.mvn/
 .vscode/

+ 0 - 0
logs/2022-05-05_chat-server.0.log


+ 0 - 0
logs/2022-05-05_chat-server_error.0.log


+ 0 - 0
logs/2022-05-05_chat-server_warn.0.log


File diff suppressed because it is too large
+ 478 - 0
logs/cms.2022-05-05.0.log


+ 14 - 18
pom.xml

@@ -9,18 +9,17 @@
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
     <groupId>cn.com.zyjblogs</groupId>
-    <artifactId>Chat</artifactId>
-    <version>0.0.1-SNAPSHOT</version>
-    <name>Chat</name>
+    <artifactId>ChatServer</artifactId>
+    <version>1.0.0</version>
+    <name>ChatServer</name>
     <description>Demo project for Spring Boot</description>
     <properties>
-        <java.version>11</java.version>
+        <java.version>18</java.version>
     </properties>
     <dependencies>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-redis</artifactId>
-            <version>2.6.7</version>
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -32,11 +31,6 @@
             <artifactId>mysql-connector-java</artifactId>
             <scope>runtime</scope>
         </dependency>
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-            <optional>true</optional>
-        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
@@ -59,6 +53,16 @@
             <artifactId>druid-spring-boot-starter</artifactId>
             <version>1.2.9</version>
         </dependency>
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+            <version>3.17.3</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>transmittable-thread-local</artifactId>
+            <version>2.12.6</version>
+        </dependency>
 
     </dependencies>
 
@@ -67,14 +71,6 @@
             <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
-                <configuration>
-                    <excludes>
-                        <exclude>
-                            <groupId>org.projectlombok</groupId>
-                            <artifactId>lombok</artifactId>
-                        </exclude>
-                    </excludes>
-                </configuration>
             </plugin>
         </plugins>
     </build>

+ 2 - 2
src/main/java/cn/com/zyjblogs/chat/ChatApplication.java → src/main/java/cn/com/zyjblogs/chat/ChatServerApplication.java

@@ -6,10 +6,10 @@ import org.springframework.scheduling.annotation.EnableAsync;
 
 @SpringBootApplication(scanBasePackages="cn.com.zyjblogs.chat")
 @EnableAsync
-public class ChatApplication {
+public class ChatServerApplication {
 
     public static void main(String[] args) {
-        SpringApplication.run(ChatApplication.class, args);
+        SpringApplication.run(ChatServerApplication.class, args);
     }
 
 }

+ 21 - 0
src/main/java/cn/com/zyjblogs/chat/common/ChatException.java

@@ -0,0 +1,21 @@
+package cn.com.zyjblogs.chat.common;
+
+/**
+ * 异常处理类
+ * @author zhuyi
+ */
+public class ChatException extends RuntimeException {
+    private ResponseCode responseCode;
+    private String msg;
+    public ChatException(){
+    }
+    public ChatException(String msg){
+        super(msg);
+        this.msg = msg;
+    }
+    public ChatException(ResponseCode responseCode,String msg){
+        super(msg);
+        this.responseCode = responseCode;
+        this.msg = msg;
+    }
+}

+ 23 - 0
src/main/java/cn/com/zyjblogs/chat/common/ResponseCode.java

@@ -0,0 +1,23 @@
+package cn.com.zyjblogs.chat.common;
+
+/**
+ * 消息码
+ */
+public enum ResponseCode {
+    SUCCESS(200,"成功"),
+    FAILD(500,"失败");
+    private final Integer code;
+    private final String message;
+    ResponseCode(Integer code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+}

+ 0 - 2
src/main/java/cn/com/zyjblogs/chat/config/rest/RestTemplateConfig.java

@@ -1,6 +1,5 @@
 package cn.com.zyjblogs.chat.config.rest;
 
-import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.client.SimpleClientHttpRequestFactory;
@@ -13,7 +12,6 @@ import org.springframework.web.client.RestTemplate;
  * @Date: 2018-12-19 16:30:00
  * @Description: rest配置
  */
-@Slf4j
 @Configuration
 public class RestTemplateConfig {
 

+ 3 - 3
src/main/java/cn/com/zyjblogs/chat/config/threadpool/ExecutorConfig.java

@@ -1,6 +1,7 @@
 package cn.com.zyjblogs.chat.config.threadpool;
 
-import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -21,9 +22,8 @@ import java.util.concurrent.ThreadPoolExecutor;
  * @create 2021/6/7 8:38
  */
 @Configuration
-@Slf4j
 public class ExecutorConfig {
-
+    Logger log = LoggerFactory.getLogger(ExecutorConfig.class);
     @Value("${async.executor.thread.core_pool_size}")
     private int corePoolSize;
     @Value("${async.executor.thread.max_pool_size}")

+ 27 - 17
src/main/java/cn/com/zyjblogs/chat/netty/SocketServer.java → src/main/java/cn/com/zyjblogs/chat/netty/ChatServer.java

@@ -2,9 +2,13 @@ package cn.com.zyjblogs.chat.netty;
 
 import io.netty.bootstrap.ServerBootstrap;
 import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.channel.socket.nio.NioServerSocketChannel;
-import lombok.extern.slf4j.Slf4j;
+import io.netty.handler.logging.LogLevel;
+import io.netty.handler.logging.LoggingHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
@@ -14,11 +18,11 @@ import java.io.Closeable;
 /**
  * @author Gjing
  **/
-@Slf4j
 @Service
-public class SocketServer implements Runnable, Closeable {
+public class ChatServer implements Runnable, Closeable {
+    Logger log = LoggerFactory.getLogger(ChatServer.class);
     @Resource
-    private SocketInitializer socketInitializer;
+    private ChatServerInitializer chatServerInitializer;
 
     /**
      * netty服务监听端口
@@ -31,9 +35,13 @@ public class SocketServer implements Runnable, Closeable {
     @Value("${spring.netty.bossThread:1}")
     private int bossThread;
     private ServerBootstrap serverBootstrap = new ServerBootstrap();
-    // 创建两个线程组,bossGroup为接收请求的线程组,一般1-2个就行
+    /**
+     * 创建两个线程组,bossGroup为接收请求的线程组,一般1-2个就行
+     */
     private NioEventLoopGroup bossGroup = new NioEventLoopGroup(this.bossThread);
-    // 实际工作的线程组
+    /**
+     * 实际工作的线程组
+     */
     private NioEventLoopGroup workerGroup = new NioEventLoopGroup();
 
 
@@ -41,16 +49,18 @@ public class SocketServer implements Runnable, Closeable {
      * 初始化netty配置
      */
     private void init() {
-        this.serverBootstrap.group(bossGroup, workerGroup) // 两个线程组加入进来
-                .channel(NioServerSocketChannel.class)  // 配置为nio类型
-                .childHandler(this.socketInitializer); // 加入自己的初始化器
-        //对关闭通道进行监听
-        ChannelFuture cf = this.serverBootstrap.bind(this.port);
-        //对关闭通道进行监听
-        try {
-            cf.channel().closeFuture().sync();
-        } catch (InterruptedException e) {
-        }
+        // 两个线程组加入进来
+        this.serverBootstrap.group(bossGroup, workerGroup)
+                //在bossGroup中添加一个日志处理器
+                .handler(new LoggingHandler(LogLevel.INFO))
+                // 配置为nio类型
+                .channel(NioServerSocketChannel.class)
+                // 加入自己的初始化器
+                .childHandler(this.chatServerInitializer);
+        //对通道进行监听
+        this.serverBootstrap.bind(this.port);
+        log.info("bind port : {}",this.port);
+        log.info("netty server thread finish");
     }
     /**
      * 启动netty服务器
@@ -63,7 +73,7 @@ public class SocketServer implements Runnable, Closeable {
     @Override
     public void close() {
         //优雅关闭
-        log.info("netty closing");
+        log.info("netty closing ...");
         bossGroup.shutdownGracefully();
         workerGroup.shutdownGracefully();
         log.info("netty close");

+ 46 - 0
src/main/java/cn/com/zyjblogs/chat/netty/ChatServerInitializer.java

@@ -0,0 +1,46 @@
+package cn.com.zyjblogs.chat.netty;
+
+import cn.com.zyjblogs.chat.netty.handler.ChatServerHandler;
+import cn.com.zyjblogs.chat.netty.handler.FreeClientHandler;
+import cn.com.zyjblogs.chat.netty.po.Msg;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.codec.protobuf.ProtobufDecoder;
+import io.netty.handler.codec.protobuf.ProtobufEncoder;
+import io.netty.handler.timeout.IdleStateHandler;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * Socket 初始化器,每一个Channel进来都会调用这里的 InitChannel 方法
+ * @author Gjing
+ **/
+@Service
+public class ChatServerInitializer extends ChannelInitializer<SocketChannel> {
+    @Resource
+    private ChatServerHandler chatServerHandler;
+    @Resource
+    private FreeClientHandler freeClientHandler;
+    @Override
+    protected void initChannel(SocketChannel ch)  {
+        ch.pipeline()
+                .addLast("decoder",new ProtobufDecoder(Msg.DataContent.getDefaultInstance()))
+                .addLast(chatServerHandler)
+                .addLast("encoder",new ProtobufEncoder())
+                /**
+                 * IdleStateHandler 是netty 提供的处理空闲状态的处理器
+                 * 1、long readerIdleTime : 表示多长时间没有读,就会发送一个心跳检测包检测是否连接
+                 * 2、long writerIdleTime : 表示多长时间没有写,就会发送一个心跳检测包
+                 * 3、long allIdleTime : 表示多长时间没有读写 就会发送一个心跳检测包
+                 * 当IdleStateEvent触发后,就会传递给管道的下一个handler区处理通过调用(触发)
+                 * 下一个handler的userEventTiggered,该方法中区处理
+                 * IdleStateEvent(读空闲,写空闲,都写空闲)
+                 */
+                .addLast(new IdleStateHandler(15,20,10, TimeUnit.SECONDS))
+                //加入一个对空闲检测进一步处理的handler(自定义)
+                .addLast(freeClientHandler);
+    }
+}

+ 0 - 37
src/main/java/cn/com/zyjblogs/chat/netty/MessageProtocol.java

@@ -1,37 +0,0 @@
-package cn.com.zyjblogs.chat.netty;
-
-import java.util.Arrays;
-
-public class MessageProtocol {
-    private int len;
-    private byte[] content;
-
-    public int getLen() {
-        return len;
-    }
-
-    public void setLen(int len) {
-        this.len = len;
-    }
-
-    public byte[] getContent() {
-        return content;
-    }
-
-    public void setContent(byte[] content) {
-        this.content = content;
-    }
-    public MessageProtocol() {
-    }
-    public MessageProtocol(int len, byte[] content) {
-        this.len = len;
-        this.content = content;
-    }
-    @Override
-    public String toString() {
-        return "MessageProtocol{" +
-                "len=" + len +
-                ", content=" + Arrays.toString(content) +
-                '}';
-    }
-}

+ 0 - 26
src/main/java/cn/com/zyjblogs/chat/netty/MyMessageDecoder.java

@@ -1,26 +0,0 @@
-package cn.com.zyjblogs.chat.netty;
-
-
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.ReplayingDecoder;
-
-import java.util.List;
-
-public class MyMessageDecoder extends ReplayingDecoder<MessageProtocol> {
-
-
-    @Override
-    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
-        System.out.println("\nMyMessageDecoder方法被调用 解码");
-        //需要将得到的二进制字节码 转成 MessageProtocol
-        int length = in.readInt();
-        byte[] content = new byte[length];
-        in.readBytes(content);
-        //封装成MessageProtocol对象,放入out中,传给下一个handler
-        MessageProtocol messageProtocol = new MessageProtocol();
-        messageProtocol.setLen(length);
-        messageProtocol.setContent(content);
-        out.add(messageProtocol);
-    }
-}

+ 0 - 16
src/main/java/cn/com/zyjblogs/chat/netty/MyMessageEncoder.java

@@ -1,16 +0,0 @@
-package cn.com.zyjblogs.chat.netty;
-
-
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.MessageToByteEncoder;
-
-public class MyMessageEncoder extends MessageToByteEncoder<MessageProtocol> {
-
-    @Override
-    protected void encode(ChannelHandlerContext ctx, MessageProtocol msg, ByteBuf out) throws Exception {
-        System.out.println("\nMyMessageEncoder方法被调用 编码");
-        out.writeInt(msg.getLen());
-        out.writeBytes(msg.getContent());
-    }
-}

+ 0 - 36
src/main/java/cn/com/zyjblogs/chat/netty/MyServerHandler.java

@@ -1,36 +0,0 @@
-package cn.com.zyjblogs.chat.netty;
-
-
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.SimpleChannelInboundHandler;
-import io.netty.util.CharsetUtil;
-
-import java.util.UUID;
-
-public class MyServerHandler extends SimpleChannelInboundHandler<MessageProtocol> {
-    private int count=0;
-
-    @Override
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-        ctx.close();
-    }
-
-    @Override
-    protected void channelRead0(ChannelHandlerContext ctx, MessageProtocol msg) throws Exception {
-        //接收数据,并处理
-        System.out.println("服务端接收信息:");
-        System.out.println("长度="+msg.getLen());
-        System.out.println("内容="+new String(msg.getContent(),CharsetUtil.UTF_8));
-        System.out.println("服务器接收消息包数量="+(++this.count));
-
-        //回复消息
-        String responseContent = UUID.randomUUID().toString();
-        int responseLen = responseContent.getBytes(CharsetUtil.UTF_8).length;
-        MessageProtocol messageProtocol = new MessageProtocol();
-        messageProtocol.setLen(responseLen);
-        messageProtocol.setContent(responseContent.getBytes(CharsetUtil.UTF_8));
-
-        ctx.writeAndFlush(messageProtocol);
-
-    }
-}

+ 0 - 57
src/main/java/cn/com/zyjblogs/chat/netty/SocketHandler.java

@@ -1,57 +0,0 @@
-package cn.com.zyjblogs.chat.netty;
-
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandlerAdapter;
-import io.netty.channel.group.ChannelGroup;
-import io.netty.channel.group.DefaultChannelGroup;
-import io.netty.util.concurrent.GlobalEventExecutor;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * Socket拦截器,用于处理客户端的行为
- *
- * @author Gjing
- **/
-@Slf4j
-public class SocketHandler extends ChannelInboundHandlerAdapter {
-    public static final ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
-
-    /**
-     * 读取到客户端发来的消息
-     *
-     * @param ctx ChannelHandlerContext
-     * @param msg msg
-     * @throws Exception e
-     */
-    @Override
-    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
-        // 由于我们配置的是 字节数组 编解码器,所以这里取到的用户发来的数据是 byte数组
-        byte[] data = (byte[]) msg;
-        log.info("收到消息: " + new String(data));
-        // 给其他人转发消息
-        for (Channel client : clients) {
-            if (!client.equals(ctx.channel())) {
-                client.writeAndFlush(data);
-            }
-        }
-    }
-
-    @Override
-    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
-        log.info("新的客户端链接:" + ctx.channel().id().asShortText());
-        clients.add(ctx.channel());
-    }
-
-    @Override
-    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
-        clients.remove(ctx.channel());
-    }
-
-    @Override
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-        cause.printStackTrace();
-        ctx.channel().close();
-        clients.remove(ctx.channel());
-    }
-}

+ 0 - 23
src/main/java/cn/com/zyjblogs/chat/netty/SocketInitializer.java

@@ -1,23 +0,0 @@
-package cn.com.zyjblogs.chat.netty;
-
-import io.netty.channel.ChannelInitializer;
-import io.netty.channel.socket.SocketChannel;
-import org.springframework.stereotype.Service;
-
-
-/**
- * Socket 初始化器,每一个Channel进来都会调用这里的 InitChannel 方法
- * @author Gjing
- **/
-@Service
-public class SocketInitializer extends ChannelInitializer<SocketChannel> {
-    @Override
-    protected void initChannel(SocketChannel ch)  {
-        ch.pipeline()
-                //解码器
-                .addLast(new MyMessageDecoder())
-                //编码器
-                .addLast(new MyMessageEncoder())
-                .addLast(new MyServerHandler());
-    }
-}

+ 75 - 0
src/main/java/cn/com/zyjblogs/chat/netty/channel/UserChannelContext.java

@@ -0,0 +1,75 @@
+package cn.com.zyjblogs.chat.netty.channel;
+
+import com.alibaba.ttl.TransmittableThreadLocal;
+import io.netty.channel.ChannelHandlerContext;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class UserChannelContext {
+    public UserChannelContext(){
+
+    }
+    /**
+     * 用户名: ctx
+     */
+    private static final ThreadLocal<Map<String,ChannelHandlerContext>> CONTEXT = new TransmittableThreadLocal<Map<String,ChannelHandlerContext>>(){
+        @Override
+        public Map<String,ChannelHandlerContext> initialValue(){
+            return new ConcurrentHashMap<>();
+        }
+    };
+
+    /**
+     * 获取CONTEXT
+     * @return
+     */
+    public static synchronized Map<String,ChannelHandlerContext> get(){
+        return CONTEXT.get();
+    }
+
+    /**
+     * 设置CONTEXT
+     * @param map
+     */
+    public static synchronized void set(Map<String,ChannelHandlerContext> map){
+        CONTEXT.set(map);
+    }
+
+    /**
+     * 新增用户ctx
+     * @param username
+     * @param ctx
+     */
+    public static synchronized void putUserCtx(String username,ChannelHandlerContext ctx){
+        Map<String, ChannelHandlerContext> contextMap = get();
+        contextMap.put(username,ctx);
+        set(contextMap);
+    }
+
+    /**
+     * 获取ctx
+     * @param username
+     * @return
+     */
+    public static synchronized  ChannelHandlerContext getUserCtx(String username){
+        return get().get(username);
+    }
+
+    /**
+     * 移除用户ctx
+     * @param username
+     */
+    public static synchronized void removeUserCtx(String username){
+        Map<String, ChannelHandlerContext> contextMap = get();
+        contextMap.remove(username);
+        set(contextMap);
+    }
+
+    /**
+     * 清空
+     */
+    public static synchronized void clear(){
+        CONTEXT.remove();
+    }
+}

+ 36 - 0
src/main/java/cn/com/zyjblogs/chat/netty/factory/MessageHandleFactory.java

@@ -0,0 +1,36 @@
+package cn.com.zyjblogs.chat.netty.factory;
+
+import cn.com.zyjblogs.chat.netty.factory.content.MessageContent;
+import cn.com.zyjblogs.chat.netty.factory.strategy.message.GeneralMessageHandler;
+import cn.com.zyjblogs.chat.netty.factory.strategy.message.GroupMessageHandler;
+import cn.com.zyjblogs.chat.netty.factory.strategy.message.MessageHandler;
+import cn.com.zyjblogs.chat.netty.factory.strategy.message.SystemMessageHandler;
+import cn.com.zyjblogs.chat.netty.po.Msg;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Component
+public class MessageHandleFactory {
+
+    @Resource
+    private MessageHandler systemMessageHandler;
+
+    @Resource
+    private MessageHandler groupMessageHandler;
+
+    @Resource
+    private MessageHandler generalMessageHandler;
+
+    @Bean("messageContent")
+    public MessageContent<Integer, MessageHandler> getMessageContent(){
+        Map<Integer,MessageHandler> map = new ConcurrentHashMap<>();
+        map.put(Msg.Message.MessageType.System.getNumber(),systemMessageHandler);
+        map.put(Msg.Message.MessageType.General.getNumber(),generalMessageHandler);
+        map.put(Msg.Message.MessageType.Group.getNumber(),groupMessageHandler);
+        return new MessageContent<>(map);
+    }
+}

+ 35 - 0
src/main/java/cn/com/zyjblogs/chat/netty/factory/content/MessageContent.java

@@ -0,0 +1,35 @@
+package cn.com.zyjblogs.chat.netty.factory.content;
+
+import cn.com.zyjblogs.chat.common.ChatException;
+import org.springframework.util.Assert;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 消息处理器内容
+ * @param <K>
+ * @param <V>
+ */
+public class MessageContent<K,V> {
+    public final Map<K,V> messageHandleMap = new ConcurrentHashMap<>();
+
+    /**
+     * 容器初始化
+     * @param messageHandleMap
+     */
+    public MessageContent(Map<K,V> messageHandleMap){
+        this.messageHandleMap.putAll(messageHandleMap);
+    }
+    /**
+     * 加在对于消息处理对象
+     */
+    public V loadStrategy(K k){
+        V v = messageHandleMap.get(k);
+        if (Objects.isNull(v)){
+            throw new ChatException("策略工厂加在"+k+"对应策略失败");
+        }
+        return v;
+    }
+}

+ 7 - 0
src/main/java/cn/com/zyjblogs/chat/netty/factory/strategy/data/DataActionHandler.java

@@ -0,0 +1,7 @@
+package cn.com.zyjblogs.chat.netty.factory.strategy.data;
+
+/**
+ * 数据类型处理工厂
+ */
+public interface DataActionHandler {
+}

+ 15 - 0
src/main/java/cn/com/zyjblogs/chat/netty/factory/strategy/message/GeneralMessageHandler.java

@@ -0,0 +1,15 @@
+package cn.com.zyjblogs.chat.netty.factory.strategy.message;
+
+import cn.com.zyjblogs.chat.netty.po.Msg;
+import org.springframework.stereotype.Component;
+
+/**
+ * 客户端连接消息处理器
+ */
+@Component
+public class GeneralMessageHandler implements MessageHandler<Boolean>{
+    @Override
+    public Boolean contentHandle(Msg.DataContent dataContent) {
+        return Boolean.TRUE;
+    }
+}

+ 15 - 0
src/main/java/cn/com/zyjblogs/chat/netty/factory/strategy/message/GroupMessageHandler.java

@@ -0,0 +1,15 @@
+package cn.com.zyjblogs.chat.netty.factory.strategy.message;
+
+import cn.com.zyjblogs.chat.netty.po.Msg;
+import org.springframework.stereotype.Component;
+
+/**
+ * 群内消息发送
+ */
+@Component
+public class GroupMessageHandler implements MessageHandler<Boolean>{
+    @Override
+    public Boolean contentHandle(Msg.DataContent dataContent) {
+        return Boolean.TRUE;
+    }
+}

+ 12 - 0
src/main/java/cn/com/zyjblogs/chat/netty/factory/strategy/message/MessageHandler.java

@@ -0,0 +1,12 @@
+package cn.com.zyjblogs.chat.netty.factory.strategy.message;
+
+import cn.com.zyjblogs.chat.netty.po.Msg;
+
+public interface MessageHandler<T> {
+    /**
+     * 内容处理
+     * @param dataContent
+     * @return
+     */
+    T contentHandle(Msg.DataContent dataContent);
+}

+ 12 - 0
src/main/java/cn/com/zyjblogs/chat/netty/factory/strategy/message/SystemMessageHandler.java

@@ -0,0 +1,12 @@
+package cn.com.zyjblogs.chat.netty.factory.strategy.message;
+
+import cn.com.zyjblogs.chat.netty.po.Msg;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SystemMessageHandler implements MessageHandler<Boolean>{
+    @Override
+    public Boolean contentHandle(Msg.DataContent dataContent) {
+        return Boolean.TRUE;
+    }
+}

+ 83 - 0
src/main/java/cn/com/zyjblogs/chat/netty/handler/ChatServerHandler.java

@@ -0,0 +1,83 @@
+package cn.com.zyjblogs.chat.netty.handler;
+
+import cn.com.zyjblogs.chat.netty.channel.UserChannelContext;
+import cn.com.zyjblogs.chat.netty.factory.MessageHandleFactory;
+import cn.com.zyjblogs.chat.netty.factory.strategy.message.MessageHandler;
+import cn.com.zyjblogs.chat.netty.po.Msg;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.util.CharsetUtil;
+import io.netty.util.ReferenceCountUtil;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+
+@Component
+@ChannelHandler.Sharable
+public class ChatServerHandler extends SimpleChannelInboundHandler<Msg.DataContent> {
+
+    @Resource
+    private MessageHandleFactory factory;
+
+    /**
+     * 当通道就绪就会触发该方法
+     * @param ctx
+     * @param dataContent
+     * @throws Exception
+     */
+    @Override
+    protected void channelRead0(ChannelHandlerContext ctx, Msg.DataContent dataContent) throws Exception {
+        Msg.DataContent.DataType dataType = dataContent.getDataType();
+        switch (dataType.getNumber()){
+            case Msg.DataContent.DataType.CONNECTING_VALUE:
+                //将channel加入到map中
+                UserChannelContext.putUserCtx(dataContent.getFromUsername(),ctx);
+                break;
+            case Msg.DataContent.DataType.CLOSING_VALUE:
+                UserChannelContext.removeUserCtx(dataContent.getFromUsername());
+                break;
+            //聊天逻辑
+            case Msg.DataContent.DataType.CHAT_VALUE:
+                MessageHandler messageHandler = factory.getMessageContent().loadStrategy(dataType.getNumber());
+                messageHandler.contentHandle(dataContent);
+                break;
+            default:
+                break;
+        }
+
+        //触发后续调用链
+        ReferenceCountUtil.retain(dataContent);
+        ctx.fireChannelRead(dataContent);
+        ctx.fireChannelActive();
+    }
+
+    //数据读取完毕
+    @Override
+    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
+        // super.channelReadComplete(ctx);
+        //writeAndFlush  是write和flush 方法  将数据写入到缓存 并刷新
+        //一般将,我们需要对发送数据进行编码
+        ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端~o( =∩ω∩= )m喵 || 1", CharsetUtil.UTF_8));
+    }
+
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+        ctx.close();
+    }
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        // remoteAddress = /192.168.52.1:59807
+        String remoteAddress = ctx.channel().remoteAddress().toString();
+        super.channelActive(ctx);
+    }
+
+    @Override
+    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+        String remoteAddress = ctx.channel().remoteAddress().toString();
+        System.out.println("有客户端断开连接... " + remoteAddress);
+        super.channelInactive(ctx);
+    }
+}

+ 30 - 0
src/main/java/cn/com/zyjblogs/chat/netty/handler/ClientManageHandler.java

@@ -0,0 +1,30 @@
+package cn.com.zyjblogs.chat.netty.handler;
+
+import cn.com.zyjblogs.chat.netty.po.Msg;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import org.springframework.stereotype.Component;
+
+@Component
+@ChannelHandler.Sharable
+public class ClientManageHandler extends SimpleChannelInboundHandler<Msg.DataContent> {
+    @Override
+    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Msg.DataContent dataContent) throws Exception {
+        switch (dataContent.getDataType().getNumber()){
+            case Msg.DataContent.DataType.CONNECTING_VALUE:
+                break;
+            case Msg.DataContent.DataType.CLOSING_VALUE:
+                break;
+            case Msg.DataContent.DataType.KEEPALIVE_VALUE:
+                break;
+            case Msg.DataContent.DataType.SIGNED_VALUE:
+                break;
+            case Msg.DataContent.DataType.CHAT_VALUE:
+                break;
+            default:
+                break;
+        }
+
+    }
+}

+ 50 - 0
src/main/java/cn/com/zyjblogs/chat/netty/handler/FreeClientHandler.java

@@ -0,0 +1,50 @@
+package cn.com.zyjblogs.chat.netty.handler;
+
+import cn.com.zyjblogs.chat.netty.channel.UserChannelContext;
+import cn.com.zyjblogs.chat.netty.po.Msg;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.handler.timeout.IdleStateEvent;
+import org.springframework.stereotype.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component
+@ChannelHandler.Sharable
+public class FreeClientHandler extends ChannelInboundHandlerAdapter {
+    Logger logger = LoggerFactory.getLogger(FreeClientHandler.class);
+    /***
+     * 事件
+     * @param ctx 上下文
+     * @param evt 事件
+     * @throws Exception
+     */
+    @Override
+    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+        if (evt instanceof IdleStateEvent){
+            //将evt 向下转型 IdleStateEvent
+            IdleStateEvent event = (IdleStateEvent) evt;
+            String eventType = null;
+            switch (event.state()){
+                case READER_IDLE:
+                    eventType = "读空闲";
+                    break;
+                case WRITER_IDLE:
+                    eventType = "读空闲";
+                    break;
+                case ALL_IDLE:
+                    eventType = "读写空闲";
+                    break;
+                default:
+                    eventType = "类型未识别";
+                    break;
+            }
+            logger.info("{}",ctx.channel().remoteAddress()+"--TimeOut Type--"+eventType);
+            //如果发生空闲,我们关闭通道
+            Msg.DataContent build = Msg.DataContent.newBuilder().setDataType(Msg.DataContent.DataType.CLOSING).build();
+            ctx.writeAndFlush(build);
+            ctx.close();
+        }
+    }
+}

+ 3 - 2
src/main/java/cn/com/zyjblogs/chat/netty/NettyStartListener.java → src/main/java/cn/com/zyjblogs/chat/netty/listener/NettyStartListener.java

@@ -1,5 +1,6 @@
-package cn.com.zyjblogs.chat.netty;
+package cn.com.zyjblogs.chat.netty.listener;
 
+import cn.com.zyjblogs.chat.netty.ChatServer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.boot.ApplicationArguments;
@@ -16,7 +17,7 @@ import javax.annotation.Resource;
 public class NettyStartListener implements ApplicationRunner {
     protected Logger logger = LoggerFactory.getLogger(NettyStartListener.class);
     @Resource
-    private SocketServer socketServer;
+    private ChatServer socketServer;
 
     @Override
     public void run(ApplicationArguments args) {

+ 56 - 0
src/main/java/cn/com/zyjblogs/chat/netty/po/Message.proto

@@ -0,0 +1,56 @@
+syntax = "proto3";
+//快速解析
+option optimize_for = SPEED;
+//指定生成到那个包下面
+option java_package = "cn.com.zyjblogs.chat.netty.po";
+//生产的类名 同时也是文件名
+option java_outer_classname = "Msg";
+import "google/protobuf/timestamp.proto";
+/**
+protobuf 可以使用message 管理其他的message
+ */
+
+
+message DataContent{
+  enum DataType{
+    //enum的编号要从0开始
+    //连接
+    CONNECTING = 0;
+    //客户端保持心跳
+    KEEPALIVE = 1;
+    //聊天消息
+    CHAT = 2;
+    //断开
+    CLOSING = 3;
+    //消息签收
+    SIGNED = 4;
+  }
+  //用DataType标识传的是那个枚举类型
+  DataType dataType = 1;
+  //表示每次枚举类型最多只能出现其中的一个,节省空间
+  oneof dataBody{
+      Message message = 2;
+  }
+  string fromUsername = 3;
+  string expand = 4;
+}
+
+message Message{
+  enum MessageType {
+    System = 0;
+    General = 1;
+    Group = 2;
+  }
+  enum MessageStatus{
+    UNREAD = 0;
+    READ = 1;
+  }
+  int64 id=1;
+  string fromUsername = 2;
+  string messageBody = 3;
+  MessageType messageType=4;
+  MessageStatus messageStatus = 5;
+  string toUsername = 6;
+  google.protobuf.Timestamp createTime = 7;
+  google.protobuf.Timestamp updateTime = 8;
+}

+ 3198 - 0
src/main/java/cn/com/zyjblogs/chat/netty/po/Msg.java

@@ -0,0 +1,3198 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: cn/com/zyjblogs/chat/netty/po/Message.proto
+
+package cn.com.zyjblogs.chat.netty.po;
+
+public final class Msg {
+  private Msg() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistryLite registry) {
+  }
+
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+    registerAllExtensions(
+        (com.google.protobuf.ExtensionRegistryLite) registry);
+  }
+  public interface DataContentOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:DataContent)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <pre>
+     *用DataType标识传的是那个枚举类型
+     * </pre>
+     *
+     * <code>.DataContent.DataType dataType = 1;</code>
+     * @return The enum numeric value on the wire for dataType.
+     */
+    int getDataTypeValue();
+    /**
+     * <pre>
+     *用DataType标识传的是那个枚举类型
+     * </pre>
+     *
+     * <code>.DataContent.DataType dataType = 1;</code>
+     * @return The dataType.
+     */
+    cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataType getDataType();
+
+    /**
+     * <code>.Message message = 2;</code>
+     * @return Whether the message field is set.
+     */
+    boolean hasMessage();
+    /**
+     * <code>.Message message = 2;</code>
+     * @return The message.
+     */
+    cn.com.zyjblogs.chat.netty.po.Msg.Message getMessage();
+    /**
+     * <code>.Message message = 2;</code>
+     */
+    cn.com.zyjblogs.chat.netty.po.Msg.MessageOrBuilder getMessageOrBuilder();
+
+    /**
+     * <code>string fromUsername = 3;</code>
+     * @return The fromUsername.
+     */
+    java.lang.String getFromUsername();
+    /**
+     * <code>string fromUsername = 3;</code>
+     * @return The bytes for fromUsername.
+     */
+    com.google.protobuf.ByteString
+        getFromUsernameBytes();
+
+    /**
+     * <code>string expand = 4;</code>
+     * @return The expand.
+     */
+    java.lang.String getExpand();
+    /**
+     * <code>string expand = 4;</code>
+     * @return The bytes for expand.
+     */
+    com.google.protobuf.ByteString
+        getExpandBytes();
+
+    public cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataBodyCase getDataBodyCase();
+  }
+  /**
+   * Protobuf type {@code DataContent}
+   */
+  public static final class DataContent extends
+      com.google.protobuf.GeneratedMessageV3 implements
+      // @@protoc_insertion_point(message_implements:DataContent)
+      DataContentOrBuilder {
+  private static final long serialVersionUID = 0L;
+    // Use DataContent.newBuilder() to construct.
+    private DataContent(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+      super(builder);
+    }
+    private DataContent() {
+      dataType_ = 0;
+      fromUsername_ = "";
+      expand_ = "";
+    }
+
+    @java.lang.Override
+    @SuppressWarnings({"unused"})
+    protected java.lang.Object newInstance(
+        UnusedPrivateParameter unused) {
+      return new DataContent();
+    }
+
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+    getUnknownFields() {
+      return this.unknownFields;
+    }
+    private DataContent(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      this();
+      if (extensionRegistry == null) {
+        throw new java.lang.NullPointerException();
+      }
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            case 8: {
+              int rawValue = input.readEnum();
+
+              dataType_ = rawValue;
+              break;
+            }
+            case 18: {
+              cn.com.zyjblogs.chat.netty.po.Msg.Message.Builder subBuilder = null;
+              if (dataBodyCase_ == 2) {
+                subBuilder = ((cn.com.zyjblogs.chat.netty.po.Msg.Message) dataBody_).toBuilder();
+              }
+              dataBody_ =
+                  input.readMessage(cn.com.zyjblogs.chat.netty.po.Msg.Message.parser(), extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom((cn.com.zyjblogs.chat.netty.po.Msg.Message) dataBody_);
+                dataBody_ = subBuilder.buildPartial();
+              }
+              dataBodyCase_ = 2;
+              break;
+            }
+            case 26: {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              fromUsername_ = s;
+              break;
+            }
+            case 34: {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              expand_ = s;
+              break;
+            }
+            default: {
+              if (!parseUnknownField(
+                  input, unknownFields, extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return cn.com.zyjblogs.chat.netty.po.Msg.internal_static_DataContent_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return cn.com.zyjblogs.chat.netty.po.Msg.internal_static_DataContent_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              cn.com.zyjblogs.chat.netty.po.Msg.DataContent.class, cn.com.zyjblogs.chat.netty.po.Msg.DataContent.Builder.class);
+    }
+
+    /**
+     * Protobuf enum {@code DataContent.DataType}
+     */
+    public enum DataType
+        implements com.google.protobuf.ProtocolMessageEnum {
+      /**
+       * <pre>
+       *enum的编号要从0开始
+       *连接
+       * </pre>
+       *
+       * <code>CONNECTING = 0;</code>
+       */
+      CONNECTING(0),
+      /**
+       * <pre>
+       *客户端保持心跳
+       * </pre>
+       *
+       * <code>KEEPALIVE = 1;</code>
+       */
+      KEEPALIVE(1),
+      /**
+       * <pre>
+       *聊天消息
+       * </pre>
+       *
+       * <code>CHAT = 2;</code>
+       */
+      CHAT(2),
+      /**
+       * <pre>
+       *断开
+       * </pre>
+       *
+       * <code>CLOSING = 3;</code>
+       */
+      CLOSING(3),
+      /**
+       * <pre>
+       *消息签收
+       * </pre>
+       *
+       * <code>SIGNED = 4;</code>
+       */
+      SIGNED(4),
+      UNRECOGNIZED(-1),
+      ;
+
+      /**
+       * <pre>
+       *enum的编号要从0开始
+       *连接
+       * </pre>
+       *
+       * <code>CONNECTING = 0;</code>
+       */
+      public static final int CONNECTING_VALUE = 0;
+      /**
+       * <pre>
+       *客户端保持心跳
+       * </pre>
+       *
+       * <code>KEEPALIVE = 1;</code>
+       */
+      public static final int KEEPALIVE_VALUE = 1;
+      /**
+       * <pre>
+       *聊天消息
+       * </pre>
+       *
+       * <code>CHAT = 2;</code>
+       */
+      public static final int CHAT_VALUE = 2;
+      /**
+       * <pre>
+       *断开
+       * </pre>
+       *
+       * <code>CLOSING = 3;</code>
+       */
+      public static final int CLOSING_VALUE = 3;
+      /**
+       * <pre>
+       *消息签收
+       * </pre>
+       *
+       * <code>SIGNED = 4;</code>
+       */
+      public static final int SIGNED_VALUE = 4;
+
+
+      public final int getNumber() {
+        if (this == UNRECOGNIZED) {
+          throw new java.lang.IllegalArgumentException(
+              "Can't get the number of an unknown enum value.");
+        }
+        return value;
+      }
+
+      /**
+       * @param value The numeric wire value of the corresponding enum entry.
+       * @return The enum associated with the given numeric wire value.
+       * @deprecated Use {@link #forNumber(int)} instead.
+       */
+      @java.lang.Deprecated
+      public static DataType valueOf(int value) {
+        return forNumber(value);
+      }
+
+      /**
+       * @param value The numeric wire value of the corresponding enum entry.
+       * @return The enum associated with the given numeric wire value.
+       */
+      public static DataType forNumber(int value) {
+        switch (value) {
+          case 0: return CONNECTING;
+          case 1: return KEEPALIVE;
+          case 2: return CHAT;
+          case 3: return CLOSING;
+          case 4: return SIGNED;
+          default: return null;
+        }
+      }
+
+      public static com.google.protobuf.Internal.EnumLiteMap<DataType>
+          internalGetValueMap() {
+        return internalValueMap;
+      }
+      private static final com.google.protobuf.Internal.EnumLiteMap<
+          DataType> internalValueMap =
+            new com.google.protobuf.Internal.EnumLiteMap<DataType>() {
+              public DataType findValueByNumber(int number) {
+                return DataType.forNumber(number);
+              }
+            };
+
+      public final com.google.protobuf.Descriptors.EnumValueDescriptor
+          getValueDescriptor() {
+        if (this == UNRECOGNIZED) {
+          throw new java.lang.IllegalStateException(
+              "Can't get the descriptor of an unrecognized enum value.");
+        }
+        return getDescriptor().getValues().get(ordinal());
+      }
+      public final com.google.protobuf.Descriptors.EnumDescriptor
+          getDescriptorForType() {
+        return getDescriptor();
+      }
+      public static final com.google.protobuf.Descriptors.EnumDescriptor
+          getDescriptor() {
+        return cn.com.zyjblogs.chat.netty.po.Msg.DataContent.getDescriptor().getEnumTypes().get(0);
+      }
+
+      private static final DataType[] VALUES = values();
+
+      public static DataType valueOf(
+          com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+        if (desc.getType() != getDescriptor()) {
+          throw new java.lang.IllegalArgumentException(
+            "EnumValueDescriptor is not for this type.");
+        }
+        if (desc.getIndex() == -1) {
+          return UNRECOGNIZED;
+        }
+        return VALUES[desc.getIndex()];
+      }
+
+      private final int value;
+
+      private DataType(int value) {
+        this.value = value;
+      }
+
+      // @@protoc_insertion_point(enum_scope:DataContent.DataType)
+    }
+
+    private int dataBodyCase_ = 0;
+    private java.lang.Object dataBody_;
+    public enum DataBodyCase
+        implements com.google.protobuf.Internal.EnumLite,
+            com.google.protobuf.AbstractMessage.InternalOneOfEnum {
+      MESSAGE(2),
+      DATABODY_NOT_SET(0);
+      private final int value;
+      private DataBodyCase(int value) {
+        this.value = value;
+      }
+      /**
+       * @param value The number of the enum to look for.
+       * @return The enum associated with the given number.
+       * @deprecated Use {@link #forNumber(int)} instead.
+       */
+      @java.lang.Deprecated
+      public static DataBodyCase valueOf(int value) {
+        return forNumber(value);
+      }
+
+      public static DataBodyCase forNumber(int value) {
+        switch (value) {
+          case 2: return MESSAGE;
+          case 0: return DATABODY_NOT_SET;
+          default: return null;
+        }
+      }
+      public int getNumber() {
+        return this.value;
+      }
+    };
+
+    public DataBodyCase
+    getDataBodyCase() {
+      return DataBodyCase.forNumber(
+          dataBodyCase_);
+    }
+
+    public static final int DATATYPE_FIELD_NUMBER = 1;
+    private int dataType_;
+    /**
+     * <pre>
+     *用DataType标识传的是那个枚举类型
+     * </pre>
+     *
+     * <code>.DataContent.DataType dataType = 1;</code>
+     * @return The enum numeric value on the wire for dataType.
+     */
+    @java.lang.Override public int getDataTypeValue() {
+      return dataType_;
+    }
+    /**
+     * <pre>
+     *用DataType标识传的是那个枚举类型
+     * </pre>
+     *
+     * <code>.DataContent.DataType dataType = 1;</code>
+     * @return The dataType.
+     */
+    @java.lang.Override public cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataType getDataType() {
+      @SuppressWarnings("deprecation")
+      cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataType result = cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataType.valueOf(dataType_);
+      return result == null ? cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataType.UNRECOGNIZED : result;
+    }
+
+    public static final int MESSAGE_FIELD_NUMBER = 2;
+    /**
+     * <code>.Message message = 2;</code>
+     * @return Whether the message field is set.
+     */
+    @java.lang.Override
+    public boolean hasMessage() {
+      return dataBodyCase_ == 2;
+    }
+    /**
+     * <code>.Message message = 2;</code>
+     * @return The message.
+     */
+    @java.lang.Override
+    public cn.com.zyjblogs.chat.netty.po.Msg.Message getMessage() {
+      if (dataBodyCase_ == 2) {
+         return (cn.com.zyjblogs.chat.netty.po.Msg.Message) dataBody_;
+      }
+      return cn.com.zyjblogs.chat.netty.po.Msg.Message.getDefaultInstance();
+    }
+    /**
+     * <code>.Message message = 2;</code>
+     */
+    @java.lang.Override
+    public cn.com.zyjblogs.chat.netty.po.Msg.MessageOrBuilder getMessageOrBuilder() {
+      if (dataBodyCase_ == 2) {
+         return (cn.com.zyjblogs.chat.netty.po.Msg.Message) dataBody_;
+      }
+      return cn.com.zyjblogs.chat.netty.po.Msg.Message.getDefaultInstance();
+    }
+
+    public static final int FROMUSERNAME_FIELD_NUMBER = 3;
+    private volatile java.lang.Object fromUsername_;
+    /**
+     * <code>string fromUsername = 3;</code>
+     * @return The fromUsername.
+     */
+    @java.lang.Override
+    public java.lang.String getFromUsername() {
+      java.lang.Object ref = fromUsername_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        fromUsername_ = s;
+        return s;
+      }
+    }
+    /**
+     * <code>string fromUsername = 3;</code>
+     * @return The bytes for fromUsername.
+     */
+    @java.lang.Override
+    public com.google.protobuf.ByteString
+        getFromUsernameBytes() {
+      java.lang.Object ref = fromUsername_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        fromUsername_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int EXPAND_FIELD_NUMBER = 4;
+    private volatile java.lang.Object expand_;
+    /**
+     * <code>string expand = 4;</code>
+     * @return The expand.
+     */
+    @java.lang.Override
+    public java.lang.String getExpand() {
+      java.lang.Object ref = expand_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        expand_ = s;
+        return s;
+      }
+    }
+    /**
+     * <code>string expand = 4;</code>
+     * @return The bytes for expand.
+     */
+    @java.lang.Override
+    public com.google.protobuf.ByteString
+        getExpandBytes() {
+      java.lang.Object ref = expand_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        expand_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private byte memoizedIsInitialized = -1;
+    @java.lang.Override
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    @java.lang.Override
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      if (dataType_ != cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataType.CONNECTING.getNumber()) {
+        output.writeEnum(1, dataType_);
+      }
+      if (dataBodyCase_ == 2) {
+        output.writeMessage(2, (cn.com.zyjblogs.chat.netty.po.Msg.Message) dataBody_);
+      }
+      if (!getFromUsernameBytes().isEmpty()) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 3, fromUsername_);
+      }
+      if (!getExpandBytes().isEmpty()) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 4, expand_);
+      }
+      unknownFields.writeTo(output);
+    }
+
+    @java.lang.Override
+    public int getSerializedSize() {
+      int size = memoizedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (dataType_ != cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataType.CONNECTING.getNumber()) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeEnumSize(1, dataType_);
+      }
+      if (dataBodyCase_ == 2) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(2, (cn.com.zyjblogs.chat.netty.po.Msg.Message) dataBody_);
+      }
+      if (!getFromUsernameBytes().isEmpty()) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, fromUsername_);
+      }
+      if (!getExpandBytes().isEmpty()) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, expand_);
+      }
+      size += unknownFields.getSerializedSize();
+      memoizedSize = size;
+      return size;
+    }
+
+    @java.lang.Override
+    public boolean equals(final java.lang.Object obj) {
+      if (obj == this) {
+       return true;
+      }
+      if (!(obj instanceof cn.com.zyjblogs.chat.netty.po.Msg.DataContent)) {
+        return super.equals(obj);
+      }
+      cn.com.zyjblogs.chat.netty.po.Msg.DataContent other = (cn.com.zyjblogs.chat.netty.po.Msg.DataContent) obj;
+
+      if (dataType_ != other.dataType_) return false;
+      if (!getFromUsername()
+          .equals(other.getFromUsername())) return false;
+      if (!getExpand()
+          .equals(other.getExpand())) return false;
+      if (!getDataBodyCase().equals(other.getDataBodyCase())) return false;
+      switch (dataBodyCase_) {
+        case 2:
+          if (!getMessage()
+              .equals(other.getMessage())) return false;
+          break;
+        case 0:
+        default:
+      }
+      if (!unknownFields.equals(other.unknownFields)) return false;
+      return true;
+    }
+
+    @java.lang.Override
+    public int hashCode() {
+      if (memoizedHashCode != 0) {
+        return memoizedHashCode;
+      }
+      int hash = 41;
+      hash = (19 * hash) + getDescriptor().hashCode();
+      hash = (37 * hash) + DATATYPE_FIELD_NUMBER;
+      hash = (53 * hash) + dataType_;
+      hash = (37 * hash) + FROMUSERNAME_FIELD_NUMBER;
+      hash = (53 * hash) + getFromUsername().hashCode();
+      hash = (37 * hash) + EXPAND_FIELD_NUMBER;
+      hash = (53 * hash) + getExpand().hashCode();
+      switch (dataBodyCase_) {
+        case 2:
+          hash = (37 * hash) + MESSAGE_FIELD_NUMBER;
+          hash = (53 * hash) + getMessage().hashCode();
+          break;
+        case 0:
+        default:
+      }
+      hash = (29 * hash) + unknownFields.hashCode();
+      memoizedHashCode = hash;
+      return hash;
+    }
+
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent parseFrom(
+        java.nio.ByteBuffer data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent parseFrom(
+        java.nio.ByteBuffer data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input, extensionRegistry);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseDelimitedWithIOException(PARSER, input);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input, extensionRegistry);
+    }
+
+    @java.lang.Override
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder() {
+      return DEFAULT_INSTANCE.toBuilder();
+    }
+    public static Builder newBuilder(cn.com.zyjblogs.chat.netty.po.Msg.DataContent prototype) {
+      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+    }
+    @java.lang.Override
+    public Builder toBuilder() {
+      return this == DEFAULT_INSTANCE
+          ? new Builder() : new Builder().mergeFrom(this);
+    }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code DataContent}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:DataContent)
+        cn.com.zyjblogs.chat.netty.po.Msg.DataContentOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return cn.com.zyjblogs.chat.netty.po.Msg.internal_static_DataContent_descriptor;
+      }
+
+      @java.lang.Override
+      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return cn.com.zyjblogs.chat.netty.po.Msg.internal_static_DataContent_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                cn.com.zyjblogs.chat.netty.po.Msg.DataContent.class, cn.com.zyjblogs.chat.netty.po.Msg.DataContent.Builder.class);
+      }
+
+      // Construct using cn.com.zyjblogs.chat.netty.po.Msg.DataContent.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessageV3
+                .alwaysUseFieldBuilders) {
+        }
+      }
+      @java.lang.Override
+      public Builder clear() {
+        super.clear();
+        dataType_ = 0;
+
+        fromUsername_ = "";
+
+        expand_ = "";
+
+        dataBodyCase_ = 0;
+        dataBody_ = null;
+        return this;
+      }
+
+      @java.lang.Override
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return cn.com.zyjblogs.chat.netty.po.Msg.internal_static_DataContent_descriptor;
+      }
+
+      @java.lang.Override
+      public cn.com.zyjblogs.chat.netty.po.Msg.DataContent getDefaultInstanceForType() {
+        return cn.com.zyjblogs.chat.netty.po.Msg.DataContent.getDefaultInstance();
+      }
+
+      @java.lang.Override
+      public cn.com.zyjblogs.chat.netty.po.Msg.DataContent build() {
+        cn.com.zyjblogs.chat.netty.po.Msg.DataContent result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      @java.lang.Override
+      public cn.com.zyjblogs.chat.netty.po.Msg.DataContent buildPartial() {
+        cn.com.zyjblogs.chat.netty.po.Msg.DataContent result = new cn.com.zyjblogs.chat.netty.po.Msg.DataContent(this);
+        result.dataType_ = dataType_;
+        if (dataBodyCase_ == 2) {
+          if (messageBuilder_ == null) {
+            result.dataBody_ = dataBody_;
+          } else {
+            result.dataBody_ = messageBuilder_.build();
+          }
+        }
+        result.fromUsername_ = fromUsername_;
+        result.expand_ = expand_;
+        result.dataBodyCase_ = dataBodyCase_;
+        onBuilt();
+        return result;
+      }
+
+      @java.lang.Override
+      public Builder clone() {
+        return super.clone();
+      }
+      @java.lang.Override
+      public Builder setField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          java.lang.Object value) {
+        return super.setField(field, value);
+      }
+      @java.lang.Override
+      public Builder clearField(
+          com.google.protobuf.Descriptors.FieldDescriptor field) {
+        return super.clearField(field);
+      }
+      @java.lang.Override
+      public Builder clearOneof(
+          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+        return super.clearOneof(oneof);
+      }
+      @java.lang.Override
+      public Builder setRepeatedField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          int index, java.lang.Object value) {
+        return super.setRepeatedField(field, index, value);
+      }
+      @java.lang.Override
+      public Builder addRepeatedField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          java.lang.Object value) {
+        return super.addRepeatedField(field, value);
+      }
+      @java.lang.Override
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof cn.com.zyjblogs.chat.netty.po.Msg.DataContent) {
+          return mergeFrom((cn.com.zyjblogs.chat.netty.po.Msg.DataContent)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(cn.com.zyjblogs.chat.netty.po.Msg.DataContent other) {
+        if (other == cn.com.zyjblogs.chat.netty.po.Msg.DataContent.getDefaultInstance()) return this;
+        if (other.dataType_ != 0) {
+          setDataTypeValue(other.getDataTypeValue());
+        }
+        if (!other.getFromUsername().isEmpty()) {
+          fromUsername_ = other.fromUsername_;
+          onChanged();
+        }
+        if (!other.getExpand().isEmpty()) {
+          expand_ = other.expand_;
+          onChanged();
+        }
+        switch (other.getDataBodyCase()) {
+          case MESSAGE: {
+            mergeMessage(other.getMessage());
+            break;
+          }
+          case DATABODY_NOT_SET: {
+            break;
+          }
+        }
+        this.mergeUnknownFields(other.unknownFields);
+        onChanged();
+        return this;
+      }
+
+      @java.lang.Override
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      @java.lang.Override
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        cn.com.zyjblogs.chat.netty.po.Msg.DataContent parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (cn.com.zyjblogs.chat.netty.po.Msg.DataContent) e.getUnfinishedMessage();
+          throw e.unwrapIOException();
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int dataBodyCase_ = 0;
+      private java.lang.Object dataBody_;
+      public DataBodyCase
+          getDataBodyCase() {
+        return DataBodyCase.forNumber(
+            dataBodyCase_);
+      }
+
+      public Builder clearDataBody() {
+        dataBodyCase_ = 0;
+        dataBody_ = null;
+        onChanged();
+        return this;
+      }
+
+
+      private int dataType_ = 0;
+      /**
+       * <pre>
+       *用DataType标识传的是那个枚举类型
+       * </pre>
+       *
+       * <code>.DataContent.DataType dataType = 1;</code>
+       * @return The enum numeric value on the wire for dataType.
+       */
+      @java.lang.Override public int getDataTypeValue() {
+        return dataType_;
+      }
+      /**
+       * <pre>
+       *用DataType标识传的是那个枚举类型
+       * </pre>
+       *
+       * <code>.DataContent.DataType dataType = 1;</code>
+       * @param value The enum numeric value on the wire for dataType to set.
+       * @return This builder for chaining.
+       */
+      public Builder setDataTypeValue(int value) {
+        
+        dataType_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <pre>
+       *用DataType标识传的是那个枚举类型
+       * </pre>
+       *
+       * <code>.DataContent.DataType dataType = 1;</code>
+       * @return The dataType.
+       */
+      @java.lang.Override
+      public cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataType getDataType() {
+        @SuppressWarnings("deprecation")
+        cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataType result = cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataType.valueOf(dataType_);
+        return result == null ? cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataType.UNRECOGNIZED : result;
+      }
+      /**
+       * <pre>
+       *用DataType标识传的是那个枚举类型
+       * </pre>
+       *
+       * <code>.DataContent.DataType dataType = 1;</code>
+       * @param value The dataType to set.
+       * @return This builder for chaining.
+       */
+      public Builder setDataType(cn.com.zyjblogs.chat.netty.po.Msg.DataContent.DataType value) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        
+        dataType_ = value.getNumber();
+        onChanged();
+        return this;
+      }
+      /**
+       * <pre>
+       *用DataType标识传的是那个枚举类型
+       * </pre>
+       *
+       * <code>.DataContent.DataType dataType = 1;</code>
+       * @return This builder for chaining.
+       */
+      public Builder clearDataType() {
+        
+        dataType_ = 0;
+        onChanged();
+        return this;
+      }
+
+      private com.google.protobuf.SingleFieldBuilderV3<
+          cn.com.zyjblogs.chat.netty.po.Msg.Message, cn.com.zyjblogs.chat.netty.po.Msg.Message.Builder, cn.com.zyjblogs.chat.netty.po.Msg.MessageOrBuilder> messageBuilder_;
+      /**
+       * <code>.Message message = 2;</code>
+       * @return Whether the message field is set.
+       */
+      @java.lang.Override
+      public boolean hasMessage() {
+        return dataBodyCase_ == 2;
+      }
+      /**
+       * <code>.Message message = 2;</code>
+       * @return The message.
+       */
+      @java.lang.Override
+      public cn.com.zyjblogs.chat.netty.po.Msg.Message getMessage() {
+        if (messageBuilder_ == null) {
+          if (dataBodyCase_ == 2) {
+            return (cn.com.zyjblogs.chat.netty.po.Msg.Message) dataBody_;
+          }
+          return cn.com.zyjblogs.chat.netty.po.Msg.Message.getDefaultInstance();
+        } else {
+          if (dataBodyCase_ == 2) {
+            return messageBuilder_.getMessage();
+          }
+          return cn.com.zyjblogs.chat.netty.po.Msg.Message.getDefaultInstance();
+        }
+      }
+      /**
+       * <code>.Message message = 2;</code>
+       */
+      public Builder setMessage(cn.com.zyjblogs.chat.netty.po.Msg.Message value) {
+        if (messageBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          dataBody_ = value;
+          onChanged();
+        } else {
+          messageBuilder_.setMessage(value);
+        }
+        dataBodyCase_ = 2;
+        return this;
+      }
+      /**
+       * <code>.Message message = 2;</code>
+       */
+      public Builder setMessage(
+          cn.com.zyjblogs.chat.netty.po.Msg.Message.Builder builderForValue) {
+        if (messageBuilder_ == null) {
+          dataBody_ = builderForValue.build();
+          onChanged();
+        } else {
+          messageBuilder_.setMessage(builderForValue.build());
+        }
+        dataBodyCase_ = 2;
+        return this;
+      }
+      /**
+       * <code>.Message message = 2;</code>
+       */
+      public Builder mergeMessage(cn.com.zyjblogs.chat.netty.po.Msg.Message value) {
+        if (messageBuilder_ == null) {
+          if (dataBodyCase_ == 2 &&
+              dataBody_ != cn.com.zyjblogs.chat.netty.po.Msg.Message.getDefaultInstance()) {
+            dataBody_ = cn.com.zyjblogs.chat.netty.po.Msg.Message.newBuilder((cn.com.zyjblogs.chat.netty.po.Msg.Message) dataBody_)
+                .mergeFrom(value).buildPartial();
+          } else {
+            dataBody_ = value;
+          }
+          onChanged();
+        } else {
+          if (dataBodyCase_ == 2) {
+            messageBuilder_.mergeFrom(value);
+          }
+          messageBuilder_.setMessage(value);
+        }
+        dataBodyCase_ = 2;
+        return this;
+      }
+      /**
+       * <code>.Message message = 2;</code>
+       */
+      public Builder clearMessage() {
+        if (messageBuilder_ == null) {
+          if (dataBodyCase_ == 2) {
+            dataBodyCase_ = 0;
+            dataBody_ = null;
+            onChanged();
+          }
+        } else {
+          if (dataBodyCase_ == 2) {
+            dataBodyCase_ = 0;
+            dataBody_ = null;
+          }
+          messageBuilder_.clear();
+        }
+        return this;
+      }
+      /**
+       * <code>.Message message = 2;</code>
+       */
+      public cn.com.zyjblogs.chat.netty.po.Msg.Message.Builder getMessageBuilder() {
+        return getMessageFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>.Message message = 2;</code>
+       */
+      @java.lang.Override
+      public cn.com.zyjblogs.chat.netty.po.Msg.MessageOrBuilder getMessageOrBuilder() {
+        if ((dataBodyCase_ == 2) && (messageBuilder_ != null)) {
+          return messageBuilder_.getMessageOrBuilder();
+        } else {
+          if (dataBodyCase_ == 2) {
+            return (cn.com.zyjblogs.chat.netty.po.Msg.Message) dataBody_;
+          }
+          return cn.com.zyjblogs.chat.netty.po.Msg.Message.getDefaultInstance();
+        }
+      }
+      /**
+       * <code>.Message message = 2;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilderV3<
+          cn.com.zyjblogs.chat.netty.po.Msg.Message, cn.com.zyjblogs.chat.netty.po.Msg.Message.Builder, cn.com.zyjblogs.chat.netty.po.Msg.MessageOrBuilder> 
+          getMessageFieldBuilder() {
+        if (messageBuilder_ == null) {
+          if (!(dataBodyCase_ == 2)) {
+            dataBody_ = cn.com.zyjblogs.chat.netty.po.Msg.Message.getDefaultInstance();
+          }
+          messageBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+              cn.com.zyjblogs.chat.netty.po.Msg.Message, cn.com.zyjblogs.chat.netty.po.Msg.Message.Builder, cn.com.zyjblogs.chat.netty.po.Msg.MessageOrBuilder>(
+                  (cn.com.zyjblogs.chat.netty.po.Msg.Message) dataBody_,
+                  getParentForChildren(),
+                  isClean());
+          dataBody_ = null;
+        }
+        dataBodyCase_ = 2;
+        onChanged();;
+        return messageBuilder_;
+      }
+
+      private java.lang.Object fromUsername_ = "";
+      /**
+       * <code>string fromUsername = 3;</code>
+       * @return The fromUsername.
+       */
+      public java.lang.String getFromUsername() {
+        java.lang.Object ref = fromUsername_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          fromUsername_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>string fromUsername = 3;</code>
+       * @return The bytes for fromUsername.
+       */
+      public com.google.protobuf.ByteString
+          getFromUsernameBytes() {
+        java.lang.Object ref = fromUsername_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          fromUsername_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>string fromUsername = 3;</code>
+       * @param value The fromUsername to set.
+       * @return This builder for chaining.
+       */
+      public Builder setFromUsername(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        fromUsername_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string fromUsername = 3;</code>
+       * @return This builder for chaining.
+       */
+      public Builder clearFromUsername() {
+        
+        fromUsername_ = getDefaultInstance().getFromUsername();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string fromUsername = 3;</code>
+       * @param value The bytes for fromUsername to set.
+       * @return This builder for chaining.
+       */
+      public Builder setFromUsernameBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+        
+        fromUsername_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object expand_ = "";
+      /**
+       * <code>string expand = 4;</code>
+       * @return The expand.
+       */
+      public java.lang.String getExpand() {
+        java.lang.Object ref = expand_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          expand_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>string expand = 4;</code>
+       * @return The bytes for expand.
+       */
+      public com.google.protobuf.ByteString
+          getExpandBytes() {
+        java.lang.Object ref = expand_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          expand_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>string expand = 4;</code>
+       * @param value The expand to set.
+       * @return This builder for chaining.
+       */
+      public Builder setExpand(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        expand_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string expand = 4;</code>
+       * @return This builder for chaining.
+       */
+      public Builder clearExpand() {
+        
+        expand_ = getDefaultInstance().getExpand();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string expand = 4;</code>
+       * @param value The bytes for expand to set.
+       * @return This builder for chaining.
+       */
+      public Builder setExpandBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+        
+        expand_ = value;
+        onChanged();
+        return this;
+      }
+      @java.lang.Override
+      public final Builder setUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return super.setUnknownFields(unknownFields);
+      }
+
+      @java.lang.Override
+      public final Builder mergeUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return super.mergeUnknownFields(unknownFields);
+      }
+
+
+      // @@protoc_insertion_point(builder_scope:DataContent)
+    }
+
+    // @@protoc_insertion_point(class_scope:DataContent)
+    private static final cn.com.zyjblogs.chat.netty.po.Msg.DataContent DEFAULT_INSTANCE;
+    static {
+      DEFAULT_INSTANCE = new cn.com.zyjblogs.chat.netty.po.Msg.DataContent();
+    }
+
+    public static cn.com.zyjblogs.chat.netty.po.Msg.DataContent getDefaultInstance() {
+      return DEFAULT_INSTANCE;
+    }
+
+    private static final com.google.protobuf.Parser<DataContent>
+        PARSER = new com.google.protobuf.AbstractParser<DataContent>() {
+      @java.lang.Override
+      public DataContent parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new DataContent(input, extensionRegistry);
+      }
+    };
+
+    public static com.google.protobuf.Parser<DataContent> parser() {
+      return PARSER;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<DataContent> getParserForType() {
+      return PARSER;
+    }
+
+    @java.lang.Override
+    public cn.com.zyjblogs.chat.netty.po.Msg.DataContent getDefaultInstanceForType() {
+      return DEFAULT_INSTANCE;
+    }
+
+  }
+
+  public interface MessageOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:Message)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>int64 id = 1;</code>
+     * @return The id.
+     */
+    long getId();
+
+    /**
+     * <code>string fromUsername = 2;</code>
+     * @return The fromUsername.
+     */
+    java.lang.String getFromUsername();
+    /**
+     * <code>string fromUsername = 2;</code>
+     * @return The bytes for fromUsername.
+     */
+    com.google.protobuf.ByteString
+        getFromUsernameBytes();
+
+    /**
+     * <code>string messageBody = 3;</code>
+     * @return The messageBody.
+     */
+    java.lang.String getMessageBody();
+    /**
+     * <code>string messageBody = 3;</code>
+     * @return The bytes for messageBody.
+     */
+    com.google.protobuf.ByteString
+        getMessageBodyBytes();
+
+    /**
+     * <code>.Message.MessageType messageType = 4;</code>
+     * @return The enum numeric value on the wire for messageType.
+     */
+    int getMessageTypeValue();
+    /**
+     * <code>.Message.MessageType messageType = 4;</code>
+     * @return The messageType.
+     */
+    cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageType getMessageType();
+
+    /**
+     * <code>.Message.MessageStatus messageStatus = 5;</code>
+     * @return The enum numeric value on the wire for messageStatus.
+     */
+    int getMessageStatusValue();
+    /**
+     * <code>.Message.MessageStatus messageStatus = 5;</code>
+     * @return The messageStatus.
+     */
+    cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageStatus getMessageStatus();
+
+    /**
+     * <code>string toUsername = 6;</code>
+     * @return The toUsername.
+     */
+    java.lang.String getToUsername();
+    /**
+     * <code>string toUsername = 6;</code>
+     * @return The bytes for toUsername.
+     */
+    com.google.protobuf.ByteString
+        getToUsernameBytes();
+
+    /**
+     * <code>.google.protobuf.Timestamp createTime = 7;</code>
+     * @return Whether the createTime field is set.
+     */
+    boolean hasCreateTime();
+    /**
+     * <code>.google.protobuf.Timestamp createTime = 7;</code>
+     * @return The createTime.
+     */
+    com.google.protobuf.Timestamp getCreateTime();
+    /**
+     * <code>.google.protobuf.Timestamp createTime = 7;</code>
+     */
+    com.google.protobuf.TimestampOrBuilder getCreateTimeOrBuilder();
+
+    /**
+     * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+     * @return Whether the updateTime field is set.
+     */
+    boolean hasUpdateTime();
+    /**
+     * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+     * @return The updateTime.
+     */
+    com.google.protobuf.Timestamp getUpdateTime();
+    /**
+     * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+     */
+    com.google.protobuf.TimestampOrBuilder getUpdateTimeOrBuilder();
+  }
+  /**
+   * Protobuf type {@code Message}
+   */
+  public static final class Message extends
+      com.google.protobuf.GeneratedMessageV3 implements
+      // @@protoc_insertion_point(message_implements:Message)
+      MessageOrBuilder {
+  private static final long serialVersionUID = 0L;
+    // Use Message.newBuilder() to construct.
+    private Message(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+      super(builder);
+    }
+    private Message() {
+      fromUsername_ = "";
+      messageBody_ = "";
+      messageType_ = 0;
+      messageStatus_ = 0;
+      toUsername_ = "";
+    }
+
+    @java.lang.Override
+    @SuppressWarnings({"unused"})
+    protected java.lang.Object newInstance(
+        UnusedPrivateParameter unused) {
+      return new Message();
+    }
+
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+    getUnknownFields() {
+      return this.unknownFields;
+    }
+    private Message(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      this();
+      if (extensionRegistry == null) {
+        throw new java.lang.NullPointerException();
+      }
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            case 8: {
+
+              id_ = input.readInt64();
+              break;
+            }
+            case 18: {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              fromUsername_ = s;
+              break;
+            }
+            case 26: {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              messageBody_ = s;
+              break;
+            }
+            case 32: {
+              int rawValue = input.readEnum();
+
+              messageType_ = rawValue;
+              break;
+            }
+            case 40: {
+              int rawValue = input.readEnum();
+
+              messageStatus_ = rawValue;
+              break;
+            }
+            case 50: {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              toUsername_ = s;
+              break;
+            }
+            case 58: {
+              com.google.protobuf.Timestamp.Builder subBuilder = null;
+              if (createTime_ != null) {
+                subBuilder = createTime_.toBuilder();
+              }
+              createTime_ = input.readMessage(com.google.protobuf.Timestamp.parser(), extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(createTime_);
+                createTime_ = subBuilder.buildPartial();
+              }
+
+              break;
+            }
+            case 66: {
+              com.google.protobuf.Timestamp.Builder subBuilder = null;
+              if (updateTime_ != null) {
+                subBuilder = updateTime_.toBuilder();
+              }
+              updateTime_ = input.readMessage(com.google.protobuf.Timestamp.parser(), extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(updateTime_);
+                updateTime_ = subBuilder.buildPartial();
+              }
+
+              break;
+            }
+            default: {
+              if (!parseUnknownField(
+                  input, unknownFields, extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return cn.com.zyjblogs.chat.netty.po.Msg.internal_static_Message_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return cn.com.zyjblogs.chat.netty.po.Msg.internal_static_Message_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              cn.com.zyjblogs.chat.netty.po.Msg.Message.class, cn.com.zyjblogs.chat.netty.po.Msg.Message.Builder.class);
+    }
+
+    /**
+     * Protobuf enum {@code Message.MessageType}
+     */
+    public enum MessageType
+        implements com.google.protobuf.ProtocolMessageEnum {
+      /**
+       * <code>System = 0;</code>
+       */
+      System(0),
+      /**
+       * <code>General = 1;</code>
+       */
+      General(1),
+      /**
+       * <code>Group = 2;</code>
+       */
+      Group(2),
+      UNRECOGNIZED(-1),
+      ;
+
+      /**
+       * <code>System = 0;</code>
+       */
+      public static final int System_VALUE = 0;
+      /**
+       * <code>General = 1;</code>
+       */
+      public static final int General_VALUE = 1;
+      /**
+       * <code>Group = 2;</code>
+       */
+      public static final int Group_VALUE = 2;
+
+
+      public final int getNumber() {
+        if (this == UNRECOGNIZED) {
+          throw new java.lang.IllegalArgumentException(
+              "Can't get the number of an unknown enum value.");
+        }
+        return value;
+      }
+
+      /**
+       * @param value The numeric wire value of the corresponding enum entry.
+       * @return The enum associated with the given numeric wire value.
+       * @deprecated Use {@link #forNumber(int)} instead.
+       */
+      @java.lang.Deprecated
+      public static MessageType valueOf(int value) {
+        return forNumber(value);
+      }
+
+      /**
+       * @param value The numeric wire value of the corresponding enum entry.
+       * @return The enum associated with the given numeric wire value.
+       */
+      public static MessageType forNumber(int value) {
+        switch (value) {
+          case 0: return System;
+          case 1: return General;
+          case 2: return Group;
+          default: return null;
+        }
+      }
+
+      public static com.google.protobuf.Internal.EnumLiteMap<MessageType>
+          internalGetValueMap() {
+        return internalValueMap;
+      }
+      private static final com.google.protobuf.Internal.EnumLiteMap<
+          MessageType> internalValueMap =
+            new com.google.protobuf.Internal.EnumLiteMap<MessageType>() {
+              public MessageType findValueByNumber(int number) {
+                return MessageType.forNumber(number);
+              }
+            };
+
+      public final com.google.protobuf.Descriptors.EnumValueDescriptor
+          getValueDescriptor() {
+        if (this == UNRECOGNIZED) {
+          throw new java.lang.IllegalStateException(
+              "Can't get the descriptor of an unrecognized enum value.");
+        }
+        return getDescriptor().getValues().get(ordinal());
+      }
+      public final com.google.protobuf.Descriptors.EnumDescriptor
+          getDescriptorForType() {
+        return getDescriptor();
+      }
+      public static final com.google.protobuf.Descriptors.EnumDescriptor
+          getDescriptor() {
+        return cn.com.zyjblogs.chat.netty.po.Msg.Message.getDescriptor().getEnumTypes().get(0);
+      }
+
+      private static final MessageType[] VALUES = values();
+
+      public static MessageType valueOf(
+          com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+        if (desc.getType() != getDescriptor()) {
+          throw new java.lang.IllegalArgumentException(
+            "EnumValueDescriptor is not for this type.");
+        }
+        if (desc.getIndex() == -1) {
+          return UNRECOGNIZED;
+        }
+        return VALUES[desc.getIndex()];
+      }
+
+      private final int value;
+
+      private MessageType(int value) {
+        this.value = value;
+      }
+
+      // @@protoc_insertion_point(enum_scope:Message.MessageType)
+    }
+
+    /**
+     * Protobuf enum {@code Message.MessageStatus}
+     */
+    public enum MessageStatus
+        implements com.google.protobuf.ProtocolMessageEnum {
+      /**
+       * <code>UNREAD = 0;</code>
+       */
+      UNREAD(0),
+      /**
+       * <code>READ = 1;</code>
+       */
+      READ(1),
+      UNRECOGNIZED(-1),
+      ;
+
+      /**
+       * <code>UNREAD = 0;</code>
+       */
+      public static final int UNREAD_VALUE = 0;
+      /**
+       * <code>READ = 1;</code>
+       */
+      public static final int READ_VALUE = 1;
+
+
+      public final int getNumber() {
+        if (this == UNRECOGNIZED) {
+          throw new java.lang.IllegalArgumentException(
+              "Can't get the number of an unknown enum value.");
+        }
+        return value;
+      }
+
+      /**
+       * @param value The numeric wire value of the corresponding enum entry.
+       * @return The enum associated with the given numeric wire value.
+       * @deprecated Use {@link #forNumber(int)} instead.
+       */
+      @java.lang.Deprecated
+      public static MessageStatus valueOf(int value) {
+        return forNumber(value);
+      }
+
+      /**
+       * @param value The numeric wire value of the corresponding enum entry.
+       * @return The enum associated with the given numeric wire value.
+       */
+      public static MessageStatus forNumber(int value) {
+        switch (value) {
+          case 0: return UNREAD;
+          case 1: return READ;
+          default: return null;
+        }
+      }
+
+      public static com.google.protobuf.Internal.EnumLiteMap<MessageStatus>
+          internalGetValueMap() {
+        return internalValueMap;
+      }
+      private static final com.google.protobuf.Internal.EnumLiteMap<
+          MessageStatus> internalValueMap =
+            new com.google.protobuf.Internal.EnumLiteMap<MessageStatus>() {
+              public MessageStatus findValueByNumber(int number) {
+                return MessageStatus.forNumber(number);
+              }
+            };
+
+      public final com.google.protobuf.Descriptors.EnumValueDescriptor
+          getValueDescriptor() {
+        if (this == UNRECOGNIZED) {
+          throw new java.lang.IllegalStateException(
+              "Can't get the descriptor of an unrecognized enum value.");
+        }
+        return getDescriptor().getValues().get(ordinal());
+      }
+      public final com.google.protobuf.Descriptors.EnumDescriptor
+          getDescriptorForType() {
+        return getDescriptor();
+      }
+      public static final com.google.protobuf.Descriptors.EnumDescriptor
+          getDescriptor() {
+        return cn.com.zyjblogs.chat.netty.po.Msg.Message.getDescriptor().getEnumTypes().get(1);
+      }
+
+      private static final MessageStatus[] VALUES = values();
+
+      public static MessageStatus valueOf(
+          com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+        if (desc.getType() != getDescriptor()) {
+          throw new java.lang.IllegalArgumentException(
+            "EnumValueDescriptor is not for this type.");
+        }
+        if (desc.getIndex() == -1) {
+          return UNRECOGNIZED;
+        }
+        return VALUES[desc.getIndex()];
+      }
+
+      private final int value;
+
+      private MessageStatus(int value) {
+        this.value = value;
+      }
+
+      // @@protoc_insertion_point(enum_scope:Message.MessageStatus)
+    }
+
+    public static final int ID_FIELD_NUMBER = 1;
+    private long id_;
+    /**
+     * <code>int64 id = 1;</code>
+     * @return The id.
+     */
+    @java.lang.Override
+    public long getId() {
+      return id_;
+    }
+
+    public static final int FROMUSERNAME_FIELD_NUMBER = 2;
+    private volatile java.lang.Object fromUsername_;
+    /**
+     * <code>string fromUsername = 2;</code>
+     * @return The fromUsername.
+     */
+    @java.lang.Override
+    public java.lang.String getFromUsername() {
+      java.lang.Object ref = fromUsername_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        fromUsername_ = s;
+        return s;
+      }
+    }
+    /**
+     * <code>string fromUsername = 2;</code>
+     * @return The bytes for fromUsername.
+     */
+    @java.lang.Override
+    public com.google.protobuf.ByteString
+        getFromUsernameBytes() {
+      java.lang.Object ref = fromUsername_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        fromUsername_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int MESSAGEBODY_FIELD_NUMBER = 3;
+    private volatile java.lang.Object messageBody_;
+    /**
+     * <code>string messageBody = 3;</code>
+     * @return The messageBody.
+     */
+    @java.lang.Override
+    public java.lang.String getMessageBody() {
+      java.lang.Object ref = messageBody_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        messageBody_ = s;
+        return s;
+      }
+    }
+    /**
+     * <code>string messageBody = 3;</code>
+     * @return The bytes for messageBody.
+     */
+    @java.lang.Override
+    public com.google.protobuf.ByteString
+        getMessageBodyBytes() {
+      java.lang.Object ref = messageBody_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        messageBody_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int MESSAGETYPE_FIELD_NUMBER = 4;
+    private int messageType_;
+    /**
+     * <code>.Message.MessageType messageType = 4;</code>
+     * @return The enum numeric value on the wire for messageType.
+     */
+    @java.lang.Override public int getMessageTypeValue() {
+      return messageType_;
+    }
+    /**
+     * <code>.Message.MessageType messageType = 4;</code>
+     * @return The messageType.
+     */
+    @java.lang.Override public cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageType getMessageType() {
+      @SuppressWarnings("deprecation")
+      cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageType result = cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageType.valueOf(messageType_);
+      return result == null ? cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageType.UNRECOGNIZED : result;
+    }
+
+    public static final int MESSAGESTATUS_FIELD_NUMBER = 5;
+    private int messageStatus_;
+    /**
+     * <code>.Message.MessageStatus messageStatus = 5;</code>
+     * @return The enum numeric value on the wire for messageStatus.
+     */
+    @java.lang.Override public int getMessageStatusValue() {
+      return messageStatus_;
+    }
+    /**
+     * <code>.Message.MessageStatus messageStatus = 5;</code>
+     * @return The messageStatus.
+     */
+    @java.lang.Override public cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageStatus getMessageStatus() {
+      @SuppressWarnings("deprecation")
+      cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageStatus result = cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageStatus.valueOf(messageStatus_);
+      return result == null ? cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageStatus.UNRECOGNIZED : result;
+    }
+
+    public static final int TOUSERNAME_FIELD_NUMBER = 6;
+    private volatile java.lang.Object toUsername_;
+    /**
+     * <code>string toUsername = 6;</code>
+     * @return The toUsername.
+     */
+    @java.lang.Override
+    public java.lang.String getToUsername() {
+      java.lang.Object ref = toUsername_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        toUsername_ = s;
+        return s;
+      }
+    }
+    /**
+     * <code>string toUsername = 6;</code>
+     * @return The bytes for toUsername.
+     */
+    @java.lang.Override
+    public com.google.protobuf.ByteString
+        getToUsernameBytes() {
+      java.lang.Object ref = toUsername_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        toUsername_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int CREATETIME_FIELD_NUMBER = 7;
+    private com.google.protobuf.Timestamp createTime_;
+    /**
+     * <code>.google.protobuf.Timestamp createTime = 7;</code>
+     * @return Whether the createTime field is set.
+     */
+    @java.lang.Override
+    public boolean hasCreateTime() {
+      return createTime_ != null;
+    }
+    /**
+     * <code>.google.protobuf.Timestamp createTime = 7;</code>
+     * @return The createTime.
+     */
+    @java.lang.Override
+    public com.google.protobuf.Timestamp getCreateTime() {
+      return createTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : createTime_;
+    }
+    /**
+     * <code>.google.protobuf.Timestamp createTime = 7;</code>
+     */
+    @java.lang.Override
+    public com.google.protobuf.TimestampOrBuilder getCreateTimeOrBuilder() {
+      return getCreateTime();
+    }
+
+    public static final int UPDATETIME_FIELD_NUMBER = 8;
+    private com.google.protobuf.Timestamp updateTime_;
+    /**
+     * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+     * @return Whether the updateTime field is set.
+     */
+    @java.lang.Override
+    public boolean hasUpdateTime() {
+      return updateTime_ != null;
+    }
+    /**
+     * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+     * @return The updateTime.
+     */
+    @java.lang.Override
+    public com.google.protobuf.Timestamp getUpdateTime() {
+      return updateTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : updateTime_;
+    }
+    /**
+     * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+     */
+    @java.lang.Override
+    public com.google.protobuf.TimestampOrBuilder getUpdateTimeOrBuilder() {
+      return getUpdateTime();
+    }
+
+    private byte memoizedIsInitialized = -1;
+    @java.lang.Override
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    @java.lang.Override
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      if (id_ != 0L) {
+        output.writeInt64(1, id_);
+      }
+      if (!getFromUsernameBytes().isEmpty()) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 2, fromUsername_);
+      }
+      if (!getMessageBodyBytes().isEmpty()) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 3, messageBody_);
+      }
+      if (messageType_ != cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageType.System.getNumber()) {
+        output.writeEnum(4, messageType_);
+      }
+      if (messageStatus_ != cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageStatus.UNREAD.getNumber()) {
+        output.writeEnum(5, messageStatus_);
+      }
+      if (!getToUsernameBytes().isEmpty()) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 6, toUsername_);
+      }
+      if (createTime_ != null) {
+        output.writeMessage(7, getCreateTime());
+      }
+      if (updateTime_ != null) {
+        output.writeMessage(8, getUpdateTime());
+      }
+      unknownFields.writeTo(output);
+    }
+
+    @java.lang.Override
+    public int getSerializedSize() {
+      int size = memoizedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (id_ != 0L) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(1, id_);
+      }
+      if (!getFromUsernameBytes().isEmpty()) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, fromUsername_);
+      }
+      if (!getMessageBodyBytes().isEmpty()) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, messageBody_);
+      }
+      if (messageType_ != cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageType.System.getNumber()) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeEnumSize(4, messageType_);
+      }
+      if (messageStatus_ != cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageStatus.UNREAD.getNumber()) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeEnumSize(5, messageStatus_);
+      }
+      if (!getToUsernameBytes().isEmpty()) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(6, toUsername_);
+      }
+      if (createTime_ != null) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(7, getCreateTime());
+      }
+      if (updateTime_ != null) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(8, getUpdateTime());
+      }
+      size += unknownFields.getSerializedSize();
+      memoizedSize = size;
+      return size;
+    }
+
+    @java.lang.Override
+    public boolean equals(final java.lang.Object obj) {
+      if (obj == this) {
+       return true;
+      }
+      if (!(obj instanceof cn.com.zyjblogs.chat.netty.po.Msg.Message)) {
+        return super.equals(obj);
+      }
+      cn.com.zyjblogs.chat.netty.po.Msg.Message other = (cn.com.zyjblogs.chat.netty.po.Msg.Message) obj;
+
+      if (getId()
+          != other.getId()) return false;
+      if (!getFromUsername()
+          .equals(other.getFromUsername())) return false;
+      if (!getMessageBody()
+          .equals(other.getMessageBody())) return false;
+      if (messageType_ != other.messageType_) return false;
+      if (messageStatus_ != other.messageStatus_) return false;
+      if (!getToUsername()
+          .equals(other.getToUsername())) return false;
+      if (hasCreateTime() != other.hasCreateTime()) return false;
+      if (hasCreateTime()) {
+        if (!getCreateTime()
+            .equals(other.getCreateTime())) return false;
+      }
+      if (hasUpdateTime() != other.hasUpdateTime()) return false;
+      if (hasUpdateTime()) {
+        if (!getUpdateTime()
+            .equals(other.getUpdateTime())) return false;
+      }
+      if (!unknownFields.equals(other.unknownFields)) return false;
+      return true;
+    }
+
+    @java.lang.Override
+    public int hashCode() {
+      if (memoizedHashCode != 0) {
+        return memoizedHashCode;
+      }
+      int hash = 41;
+      hash = (19 * hash) + getDescriptor().hashCode();
+      hash = (37 * hash) + ID_FIELD_NUMBER;
+      hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+          getId());
+      hash = (37 * hash) + FROMUSERNAME_FIELD_NUMBER;
+      hash = (53 * hash) + getFromUsername().hashCode();
+      hash = (37 * hash) + MESSAGEBODY_FIELD_NUMBER;
+      hash = (53 * hash) + getMessageBody().hashCode();
+      hash = (37 * hash) + MESSAGETYPE_FIELD_NUMBER;
+      hash = (53 * hash) + messageType_;
+      hash = (37 * hash) + MESSAGESTATUS_FIELD_NUMBER;
+      hash = (53 * hash) + messageStatus_;
+      hash = (37 * hash) + TOUSERNAME_FIELD_NUMBER;
+      hash = (53 * hash) + getToUsername().hashCode();
+      if (hasCreateTime()) {
+        hash = (37 * hash) + CREATETIME_FIELD_NUMBER;
+        hash = (53 * hash) + getCreateTime().hashCode();
+      }
+      if (hasUpdateTime()) {
+        hash = (37 * hash) + UPDATETIME_FIELD_NUMBER;
+        hash = (53 * hash) + getUpdateTime().hashCode();
+      }
+      hash = (29 * hash) + unknownFields.hashCode();
+      memoizedHashCode = hash;
+      return hash;
+    }
+
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message parseFrom(
+        java.nio.ByteBuffer data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message parseFrom(
+        java.nio.ByteBuffer data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input, extensionRegistry);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseDelimitedWithIOException(PARSER, input);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input);
+    }
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input, extensionRegistry);
+    }
+
+    @java.lang.Override
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder() {
+      return DEFAULT_INSTANCE.toBuilder();
+    }
+    public static Builder newBuilder(cn.com.zyjblogs.chat.netty.po.Msg.Message prototype) {
+      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+    }
+    @java.lang.Override
+    public Builder toBuilder() {
+      return this == DEFAULT_INSTANCE
+          ? new Builder() : new Builder().mergeFrom(this);
+    }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code Message}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:Message)
+        cn.com.zyjblogs.chat.netty.po.Msg.MessageOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return cn.com.zyjblogs.chat.netty.po.Msg.internal_static_Message_descriptor;
+      }
+
+      @java.lang.Override
+      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return cn.com.zyjblogs.chat.netty.po.Msg.internal_static_Message_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                cn.com.zyjblogs.chat.netty.po.Msg.Message.class, cn.com.zyjblogs.chat.netty.po.Msg.Message.Builder.class);
+      }
+
+      // Construct using cn.com.zyjblogs.chat.netty.po.Msg.Message.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessageV3
+                .alwaysUseFieldBuilders) {
+        }
+      }
+      @java.lang.Override
+      public Builder clear() {
+        super.clear();
+        id_ = 0L;
+
+        fromUsername_ = "";
+
+        messageBody_ = "";
+
+        messageType_ = 0;
+
+        messageStatus_ = 0;
+
+        toUsername_ = "";
+
+        if (createTimeBuilder_ == null) {
+          createTime_ = null;
+        } else {
+          createTime_ = null;
+          createTimeBuilder_ = null;
+        }
+        if (updateTimeBuilder_ == null) {
+          updateTime_ = null;
+        } else {
+          updateTime_ = null;
+          updateTimeBuilder_ = null;
+        }
+        return this;
+      }
+
+      @java.lang.Override
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return cn.com.zyjblogs.chat.netty.po.Msg.internal_static_Message_descriptor;
+      }
+
+      @java.lang.Override
+      public cn.com.zyjblogs.chat.netty.po.Msg.Message getDefaultInstanceForType() {
+        return cn.com.zyjblogs.chat.netty.po.Msg.Message.getDefaultInstance();
+      }
+
+      @java.lang.Override
+      public cn.com.zyjblogs.chat.netty.po.Msg.Message build() {
+        cn.com.zyjblogs.chat.netty.po.Msg.Message result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      @java.lang.Override
+      public cn.com.zyjblogs.chat.netty.po.Msg.Message buildPartial() {
+        cn.com.zyjblogs.chat.netty.po.Msg.Message result = new cn.com.zyjblogs.chat.netty.po.Msg.Message(this);
+        result.id_ = id_;
+        result.fromUsername_ = fromUsername_;
+        result.messageBody_ = messageBody_;
+        result.messageType_ = messageType_;
+        result.messageStatus_ = messageStatus_;
+        result.toUsername_ = toUsername_;
+        if (createTimeBuilder_ == null) {
+          result.createTime_ = createTime_;
+        } else {
+          result.createTime_ = createTimeBuilder_.build();
+        }
+        if (updateTimeBuilder_ == null) {
+          result.updateTime_ = updateTime_;
+        } else {
+          result.updateTime_ = updateTimeBuilder_.build();
+        }
+        onBuilt();
+        return result;
+      }
+
+      @java.lang.Override
+      public Builder clone() {
+        return super.clone();
+      }
+      @java.lang.Override
+      public Builder setField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          java.lang.Object value) {
+        return super.setField(field, value);
+      }
+      @java.lang.Override
+      public Builder clearField(
+          com.google.protobuf.Descriptors.FieldDescriptor field) {
+        return super.clearField(field);
+      }
+      @java.lang.Override
+      public Builder clearOneof(
+          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+        return super.clearOneof(oneof);
+      }
+      @java.lang.Override
+      public Builder setRepeatedField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          int index, java.lang.Object value) {
+        return super.setRepeatedField(field, index, value);
+      }
+      @java.lang.Override
+      public Builder addRepeatedField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          java.lang.Object value) {
+        return super.addRepeatedField(field, value);
+      }
+      @java.lang.Override
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof cn.com.zyjblogs.chat.netty.po.Msg.Message) {
+          return mergeFrom((cn.com.zyjblogs.chat.netty.po.Msg.Message)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(cn.com.zyjblogs.chat.netty.po.Msg.Message other) {
+        if (other == cn.com.zyjblogs.chat.netty.po.Msg.Message.getDefaultInstance()) return this;
+        if (other.getId() != 0L) {
+          setId(other.getId());
+        }
+        if (!other.getFromUsername().isEmpty()) {
+          fromUsername_ = other.fromUsername_;
+          onChanged();
+        }
+        if (!other.getMessageBody().isEmpty()) {
+          messageBody_ = other.messageBody_;
+          onChanged();
+        }
+        if (other.messageType_ != 0) {
+          setMessageTypeValue(other.getMessageTypeValue());
+        }
+        if (other.messageStatus_ != 0) {
+          setMessageStatusValue(other.getMessageStatusValue());
+        }
+        if (!other.getToUsername().isEmpty()) {
+          toUsername_ = other.toUsername_;
+          onChanged();
+        }
+        if (other.hasCreateTime()) {
+          mergeCreateTime(other.getCreateTime());
+        }
+        if (other.hasUpdateTime()) {
+          mergeUpdateTime(other.getUpdateTime());
+        }
+        this.mergeUnknownFields(other.unknownFields);
+        onChanged();
+        return this;
+      }
+
+      @java.lang.Override
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      @java.lang.Override
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        cn.com.zyjblogs.chat.netty.po.Msg.Message parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (cn.com.zyjblogs.chat.netty.po.Msg.Message) e.getUnfinishedMessage();
+          throw e.unwrapIOException();
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      private long id_ ;
+      /**
+       * <code>int64 id = 1;</code>
+       * @return The id.
+       */
+      @java.lang.Override
+      public long getId() {
+        return id_;
+      }
+      /**
+       * <code>int64 id = 1;</code>
+       * @param value The id to set.
+       * @return This builder for chaining.
+       */
+      public Builder setId(long value) {
+        
+        id_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>int64 id = 1;</code>
+       * @return This builder for chaining.
+       */
+      public Builder clearId() {
+        
+        id_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object fromUsername_ = "";
+      /**
+       * <code>string fromUsername = 2;</code>
+       * @return The fromUsername.
+       */
+      public java.lang.String getFromUsername() {
+        java.lang.Object ref = fromUsername_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          fromUsername_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>string fromUsername = 2;</code>
+       * @return The bytes for fromUsername.
+       */
+      public com.google.protobuf.ByteString
+          getFromUsernameBytes() {
+        java.lang.Object ref = fromUsername_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          fromUsername_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>string fromUsername = 2;</code>
+       * @param value The fromUsername to set.
+       * @return This builder for chaining.
+       */
+      public Builder setFromUsername(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        fromUsername_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string fromUsername = 2;</code>
+       * @return This builder for chaining.
+       */
+      public Builder clearFromUsername() {
+        
+        fromUsername_ = getDefaultInstance().getFromUsername();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string fromUsername = 2;</code>
+       * @param value The bytes for fromUsername to set.
+       * @return This builder for chaining.
+       */
+      public Builder setFromUsernameBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+        
+        fromUsername_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object messageBody_ = "";
+      /**
+       * <code>string messageBody = 3;</code>
+       * @return The messageBody.
+       */
+      public java.lang.String getMessageBody() {
+        java.lang.Object ref = messageBody_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          messageBody_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>string messageBody = 3;</code>
+       * @return The bytes for messageBody.
+       */
+      public com.google.protobuf.ByteString
+          getMessageBodyBytes() {
+        java.lang.Object ref = messageBody_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          messageBody_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>string messageBody = 3;</code>
+       * @param value The messageBody to set.
+       * @return This builder for chaining.
+       */
+      public Builder setMessageBody(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        messageBody_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string messageBody = 3;</code>
+       * @return This builder for chaining.
+       */
+      public Builder clearMessageBody() {
+        
+        messageBody_ = getDefaultInstance().getMessageBody();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string messageBody = 3;</code>
+       * @param value The bytes for messageBody to set.
+       * @return This builder for chaining.
+       */
+      public Builder setMessageBodyBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+        
+        messageBody_ = value;
+        onChanged();
+        return this;
+      }
+
+      private int messageType_ = 0;
+      /**
+       * <code>.Message.MessageType messageType = 4;</code>
+       * @return The enum numeric value on the wire for messageType.
+       */
+      @java.lang.Override public int getMessageTypeValue() {
+        return messageType_;
+      }
+      /**
+       * <code>.Message.MessageType messageType = 4;</code>
+       * @param value The enum numeric value on the wire for messageType to set.
+       * @return This builder for chaining.
+       */
+      public Builder setMessageTypeValue(int value) {
+        
+        messageType_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>.Message.MessageType messageType = 4;</code>
+       * @return The messageType.
+       */
+      @java.lang.Override
+      public cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageType getMessageType() {
+        @SuppressWarnings("deprecation")
+        cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageType result = cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageType.valueOf(messageType_);
+        return result == null ? cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageType.UNRECOGNIZED : result;
+      }
+      /**
+       * <code>.Message.MessageType messageType = 4;</code>
+       * @param value The messageType to set.
+       * @return This builder for chaining.
+       */
+      public Builder setMessageType(cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageType value) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        
+        messageType_ = value.getNumber();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>.Message.MessageType messageType = 4;</code>
+       * @return This builder for chaining.
+       */
+      public Builder clearMessageType() {
+        
+        messageType_ = 0;
+        onChanged();
+        return this;
+      }
+
+      private int messageStatus_ = 0;
+      /**
+       * <code>.Message.MessageStatus messageStatus = 5;</code>
+       * @return The enum numeric value on the wire for messageStatus.
+       */
+      @java.lang.Override public int getMessageStatusValue() {
+        return messageStatus_;
+      }
+      /**
+       * <code>.Message.MessageStatus messageStatus = 5;</code>
+       * @param value The enum numeric value on the wire for messageStatus to set.
+       * @return This builder for chaining.
+       */
+      public Builder setMessageStatusValue(int value) {
+        
+        messageStatus_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>.Message.MessageStatus messageStatus = 5;</code>
+       * @return The messageStatus.
+       */
+      @java.lang.Override
+      public cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageStatus getMessageStatus() {
+        @SuppressWarnings("deprecation")
+        cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageStatus result = cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageStatus.valueOf(messageStatus_);
+        return result == null ? cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageStatus.UNRECOGNIZED : result;
+      }
+      /**
+       * <code>.Message.MessageStatus messageStatus = 5;</code>
+       * @param value The messageStatus to set.
+       * @return This builder for chaining.
+       */
+      public Builder setMessageStatus(cn.com.zyjblogs.chat.netty.po.Msg.Message.MessageStatus value) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        
+        messageStatus_ = value.getNumber();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>.Message.MessageStatus messageStatus = 5;</code>
+       * @return This builder for chaining.
+       */
+      public Builder clearMessageStatus() {
+        
+        messageStatus_ = 0;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object toUsername_ = "";
+      /**
+       * <code>string toUsername = 6;</code>
+       * @return The toUsername.
+       */
+      public java.lang.String getToUsername() {
+        java.lang.Object ref = toUsername_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          toUsername_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>string toUsername = 6;</code>
+       * @return The bytes for toUsername.
+       */
+      public com.google.protobuf.ByteString
+          getToUsernameBytes() {
+        java.lang.Object ref = toUsername_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          toUsername_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>string toUsername = 6;</code>
+       * @param value The toUsername to set.
+       * @return This builder for chaining.
+       */
+      public Builder setToUsername(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        toUsername_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string toUsername = 6;</code>
+       * @return This builder for chaining.
+       */
+      public Builder clearToUsername() {
+        
+        toUsername_ = getDefaultInstance().getToUsername();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>string toUsername = 6;</code>
+       * @param value The bytes for toUsername to set.
+       * @return This builder for chaining.
+       */
+      public Builder setToUsernameBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+        
+        toUsername_ = value;
+        onChanged();
+        return this;
+      }
+
+      private com.google.protobuf.Timestamp createTime_;
+      private com.google.protobuf.SingleFieldBuilderV3<
+          com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> createTimeBuilder_;
+      /**
+       * <code>.google.protobuf.Timestamp createTime = 7;</code>
+       * @return Whether the createTime field is set.
+       */
+      public boolean hasCreateTime() {
+        return createTimeBuilder_ != null || createTime_ != null;
+      }
+      /**
+       * <code>.google.protobuf.Timestamp createTime = 7;</code>
+       * @return The createTime.
+       */
+      public com.google.protobuf.Timestamp getCreateTime() {
+        if (createTimeBuilder_ == null) {
+          return createTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : createTime_;
+        } else {
+          return createTimeBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>.google.protobuf.Timestamp createTime = 7;</code>
+       */
+      public Builder setCreateTime(com.google.protobuf.Timestamp value) {
+        if (createTimeBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          createTime_ = value;
+          onChanged();
+        } else {
+          createTimeBuilder_.setMessage(value);
+        }
+
+        return this;
+      }
+      /**
+       * <code>.google.protobuf.Timestamp createTime = 7;</code>
+       */
+      public Builder setCreateTime(
+          com.google.protobuf.Timestamp.Builder builderForValue) {
+        if (createTimeBuilder_ == null) {
+          createTime_ = builderForValue.build();
+          onChanged();
+        } else {
+          createTimeBuilder_.setMessage(builderForValue.build());
+        }
+
+        return this;
+      }
+      /**
+       * <code>.google.protobuf.Timestamp createTime = 7;</code>
+       */
+      public Builder mergeCreateTime(com.google.protobuf.Timestamp value) {
+        if (createTimeBuilder_ == null) {
+          if (createTime_ != null) {
+            createTime_ =
+              com.google.protobuf.Timestamp.newBuilder(createTime_).mergeFrom(value).buildPartial();
+          } else {
+            createTime_ = value;
+          }
+          onChanged();
+        } else {
+          createTimeBuilder_.mergeFrom(value);
+        }
+
+        return this;
+      }
+      /**
+       * <code>.google.protobuf.Timestamp createTime = 7;</code>
+       */
+      public Builder clearCreateTime() {
+        if (createTimeBuilder_ == null) {
+          createTime_ = null;
+          onChanged();
+        } else {
+          createTime_ = null;
+          createTimeBuilder_ = null;
+        }
+
+        return this;
+      }
+      /**
+       * <code>.google.protobuf.Timestamp createTime = 7;</code>
+       */
+      public com.google.protobuf.Timestamp.Builder getCreateTimeBuilder() {
+        
+        onChanged();
+        return getCreateTimeFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>.google.protobuf.Timestamp createTime = 7;</code>
+       */
+      public com.google.protobuf.TimestampOrBuilder getCreateTimeOrBuilder() {
+        if (createTimeBuilder_ != null) {
+          return createTimeBuilder_.getMessageOrBuilder();
+        } else {
+          return createTime_ == null ?
+              com.google.protobuf.Timestamp.getDefaultInstance() : createTime_;
+        }
+      }
+      /**
+       * <code>.google.protobuf.Timestamp createTime = 7;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilderV3<
+          com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> 
+          getCreateTimeFieldBuilder() {
+        if (createTimeBuilder_ == null) {
+          createTimeBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+              com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder>(
+                  getCreateTime(),
+                  getParentForChildren(),
+                  isClean());
+          createTime_ = null;
+        }
+        return createTimeBuilder_;
+      }
+
+      private com.google.protobuf.Timestamp updateTime_;
+      private com.google.protobuf.SingleFieldBuilderV3<
+          com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> updateTimeBuilder_;
+      /**
+       * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+       * @return Whether the updateTime field is set.
+       */
+      public boolean hasUpdateTime() {
+        return updateTimeBuilder_ != null || updateTime_ != null;
+      }
+      /**
+       * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+       * @return The updateTime.
+       */
+      public com.google.protobuf.Timestamp getUpdateTime() {
+        if (updateTimeBuilder_ == null) {
+          return updateTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : updateTime_;
+        } else {
+          return updateTimeBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+       */
+      public Builder setUpdateTime(com.google.protobuf.Timestamp value) {
+        if (updateTimeBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          updateTime_ = value;
+          onChanged();
+        } else {
+          updateTimeBuilder_.setMessage(value);
+        }
+
+        return this;
+      }
+      /**
+       * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+       */
+      public Builder setUpdateTime(
+          com.google.protobuf.Timestamp.Builder builderForValue) {
+        if (updateTimeBuilder_ == null) {
+          updateTime_ = builderForValue.build();
+          onChanged();
+        } else {
+          updateTimeBuilder_.setMessage(builderForValue.build());
+        }
+
+        return this;
+      }
+      /**
+       * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+       */
+      public Builder mergeUpdateTime(com.google.protobuf.Timestamp value) {
+        if (updateTimeBuilder_ == null) {
+          if (updateTime_ != null) {
+            updateTime_ =
+              com.google.protobuf.Timestamp.newBuilder(updateTime_).mergeFrom(value).buildPartial();
+          } else {
+            updateTime_ = value;
+          }
+          onChanged();
+        } else {
+          updateTimeBuilder_.mergeFrom(value);
+        }
+
+        return this;
+      }
+      /**
+       * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+       */
+      public Builder clearUpdateTime() {
+        if (updateTimeBuilder_ == null) {
+          updateTime_ = null;
+          onChanged();
+        } else {
+          updateTime_ = null;
+          updateTimeBuilder_ = null;
+        }
+
+        return this;
+      }
+      /**
+       * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+       */
+      public com.google.protobuf.Timestamp.Builder getUpdateTimeBuilder() {
+        
+        onChanged();
+        return getUpdateTimeFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+       */
+      public com.google.protobuf.TimestampOrBuilder getUpdateTimeOrBuilder() {
+        if (updateTimeBuilder_ != null) {
+          return updateTimeBuilder_.getMessageOrBuilder();
+        } else {
+          return updateTime_ == null ?
+              com.google.protobuf.Timestamp.getDefaultInstance() : updateTime_;
+        }
+      }
+      /**
+       * <code>.google.protobuf.Timestamp updateTime = 8;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilderV3<
+          com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> 
+          getUpdateTimeFieldBuilder() {
+        if (updateTimeBuilder_ == null) {
+          updateTimeBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+              com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder>(
+                  getUpdateTime(),
+                  getParentForChildren(),
+                  isClean());
+          updateTime_ = null;
+        }
+        return updateTimeBuilder_;
+      }
+      @java.lang.Override
+      public final Builder setUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return super.setUnknownFields(unknownFields);
+      }
+
+      @java.lang.Override
+      public final Builder mergeUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return super.mergeUnknownFields(unknownFields);
+      }
+
+
+      // @@protoc_insertion_point(builder_scope:Message)
+    }
+
+    // @@protoc_insertion_point(class_scope:Message)
+    private static final cn.com.zyjblogs.chat.netty.po.Msg.Message DEFAULT_INSTANCE;
+    static {
+      DEFAULT_INSTANCE = new cn.com.zyjblogs.chat.netty.po.Msg.Message();
+    }
+
+    public static cn.com.zyjblogs.chat.netty.po.Msg.Message getDefaultInstance() {
+      return DEFAULT_INSTANCE;
+    }
+
+    private static final com.google.protobuf.Parser<Message>
+        PARSER = new com.google.protobuf.AbstractParser<Message>() {
+      @java.lang.Override
+      public Message parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new Message(input, extensionRegistry);
+      }
+    };
+
+    public static com.google.protobuf.Parser<Message> parser() {
+      return PARSER;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<Message> getParserForType() {
+      return PARSER;
+    }
+
+    @java.lang.Override
+    public cn.com.zyjblogs.chat.netty.po.Msg.Message getDefaultInstanceForType() {
+      return DEFAULT_INSTANCE;
+    }
+
+  }
+
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_DataContent_descriptor;
+  private static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_DataContent_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_Message_descriptor;
+  private static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_Message_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static  com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n+cn/com/zyjblogs/chat/netty/po/Message." +
+      "proto\032\037google/protobuf/timestamp.proto\"\323" +
+      "\001\n\013DataContent\022\'\n\010dataType\030\001 \001(\0162\025.DataC" +
+      "ontent.DataType\022\033\n\007message\030\002 \001(\0132\010.Messa" +
+      "geH\000\022\024\n\014fromUsername\030\003 \001(\t\022\016\n\006expand\030\004 \001" +
+      "(\t\"L\n\010DataType\022\016\n\nCONNECTING\020\000\022\r\n\tKEEPAL" +
+      "IVE\020\001\022\010\n\004CHAT\020\002\022\013\n\007CLOSING\020\003\022\n\n\006SIGNED\020\004" +
+      "B\n\n\010dataBody\"\350\002\n\007Message\022\n\n\002id\030\001 \001(\003\022\024\n\014" +
+      "fromUsername\030\002 \001(\t\022\023\n\013messageBody\030\003 \001(\t\022" +
+      ")\n\013messageType\030\004 \001(\0162\024.Message.MessageTy" +
+      "pe\022-\n\rmessageStatus\030\005 \001(\0162\026.Message.Mess" +
+      "ageStatus\022\022\n\ntoUsername\030\006 \001(\t\022.\n\ncreateT" +
+      "ime\030\007 \001(\0132\032.google.protobuf.Timestamp\022.\n" +
+      "\nupdateTime\030\010 \001(\0132\032.google.protobuf.Time" +
+      "stamp\"1\n\013MessageType\022\n\n\006System\020\000\022\013\n\007Gene" +
+      "ral\020\001\022\t\n\005Group\020\002\"%\n\rMessageStatus\022\n\n\006UNR" +
+      "EAD\020\000\022\010\n\004READ\020\001B&\n\035cn.com.zyjblogs.chat." +
+      "netty.poB\003MsgH\001b\006proto3"
+    };
+    descriptor = com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+          com.google.protobuf.TimestampProto.getDescriptor(),
+        });
+    internal_static_DataContent_descriptor =
+      getDescriptor().getMessageTypes().get(0);
+    internal_static_DataContent_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_DataContent_descriptor,
+        new java.lang.String[] { "DataType", "Message", "FromUsername", "Expand", "DataBody", });
+    internal_static_Message_descriptor =
+      getDescriptor().getMessageTypes().get(1);
+    internal_static_Message_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_Message_descriptor,
+        new java.lang.String[] { "Id", "FromUsername", "MessageBody", "MessageType", "MessageStatus", "ToUsername", "CreateTime", "UpdateTime", });
+    com.google.protobuf.TimestampProto.getDescriptor();
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}

+ 5 - 3
src/main/resources/application.yml

@@ -8,7 +8,9 @@ server:
 
 logging:
   level:
-    root: INFO
+    root: DEBUG
+  file:
+    path: ./logs
 
 management:
   endpoints:
@@ -23,7 +25,7 @@ management:
 # 服务名称配置(同时测名称也是注册到eureka中心的名称)
 spring:
   application:
-    name: hatech-bcms-core
+    name: chat-server
   zipkin:
     #base-url:当你设置sleuth-cli收集信息后通过http传输到zinkin-server时,需要在这里配置
     base-url: http://10.27.5.129:9411
@@ -145,4 +147,4 @@ async:
       queue_capacity: 50
       # 配置线程池中的线程的名称前缀
       name:
-        prefix: async-service-
+        prefix: async-service-

+ 17 - 3
src/main/resources/banner.txt

@@ -1,3 +1,17 @@
-///////////////
-    逝水无痕
-////////////
+${AnsiColor.GREEN}
+                                                        ,--,
+         ,----,                   ,---._             ,---.'|       ,----..
+       .'   .`|                 .-- -.' \     ,---,. |   | :      /   /   \    ,----..    .--.--.
+    .'   .'   ;      ,---,      |    |   :  ,'  .'  \:   : |     /   .     :  /   /   \  /  /    '.
+  ,---, '    .'     /_ ./|      :    ;   |,---.' .' ||   ' :    .   /   ;.  \|   :     :|  :  /`. /
+  |   :     ./,---, |  ' :      :        ||   |  |: |;   ; '   .   ;   /  ` ;.   |  ;. /;  |  |--`
+  ;   | .'  //___/ \.  : |      |    :   ::   :  :  /'   | |__ ;   |  ; \ ; |.   ; /--` |  :  ;_
+  `---' /  ;  .  \  \ ,' '      :         :   |    ; |   | :.'||   :  | ; | ';   | ;  __ \  \    `.
+    /  ;  /    \  ;  `  ,'      |    ;   ||   :     \'   :    ;.   |  ' ' ' :|   : |.' .' `----.   \
+   ;  /  /--,   \  \    '   ___ l         |   |   . ||   |  ./ '   ;  \; /  |.   | '_.' : __ \  \  |
+  /  /  / .`|    '  \   | /    /\    J   :'   :  '; |;   : ;    \   \  ',  / '   ; : \  |/  /`--'  /
+./__;       :     \  ;  ;/  ../  `..-    ,|   |  | ; |   ,/      ;   :    /  '   | '/  .'--'.     /
+|   :     .'       :  \  \    \         ; |   :   /  '---'        \   \ .'   |   :    /   `--'---'
+;   |  .'           \  ' ;\    \      ,'  |   | ,'                 `---`      \   \ .'
+`---'                `--`  "---....--'    `----'                               `---`
+ChatServer ${spring-boot.version}

+ 39 - 0
src/main/resources/logback-spring.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <property name="LOG_PATH" value="logs" />
+    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %-40.40logger{39} : %msg%n" />
+
+    <!-- 控制台输出 -->
+    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
+        <!-- 彩色日志 -->
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <pattern>
+                %d{yyyy-MM-dd HH:mm:ss} [%-30.30thread] %magenta(%-5level) %green([%-50.50class]) >>> %cyan(%msg) %n
+            </pattern>
+        </layout>
+    </appender>
+
+    <!-- 按照每天生成日志文件 -->
+    <appender name="fileLog"  class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志文件输出的文件名-->
+            <FileNamePattern>${LOG_PATH}/cms.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
+            <!--日志文件最大的大小-->
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <MaxHistory>30</MaxHistory>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${LOG_PATTERN}</pattern>
+        </encoder>
+    </appender>
+
+    <!-- 日志输出级别 -->
+    <root level="info">
+        <appender-ref ref="consoleLog" />
+        <appender-ref ref="fileLog" />
+    </root>
+
+</configuration>

+ 1 - 1
src/test/java/cn/com/zyjblogs/chat/ChatApplicationTests.java → src/test/java/cn/com/zyjblogs/chat/ChatServerApplicationTests.java

@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
 
 @SpringBootTest
-class ChatApplicationTests {
+class ChatServerApplicationTests {
 
     @Test
     void contextLoads() {

Some files were not shown because too many files changed in this diff