SpringBoot整合Protobuf

SpringBoot 整合 Protobuf

安装

  1. 下载链接:https://github.com/protocolbuffers/protobuf/releases

  2. 将 protobuf/bin 添加至环境变量 Path

  3. 控制台执行 protoc –version,查看是否安装成功

使用

image.png

  1. 依赖
1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.25.2</version>
</dependency>

<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.25.2</version>
</dependency>
  1. 生成 Java 文件

src/main 目录下执行 protoc –java_out=java resources/training.proto

  1. 代码
1
2
3
4
5
6
7
8
@Configuration
public class ProtobufConfig {

@Bean
public ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
}
1
2
3
4
5
6
7
8
9
10
11
@RestController
public class TrainingController {

@Autowired
private CourseRepository courseRepo;

@GetMapping("/courses/{id}")
public Training.Course customer(@PathVariable Integer id) {
return courseRepo.getCourse(id);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@Component
public class CourseRepository {

private final Map<Integer, Course> courses;

public CourseRepository() {
this.courses = new HashMap<>();

Course course1 = Course.newBuilder().setId(1)
.setCourseName("REST with Spring").addAllStudent(createTestStudents()).build();
Course course2 = Course.newBuilder().setId(2)
.setCourseName("Learn Spring Security").addAllStudent(new ArrayList<>()).build();

courses.put(course1.getId(), course1);
courses.put(course2.getId(), course2);
}

public Course getCourse(int id) {
return courses.get(id);
}

private List<Student> createTestStudents() {
PhoneNumber phone1 = createPhone("123456", PhoneType.MOBILE);
Student student1 = createStudent(1, "John", "Doe", "john.doe@baeldung.com", List.of(phone1));

PhoneNumber phone2 = createPhone("234567", PhoneType.LANDLINE);
Student student2 = createStudent(2, "Richard", "Roe", "richard.roe@baeldung.com", List.of(phone2));

PhoneNumber phone3_1 = createPhone("345678", PhoneType.MOBILE);
PhoneNumber phone3_2 = createPhone("456789", PhoneType.LANDLINE);
Student student3 = createStudent(3, "Jane", "Doe", "jane.doe@baeldung.com", Arrays.asList(phone3_1, phone3_2));

return Arrays.asList(student1, student2, student3);
}

private Student createStudent(int id, String firstName, String lastName, String email, List<PhoneNumber> phones) {
return Student.newBuilder().setId(id)
.setFirstName(firstName).setLastName(lastName).setEmail(email).addAllPhone(phones).build();
}

private PhoneNumber createPhone(String number, PhoneType type) {
return PhoneNumber.newBuilder().setNumber(number).setType(type).build();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
syntax = "proto3";

package model;

option java_package = "ink.ckx.protobuf_test.model";
option java_outer_classname = "Training";

message Course {
int32 id = 1;
string course_name = 2;
repeated Student student = 3;
}

message Student {
int32 id = 1;
string first_name = 2;
string last_name = 3;
string email = 4;
repeated PhoneNumber phone = 5;

message PhoneNumber {
string number = 1;
PhoneType type = 2;
}

enum PhoneType {
MOBILE = 0;
LANDLINE = 1;
}
}

测试

  1. 调用 /courses/1 及 /courses/2 接口是否正常,保存文件
  2. 反序列化 protobuf 文件,查看结果是否正常
1
2
3
4
5
6
7
8
public static void main(String[] args) throws IOException {
Course course;
try (FileInputStream file = new FileInputStream("C:\\Users\\chenkaixin12121\\Downloads\\2")) {
course = Course.parseFrom(file.readAllBytes());
}
String json = com.google.protobuf.util.JsonFormat.printer().print(course);
System.out.println(json);
}