springboot 集成 grpc 和 protobuf(二) | 在实际项目中使用 grpc 和 protobuf


不熟悉grpc和protobuf的请参考第一篇:

springboot 集成 grpc 和 protobuf(一) | grpc和protobuf 的简介及本地使用.


注意:下面的测试代码写在同一个项目中!


一、项目结构:如下图


二、项目搭建

2.1 引入pom依赖:代码比较长,请耐心

<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.45</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.9</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.0</version></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.38</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency><!--使用grpc和protobuf--><!-- protobuf依赖--><dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>3.5.1</version></dependency><!--grpc依赖--><dependency><groupId>io.grpc</groupId><artifactId>grpc-all</artifactId><version>1.11.0</version></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.25.Final</version></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-tcnative-boringssl-static</artifactId><version>2.0.8.Final</version></dependency><!--grpc客户端--><dependency><groupId>net.devh</groupId><artifactId>grpc-client-spring-boot-starter</artifactId><version>1.3.0-RELEASE</version></dependency><!--grpc服务端--><dependency><groupId>net.devh</groupId><artifactId>grpc-server-spring-boot-starter</artifactId><version>1.3.0-RELEASE</version></dependency></dependencies><build><extensions><extension><groupId>kr.motd.maven</groupId><artifactId>os-maven-plugin</artifactId><version>1.6.0</version></extension></extensions><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin><!--跳过test测试--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><skip>true</skip></configuration></plugin><plugin><groupId>org.xolstice.maven.plugins</groupId><artifactId>protobuf-maven-plugin</artifactId><version>0.5.0</version><configuration><protocArtifact>com.google.protobuf:protoc:3.5.1:exe:${os.detected.classifier}</protocArtifact><pluginId>grpc-java</pluginId><pluginArtifact>io.grpc:protoc-gen-grpc-java:1.11.0:exe:${os.detected.classifier}</pluginArtifact><!--默认值--><protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot><!--默认值--><!--<outputDirectory>${project.build.directory}/generated-sources/protobuf/java</outputDirectory>--><outputDirectory>${project.basedir}/src/main/java</outputDirectory><!--设置是否在生成java文件之前清空outputDirectory的文件,默认值为true,设置为false时也会覆盖同名文件--><clearOutputDirectory>false</clearOutputDirectory></configuration><executions><execution><!--在执行mvn compile的时候会执行以下操作--><phase>compile</phase><goals><!--生成OuterClass类--><goal>compile</goal><!--生成Grpc类--><goal>compile-custom</goal></goals></execution></executions></plugin></plugins></build>

2.2 proto 文件介绍,第一篇也有介绍

文件名:data.proto
syntax = "proto3";package example; //编译出来的文件存放目录service FormatData {  rpc DoFormat(Data) returns (Data){}  //这里后面会用到,注意!!!// DoForma 客户端调用服务端使用的方法// Data 消息体,跟实体类类似,传参和返回都是一个实体接收
}message Data {string text = 1;  // 1:代表第一个参数string flag = 2;  // 2:代表第二个参数
}

2.3 项目搭建好后,使用 maven 编译一下


2.4 然后会在java目录下生成:以Grpc结尾的文件才是连接的主要

2.4.1 DataOuterClass 文件是生成上面 data.proto 里面的message下面的 text 和 flag 参数的set和get方法,相当于实体Bean
2.4.2 FormatDataGrpc 文件是 grpc 的连接服务,下面会用这个调用


2.5 编写客户端:


三、代码编写:下面是先写的客户端代码,再写的服务端代码


客户端

3.1 application.yml文件配置(注意,yml文件中最下面url和端口根据启动项目打印的来,服务端有启动时有介绍)

server:port: 8078servlet:context-path: /huangtu-timer# mysql
spring:# 环境 dev|test|prodprofiles:active: testlogging:level: debuglevel.com.huangtu: debugpath: logs/file: timer.log# Grpc配置
grpc:client:local-grpc-server:#测试,大写转小写host: 0.0.0.0           #grpc服务端的 urlport: 9090             #grpc服务端的端口enableKeepAlive: truekeepAliveWithoutCalls: true

3.2 客户端代码如下:一边参考 data.proto 文件一边理解更好

使用自动注入只需要配置yml中的即可,手动配置url和端口的话就注释上面的代码,放开下面代码的注释,然后直接用构造方法调用即可

