最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Spring Boot 4.0 与 gRPC 极简集成:4步搞定 比REST还丝滑
时间:2026-07-17 08:42:03 编辑:袖梨 来源:一聚教程网
01 引言
gRPC 是 Google 开源的高性能 RPC 框架,基于 HTTP/2 + Protocol Buffers,序列化效率和传输速度都比传统 REST + JSON 高出一截,在微服务内部通信、移动端调用、跨语言服务等场景下非常吃香。
但传统 gRPC 的 Java 集成姿势比较原始:手写 ServerBuilder、手写 ManagedChannel、手写拦截器链,样板代码一堆。Spring gRPC(1.0.x,2025 年正式发布)的目标就是把这些脏活全包了,让你像写普通 Spring Boot 应用一样写 gRPC。

02 环境准备
Spring gRPC对环境还是有要求的:
- 最低Java17
Spring Framework 7.0.1- Spring gRPC
1.0.x使用Spring Boot要求4.0.x

03 Spring gRPC Server
3.1 Maven依赖
复制代码<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-grpc-server</artifactId>
</dependency>
使用Spring的脚手架,还引入了protobuf-maven-plugin编译插件。

Protobuf 编译插件,让 Maven/Gradle 自动把 .proto 文件编译成 Java 类。
3.2 定义 proto 文件
在 src/main/proto/hello.proto 创建服务定义(注意把 java_package 换成你自己的包名)。
使用Spring脚手架自动生成proto文件包。

复制代码syntax = "proto3";option java_multiple_files = true;
option java_package = "com.simonking.ws.boot.grpc.server.proto";
option java_outer_classname = "UserProto";package user;// 用户信息服务 - 展示多参数 gRPC 方法
service UserService {
// 多参数创建用户
rpc CreateUser (CreateUserRequest) returns (CreateUserResponse);
// 多参数查询用户
rpc GetUser (GetUserRequest) returns (GetUserResponse);
}// ============ 通用消息 ============// 用户信息
message UserInfo {
int64 id = 1;
string username = 2;
string email = 3;
int32 age = 4;
string phone = 5;
string created_at = 6;
string updated_at = 7;
}// ============ 创建用户 (多参数) ============message CreateUserRequest {
string username = 1;
string email = 2;
int32 age = 3;
string phone = 4;
string password = 5;
string nickname = 6;
}message CreateUserResponse {
bool success = 1;
string message = 2;
int64 user_id = 3;
}// ============ 查询用户 ============message GetUserRequest {
int64 user_id = 1;
}message GetUserResponse {
bool success = 1;
string message = 2;
UserInfo user = 3;
}
在这里定义方法,参数以及响应。
字段说明:
java_package:生成的 Java 类放在哪个包java_multiple_files = true:每个 message 一个独立 .java 文件(推荐)java_outer_classname:容器类名(一般用不到,因为开了 multiple_files)- 字段后面的
= 1是 protobuf 的字段编号,不能改也不能重用,是序列化兼容性的关键
3.3 编译生成stub
执行:
复制代码./mvnw clean compile
编译完成之后,会在target/generated-sources/protobuf 生成对应的实体和服务:

