grpc-java 常用的.proto类型 demo 整理
博主近期在调研 istio,其中涉及需要将自己部门的 rpc 框架切换到 grpc-java 上,因此对 grpc-java 进行了相关调研,这里就对常用的.proto类型进行整理。
.proto文件中消息结构里用于定义字段的标准数据类型如下表所示,后面几列是.proto文件中定义的标准类型编译转换后在编程语言中的类型对照。

下面将对上面提到的 .proto 类型在 Java 代码中的使用给出代码示例
(下面的项目将在上一个示例:grpc-java springboot 同步异步调用 demo 的基础上进一步扩展)
主要包含的复杂结构:数组,Map,byte[],自定义结构,枚举类型
首先是 .proto 文件:
syntax = "proto3"; //指定正在使用proto3语法,没有则默认为proto2
option java_package = "grpc.springboot.demo.api";
option java_outer_classname = "ComplexStructService";
package complex.struct.service;
service ComplexStruct {
//定义一个rpc方法,请求跟相应的内容,均为自定义类型
rpc invoker (ComplexStructRequest) returns (ComplexStructResponse) {}
}
//定义请求体
message ComplexStructRequest {
//定义字符串类型
string msg = 1;
//定义浮点类型
double num = 2;
//定义long类型
sint64 longNum = 3;
//定义int类型
sint32 shortNum = 4;
//定义boolean类型
bool check = 5;
//定义int型数组
repeated sint32 shortNumArray = 6;
//定义字符串数组
repeated string messageArray = 7;
//定义map结构,k-v均为字符串
map<string, string> testMap = 8;
//定义枚举类型
enumType enumTypeNum = 9;
//定义字节数组
bytes data = 10;
}
//定义响应类型
message ComplexStructResponse {
//包含了自定义Result
Result result = 1;
//自定义Result的数组
repeated Result resultList = 2;
//自定义Result的map
map<string, Result> resultMap = 3;
}
message Result {
sint64 id = 1;
string message = 2;
}
//枚举类型
enum enumType {
ENUM_TYPE_0 = 0;
ENUM_TYPE_1 = 1;
ENUM_TYPE_2 = 2;
ENUM_TYPE_3 = 3;
}
对于 List 或者是 Map,代码添加时,都可以通过 addAllXxxx 整个 List/Map 对象赋值,或者通过 addXxx 的方法,依次进行赋值。具体见客户端与服务端代码。
客户端代码:
@RestController
public class ComplexStructController {
private static final Logger logger = LoggerFactory.getLogger(ComplexStructController.class);
private GrpcClient client;
@Autowired
public ComplexStructController(GrpcClient client) {
this.client = client;
}
// 这里构建了一个请求,用于触发客户端调用服务端
@GetMapping("/complex/struct/hello")
public String hello() {
List<String> allMessageArray = new ArrayList<>();
allMessageArray.add("string1");
allMessageArray.add("string2");
allMessageArray.add("string3");
Map<String, String> testMap = new HashMap<>();
testMap.put("key1", "value1");
testMap.put("key2", "value2");
String string = "hello world";
byte[] bytes = string.getBytes();
ComplexStructService.ComplexStructRequest request = ComplexStructService.ComplexStructRequest
.newBuilder()
// 添加基础的数据类型
.setMsg("msg")
.setNum(12.5)
.setLongNum(12L)
.setShortNum(10)
.setCheck(true)
.addShortNumArray(100)
.addShortNumArray(200)
.addShortNumArray(300)
// 添加字符串数组对象
.addAllMessageArray(allMessageArray)
// 添加 map 对象
.putAllTestMap(testMap)
// 在已添加的 map 对象基础上,再添加元素
.putTestMap("key3", "value3")
.setEnumTypeNum(ComplexStructService.enumType.ENUM_TYPE_3)
// 不能直接将byte[]类型放入,需要通过protobuf的ByteString进行一次转换
.setData(ByteString.copyFrom(bytes))
.build();
logger.info("Build request:{}", request);
try {
// 获取同步存根
ComplexStructGrpc.ComplexStructBlockingStub stub = client.getComplexStructBlockingStub();
ComplexStructService.ComplexStructResponse response = stub.invoker(request);
logger.info("Get response:{}", response);
return "success";
} catch (StatusRuntimeException e) {
logger.info(" Error Received - Error code : {}", e.getStatus().getCode());
}
return "error";
}
}
服务端代码:
@Component
public class ComplexStructServiceImpl extends ComplexStructGrpc.ComplexStructImplBase {
private static final Logger logger = LoggerFactory.getLogger(ComplexStructServiceImpl.class);
@Override
public void invoker(ComplexStructService.ComplexStructRequest request,
StreamObserver<ComplexStructService.ComplexStructResponse> responseObserver) {
logger.info("receive request:{}", request);
// 对于基础的数据类型,直接通过 getXxx() 获取
String msg = request.getMsg();
double num = request.getNum();
long longNum = request.getLongNum();
int shortNum = request.getShortNum();
boolean check = request.getCheck();
logger.info("msg:{}, num:{}, longNum:{}, shortNum:{}, check:{}", msg, num, longNum, shortNum, check);
// 对于数组,可以获取完整的 List 对象,也可以获取数组对象的长度,再通过下标获取特定的对象
List<Integer> shortNumList = request.getShortNumArrayList();
int shortNumListNum = request.getShortNumArrayCount();
int shortNumListFirstNum = request.getShortNumArray(0);
logger.info("shortNumListNum:{}, shortNumListFirstNum:{}, shortNumList[1]:{}",
shortNumListNum, shortNumListFirstNum, shortNumList.get(1)) ;
// 字符串数组同上
List<String> messageArray = request.getMessageArrayList();
int messageArrayNum = request.getMessageArrayCount();
String messageArrayFirstMsg =request.getMessageArray(0);
logger.info("messageArrayNum:{}, messageArrayFirstMsg:{}, messageArray[1]:{}",
messageArrayNum, messageArrayFirstMsg, messageArray.get(1)) ;
// 对于 map 类型,也可以直接获取到完整的对象
Map<String, String> testMap = request.getTestMapMap();
for (String key : testMap.keySet()) {
logger.info("testMap: key:{}, value:{}", key, testMap.get(key));
}
// 获取枚举类型 或 直接获取枚举类型的值
ComplexStructService.enumType enumType = request.getEnumTypeNum();
int enumTypeValue = request.getEnumTypeNumValue();
logger.info("enumType:{}, enumTypeValue:{}", enumType, enumTypeValue);
// 获取字节数组
byte[] bytes = request.getData().toByteArray();
logger.info("data:{}", new String(bytes));
// 构建响应类
ComplexStructService.Result result = buildResult(100L, "single result");
// 构建响应数组
List<ComplexStructService.Result> resultList = new ArrayList<>();
resultList.add(buildResult(1L, "result list 1"));
resultList.add(buildResult(2L, "result list 2"));
// 构建响应 Map 结构
Map<String, ComplexStructService.Result> resultMap = new HashMap<>();
resultMap.put("resultMap-key1", buildResult(1L, "result map 1"));
resultMap.put("resultMap-key2", buildResult(2L, "result map 2"));
ComplexStructService.ComplexStructResponse response =
ComplexStructService.ComplexStructResponse
.newBuilder()
.setResult(result)
// 加入定义的 Result 数组
.addAllResultList(resultList)
// 在 Result 数组上再加入新的 Result 对象
.addResultList(buildResult(3L, "result list 3"))
// 加入定义的 Map 对象
.putAllResultMap(resultMap)
// 在 Map 对象上再加入新的元素
.putResultMap("resultMap-key3", buildResult(3L, "result map 3"))
.build();
logger.info("return response:{}", response);
responseObserver.onNext(response);
responseObserver.onCompleted();
}
private ComplexStructService.Result buildResult(long id, String msg) {
return ComplexStructService.Result
.newBuilder()
.setId(id)
.setMessage(msg)
.build();
}
}
运行结果:
服务端:
2021-04-01 00:46:29.870 INFO 6460 --- [ault-executor-0] c.p.g.d.s.s.ComplexStructServiceImpl : receive request:msg: "msg"
num: 12.5
longNum: 12
shortNum: 10
check: true
shortNumArray: 100
shortNumArray: 200
shortNumArray: 300
messageArray: "string1"
messageArray: "string2"
messageArray: "string3"
testMap {
key: "key1"
value: "value1"
}
testMap {
key: "key2"
value: "value2"
}
testMap {
key: "key3"
value: "value3"
}
enumTypeNum: ENUM_TYPE_3
data: "hello world"
2021-04-01 00:46:29.879 INFO 6460 --- [ault-executor-0] c.p.g.d.s.s.ComplexStructServiceImpl : msg:msg, num:12.5, longNum:12, shortNum:10, check:true
2021-04-01 00:46:29.880 INFO 6460 --- [ault-executor-0] c.p.g.d.s.s.ComplexStructServiceImpl : shortNumListNum:3, shortNumListFirstNum:100, shortNumList[1]:200
2021-04-01 00:46:29.880 INFO 6460 --- [ault-executor-0] c.p.g.d.s.s.ComplexStructServiceImpl : messageArrayNum:3, messageArrayFirstMsg:string1, messageArray[1]:string2
2021-04-01 00:46:29.880 INFO 6460 --- [ault-executor-0] c.p.g.d.s.s.ComplexStructServiceImpl : testMap: key:key1, value:value1
2021-04-01 00:46:29.880 INFO 6460 --- [ault-executor-0] c.p.g.d.s.s.ComplexStructServiceImpl : testMap: key:key2, value:value2
2021-04-01 00:46:29.880 INFO 6460 --- [ault-executor-0] c.p.g.d.s.s.ComplexStructServiceImpl : testMap: key:key3, value:value3
2021-04-01 00:46:29.880 INFO 6460 --- [ault-executor-0] c.p.g.d.s.s.ComplexStructServiceImpl : enumType:ENUM_TYPE_3, enumTypeValue:3
2021-04-01 00:46:29.880 INFO 6460 --- [ault-executor-0] c.p.g.d.s.s.ComplexStructServiceImpl : data:hello world
2021-04-01 00:46:29.883 INFO 6460 --- [ault-executor-0] c.p.g.d.s.s.ComplexStructServiceImpl : return response:result {
id: 100
message: "single result"
}
resultList {
id: 1
message: "result list 1"
}
resultList {
id: 2
message: "result list 2"
}
resultList {
id: 3
message: "result list 3"
}
resultMap {
key: "resultMap-key1"
value {
id: 1
message: "result map 1"
}
}
resultMap {
key: "resultMap-key2"
value {
id: 2
message: "result map 2"
}
}
resultMap {
key: "resultMap-key3"
value {
id: 3
message: "result map 3"
}
}
客户端运行结果:
2021-04-01 00:46:28.666 INFO 4616 --- [io-10088-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2021-04-01 00:46:28.667 INFO 4616 --- [io-10088-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2021-04-01 00:46:28.684 INFO 4616 --- [io-10088-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 17 ms
2021-04-01 00:46:28.743 INFO 4616 --- [io-10088-exec-1] c.p.g.d.c.c.ComplexStructController : Build request:msg: "msg"
num: 12.5
longNum: 12
shortNum: 10
check: true
shortNumArray: 100
shortNumArray: 200
shortNumArray: 300
messageArray: "string1"
messageArray: "string2"
messageArray: "string3"
testMap {
key: "key1"
value: "value1"
}
testMap {
key: "key2"
value: "value2"
}
testMap {
key: "key3"
value: "value3"
}
enumTypeNum: ENUM_TYPE_3
data: "hello world"
2021-04-01 00:46:29.911 INFO 4616 --- [io-10088-exec-1] c.p.g.d.c.c.ComplexStructController : Get response:result {
id: 100
message: "single result"
}
resultList {
id: 1
message: "result list 1"
}
resultList {
id: 2
message: "result list 2"
}
resultList {
id: 3
message: "result list 3"
}
resultMap {
key: "resultMap-key1"
value {
id: 1
message: "result map 1"
}
}
resultMap {
key: "resultMap-key2"
value {
id: 2
message: "result map 2"
}
}
resultMap {
key: "resultMap-key3"
value {
id: 3
message: "result map 3"
}
}
完整的代码连接:https://github.com/Parallelline1996/Daily-Learning/tree/master/gRPC/code-repository/grpc-springboot-demo
3323

被折叠的 条评论
为什么被折叠?



