SpringBoot Grpc插件自动PROTO文件生成代码

2024-03-26 15:20

本文主要是介绍SpringBoot Grpc插件自动PROTO文件生成代码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 问题:gRPC 官方文档不够详细

在调研 gRPC java 时遇到一个问题,根据官方文档,没有办法一次性就把示例跑成功。

而是花了整整两天时间,翻了各种文档才搞清楚,proto compiler、maven、gRPC-java 这几个之间的关系。

现在提供一个端到端的,能够保证一次性就跑起来的 gRPC-java 示例程序。

2 通过 maven 构建 java 工程

java version: 1.8 gRPC version: 1.29.0 pom.xml 核心配置部分

2.1 pom核心依赖

<dependency><groupId>io.grpc</groupId><artifactId>grpc-netty-shaded</artifactId><version>1.29.0</version>
</dependency>
<dependency><groupId>io.grpc</groupId><artifactId>grpc-protobuf</artifactId><version>1.29.0</version>
</dependency>
<dependency><groupId>io.grpc</groupId><artifactId>grpc-stub</artifactId><version>1.29.0</version>
</dependency>
<!-- necessary for Java 9+ -->
<!--java 低于 1.8 的版本不需要此依赖-->
<dependency> <groupId>org.apache.tomcat</groupId><artifactId>annotations-api</artifactId><version>6.0.53</version><scope>provided</scope>
</dependency>

2.2 pom配置 proto 插件

os-maven-plugin:此插件可以检测当前系统信息 ${os.detected.classifier}:这个变量获取操作系统的版本,例如osx-x86_64

<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><protocArtifact>com.google.protobuf:protoc:3.11.0:exe:${os.detected.classifier}</protocArtifact><pluginId>grpc-java</pluginId><pluginArtifact>io.grpc:protoc-gen-grpc-java:1.29.0:exe:${os.detected.classifier}</pluginArtifact></configuration><executions><execution><goals><goal>compile</goal><goal>compile-custom</goal></goals></execution></executions></plugin></plugins>
</build>

3 定义 proto 文件

在 src/main/proto 目录下放 helloworld.proto 文件

代码组织结构

代码组织结构

syntax = "proto3";option java_generic_services = true;
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";// The greeting service definition.
service Greeter {// Sends a greetingrpc SayHello (HelloRequest) returns (HelloReply) {}
}// The request message containing the user's name.
message HelloRequest {string name = 1;
}// The response message containing the greetings
message HelloReply {string message = 1;
}

4 通过 maven 插件根据 proto 生成 java 代码

执行 mvn compile命令,自动生成代码。 默认生成的代码在,target/generated-sources/protobuf 目录下。 其中 grpc-java 目录下放的是生成的 Service 对应的类,java 目录下放的是生成的message 对应的 java对象。

maven 生成的代码所在的路径

maven 生成的代码所在的路径

5 gRPC-java,server 端代码示例

直接运行 main 函数,服务端就开始工作。

