grpc例子 Java后端和Android端实现

文章目录

        • 效果
          • 电脑端
          • Android手机端
        • demo下载
        • 实现
          • Server端
            • 工具:idea
            • proto 文件的主要代码
            • 生成Java代码
            • Server类的主要代码
            • client类的主要代码
          • Android手机端的步骤
            • 引入相关库
            • 引入proto文件并生成java代码
            • 主要代码
        • 参考文献

效果
电脑端

grpc例子 Java后端和Android端实现_第1张图片

Android手机端

demo下载

下载demo请点击这里

实现
  • 这里使用的grpc的版本是 1.42.1
Server端
工具:idea
  • 具体的引入库我这里就不多介绍了,都在demo里,回头自己在demo看

以下是通过idea创建项目,熟悉的可以直接看下一步

  1. 步骤一:
    grpc例子 Java后端和Android端实现_第2张图片
  2. 步骤二
    grpc例子 Java后端和Android端实现_第3张图片
  3. 步骤三:导入相关库并点击如下按钮进行同步
    grpc例子 Java后端和Android端实现_第4张图片
proto 文件的主要代码
syntax = "proto3";
service TestService{
  // 第一种
  rpc add(TRequest) returns (TReply){}
  // 第二种
  rpc min(TRequest) returns(stream TReply){}
  // 第三种
  rpc max(stream TRequest) returns(stream TReply){}
  // 第四种
  rpc talk(stream Msg) returns(stream Msg){}
}
生成Java代码

grpc例子 Java后端和Android端实现_第5张图片

Server类的主要代码
public class TestServer extends TestServiceGrpc.TestServiceImplBase {

    private StreamObserver<Msg> responseObserver;

    @Override
    public void add(TRequest request, StreamObserver<TReply> responseObserver) {
        int res = myAdd(request.getA(), request.getB());
        responseObserver.onNext(TReply.newBuilder().setRes(res).build());
        responseObserver.onCompleted();
    }

    @Override
    public void min(TRequest request, StreamObserver<TReply> responseObserver) {
        int myMin = myMin(request.getA(), request.getB());
        responseObserver.onNext(TReply.newBuilder().setRes(myMin).build());
        responseObserver.onCompleted();
    }

    @Override
    public StreamObserver<TRequest> max(StreamObserver<TReply> responseObserver) {
        return new StreamObserver<TRequest>() {
            @Override
            public void onNext(TRequest tRequest) {
                int myMax = myMax(tRequest.getA(), tRequest.getB());
                responseObserver.onNext(TReply.newBuilder().setRes(myMax).build());
            }

            @Override
            public void onError(Throwable throwable) {
                responseObserver.onError(throwable);
            }

            @Override
            public void onCompleted() {
                responseObserver.onCompleted();
            }
        };
    }

    @Override
    public StreamObserver<Msg> talk(StreamObserver<Msg> responseObserver) {
        this.responseObserver = responseObserver;
        return new StreamObserver<Msg>() {
            @Override
            public void onNext(Msg msg) {
                System.out.println("进入talk:" + msg.getMsg());
//                responseObserver.onNext(msg);
            }

            @Override
            public void onError(Throwable throwable) {
                responseObserver.onError(throwable);
            }

            @Override
            public void onCompleted() {
                System.out.println("onCompleted");
                responseObserver.onCompleted();
            }
        };
    }
    public StreamObserver<Msg> getResponseSo() {
        return responseObserver;
    }
}
client类的主要代码
public class TestClient {

    TestServiceGrpc.TestServiceBlockingStub blockingStub;
    TestServiceGrpc.TestServiceStub stub;
    ManagedChannel channel;
    int port = 10086;
    boolean isD = false;

