本文介绍在http协议中,使用protobuf格式进行二进制数据通信。双方需设置http的header中ContentType为application/x-protobuf。
1)pom.xml
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
- <dependency>
- <groupId>com.google.protobufgroupId>
- <artifactId>protobuf-javaartifactId>
- <version>3.11.0version>
- dependency>
- <dependency>
- <groupId>com.google.protobufgroupId>
- <artifactId>protobuf-java-utilartifactId>
- <version>3.11.0version>
- dependency>
- <dependency>
- <groupId>com.googlecode.protobuf-java-formatgroupId>
- <artifactId>protobuf-java-formatartifactId>
- <version>1.2version>
- dependency>
- <dependency>
- <groupId>org.apache.httpcomponentsgroupId>
- <artifactId>httpclientartifactId>
- <version>4.5.2version>
- dependency>
- <dependency>
- <groupId>org.apache.httpcomponentsgroupId>
- <artifactId>httpcoreartifactId>
- <version>4.4version>
- dependency>
2)user_login.proto
- syntax = "proto3";
- // 转成java后所在包
- option java_package = "com.tencent.rating.audi_model_api.pb";
- // 转成java后的类名
- option java_outer_classname = "MessageUserLogin";
- // 转java后生成一个java文件
- option java_multiple_files = false;
-
- message MessageUserLoginRequest {
- string username = 1;
- string password = 2;
- }
- message MessageUserLoginResponse {
- string access_token = 1;
- string username = 2;
- }
编译:
protoc --proto_path=/data/ --java_out=./ /data/user_login.proto
3)创建springboot工程,编写config:
- @Configuration
- public class WebConfig {
- @Bean
- ProtobufHttpMessageConverter protobufHttpMessageConverter() {
- return new ProtobufHttpMessageConverter();
- }
- /**
- * protobuf 反序列化 可以不用配置
- */
- // @Bean
- // RestTemplate restTemplate(ProtobufHttpMessageConverter protobufHttpMessageConverter) {
- // return new RestTemplate(Collections.singletonList(protobufHttpMessageConverter));
- // }
- }
4)编写contorller:
- import java.util.UUID;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
- import com.tencent.rating.audi_model_api.pb.MessageUserLogin;
-
- @Controller
- public class PbTestController {
- @RequestMapping(value = "/pbtest", produces = "application/x-protobuf")
- @ResponseBody
- public MessageUserLogin.MessageUserLoginResponse getPersonProto(@RequestBody MessageUserLogin.MessageUserLoginRequest request) {
- System.out.println("request:" + request.toString());
-
- MessageUserLogin.MessageUserLoginResponse.Builder builder = MessageUserLogin.MessageUserLoginResponse.newBuilder();
- builder.setAccessToken(UUID.randomUUID().toString()+"_res");
- builder.setUsername(request.getUsername()+"_res");
- return builder.build();
- }
- }
然后启动sprinboot工程。监听8080端口
5)编写客户端请求:
- public class PbTest {
-
- public static void main(String...strings) {
- try {
- String uri = "http://127.0.0.1:8080/clue/pbtest";
- MessageUserLogin.MessageUserLoginRequest.Builder builder = MessageUserLogin.MessageUserLoginRequest.newBuilder();
- builder.setUsername("tom");
- builder.setPassword("123456");
- HttpResponse response = doPost(uri, builder.build().toByteArray());
- MessageUserLogin.MessageUserLoginResponse messageUserLoginResponse = MessageUserLogin.MessageUserLoginResponse.parseFrom(response.getEntity().getContent());
- System.out.println("response:" + messageUserLoginResponse.toString());
- System.err.println(messageUserLoginResponse.getAccessToken());
- } catch (Exception e) {
-
- }
- }
-
- private static HttpResponse doPost(String uri, byte[] bytes) throws Exception {
- CloseableHttpResponse closeableHttpResponse = null;
- CloseableHttpClient httpclient = HttpClients.createDefault();
- try {
- HttpPost post = new HttpPost(uri);
- ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
- InputStreamEntity inputStreamEntity = new InputStreamEntity(inputStream);
- post.setEntity(inputStreamEntity);
- post.addHeader("Content-Type", "application/x-protobuf");
- closeableHttpResponse = httpclient.execute(post);
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- // httpclient.close();
- }
- return closeableHttpResponse;
- }
- }
1)创建servlet项目,编写servlet代码:
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.UUID;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import servlet_test.pb.MessageUserLogin;
- import servlet_test.pb.MessageUserLogin.MessageUserLoginRequest;
- import servlet_test.pb.MessageUserLogin.MessageUserLoginResponse.Builder;
-
- @WebServlet(urlPatterns = {"/syncServlet2"})
- public class SyncServlet2 extends HttpServlet {
- private static final long serialVersionUID = 1L;
-
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
- //解析请求
- InputStream stream=request.getInputStream();
- MessageUserLoginRequest mlr = MessageUserLogin.MessageUserLoginRequest.parseFrom(stream);
- System.out.println(mlr.toString());
- //创建响应
- Builder newBuilder = MessageUserLogin.MessageUserLoginResponse.newBuilder();
- newBuilder.setAccessToken(UUID.randomUUID().toString()+"_res");
- newBuilder.setUsername(mlr.getUsername()+"_res");
- response.setCharacterEncoding("UTF-8");
- ServletOutputStream out = response.getOutputStream();
- out.write(newBuilder.build().toByteArray());
-
- out.flush();
- out.close();
- }
- }
2)客户端测试:
同上。