IntelliJ 用户注意:右键 target/generated-sources 目录 → Mark Directory as → Generated Sources Root,否则 IDE 识别不到。
3.4 实现方法
继承XxxGrpc.XxxImplBase即可。
复制代码@GrpcService
public class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase { private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 内存存储模拟数据库
private final ConcurrentHashMap<Long, UserInfo> userStore = new ConcurrentHashMap<>();
private final AtomicLong idGenerator = new AtomicLong(1); // ===================== 1. 创建用户 ===================== @Override
public void createUser(CreateUserRequest request,
StreamObserver<CreateUserResponse> responseObserver) {
long userId = idGenerator.getAndIncrement();
String now = LocalDateTime.now().format(DTF); UserInfo user = UserInfo.newBuilder()
.setId(userId)
.setUsername(request.getUsername())
.setEmail(request.getEmail())
.setAge(request.getAge())
.setPhone(request.getPhone())
.setCreatedAt(now)
.setUpdatedAt(now)
.build(); userStore.put(userId, user); CreateUserResponse response = CreateUserResponse.newBuilder()
.setSuccess(true)
.setMessage("用户创建成功")
.setUserId(userId)
.build(); responseObserver.onNext(response);
responseObserver.onCompleted();
log.info("===== createUser 响应: userId={} =====", userId);
} // ===================== 2. 查询用户 ===================== @Override
public void getUser(GetUserRequest request,
StreamObserver<GetUserResponse> responseObserver) {
log.info("===== getUser: userId={} =====", request.getUserId()); UserInfo user = userStore.get(request.getUserId());
if (user == null) {
GetUserResponse response = GetUserResponse.newBuilder()
.setSuccess(false)
.setMessage("用户不存在: " + request.getUserId())
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
return;
} GetUserResponse response = GetUserResponse.newBuilder()
.setSuccess(true)
.setMessage("查询成功")
.setUser(user)
.build(); responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
注意实现类上的注解:org.springframework.grpc.server.service.GrpcService
3.5 启动类
启动类不需要额外的编写,但是启动类帮我们做了三件事:
- 启动 Netty-based gRPC Server
- 监听
spring.grpc.server.port(默认 9090) - 把所有
BindableServiceBean 注册上去
04 Spring gRPC Client
客户端的编写和服务端差不多。
4.1 Maven依赖
复制代码<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-grpc-client</artifactId>
</dependency><build>
<plugins>
<plugin>
<groupId>io.github.ascopes</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3.2 定义 proto 文件
同服务端
3.3 编译生成stub
同服务端
3.4 配置客户端
由于gRPC基于Netty,所以需要配置通道信息。
复制代码@Configuration
public class GrpcClientConfig { @Value("${grpc.client.host:localhost}")
private String host; @Value("${grpc.client.port:9090}")
private int port; @Bean(destroyMethod = "shutdown")
public ManagedChannel grpcChannel() {
return ManagedChannelBuilder.forAddress(host, port)
.usePlaintext()
.build();
} @Bean
public UserServiceGrpc.UserServiceBlockingStub blockingStub(ManagedChannel channel) {
return UserServiceGrpc.newBlockingStub(channel);
}
}
3.5 调用方法
复制代码@RestController
@RequestMapping("/user")
public class UserController { private static final Logger log = LoggerFactory.getLogger(UserController.class); @Autowired
private UserServiceBlockingStub blockingStub; // ===================== 1. 创建用户 ===================== @PostMapping("/create")
public Map<String, Object> createUser() {
CreateUserRequest request = CreateUserRequest.newBuilder()
.setUsername("test_user")
.setEmail("[email protected]")
.setAge(25)
.setPhone("13800138000")
.setPassword("123456")
.setNickname("测试用户")
.build(); CreateUserResponse resp = blockingStub.createUser(request);
log.info("createUser -> userId={}", resp.getUserId());
return Map.of("success", resp.getSuccess(), "message", resp.getMessage(), "userId", resp.getUserId());
} // ===================== 2. 查询用户 ===================== @GetMapping("/{userId}")
public Map<String, Object> getUser(@PathVariable long userId) {
GetUserRequest request = GetUserRequest.newBuilder()
.setUserId(userId)
.build();
GetUserResponse resp = blockingStub.getUser(request); Map<String, Object> result = new LinkedHashMap<>();
result.put("success", resp.getSuccess());
result.put("message", resp.getMessage());
if (resp.hasUser()) {
result.put("user", toUserMap(resp.getUser()));
}
return result;
} // ===================== 工具方法 ===================== private Map<String, Object> toUserMap(UserInfo user) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("id", user.getId());
map.put("username", user.getUsername());
map.put("email", user.getEmail());
map.put("age", user.getAge());
map.put("phone", user.getPhone());
map.put("createdAt", user.getCreatedAt());
map.put("updatedAt", user.getUpdatedAt());
return map;
}
}
3.6 测试
创建用户

查询用户

相关文章
- 如何查询hive元数据库 07-17
- hive元数据库使用方法 07-17
- 《世界启元》平阳马超阵容搭配推荐-最佳组合解析 07-17
- hive元数据库怎样配置 07-17
- hive元数据库怎样扩展 07-17
- 如何备份hive元数据库 07-17