    public static void main(String[] args) {

        TestClient client = new TestClient();
        Scanner scanner = new Scanner(System.in);

        // max
        StreamObserver<TRequest> maxRequest = client.stub.max(new MyStreamObserver<TReply>("max", tReply -> System.out.println("max:结果为:" + tReply.getRes())));
        StreamObserver<Msg> talkRequest = client.stub.talk(new MyStreamObserver<Msg>("talk", msg -> System.out.println("服务端:" + msg.getMsg())));

        while (true) {
            if (!client.isD)
                System.out.println("请先确定方式:\n\r a:add  b:min  c:max  d:talk q:quit");
            String type = scanner.nextLine();
            if (type.equals("q")) {
                if (client.isD) {
                    client.isD = false;
                } else {
                    maxRequest.onCompleted();
                    talkRequest.onCompleted();
                    client.channel.shutdown();
                    break;
                }
            }
            if (client.isD) {
                talkRequest.onNext(Msg.newBuilder().setMsg(type).build());
            } else
                switch (type) {
                    case "a":
                        // add
                        System.out.println("请输入两个数 用空格分开");
                        String[] s = scanner.nextLine().split(" ");
                        if (s.length >= 2) {
                            int i1 = Integer.parseInt(s[0]);
                            int i2 = Integer.parseInt(s[1]);
                            try {
                                TReply reply = client.blockingStub.add(TRequest.newBuilder().setA(i1).setB(i2).build());
                                System.out.println("结果为:" + reply.getRes());
                            } catch (Exception e) {
                                System.out.println("发生错误:" + e.getMessage());
                            }
                        } else {
                            System.out.println("输入错误!");
                        }
                        break;
                    case "b":
                        // min
                        System.out.println("请输入两个数 用空格分开");
                        s = scanner.nextLine().split(" ");
                        if (s.length >= 2) {
                            int i1 = Integer.parseInt(s[0]);
                            int i2 = Integer.parseInt(s[1]);
                            try {
                                Iterator<TReply> it = client.blockingStub.min(TRequest.newBuilder().setA(i1).setB(i2).build());
                                TReply reply;
                                while (it.hasNext()) {
                                    reply = it.next();
                                    System.out.println("结果为:" + reply.getRes());
                                }
                            } catch (Exception e) {
                                System.out.println("发生错误:" + e.getMessage());
                            }
                        } else {
                            System.out.println("输入错误!");
                        }
                        break;
                    case "c":
                        // min
                        System.out.println("请输入两个数 用空格分开");
                        s = scanner.nextLine().trim().split(" ");
                        if (s.length >= 2) {
                            int i1 = Integer.parseInt(s[0]);
                            int i2 = Integer.parseInt(s[1]);
                            try {
                                maxRequest.onNext(TRequest.newBuilder().setA(i1).setB(i2).build());
                            } catch (Exception e) {
                                System.out.println("发生错误:" + e.getMessage());
                            }
                        } else {
                            System.out.println("输入错误!");
                        }
                        break;
                    case "d":
                        client.isD = true;
                        System.out.println("请输入内容");
                        break;
                }
        }

    }

    public TestClient() {
        channel = ManagedChannelBuilder
                .forAddress("127.0.0.1", port)
                .usePlaintext()
                .build();
        stub = TestServiceGrpc.newStub(channel);
        blockingStub = TestServiceGrpc.newBlockingStub(channel);
    }
}

写到这里,就可以在电脑端进行测试

Android手机端的步骤
引入相关库
  1. 在最外层build.gradle中引入protobuf的plugin
buildscript {
    dependencies {
        ....
        classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.17"
    }
}
  1. 在module的build.gradle中引入如下代码
plugins {
	...
    id 'com.google.protobuf'
}
protobuf {
    protoc { artifact = 'com.google.protobuf:protoc:3.17.2' }
    plugins {
        javalite { artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0" }
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.42.1' // CURRENT_GRPC_VERSION
        }
    }
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                java { option 'lite' }
            }
            task.plugins {
                grpc { // Options added to --grpc_out
                    option 'lite'
                }
            }
        }
    }
    //配置proto生成java代码的目录 (可选)
    generatedFilesBaseDir = "$projectDir/src/generated"
}
dependencies {
	...
    implementation 'io.grpc:grpc-okhttp:1.42.1' // CURRENT_GRPC_VERSION
    implementation 'io.grpc:grpc-protobuf-lite:1.42.1' // CURRENT_GRPC_VERSION
    implementation 'io.grpc:grpc-stub:1.42.1' // CURRENT_GRPC_VERSION
    implementation 'org.apache.tomcat:annotations-api:6.0.53'
}
引入proto文件并生成java代码

引入相关proto文件并重新rebuild项目来生成相关的java代码
grpc例子 Java后端和Android端实现_第6张图片

主要代码

与服务端建立通讯

private fun init() {
    // 在这里根据IP地址和端口号创建管道
    channel = ManagedChannelBuilder.forAddress(address, port).usePlaintext().build()
    // 然后根据管道创建 stub
    // 这俩的区别是 blockingStub是阻塞式的,stub是异步的,
    // 通过调用就可以看出来它们的区别
    stub = TestServiceGrpc.newStub(channel)
    blockingStub = TestServiceGrpc.newBlockingStub(channel)
}
  1. 客户端的几个主要方法
  • add
// 直接通过blockingStub调用方法,它是阻塞式的,直接是等待服务端返回结果
// reply 就是服务端返回的数据                   
val reply = blockingStub?.add(TRequest.newBuilder().setA(str1.toInt()).setB(str2.toInt()).build())
bind.tvResult.text = reply?.res.toString()
  • talk
// 首先是设置服务端的数据回调
// 下面就是拿着这个request来进行访问
// stub就是异步的
talkRequest = stub?.talk(MyStreamObserver("talk", object : OnResult<Msg> {
    @SuppressLint("NotifyDataSetChanged")
    override fun onNext(v: Msg) {
        // 这里就是服务端返回的数据
    }
}))
// 下面就是直接通过onNext方法就可以把数据传给服务端,
// 服务端返回的数据就会通过上面的回调函数传过来
talkRequest?.onNext(Msg.newBuilder().setMsg(str).build())

好了,这里就列举了add和talk两个实现方式不同的方法,其他的都跟这俩类似,就不重复写了。

参考文献
  1. https://github.com/grpc/grpc-java
  2. grpc为例了解rpc的用法
  3. grpc for java 双向流式通信实践
  4. 执行jar包中指定main方法

你可能感兴趣的:(java,java,android,grpc,protobuf)