Netty整合protobuf解决多message的多协议实现的项目演示

上一篇文章已经实现了通过Netty整合protobuf进行简单的客户端给服务端发消息,功能上来说protobuf确实不太能看出有其他业务能力,但是性能上来说确实是提升了很多毕竟主要作用是序列化后和反序列化。但是一个问题是如果.proto里面有多个message,那么方法内该如何识别传输/接收哪个message属性呢???

接下来说一下解决这个问题的步骤:可以将多个message放在外部,然后一个主message,在里面通过DataType设立一个枚举组来调用他们,并且使用oneof保证一次只调用一个节省内存。

syntax = "proto2";

package com.gongda.protobuf;

option optimize_for = SPEED;
option java_package = "netty.protobuf";
option java_outer_classname = "DataInfo";

message MyMessage{
    enum DataType{
        StudentType = 1;
        DogType = 2;
        CatType = 3;
    }

    required DataType data_type = 1;

    oneof dataBody{
        Student  student = 2;
        Dog dog = 3;
        Cat cat = 4;
    }
}

message Student{
    optional string name = 1;
    optional int32 age = 2;
    optional string address = 3;
}

message Dog{
    optional string name = 1;
    optional int32 age = 2;
}

message Cat{
    optional string name = 1;
    optional string city = 2;
}

oneof:有多个字段但是只想选择其中的一个字段的时候,oneof可以节省内存

既然选择了这个规则,有一个原则不能忘记,在调用的时候只能调用最外部的message去实现,就是MyMessage而且为了保证是可以去随意去调用的,要去修改Handler并且用一个随机函数来证明。。。

现在主要来说一下逻辑,先说说客户端的Handler要使用客户端给服务器端发消息,在SpringMVC中服务端虽然不用去写,是前端的工作但是必须要说一下还是建议去了解Servlet生命周期。。

Handler实现中要了解的事情:

  1. 显示出上面提到的oneof关键字的效果,需要用一个随机数体现出每次只实现其中一个message逻辑
  2. 发送信息的格式还是采用设计模式中的构造者模式,先实现枚举组中最大的DataType,然后由DataType去实现,内部包含三个Message
  3. 节省空间采用单例模式,保证只实例化一次。

TestClientHandler:

package netty.sixthexample;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import netty.protobuf.DataInfo;

import java.util.Random;

public class TestClientHandler extends SimpleChannelInboundHandler<DataInfo.MyMessage> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, DataInfo.MyMessage msg) throws Exception {

    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

        int randomInt = new Random().nextInt(3);

        DataInfo.MyMessage myMessage = null;

        if (0 == randomInt) {
            myMessage = DataInfo.MyMessage.newBuilder().setDataType(DataInfo.MyMessage.DataType.StudentType).setStudent(DataInfo.Student.newBuilder().setName("zxvc").setAge(18).setAddress("anhui").build()).build();
        }else if (1 == randomInt){
            myMessage = DataInfo.MyMessage.newBuilder().setDataType(DataInfo.MyMessage.DataType.DogType).setDog(DataInfo.Dog.newBuilder().setName("happy").setAge(1).build()).build();
        }else {
            myMessage = DataInfo.MyMessage.newBuilder().setDataType(DataInfo.MyMessage.DataType.CatType).setCat(DataInfo.Cat.newBuilder().setName("haha").setCity("上海").build()).build();
        }
        ctx.channel().writeAndFlush(myMessage);
    }
}

现在来说一下服务端Handler 的实现思路:

  1. msg里面封装好了Client发送过来的信息,信息确实在msg但是确切说是在msg的dataType里面,因此首先要获取到dataType
  2. 获取到DataType后可以根据枚举组去获取到想要的信息了,但是注意的是因为之前用的是随机,因此这里肯定也是if-else去获取信息

来看一下TestServerHandler的具体实现:

package netty.sixthexample;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import netty.protobuf.DataInfo;

public class TestServerHandler extends SimpleChannelInboundHandler<DataInfo.MyMessage> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, DataInfo.MyMessage msg) throws Exception {
        DataInfo.MyMessage.DataType dataType = msg.getDataType();

        if (dataType == DataInfo.MyMessage.DataType.StudentType) {
            DataInfo.Student student = msg.getStudent();
            System.out.println(student.getName());
            System.out.println(student.getAge());
            System.out.println(student.getAddress());
        }else if (dataType == DataInfo.MyMessage.DataType.DogType){
            DataInfo.Dog dog = msg.getDog();
            System.out.println(dog.getName());
            System.out.println(dog.getAge());
        }else {
            DataInfo.Cat cat = msg.getCat();
            System.out.println(cat.getName());
            System.out.println(cat.getCity());
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值