import example.DataOuterClass;
import example.FormatDataGrpc;
import io.grpc.Channel;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import net.devh.springboot.autoconfigure.grpc.client.GrpcClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import types.Common;
import types.Unlock;
import types.WalletServiceGrpc;import java.util.concurrent.TimeUnit;/*** CreateBy: huangtu*/
@Component
public class GrpcClientService {private Logger logger = LoggerFactory.getLogger(GrpcClientService.class);/** yml文件配置自动注入grpc的url和端口 */
//    @GrpcClient("local-grpc-server")
//    private Channel serverChannel;/*** 测试方法* @param letter        字母大小写转换*/
//    public void sendMessage(String letter) {//将yml文件中的url和端口封装进连接服务 -- //这里大部分都是一样的,proto文件里面的server是什么方法,这里就会自带 xxxxxBlockingStub
//        FormatDataGrpc.FormatDataBlockingStub stub = FormatDataGrpc.newBlockingStub(serverChannel);//调用连接方法,封装参数,进行传输和接收//自己自定义的 proto 文件直接参考替换类和方法就行//       DataOuterClass.Data data = stub.doFormat(DataOuterClass.Data.newBuilder().setText(letter).build());//       logger.info(data.getText()+"=======");//   }/** 手动配置grpc的url和端口 */private final ManagedChannel channel;private final FormatDataGrpc.FormatDataBlockingStub blockingStub;public GrpcClientService(String host, int port) {ManagedChannelBuilder<?> channelBuilder = ManagedChannelBuilder.forAddress(host, port).usePlaintext(true);channel = channelBuilder.build();blockingStub = FormatDataGrpc.newBlockingStub(channel);}/*** 停止连接---遇到异常可关闭连接----一般不用,因为连接是一直在的,报错看日志即可,关闭则需要重启服务端*/public void shutdown() throws InterruptedException {channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);}/*** 测试方法* @param letter        字母:大小写转换*/public void sendMessage(String letter) {//将yml文件中的url和端口封装进连接服务 -- //这里大部分都是一样的,proto文件里面的server是什么方法,这里就会自带 xxxxxBlockingStubFormatDataGrpc.FormatDataBlockingStub stub = FormatDataGrpc.newBlockingStub(serverChannel);//调用连接方法,封装参数,进行传输和接收//自己自定义的 proto 文件直接参考替换类和方法就行DataOuterClass.Data data = stub.doFormat(DataOuterClass.Data.newBuilder().setText(letter).build());logger.info(data.getText()+"=======");}}

服务端----


3.3 java服务端代码:

3.3.1 加入pom依赖:这里的服务端依赖已经在上面加了,所以可以不用重复加
<!--grpc服务端-->
<dependency><groupId>net.devh</groupId><artifactId>grpc-server-spring-boot-starter</artifactId><version>1.3.0-RELEASE</version>
</dependency>

3.3.2 服务端代码
import example.DataOuterClass;
import example.FormatDataGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.springboot.autoconfigure.grpc.server.GrpcService;/*** CreateBy: huangtu*/
@GrpcService(DataOuterClass.class)
public class GrpcServerService extends FormatDataGrpc.FormatDataImplBase {//注意,这里的 doFormat 方法,要跟dat.proto文件的server代码块里面的方法一样,注意大小写//因为我这里message 代码块 是Data。我自己既用它做传参也用它做返回//request是客户端传过来的参数,responseObserver是返回给客户端响应的参数public void doFormat(DataOuterClass.Data request, StreamObserver<DataOuterClass.Data> responseObserver) {String text = request.getText();StringBuffer stringBuffer = new StringBuffer();//大小写转换for(int i=0;i<text.length();i++) {//如果是小写if (text.substring(i, i + 1).equals(text.substring(i, i + 1).toLowerCase())) {stringBuffer.append(text.substring(i, i + 1).toUpperCase());System.out.print(text.substring(i, i + 1).toUpperCase());} else {stringBuffer.append(text.substring(i, i + 1).toLowerCase());System.out.print(text.substring(i, i + 1).toLowerCase());}}DataOuterClass.Data.Builder abc = DataOuterClass.Data.newBuilder().setText(stringBuffer.toString());//客户端每传一个消息过来都会调用一次onNext方法,当客户端发送完毕后,会执行onCompleted来返回一个对象给客户端responseObserver.onNext(abc.build());responseObserver.onCompleted();}
}

3.4 启动项目:

在用一个项目中即在控制台可以看到客户端需要访问服务端的URL和端口,如果是两个单独的项目,根据自己的配置来。


3.5 方法调用

注意:自己写个测试类,用main方法的话直接仿照我的即可。使用yml配置的方式的话就放开客户端 GrpcClientService 代码上面的注释,把下面的代码注释

main方法测试:

public static void main(String[] args) {//同一个项目启动,这里的端口和url跟日志上的一样。不同项目自己配置GrpcClientService client = new GrpcClientService ("0.0.0.0", 9090);try {client.sendMessage("aaBBcc======");} catch (Exception e) {client.shutdown();}
}

使用yml方式如下:

@Autowired
private GrpcClientService grpcClientService;public void test(){grpcClientService.sendMessage("aaBBcc======");
}

3.6 返回结果

AAbbCC=============

四、扩展,遇到的bug

1. springboot集成grpc报错:io.grpc.StatusRuntimeException: UNAVAILABLE.

2. springboot集成grpc报错:io.grpc.StatusRuntimeException: INTERNAL: Connection closed with unknown cause.


springboot 集成 grpc 和 protobuf(二) | 在实际项目中使用 grpc 和 protobuf相关推荐

