mitesi 2020-04-07
Protobuf(Google Protocol Buffer)是Google公司开发的一种跨语言和平台的序列化数据结构的方式,是一个灵活的、高效的用于序列化数据的协议
protobuf是跨语言的,并且自带一个编译器(protoc),只需要用protoc进行编译,就可以编译成Java、Python、C++、C#、Go等多种语言代码,然后可以直接使用,不需要再写其它代码,自带有解析的代码。
对于结构中的每个成员会提供set系列函数和get系列函数。
protobuf的优点:
性能好/效率高,序列化和反序列化的时间开销都很小
与XML和JSON格式相比,protobuf更小、更快、更便捷
扩展性好,兼容性好
支持多种语言
protobuf的不足:
采用二进制编码,可读性差
缺乏自描述,二进制的协议内容必须配合.proto文件的定义才有含义
protoc.exe 下载 https://github.com/protocolbuffers/protobuf/releases
添加protobuf文件user.proto
syntax = "proto3"; option java_package = "com.example.demo.protobuf"; option java_outer_classname = "MessageUser"; message MessageUserLogin { string access_token = 1; string username = 2; }
使用protoc.exe生成java文件
protoc.exe --java_out=./ user.proto
将生成的MessageUser.java放到对应的位置,如
com\example\demo\protobuf
添加依赖
<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.11.4</version> </dependency> <dependency> <groupId>com.googlecode.protobuf-java-format</groupId> <artifactId>protobuf-java-format</artifactId> <version>1.4</version> </dependency>
添加protobuf序列化支持
package com.example.demo; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter; import org.springframework.web.client.RestTemplate; import java.util.Collections; @Configuration public class CommonConfig { /** * protobuf 序列化 */ @Bean ProtobufHttpMessageConverter protobufHttpMessageConverter() { return new ProtobufHttpMessageConverter(); } /** * protobuf 反序列化 */ @Bean RestTemplate restTemplate(ProtobufHttpMessageConverter protobufHttpMessageConverter) { return new RestTemplate(Collections.singletonList(protobufHttpMessageConverter)); } }
控制器
package com.example.demo.controller; import com.example.demo.protobuf.MessageUser; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import java.util.UUID; @Slf4j @RestController public class DemoController { @RequestMapping(value = "/test", produces = "application/x-protobuf") @ResponseBody public MessageUser.MessageUserLogin getProto() { MessageUser.MessageUserLogin.Builder builder = MessageUser.MessageUserLogin.newBuilder(); builder.setAccessToken(UUID.randomUUID().toString()+"_res"); builder.setUsername("abc"); return builder.build(); } }
启动项目
GET http://127.0.0.1:8080/test
结果为
(2fa3543c-4155-45be-bfd9-19e0ebdb98bb_resabc
可以看出这种结果适合给机器看
添加测试
package com.example.demo; import com.example.demo.protobuf.MessageUser; import org.junit.Test; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import java.net.URI; public class DemoApplicationTests { private WebClient webClient = WebClient.builder() .baseUrl("http://127.0.0.1:8080") .defaultHeader(HttpHeaders.USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)") .defaultCookie("ACCESS_TOKEN", "test_token").build(); @Test public void test() { try { URI uri = new URI("http", null, "127.0.0.1", 8080, "/demo/test", "", null); try { Mono<MessageUser.MessageUserLogin> resp = webClient.method(HttpMethod.GET).uri("test") .retrieve() .bodyToMono(MessageUser.MessageUserLogin.class); MessageUser.MessageUserLogin data = resp.block(); System.out.println("token----- " + data.getAccessToken()); System.out.println("username----- " + data.getUsername()); } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { } } }
token----- ba2c8328-ea33-48ab-ad07-beb3a10eacfc_res
username----- abc