項目使用maven構建,執行mvn compile 命令後,proto文件自動生成java文件,這個功能須要依賴相關編譯插件。
1、pom.xml配置java
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.test.grpcTest</groupId> <artifactId>grpc-api</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>`` <name>grpc-api</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- 添加grpc相關依賴包 --> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-all</artifactId> <version>0.13.2</version> </dependency> </dependencies> <!-- proto自動生成java文件所需的編譯插件 --> <build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.4.1.Final</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.5.0</version> <configuration> <protocArtifact>com.google.protobuf:protoc:3.0.0:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.0.0:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
2、proto文檔(IDL文檔)編輯和編譯成java文件apache
//指定proto3格式 syntax = "proto3"; //一些生成代碼的設置 option java_multiple_files = false;//以非外部類模式生成 option java_package = "com.test.grpcTest.grpc_api";//所在包名 option java_outer_classname = "Grpc";//最外層類名稱 message UnaryRequest{ string serviceName = 1; string methodName = 2; bytes data = 3; string request_id = 4;//參數默認都爲可選,若是沒有賦值,那麼接口中不會出現該參數,不會默認爲null之類的 } message UnaryResponse{ string serviceName = 1; string methodName = 2; bytes data = 3; string request_id = 4; } service GrpcService{ // 一對一服務請求 rpc SendUnaryRequest(UnaryRequest) returns(UnaryResponse); }
proto文件編輯好後,在項目根目錄下執行 **mvn compile** 進行編譯 。 若是使用maven編譯proto文件,那麼須要默認將proto文件放在 /src/main/proto/ 路徑下。 編譯後生成的java文件在 target/generated-sources/ 路徑下。 將 java 文件拷貝到 /src/main/java/ 路徑下。 項目文件結構以下:
3、服務端代碼
在 /src/main/java/ 路徑下新建目錄 /server,存放服務端代碼。api
package com.test.grpcTest.grpc_api.server; import com.test.grpcTest.grpc_api.GrpcServiceGrpc; import com.test.grpcTest.grpc_api.UnaryRequest; import com.test.grpcTest.grpc_api.UnaryResponse; import com.google.protobuf.ByteString; import io.grpc.Server; import io.grpc.ServerBuilder; import io.grpc.stub.StreamObserver; import java.io.IOException; //Grpc服務器對象 public class GrpcServer { private int port = 50051;//grpc服務端口 private Server server;//grpc server public static void main(String[] args) throws IOException,InterruptedException { final GrpcServer server = new GrpcServer(); server.start(); server.blockUntilShutdown(); } private void start() throws IOException { //指定grpc服務器端口、接口服務對象,啓動grpc服務器 server = ServerBuilder.forPort(port).addService(new GreeterImpl()) .build().start(); System.out.println("service start..."); //添加停機邏輯 Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { System.err.println("*** shutting down gRPC server since JVM is shutting down"); GrpcServer.this.stop(); System.err.println("*** server shut down"); } }); } private void blockUntilShutdown() throws InterruptedException { if (server != null) { server.awaitTermination(); } } private void stop() { if (server != null) { server.shutdown(); } } //內部類,繼承抽象類 GrpcServiceGrpc.GrpcServiceImplBase, //並重寫服務方法 sendUnaryRequest private class GreeterImpl extends GrpcServiceGrpc.GrpcServiceImplBase { //UnaryRequest 客戶端請求參數, //StreamObserver<UnaryResponse> 返回給客戶端的封裝參數 public void sendUnaryRequest(UnaryRequest request,StreamObserver<UnaryResponse> responseObserver) { ByteString message = request.getData(); System.out.println("server, serviceName:" + request.getServiceName() + "; methodName:" + request.getMethodName()+"; datas:"+new String(message.toByteArray())); UnaryResponse.Builder builder = UnaryResponse.newBuilder(); builder.setServiceName("GrpcServiceResponse").setMethodName("sendUnaryResponse"); responseObserver.onNext(builder.build()); responseObserver.onCompleted(); } } }
4、客戶端代碼服務器
package com.test.grpcTest.grpc_api.client; import java.util.concurrent.TimeUnit; import com.test.grpcTest.grpc_api.GrpcServiceGrpc; import com.test.grpcTest.grpc_api.UnaryRequest; import com.test.grpcTest.grpc_api.UnaryResponse; import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; //grpc客戶端類 public class GrpcClient { private final ManagedChannel channel;//客戶端與服務器的通訊channel private final GrpcServiceGrpc.GrpcServiceBlockingStub blockStub;//阻塞式客戶端存根節點 public GrpcClient(String host, int port) { channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext(true).build();//指定grpc服務器地址和端口初始化通訊channel blockStub = GrpcServiceGrpc.newBlockingStub(channel);//根據通訊channel初始化客戶端存根節點 } public void shutdown() throws InterruptedException{ channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); } //客戶端方法 public void sayHello(String str){ //封裝請求參數 UnaryRequest request = UnaryRequest.newBuilder() .setServiceName("GrpcServiceRequest").setMethodName("sendUnaryRequest").setData(ByteString.copyFrom(str.getBytes())) .build(); //客戶端存根節點調用grpc服務接口,傳遞請求參數 UnaryResponse response = blockStub.sendUnaryRequest(request); System.out.println("client, serviceName:"+response.getServiceName()+"; methodName:"+response.getMethodName()); } public static void main(String[] args) throws InterruptedException{ //初始化grpc客戶端對象 GrpcClient client = new GrpcClient("127.0.0.1",50051); for(int i=0; i<5; i++){ client.sayHello("client word:"+ i); Thread.sleep(3000); } } }