spring boot restTemplate protobuf(protocal buffer) demo

来源:互联网 发布:ipad看文献 知乎 编辑:程序博客网 时间:2024/05/16 08:42

protobuf 个人理解就是一种数据格式,只不过在序列化后的大小、序列化、反序列化方面更优秀一些。


demo 是用spring boot做了一个server,一个test。server暴露出来的服务是rest的,数据格式就是protobuf。


直接上代码

common:

proto数据结构文件

 syntax = "proto3";// package comp.protobuf.pb; option java_package = "com.protobuf.model";  option java_outer_classname = "UserProto"; message User {   int64 id = 1;   string name = 2;   message PhoneNumber {       string number = 1;     }     repeated PhoneNumber phone = 4;      }


生成对应语言的类,我这直接用java 的runtime,也可以直接再cmd中操作

package com.protobuf;import java.io.IOException;public class GenerateClass {public static void main(String[] args) {        String protoFile = "user.proto";//          String strCmd = "D:/software/protobuf-3.3.0/protoc.exe --java_out=./src/main/java ./src/main/resources/"+ protoFile;          try {            Runtime.getRuntime().exec(strCmd);        } catch (IOException e) {            e.printStackTrace();        }//通过执行cmd命令调用protoc.exe程序      }}

生成的java类文件 UserProto.java




2. server   port:8080

application, controller

package com.protobuf;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Bean;import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import com.protobuf.model.UserProto;import java.util.Arrays;import java.util.Collection;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import java.util.stream.Collectors;/** * This example demonstrates serving up REST payloads encoded using * <a href="https://developers.google.com/protocol-buffers/">Google Protocol Buffers</a>. */@SpringBootApplicationpublic class ProtoServerApplication {    public static void main(String[] args) {        SpringApplication.run(ProtoServerApplication.class, args);    }    @Bean    ProtobufHttpMessageConverter protobufHttpMessageConverter() {        return new ProtobufHttpMessageConverter();    }    private UserProto.User user(long id, String name, Collection<String> phones) {        Collection<UserProto.User.PhoneNumber> pnList =        phones.stream().map(e -> UserProto.User.PhoneNumber.newBuilder().setNumber(e).build()).collect(Collectors.toList());        return UserProto.User.newBuilder().setId(id).setName(name).addAllPhone(pnList).build();            }            @Bean    UserRepository userRepository() {        Map<Long, UserProto.User> userM = new ConcurrentHashMap<>();        Arrays.asList(                user(1, "Chris", Arrays.asList("1566666","15777777")),                user(2, "Josh", Arrays.asList("157777777777","158888888888")),                user(3, "Matt", Arrays.asList("1566666","159999999999999")),                user(4, "Russ", Arrays.asList("1599999999","15733337"))        ).forEach(c -> userM.put(c.getId(), c));        //UserRepository 只有一个抽象方法,可以认为是一个函数接口,所以可以用lambda表达式 表示。        return userM::get;    }}interface UserRepository {UserProto.User findById(long id);}@RestControllerclass UserRestController {    @Autowired    private UserRepository userRepository;    @RequestMapping("/user/{id}")    UserProto.User user(@PathVariable Integer id) {        return userRepository.findById(id);    }        @RequestMapping("/map/{id}")    Map<String,String> map(@PathVariable Integer id) {    Map<String,String> m = new HashMap<String,String>();m.put("name", "yonyou");m.put("www","yonyou.com");return m;    }            }

3. test    port:8181

application, controller

package com.protobuf;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Bean;import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import com.protobuf.model.UserProto;import java.util.Arrays;import java.util.Collection;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import java.util.stream.Collectors;/** * This example demonstrates serving up REST payloads encoded using * <a href="https://developers.google.com/protocol-buffers/">Google Protocol Buffers</a>. */@SpringBootApplicationpublic class ProtobufTestApplication {    public static void main(String[] args) {        SpringApplication.run(ProtobufTestApplication.class, args);    }    @BeanRestTemplate restTemplate() {RestTemplate rt = new RestTemplate();rt.getMessageConverters().add(new ProtobufHttpMessageConverter());return rt;}}@RestControllerclass UserRestController {@Autowiredprivate RestTemplate restTemplate;    @RequestMapping("/user/{id}")    UserProto.User user(@PathVariable Integer id) {        UserProto.User obj = this.restTemplate.getForObject("http://127.0.0.1:8080/user/" + id,    UserProto.User.class);        return obj;    }        @RequestMapping("/user2/{id}")    String user2(@PathVariable Integer id) {        UserProto.User obj = this.restTemplate.getForObject("http://127.0.0.1:8080/user/" + id,    UserProto.User.class);        return obj.toString();    }        @RequestMapping("/map/{id}")    Map<String,String> map(@PathVariable Integer id) {    Map m = this.restTemplate.getForObject("http://127.0.0.1:8080/map/" + id, Map.class);return m;    }            }


还有一个本地测试的 Test.java

package com.protobuf;import java.io.IOException;import com.protobuf.model.UserProto;import com.protobuf.model.UserProto.User;public class Test {public static void main(String[] args) throws IOException {        //模拟将对象转成byte[],方便传输        UserProto.User.Builder builder = UserProto.User.newBuilder();        builder.setId(1);        builder.setName("ant");                        builder.addPhone(UserProto.User.PhoneNumber.newBuilder().setNumber("15000000"));        builder.addPhone(UserProto.User.PhoneNumber.newBuilder().setNumber("15111111"));                UserProto.User user = builder.build();        System.out.println("before :"+ user.toString());        System.out.println("===========Person Byte==========");        for(byte b : user.toByteArray()){            System.out.print(b);        }        System.out.println();        System.out.println(user.toByteString());        System.out.println("================================");        //模拟接收Byte[],反序列化成Person类        byte[] byteArray =user.toByteArray();        User p2 = user.parseFrom(byteArray);        System.out.println("after :" +p2.toString());    }}


4. 测试

server 直接访问

通过test访问server

报错是因为我后台代码返回给前台的是protobuf的数据格式,前台浏览器解析不了。


换个方式,就可以了,因为返回的是string


注意代码中的resttemplate

 @BeanRestTemplate restTemplate() {RestTemplate rt = new RestTemplate();rt.getMessageConverters().add(new ProtobufHttpMessageConverter());return rt;}
若是将rt.getMessageConverters().add(new ProtobufHttpMessageConverter()); 注释掉测试,会发现test后台不能解析server返回的结果

报错


ProtobufHttpMessageConverter  是spring 4.1 新增加的支持protobuf格式的数据转换功能。


代码下载:

http://download.csdn.net/detail/stonexmx/9889649


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 红色皮衣染色了怎么办 羽绒服干了结块怎么办 羽绒服手洗后鸭毛堆在一起怎么办 白色羽绒服发霉了怎么办 早晨起床双脚冷怎么办 黑色棉衣粘毛怎么办 貂皮大衣旧了怎么办 pu皮床头掉皮怎么办 背心领子大怎么办鸡心 羊毛裙子缩水了怎么办 背带裙背带老掉怎么办 背带裙背带坏了怎么办 黑色衣服发红了怎么办 公司拖欠离职员工工资怎么办 windows系统坏了怎么办 背带裙肩带总掉怎么办 四个月宝宝干咳怎么办 4个多月宝宝干咳怎么办 小孩吃饭不嚼怎么办 四个月宝宝积食怎么办 新生儿睡枕头了怎么办 宝宝半夜练翻身怎么办 宝宝牙齿长歪怎么办 婴儿睡觉头歪怎么办 婴儿放在床就哭怎么办 宝宝米粉没吃完怎么办 宝宝吃米粉上火怎么办 幼儿发烧怎么办 两岁 七个月婴儿厌食怎么办 打卤时肉总是沾在一起怎么办 宝宝大便头干硬怎么办 婴儿辅食机的水怎么办 三岁宝宝牙痛怎么办 5岁宝宝牙痛怎么办 6岁儿童脑维缩怎么办 产后奶水多胀痛怎么办 新生儿心脏偏大怎么办 婴儿脸上长虫斑怎么办 婴儿脸上长斑怎么办 婴儿润肤油过敏怎么办 青少年眼袋太重怎么办