关注我的公众号:【编程朝花夕拾】,可获取首发内容。
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依赖
xml
<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文件包。

protobuf
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
执行:
bash
./mvnw clean compile
编译完成之后,会在target/generated-sources/protobuf 生成对应的实体和服务:

IntelliJ 用户 注意:右键 target/generated-sources 目录 → Mark Directory as → Generated Sources Root,否则 IDE 识别不到。
3.4 实现方法
继承XxxGrpc.XxxImplBase即可。
java
@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依赖
xml
<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,所以需要配置通道信息。
java
@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 调用方法
java
@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("test@example.com")
.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 测试
创建用户

查询用户
