项目使用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); } } }