春天顶部

通过参考资料,开始使用Spring 5和Spring Boot 2学习的春天课程:

> >学习春天
休息前

通过参考资料,开始使用Spring 5和Spring Boot 2学习的春天课程:

>>看看这个课程

1.概述

协议缓冲区是一种语言和平台无关的机制,用于结构化数据的序列化和反序列化,它的创建者谷歌宣称它比其他类型的有效负载(如XML和JSON)更快、更小、更简单。

本教程将指导您如何设置REST API以利用这种基于二进制的消息结构。

2.协议缓冲区

本节给出了协议缓冲区的一些基本信息,以及它们如何在Java生态系统中应用。

2.1。协议缓冲区简介

为了使用协议缓冲区,我们需要定义消息结构.proto文件。每个文件是可以从一个节点传送到另一个节点的数据的描述,或者存储在数据源中。这是一个例子.proto文件,命名为金宝搏188体育baeldung.proto.和生活在src / main /资源目录。稍后将在本教程中使用此文件:

语法=“proto3”;包装包装;金宝搏188体育选项java_package =“com.baeldu金宝搏188体育ng.protobuf”;选项java_outer_classname =“baeldu金宝搏188体育ngtring”;消息课程{Int32 ID = 1;string course_name = 2;重复学生= 3;消息学生{int32 id = 1;字符串first_name = 2;字符串last_name = 3; string email = 4; repeated PhoneNumber phone = 5; message PhoneNumber { string number = 1; PhoneType type = 2; } enum PhoneType { MOBILE = 0; LANDLINE = 1; } }

在本教程中,我们使用协议缓冲区编译器和协议缓冲区语言的版本3因此,这是.proto文件必须以语法=“proto3”声明。如果使用的是编译器版本2,则该声明将被省略。接下来是声明,这是此消息结构的命名空间,以避免与其他项目命名冲突。

以下两种声明仅用于Java:java_package选项指定我们生成的类的包,以便居住在一起,java_outer_classname.选项表示包含其中定义的所有类型的类的名称.proto文件。

下面的第2.3小节将描述剩余的元素以及如何将这些元素编译成Java代码。

2.2。使用Java的协议缓冲区

定义了消息结构后,我们需要一个编译器将此语言无关的内容转换为Java代码。你可以按照手册上的说明去做协议缓冲区存储库为了得到一个适当的编译器版本。或者,您也可以通过搜索com.google.protobuf:protoc.工件,然后为您的平台选择适当的版本。

然后,将编译器复制到src /主要在命令行中执行以下命令:

protoc --java_out = java资源/ baeld金宝搏188体育ung.proto

控件的源文件金宝搏188体育BaeldungTraining课程内部com.金宝搏188体育baeldung.protobuf类中指定的选项宣言的金宝搏188体育baeldung.proto.文件。

除了编译器之外,协议缓冲区运行时也是必需的。这可以通过向Maven POM文件添加以下依赖项来实现:

<依赖> < groupId > com.google。protobuf protobuf-java< artifactId> 3.0.0-beta-3 

我们可以使用其他版本的运行时,只要它与编译器的版本相同。对于最新的,请退房这个链接

2.3。编译消息描述

通过使用编译器,消息在.proto文件被编译成静态嵌套Java类。在上面的例子中课程学生消息转换为课程学生Java类分别。与此同时,消息“字段”将编译为JavaBeans样式的Getters和在生成的类型中的设置。每个字段声明结束时,由等号和数字组成的标记是用于以二进制形式对关联字段进行唯一标记的唯一标签。

我们将介绍消息的键入字段,以了解如何转换为访问器方法。

让我们从课程消息。它有两个简单的字段,包括ID课程名。他们的协议缓冲类型,int32细绳,被翻译成Java字符串类型。下面是编译后的相关getter(为了简洁,省略了实现):

公共int getId ();公众以getCourseName ();

请注意,类型化字段的名称应该是蛇大小写(单个单词由下划线字符分隔),以保持与其他语言的协作。编译器将根据Java约定将这些名称转换为驼峰式。

的最后一个字段课程消息,学生,是的学生复杂类型,将在下面描述。这个领域是前面的重复关键词,意味着它可以重复任何次数。编译器生成与之相关的一些方法学生字段如下(不含实现):

公众并不知道< com.baeldung.proto金宝搏188体育buf.BaeldungTraining。学生> getStudentList ();公共int getStudentCount ();getStudent(金宝搏188体育int index);

现在我们将继续前进学生类的复杂类型学生领域的课程消息。它的简单字段,包括ID,,last_name电子邮件用于创建Java Accessor方法:

公共int getId ();公共java.lang.string getfirstname();公共java.lang.string getlastname();public java.lang.string.getEmail();

最后一场,电话,是的PhoneNumber复杂类型。类似于学生领域的课程消息,此字段是重复的,有几种关联方法:

公众并不知道< com.baeldung.proto金宝搏188体育buf.BaeldungTraining.Student。PhoneNumber > getPhoneList ();公共int getPhoneCount ();getPhone(in金宝搏188体育t index);

PhoneNumber消息编译为金宝搏188体育BaeldungTraining.Student.PhoneNumber嵌套类型,具有两个getters对应于消息的字段:

公众以getNumber ();公共com.baeld金宝搏188体育ung.protobuf.BaeldungTraining.Student.PhoneType方法();

PhoneType的复杂类型类型场面的领域PhoneNumber是枚举类型,它将被转换为Java枚举类型嵌套在内金宝搏188体育BaeldungTraining。学生班级:

public enum PhoneType implements com.google.protobuf.ProtocolMessageEnum {MOBILE(0), LANDLINE(1), UNRECOGNIZED(-1),;//其他声明}

3.Spring REST API中的Protobuf

本节将指导您使用Spring Boot设置REST服务。

3.1。Bean声明

让我们从main的定义开始@SpringBootApplication:

@SpringBootApplication public class Application {@Bean ProtobufHttpMessageConverter ProtobufHttpMessageConverter(){返回新的ProtobufHttpMessageConverter();} @Bean public CourseRepository createTestCourses() {Map courses = new HashMap<>();Course Course = Course. newbuilder () .setId(1) .setCourseName(“REST with Spring”).addAllStudent(createTestStudents()) .build();Course Course = Course. newbuilder () .setId(2) .setCourseName(“学习Spring安全”).addAllStudent(new ArrayList()) .build();courses.put (course1.getId (), course1);courses.put (course2.getId (), course2);返回新CourseRepository(课程);} //其他声明}

ProtobufHttpMessageConverterBean用于转换@requestmappping.协议缓冲区消息的注释方法。

另一豆,CourseRepository,包含API的一些测试数据。

这里重要的是我们正在运作协议缓冲区特定的数据——而不是标准pojo

控件的简单实现如下CourseRepository:

公共类Courserepository {Map 课程;公共ourserepository(Map 课程){this.courses =课程;公共课程GetCourse(int ID){Return Courses.get(ID);}}

3.2。控制器配置

我们可以定义@ controller类的测试URL如下:

@RestController public class CourseController {@Autowired CourseRepository courseRepo;@RequestMapping("/courses/{id}") Course customer(@PathVariable Integer id) {return courserepop . getcourse (id);}}

此处的重要事项是,我们从控制器层返回的课程DTO不是标准的POJO。这将是它在转回客户端之前将其转换为协议缓冲消息的触发器。

4.休息客户和测试

现在我们已经了解了简单的API实现—现在让我们进行说明在客户端反序列化协议缓冲区消息-使用两种方法。

第一个利用了resttemplate.API与预配置ProtobufHttpMessageConverterBean自动转换消息。

第二个是使用Protobuf-Java格式手动将协议缓冲区响应转换为JSON文档。

首先,我们需要为集成测试设置上下文并指示Spring Boot以查找配置信息应用程序类通过如下声明一个测试类:

@ SpringJUnit4ClassRunner.class @SpringApplicationConfiguration(classes = Application.class) @WebIntegrationTest public class ApplicationTest{//其他声明}

本节中的所有代码片段将放在应用程序班级。

4.1。预期的反应

访问REST服务的第一步是确定请求URL:

private static final String COURSE1_URL = "http://localhost:8080/courses/1";

COURSE1_URL将用于从我们之前创建的REST服务中获取第一个测试双程课程。获取请求发送到上述URL后,使用以下断言验证相应的响应:

private void assertResponse(String response) {assertThat(response, containsString("id"));为了(响应,containsString (course_name "));assertThat(response, containsString("REST with Spring"));为了(响应,containsString(“学生”));为了(响应,containsString (first_name "));为了(响应,containsString (last_name "));为了(响应,containsString("电子邮件"));为了响应,containsString(“[电子邮件受保护]"));为了响应,containsString(“[电子邮件受保护]"));为了响应,containsString(“[电子邮件受保护]"));为了(响应,containsString("电话"));为了(响应,containsString (number));为了(响应,containsString(“类型”));}

我们将在后续子部分覆盖的两个测试用例中使用此辅助方法。

4.2。测试与resttemplate.

下面是我们如何创建客户机、向指定目的地发送GET请求、接收协议缓冲区消息形式的响应并使用resttemplate.API:

@autowifired私有reastemplate resttemplate;@test public void whenUsingRestTemplate_thensucceed(){analessentity <课程>课程= restTemplate.getForentity(课程1_URL,课程);assertresponse(课程.Tostring());}

要使这个测试用例工作,我们需要resttemplate.要在配置类中注册的类型:

@Bean RestTemplate RestTemplate(ProtobufHttpMessageConverter hmc) {return new RestTemplate(Arrays.asList(hmc));}

另一颗豆ProtobufHttpMessageConverter类型也需要自动转换接收的协议缓冲区消息。此bean与子部分3.1中定义的bean相同。由于客户端和服务器在本教程中共享相同的应用程序上下文,因此我们可能会声明resttemplate.豆的应用程序课程并重新使用ProtobufHttpMessageConverter豆角,扁豆。

4.3。测试与HttpClient

控件的第一步HttpClientAPI和手动转换协议缓冲区消息正在将以下两个依赖项添加到Maven POM文件:

<依赖> < groupId > com.googlecode。Protobuf-Java格式 protobuf-java-format 1.4   org.apache.httpcomponents httpclient 4.5.2 

有关这些依赖项的最新版本,请参阅Protobuf-Java格式httpclientMaven Central存储库中的伪影。

让我们继续继续创建客户端,执行Get请求并将关联的响应转换为InputStream.实例使用给定的URL:

私有InputStream ExecuteHTTPRequest(String URL)抛出IoException {CloseableHttpClient HttpClient = HttpClientS.Createdefault();httpget请求=新的httpget(url);httpresponse httpresponse = httpclient.execute(请求);返回httpresponse.cetentity()。getContent();}

现在,我们将转换协议缓冲区消息的形式InputStream.指向JSON文档的对象:

私有字符串convertprobufmessageSteamtojsonString(InputStream Protobufstream)抛出IoException {jsonformat jsonformat = new jsonformat();课程课程=课程.parsefrom(protobufstream);返回jsonformat.printtostring(课程);}

下面是一个测试用例如何使用上面声明的私有助手方法并验证响应:

@test public void whenusinghttpclient_thensucceed()抛出IoException {InputStream ConcoveryStream = ExecuteHttpRequest(课程1_URL);字符串jsonoutput = convertprotobufmessageestreamtojsonstring(ConcoverStream);assertresponse(jsonoutput);}

4.4。在JSON响应

为了更清楚地说明,我们在前面小节中描述的测试中收到的响应的JSON形式在这里包括:

id: 1 course_name: "REST with Spring" student {id: 1 first_name: "John" last_name: "Doe" email: "[电子邮件受保护]" number: "123456"}} student {id: 2 first_name: "Richard" last_name: "Roe" email: "[电子邮件受保护]" number: "234567" type: LANDLINE}} student {id: 3 first_name: "Jane" last_name: "Doe" email: "[电子邮件受保护]电话{number: "456789" type: LANDLINE}}

5.结论

本教程快速介绍了协议缓冲区,并说明了如何使用Spring格式设置REST API。然后我们转移到客户端支持和序列化-反序列化机制。

中可以找到所有示例和代码片段的实现一个GitHub的项目

弹簧底部

开始使用Spring 5和Spring Boot 2,通过学习的春天课程:

>>课程
休息下

开始使用Spring 5和Spring Boot 2,通过学习的春天课程:

>>看看这个课程
5注释
最老的
最新
内联反馈
查看所有评论
评论在本文上关闭!