项目使用maven构建,执行mvn compile 命令后,proto文件自动生成java文件,这个功能需要依赖相关编译插件。
一、pom.xml配置
<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>
二、proto文档(IDL文档)编辑和编译成java文件
//指定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/ 路径下。
项目文件结构如下:
三、服务端代码
在 /src/main/java/ 路径下新建目录 /server,存放服务端代码。
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();
}
}
}
四、客户端代码
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);
}
}
}
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。