package io.grpc.examples.helloworld;import java.io.IOException;
import java.util.concurrent.TimeUnit;import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;/*** @ClassName HelloWorldServer* @Description* @Author hugo_lei* @Date 13/5/20 上午11:09*/
public class HelloWorldServer {private Server server;private void start() throws IOException {/* The port on which the server should run */int port = 50051;server = ServerBuilder.forPort(port).addService(new GreeterImpl()).build().start();Runtime.getRuntime().addShutdownHook(new Thread() {@Overridepublic void run() {// Use stderr here since the logger may have been reset by its JVM shutdown hook.System.err.println("*** shutting down gRPC server since JVM is shutting down");try {HelloWorldServer.this.stop();} catch (InterruptedException e) {e.printStackTrace(System.err);}System.err.println("*** server shut down");}});}private void stop() throws InterruptedException {if (server != null) {server.shutdown().awaitTermination(30, TimeUnit.SECONDS);}}/*** Await termination on the main thread since the grpc library uses daemon threads.*/private void blockUntilShutdown() throws InterruptedException {if (server != null) {server.awaitTermination();}}/*** Main launches the server from the command line.*/public static void main(String[] args) throws IOException, InterruptedException {final HelloWorldServer server = new HelloWorldServer();server.start();server.blockUntilShutdown();}static class GreeterImpl extends GreeterGrpc.GreeterImplBase {@Overridepublic void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();System.out.println("=====server=====");System.out.println("server: Hello " + req.getName());responseObserver.onNext(reply);responseObserver.onCompleted();}}
}

6 gRPC-java,client 端代码示例

每执行一次 main 函数,client 就相当于向 server 发送了一次请求。

package io.grpc.examples.helloworld;import java.util.concurrent.TimeUnit;import io.grpc.Channel;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;/*** @ClassName HelloWorldClient* @Description* @Author hugo_lei* @Date 13/5/20 上午11:13*/
public class HelloWorldClient {private final GreeterGrpc.GreeterBlockingStub blockingStub;/** Construct client for accessing HelloWorld server using the existing channel. */public HelloWorldClient(Channel channel) {// 'channel' here is a Channel, not a ManagedChannel, so it is not this code's responsibility to// shut it down.// Passing Channels to code makes code easier to test and makes it easier to reuse Channels.blockingStub = GreeterGrpc.newBlockingStub(channel);}/** Say hello to server. */public void greet(String name) {HelloRequest request = HelloRequest.newBuilder().setName(name).build();HelloReply response;try {response = blockingStub.sayHello(request);} catch (StatusRuntimeException e) {return;}System.out.println("Greeting: " + response.getMessage());}/*** Greet server. If provided, the first element of {@code args} is the name to use in the* greeting. The second argument is the target server.*/public static void main(String[] args) throws Exception {String user = "hahahahah";// Access a service running on the local machine on port 50051String target = "localhost:50051";// Allow passing in the user and target strings as command line argumentsif (args.length > 0) {if ("--help".equals(args[0])) {System.err.println("Usage: [name [target]]");System.err.println("");System.err.println("  name    The name you wish to be greeted by. Defaults to " + user);System.err.println("  target  The server to connect to. Defaults to " + target);System.exit(1);}user = args[0];}if (args.length > 1) {target = args[1];}// Create a communication channel to the server, known as a Channel. Channels are thread-safe// and reusable. It is common to create channels at the beginning of your application and reuse// them until the application shuts down.ManagedChannel channel = ManagedChannelBuilder.forTarget(target)// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid// needing certificates..usePlaintext().build();try {HelloWorldClient client = new HelloWorldClient(channel);client.greet(user);} finally {// ManagedChannels use resources like threads and TCP connections. To prevent leaking these// resources the channel should be shut down when it will no longer be used. If it may be used// again leave it running.channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);}}
}

7 gRPC-java示例代码运行结果

在这里插入图片描述

这篇关于SpringBoot Grpc插件自动PROTO文件生成代码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/848935

相关文章

Java实现字符串大小写转换的常用方法

《Java实现字符串大小写转换的常用方法》在Java中,字符串大小写转换是文本处理的核心操作之一,Java提供了多种灵活的方式来实现大小写转换,适用于不同场景和需求,本文将全面解析大小写转换的各种方法... 目录前言核心转换方法1.String类的基础方法2. 考虑区域设置的转换3. 字符级别的转换高级转换

使用Python将PDF表格自动提取并写入Word文档表格

《使用Python将PDF表格自动提取并写入Word文档表格》在实际办公与数据处理场景中,PDF文件里的表格往往无法直接复制到Word中,本文将介绍如何使用Python从PDF文件中提取表格数据,并将... 目录引言1. 加载 PDF 文件并准备 Word 文档2. 提取 PDF 表格并创建 Word 表格

HTML5的input标签的`type`属性值详解和代码示例

《HTML5的input标签的`type`属性值详解和代码示例》HTML5的`input`标签提供了多种`type`属性值,用于创建不同类型的输入控件,满足用户输入的多样化需求,从文本输入、密码输入、... 目录一、引言二、文本类输入类型2.1 text2.2 password2.3 textarea(严格

SpringBoot简单整合ElasticSearch实践

《SpringBoot简单整合ElasticSearch实践》Elasticsearch支持结构化和非结构化数据检索,通过索引创建和倒排索引文档,提高搜索效率,它基于Lucene封装,分为索引库、类型... 目录一:ElasticSearch支持对结构化和非结构化的数据进行检索二:ES的核心概念Index:

Java方法重载与重写之同名方法的双面魔法(最新整理)

《Java方法重载与重写之同名方法的双面魔法(最新整理)》文章介绍了Java中的方法重载Overloading和方法重写Overriding的区别联系,方法重载是指在同一个类中,允许存在多个方法名相同... 目录Java方法重载与重写:同名方法的双面魔法方法重载(Overloading):同门师兄弟的不同绝

Spring配置扩展之JavaConfig的使用小结

《Spring配置扩展之JavaConfig的使用小结》JavaConfig是Spring框架中基于纯Java代码的配置方式,用于替代传统的XML配置,通过注解(如@Bean)定义Spring容器的组... 目录JavaConfig 的概念什么是JavaConfig?为什么使用 JavaConfig?Jav

Java数组动态扩容的实现示例

《Java数组动态扩容的实现示例》本文主要介绍了Java数组动态扩容的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1 问题2 方法3 结语1 问题实现动态的给数组添加元素效果,实现对数组扩容,原始数组使用静态分配

Java中ArrayList与顺序表示例详解

《Java中ArrayList与顺序表示例详解》顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构,:本文主要介绍Java中ArrayList与... 目录前言一、Java集合框架核心接口与分类ArrayList二、顺序表数据结构中的顺序表三、常用代码手动

JAVA项目swing转javafx语法规则以及示例代码

《JAVA项目swing转javafx语法规则以及示例代码》:本文主要介绍JAVA项目swing转javafx语法规则以及示例代码的相关资料,文中详细讲解了主类继承、窗口创建、布局管理、控件替换、... 目录最常用的“一行换一行”速查表(直接全局替换)实际转换示例(JFramejs → JavaFX)迁移建

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过