詳細說明請參考:https://github.com/grpc/grpc-java
build.gradle
build.gradle檔案中具體引用,建議看下 https://github.com/grpc/grpc-java
group 'com.hll'
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'com.google.protobuf'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile (
"io.netty:netty-all:4.1.9.Final",
"com.google.protobuf:protobuf-java:3.3.1",
"com.google.protobuf:protobuf-java-util:3.3.1",
"org.apache.thrift:libthrift:0.12.0",
"io.grpc:grpc-netty:1.4.0",
"io.grpc:grpc-protobuf:1.4.0",
"io.grpc:grpc-stub:1.4.0"
)
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.4'
}
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.2.0"
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.4.0'
}
}
//自定義檔案生成路徑
generateProtoTasks.generatedFilesBaseDir = "src"
generateProtoTasks {
all()*.plugins {
grpc {
//自定義檔案生成路徑
setOutputSubDir 'java'
}
}
}
}
配置完成之後,在Gradle的Tasks裡面可以看到generateProto,說明已經引用成功
建立 src/main/proto
檔案夾,并建立proto檔案
src/main/proto
注意:建立的proto檔案需要在
src/main/proto
路徑下。
syntax = "proto3";
package com.hll.proto;
option java_package = "com.hll.proto";
option java_outer_classname = "PersonProto";
option java_multiple_files = true;
//rpc方法
service PersonService {
rpc GetRealNameByUsername(MyRequest) returns (MyResponse) {}
}
//請求
message MyRequest {
string username = 1;
}
//響應
message MyResponse {
string realname = 2;
}
proto檔案編寫完成之後,通過Tasks裡面的
generateProto
指令生成代碼檔案。
#執行指令
gradle generateProto
成功之後,在build目錄就會有生成的檔案
然後把生成的檔案全部複制到新建立的
com.hll.proto
包中
注意
通過gradle generateProto生成檔案預設在build檔案夾下生成,然後我們會把生成的所有檔案複制到自己建立的包中,當我們對項目執行build操作時就會報錯,提示類重複了,是以我們需要将gradle generateProto生成的檔案直接在我們定義的包中生成才可以。不然每次build工程時,build檔案夾下面就會重新生成新的proto相關檔案。
服務端和用戶端業務代碼
建立一個類,實作grpc生成的方法
PersonServiceImpl
package com.hll.grpc;
import com.hll.proto.MyRequest;
import com.hll.proto.MyResponse;
import com.hll.proto.PersonServiceGrpc;
import io.grpc.stub.StreamObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 繼承grpc生成的抽象類PersonServiceImplBase
*/
public class PersonServiceImpl extends PersonServiceGrpc.PersonServiceImplBase {
private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* 用戶端向服務端發起一個rpc調用會進入到這個方法
* @param request
* @param responseObserver 該方法是void類型無傳回值, 通過responseObserver實作傳回結果
*/
@Override
public void getRealNameByUsername(MyRequest request, StreamObserver<MyResponse> responseObserver) {
logger.info("接收到用戶端資訊:" + request.getUsername());
//服務端把結果構造完并傳回給用戶端
responseObserver.onNext(MyResponse.newBuilder()
.setRealname("張三")
.build());
//通知用戶端方法執行完成,onCompleted隻能調用一次
responseObserver.onCompleted();
}
}
服務端:GrpcServer
package com.hll.grpc;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import java.io.IOException;
/**
* 服務端.可參考官方例子代碼
*/
public class GrpcServer {
private Server server;
public static void main(String[] args) throws IOException, InterruptedException {
GrpcServer server = new GrpcServer();
server.start();
server.awaitTermination();
}
//啟動服務
private void start() throws IOException {
this.server = ServerBuilder.forPort(8899).addService(new PersonServiceImpl()).build().start();
System.out.println("server started...");
}
//停止服務
private void stop() {
if (null != this.server) {
this.server.shutdown();
}
}
//服務啟動之後就會立刻停止,awaitTermination會保持服務一直運作
private void awaitTermination() throws InterruptedException {
if (null != this.server) {
this.server.awaitTermination();
}
}
}
用戶端:GrpcClient
package com.hll.grpc;
import com.hll.proto.MyRequest;
import com.hll.proto.MyResponse;
import com.hll.proto.PersonServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
/**
* 用戶端.可參考官方例子代碼
*/
public class GrpcClient {
public static void main(String[] args) {
ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 8899)
.usePlaintext(true).build();
PersonServiceGrpc.PersonServiceBlockingStub blockingStub = PersonServiceGrpc
.newBlockingStub(managedChannel);
MyResponse myResponse = blockingStub
.getRealNameByUsername(MyRequest.newBuilder().setUsername("zhangsan").build());
System.out.println(myResponse.getRealname());
}
}
啟動服務端和用戶端
在控制台可以看到通信資訊