環境配置
<?xml version="1.0" encoding="UTF-8"?>
<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>org.example</groupId>
<artifactId>JAVA-GRPC</artifactId>
<version>1.0-SNAPSHOT</version>
<properties> <maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> <dependencies> <!-- gRPC core library -->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>1.56.0</version> <!-- 使用最新版本 -->
</dependency>
<dependency> <groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.56.0</version>
</dependency> <dependency> <groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.56.0</version>
</dependency> <!-- Protocol Buffers -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.24.0</version> <!-- 使用最新版本 -->
</dependency>
<dependency> <groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency> </dependencies>
<build> <extensions> <extension> <groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</version>
</extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration> <!--suppress UnresolvedMavenProperty -->
<protocArtifact>com.google.protobuf:protoc:3.19.2:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<!--suppress UnresolvedMavenProperty -->
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.44.1:exe:${os.detected.classifier}</pluginArtifact>
</configuration> <executions> <execution> <goals> <goal>compile</goal>
<goal>compile-custom</goal>
</goals> </execution> </executions> </plugin> </plugins> </build>
</project>
程式碼生成
// 宣告版本
syntax = "proto3";
//服務方法,接受客戶端引數,返回服務端響應
service SayHello {
rpc SayHello(HelloRequest) returns (HelloResponse) {}
}
//類似結構體
message HelloRequest {
string username = 1;
int64 code = 2;
}
message HelloResponse {
string responseMsg = 1;
}
然後點選idea的maven為所有專案生成原始碼並更新資料夾,來生成對應的java程式碼。
客戶端
程式碼示例
public class Main {
public static void main(String[] args) {
// 建立 gRPC 連線
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 2333)
.usePlaintext() // 使用明文傳輸
.build();
// 建立客戶端存根
SayHelloGrpc.SayHelloBlockingStub stub = SayHelloGrpc.newBlockingStub(channel);
// 建立請求
Hello.HelloRequest request = Hello.HelloRequest.newBuilder()
.setUsername("World java")
.setCode(12345)
.build();
// 傳送請求並接收響應
Hello.HelloResponse response = stub.sayHello(request);
System.out.println("Response: " + response.getResponseMsg());
// 關閉通道
channel.shutdown();
}
}
ManagedChannel建立
ManagedChannel 是 gRPC Java 中用於與 gRPC 伺服器進行通訊的主要介面。它提供了一種安全且高效的方式來管理連線。
// 建立 gRPC 連線
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 2333).usePlaintext().build();
這裡usePlaintext()代表使用明文進行傳輸。
存根建立
SayHelloGrpc.SayHelloBlockingStub stub = SayHelloGrpc.newBlockingStub(channel);
方法呼叫
我們有了存根,那麼呼叫方法就很簡單了。
Hello.HelloRequest request = Hello.HelloRequest.newBuilder()
.setUsername("World java")
.setCode(12345)
.build();
// 傳送請求並接收響應
Hello.HelloResponse response = stub.sayHello(request);
System.out.println("Response: " + response.getResponseMsg());
建立對應的請求和回應物件,然後透過存根呼叫方法即可。
服務端
程式碼示例
public class HelloServer extends SayHelloGrpc.SayHelloImplBase {
@Override
public void sayHello(Hello.HelloRequest req, StreamObserver<Hello.HelloResponse> responseObserver) {
String message = "Hello " + req.getUsername() + "\nYour code is: " + req.getCode();
Hello.HelloResponse response = Hello.HelloResponse.newBuilder()
.setResponseMsg(message)
.build();
// 傳送響應
responseObserver.onNext(response);
responseObserver.onCompleted();
}
public static void main(String[] args) throws IOException, InterruptedException {
// 建立 gRPC 伺服器
Server server = ServerBuilder.forPort(2333)
.addService(new HelloServer())
.build()
.start();
System.out.println("Server started on port 2333...");
// 等待伺服器停止
server.awaitTermination();
}
}
服務端建立
public static void main(String[] args) throws IOException, InterruptedException {
// 建立 gRPC 伺服器
Server server = ServerBuilder.forPort(2333)
.addService(new HelloServer())
.build()
.start();
System.out.println("Server started on port 2333...");
// 等待伺服器停止
server.awaitTermination();
}
這裡類似於客戶端的存根建立,我們這裡建立服務端並進行服務繫結。
服務建立
public class HelloServer extends SayHelloGrpc.SayHelloImplBase {
@Override
public void sayHello(Hello.HelloRequest req, StreamObserver<Hello.HelloResponse> responseObserver) {
String message = "Hello " + req.getUsername() + "\nYour code is: " + req.getCode();
Hello.HelloResponse response = Hello.HelloResponse.newBuilder()
.setResponseMsg(message)
.build();
// 傳送響應
responseObserver.onNext(response);
responseObserver.onCompleted();
}
直接繼承生成的對應類,然後我們在對應的方法中填寫對應的邏輯即可。這裡的StreamObserver<Hello.HelloResponse> responseObserver類有常用的3個方法:
- onNext(HelloResponse response): 用於傳送一個響應物件到客戶端。
- onCompleted(): 指示所有響應已經傳送完成,客戶端可以結束處理。
- onError(Throwable t): 用於在發生錯誤時向客戶端報告錯誤。