  1. SpringBoot集成Spring Security(二)注册 、密码加密、修改密码

    SpringBoot集成Spring Security(一)登录注销 写在前面 上一节创建了项目并且利用Spring Security完成了登录注销功能,这里继续说一下注册.密码加密和找回密码,代码注 ...

  2. Vue学习笔记(二)—— vue项目中使用axios

    一.文档链接 axios文档 vue开发插件 二.axios 简介 axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征: 从浏览器中创建 XML ...

  3. protobuf java 编译_Maven项目中,编译proto文件成Java类

    新建Maven项目 新建一个 Maven 项目: pom定义了最小的maven2元素,即:groupId,artifactId,version. groupId:项目或者组织的唯一标志,并且配置时生成 ...

  4. springboot的jsp应该放在哪_SpringBoot 在项目中使用JSP

    1. 添加JSP支持之后的项目结构 对比以前的项目结构 main 目录下多了 webapp 目录,用来存放目录 jsp 文件. spring-boot-jsp +-src +- main +- jav ...

  5. Steam项目推进(二)—— 在项目中使用FairyGUI

    一.遇到的问题 昨天把代码大致清理了一遍之后,发现代码中存在很大的一个问题是数据和表现耦合在一起了,如下: using UnityEngine; using UnityEngine.UI;public ...

  6. VIVADO的.XCI文件探索之二:在项目中使用XCI文件

    创建一个VIVADO项目. 将PLL_100M_120M.XCI文件以及PLL_100M_120M.V文件加入项目中. 如果显示IP是锁定的,需要更新一下,步骤: Reports > Repor ...

  7. SpringBoot集成Spring Security(一)登录注销

    同个人网站 https://www.serendipper-x.cn/,欢迎访问 ! SpringBoot集成Spring Security(二)注册 .密码加密.修改密码 写在前面 Spring S ...

  8. SpringBoot集成Spring Security(2)——自动登录

    在上一章:SpringBoot集成Spring Security(1)--入门程序中,我们实现了入门程序,本篇为该程序加上自动登录的功能. 文章目录 一.修改login.html 二.两种实现方式 2 ...

  9. SpringBoot集成Dubbo

    #博学谷IT学习技术支持# 文章目录 1. 构建SpringBoot环境 1.1 创建一个dubbo-parent项目 1.2 引入依赖坐标 2. Linux 环境配置 2.1 安装docker 2. ...

  10. SpringBoot集成MySQL

    SpringBoot集成MySQL: 注:集成mysql之前请先搭建好springboot(springboot搭建) 1 配置pom.xml文件引入mysql依赖 <!--集成mysql数据库 ...

最新文章

  1. 女朋友存好多网上男明星的照片,我准备用python全部换成我的脸
  2. 【Netty】IO 模型简介 ( Netty 特点 | Netty 应用场景 | Java 三种 IO 模型 | BIO 模型 )
  3. UIWebView相关应用
  4. iframe URI钓鱼
  5. think php框架 跨域,ThinkPHP框架实现session跨域问题
  6. 前端学习(238):IE低版本常见bug
  7. 2021中国到店消费新趋势洞察报告
  8. 从欧拉公式看希尔伯特变换
  9. 蔚来上线三款硬货:更大电池包、全新EC6、改款ES8
  10. 是的,我更喜欢这样的工程师
  11. neo4j 学习笔记
  12. 网站服务器后缀名,服务器域名,域名后缀
  13. mac php fpm 502,nginx+php-fpm出现502(Bad Gateway)错误的分析与解决 | linux系统运维
  14. win7右下角声音图标不见的解决方法
  15. PHP输出分割线,dede标签调用大全dedecms隔五行一个分割线_PHP教程
  16. SEO优化应该照用户的需求去做
  17. Unity3D学习记录——NGUI Sprit2
  18. 习题 8-20 懒惰的苏珊(Lazy Susan, ACM/ICPC Danang 2007, UVa1620)
  19. 在Google Code上发布了项目VBox-OSE
  20. 资源|28本必读的经典机器学习/数据挖掘书籍(免费下载)

热门文章

  1. html放大镜原理,js放大镜效果原理
  2. 趁年轻,我们干点什么吧
  3. 赖特 因果分析_量子至上的赖特的东西
  4. spring jpa Specification in 查询
  5. 基于Vue的俄罗斯方块游戏设计与实现
  6. 飞猪官方揭秘双11爆款产品打造攻略:1个数据银行+5大设计方法论
  7. chromium的下载和编译
  8. Chromium浏览器历史版本下载
  9. CAN bus 基础知识
  10. ES6-rest参数