• 基于http的protobuf服务实现


    本文介绍在http协议中,使用protobuf格式进行二进制数据通信。双方需设置http的header中ContentType为application/x-protobuf。

    1、springboot下实现protobuf

    1)pom.xml

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-webartifactId>
    4. dependency>
    5. <dependency>
    6. <groupId>com.google.protobufgroupId>
    7. <artifactId>protobuf-javaartifactId>
    8. <version>3.11.0version>
    9. dependency>
    10. <dependency>
    11. <groupId>com.google.protobufgroupId>
    12. <artifactId>protobuf-java-utilartifactId>
    13. <version>3.11.0version>
    14. dependency>
    15. <dependency>
    16. <groupId>com.googlecode.protobuf-java-formatgroupId>
    17. <artifactId>protobuf-java-formatartifactId>
    18. <version>1.2version>
    19. dependency>
    20. <dependency>
    21. <groupId>org.apache.httpcomponentsgroupId>
    22. <artifactId>httpclientartifactId>
    23. <version>4.5.2version>
    24. dependency>
    25. <dependency>
    26. <groupId>org.apache.httpcomponentsgroupId>
    27. <artifactId>httpcoreartifactId>
    28. <version>4.4version>
    29. dependency>

    2)user_login.proto

    1. syntax = "proto3";
    2. // 转成java后所在包
    3. option java_package = "com.tencent.rating.audi_model_api.pb";
    4. // 转成java后的类名
    5. option java_outer_classname = "MessageUserLogin";
    6. // 转java后生成一个java文件
    7. option java_multiple_files = false;
    8. message MessageUserLoginRequest {
    9. string username = 1;
    10. string password = 2;
    11. }
    12. message MessageUserLoginResponse {
    13. string access_token = 1;
    14. string username = 2;
    15. }

    编译:

    protoc --proto_path=/data/ --java_out=./ /data/user_login.proto

    3)创建springboot工程,编写config:

    1. @Configuration
    2. public class WebConfig {
    3. @Bean
    4. ProtobufHttpMessageConverter protobufHttpMessageConverter() {
    5. return new ProtobufHttpMessageConverter();
    6. }
    7. /**
    8. * protobuf 反序列化 可以不用配置
    9. */
    10. // @Bean
    11. // RestTemplate restTemplate(ProtobufHttpMessageConverter protobufHttpMessageConverter) {
    12. // return new RestTemplate(Collections.singletonList(protobufHttpMessageConverter));
    13. // }
    14. }

    4)编写contorller:

    1. import java.util.UUID;
    2. import org.springframework.stereotype.Controller;
    3. import org.springframework.web.bind.annotation.RequestBody;
    4. import org.springframework.web.bind.annotation.RequestMapping;
    5. import org.springframework.web.bind.annotation.ResponseBody;
    6. import com.tencent.rating.audi_model_api.pb.MessageUserLogin;
    7. @Controller
    8. public class PbTestController {
    9. @RequestMapping(value = "/pbtest", produces = "application/x-protobuf")
    10. @ResponseBody
    11. public MessageUserLogin.MessageUserLoginResponse getPersonProto(@RequestBody MessageUserLogin.MessageUserLoginRequest request) {
    12. System.out.println("request:" + request.toString());
    13. MessageUserLogin.MessageUserLoginResponse.Builder builder = MessageUserLogin.MessageUserLoginResponse.newBuilder();
    14. builder.setAccessToken(UUID.randomUUID().toString()+"_res");
    15. builder.setUsername(request.getUsername()+"_res");
    16. return builder.build();
    17. }
    18. }

    然后启动sprinboot工程。监听8080端口

    5)编写客户端请求:

    1. public class PbTest {
    2. public static void main(String...strings) {
    3. try {
    4. String uri = "http://127.0.0.1:8080/clue/pbtest";
    5. MessageUserLogin.MessageUserLoginRequest.Builder builder = MessageUserLogin.MessageUserLoginRequest.newBuilder();
    6. builder.setUsername("tom");
    7. builder.setPassword("123456");
    8. HttpResponse response = doPost(uri, builder.build().toByteArray());
    9. MessageUserLogin.MessageUserLoginResponse messageUserLoginResponse = MessageUserLogin.MessageUserLoginResponse.parseFrom(response.getEntity().getContent());
    10. System.out.println("response:" + messageUserLoginResponse.toString());
    11. System.err.println(messageUserLoginResponse.getAccessToken());
    12. } catch (Exception e) {
    13. }
    14. }
    15. private static HttpResponse doPost(String uri, byte[] bytes) throws Exception {
    16. CloseableHttpResponse closeableHttpResponse = null;
    17. CloseableHttpClient httpclient = HttpClients.createDefault();
    18. try {
    19. HttpPost post = new HttpPost(uri);
    20. ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
    21. InputStreamEntity inputStreamEntity = new InputStreamEntity(inputStream);
    22. post.setEntity(inputStreamEntity);
    23. post.addHeader("Content-Type", "application/x-protobuf");
    24. closeableHttpResponse = httpclient.execute(post);
    25. } catch (IOException e) {
    26. e.printStackTrace();
    27. } finally {
    28. // httpclient.close();
    29. }
    30. return closeableHttpResponse;
    31. }
    32. }

    2、servlet下实现protobuf: 

    1)创建servlet项目,编写servlet代码:

    1. import java.io.IOException;
    2. import java.io.InputStream;
    3. import java.util.UUID;
    4. import javax.servlet.ServletOutputStream;
    5. import javax.servlet.annotation.WebServlet;
    6. import javax.servlet.http.HttpServlet;
    7. import javax.servlet.http.HttpServletRequest;
    8. import javax.servlet.http.HttpServletResponse;
    9. import servlet_test.pb.MessageUserLogin;
    10. import servlet_test.pb.MessageUserLogin.MessageUserLoginRequest;
    11. import servlet_test.pb.MessageUserLogin.MessageUserLoginResponse.Builder;
    12. @WebServlet(urlPatterns = {"/syncServlet2"})
    13. public class SyncServlet2 extends HttpServlet {
    14. private static final long serialVersionUID = 1L;
    15. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    16. //解析请求
    17. InputStream stream=request.getInputStream();
    18. MessageUserLoginRequest mlr = MessageUserLogin.MessageUserLoginRequest.parseFrom(stream);
    19. System.out.println(mlr.toString());
    20. //创建响应
    21. Builder newBuilder = MessageUserLogin.MessageUserLoginResponse.newBuilder();
    22. newBuilder.setAccessToken(UUID.randomUUID().toString()+"_res");
    23. newBuilder.setUsername(mlr.getUsername()+"_res");
    24. response.setCharacterEncoding("UTF-8");
    25. ServletOutputStream out = response.getOutputStream();
    26. out.write(newBuilder.build().toByteArray());
    27. out.flush();
    28. out.close();
    29. }
    30. }

    2)客户端测试:

    同上。

  • 相关阅读:
    QToolButton 使用(很好用)
    sublime删除重复字符串
    C++ 运算符
    Rockland丨Rockland HCP抗体开发流程
    【软考 系统架构设计师】操作系统① 操作系统概述
    【数字图像处理】RGB 转灰度图
    我想要点击setting界面里面的返回主菜单,重新回到mainwidget界面,关闭其他两个界面,该怎么改
    C语言常识
    面试经典-15-跳跃游戏 II
    【数据挖掘】Pandas介绍
  • 原文地址:https://blog.csdn.net/liuxiao723846/article/details/133774555