syntax = "proto3";//标识 proto版本 建议使用proto3
package userinfoservice;//proto包名 避免命名冲突,也可以作为引入其他proto文件时使用
option java_package = "com.example.userinfoservice" ;//生成的类将带有此包名,不指定则使用package
option cc_generic_services = true;
option go_package = "./pb";
option java_outer_classname = "UserInfoEntity";//指定生成后的类名,里面会包含req/res,不指定则使用文件名
message GetUserInfoReq{
string id = 1;
}
message GetUserInfoRes{
string id = 1;
string name = 2;
int32 age = 3;
}
service UserInfoService {
rpc getUserInfo(GetUserInfoReq) returns (GetUserInfoRes);
}
$ go install google.golang.org/protobuf/cmd/[email protected]
$ go install google.golang.org/grpc/cmd/[email protected]
$ export PATH="$PATH:$(go env GOPATH)/bin"
protoc --go_out=. --go_opt=paths=source_relative \\
--go-grpc_out=. --go-grpc_opt=paths=source_relative \\
proto/userinfo.proto
将你的proto文件放到src/main/proto和src/test/proto目录,并配置生成代码的插件
Gradle生成代码插件:
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java application project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at <https://docs.gradle.org/7.2/userguide/building_java_projects.html>
*/
plugins {
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
// ASSUMES GRADLE 5.6 OR HIGHER. Use plugin version 0.8.10 with earlier gradle versions
id 'com.google.protobuf' version '0.8.17'
// Generate IntelliJ IDEA's .idea & .iml project files
id 'idea'
id 'java'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
repositories {
maven { url '<https://maven.aliyun.com/repository/google/>' }
maven { url '<https://maven.aliyun.com/repository/jcenter/>'}
}
}
def grpcVersion = '1.48.0' // CURRENT_GRPC_VERSION
dependencies {
// Use JUnit test framework.
testImplementation 'junit:junit:4.13.2'
// This dependency is used by the application.
implementation 'com.google.guava:guava:30.1.1-jre'
implementation "io.grpc:grpc-netty:${grpcVersion}"
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
implementation "io.grpc:grpc-services:${grpcVersion}"
implementation "io.grpc:grpc-stub:${grpcVersion}"
}
application {
// Define the main class for the application.
mainClass = 'client.MainApplication'
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.2.0"
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.4.0'
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
}
}
Maven生成代码插件:
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.4.1.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.4.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
(1 )Java 服务端
package com.example.userinfoservice.impl;
import com.example.userinfoservice.UserInfoEntity;
import com.example.userinfoservice.UserInfoServiceGrpc;
import com.example.userinfoservice.entity.UserInfoData;
import com.google.common.collect.Maps;
import io.grpc.stub.StreamObserver;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
public class UserInfoServiceImpl extends UserInfoServiceGrpc.UserInfoServiceImplBase {
private HashMap<String, UserInfoData> userinfoHashMap = Maps.newHashMap();
@Override
public void getUserInfo(UserInfoEntity.GetUserInfoReq request, StreamObserver<UserInfoEntity.GetUserInfoRes> responseObserver) {
System.out.println("java服务收到请求");
if (StringUtils.isEmpty(request.getId())){
responseObserver.onError(new Exception("id不能为空"));
responseObserver.onCompleted();
return;
}
if (userinfoHashMap.isEmpty()){
initUserInfoHashMap();
}
UserInfoData userInfoData = userinfoHashMap.get(request.getId());
if (userInfoData == null){
responseObserver.onError(new Exception("id不能为空"));
responseObserver.onCompleted();
return;
}
responseObserver.onNext(UserInfoEntity.GetUserInfoRes.newBuilder()
.setId(userInfoData.getId())
.setName(userInfoData.getName())
.setAge(userInfoData.getAge())
.build());
responseObserver.onCompleted();
}
private void initUserInfoHashMap() {
userinfoHashMap.put("1",new UserInfoData("1","小美",24));
userinfoHashMap.put("2",new UserInfoData("2","小强",28));
userinfoHashMap.put("3",new UserInfoData("3","小刚",30));
}
}
package com.example.userinfoservice.entity;
public class UserInfoData{
private String id;
private String name;
private int age;
public UserInfoData() {
}
public UserInfoData(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package com.example.userinfoservice;
import com.example.userinfoservice.impl.UserInfoServiceImpl;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import java.io.IOException;
import java.util.logging.Logger;
public class App {
public String getGreeting() {
return "Hello World!";
}
private static final Logger logger = Logger.getLogger(App.class.getName());
private Server server;
private void start() throws IOException {
int port = 10080;
server = ServerBuilder.forPort(port)
.addService(new UserInfoServiceImpl())
.build()
.start();
logger.info("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
logger.info("*** shutting down gRPC server since JVM is shutting down");
App.this.stop();
logger.info("*** server shut down");
}));
}
private void stop() {
if (server != null) {
server.shutdown();
}
}
/**
* Await termination on the main thread since the grpc library uses daemon threads.
*/
private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
/**
* Main launches the server from the command line.
*/
public static void main(String[] args) throws IOException, InterruptedException {
final App server = new App();
server.start();
server.blockUntilShutdown();
}
}
(2)Java 客户端
package com.example.userinfoservice;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import java.util.logging.Logger;
public class MainApplication {
private static final Logger logger = Logger.getLogger(MainApplication.class.getName());
public static void main(String[] args) throws InterruptedException {
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 10080)
.usePlaintext()
.build();
UserInfoServiceGrpc.UserInfoServiceBlockingStub stub =
UserInfoServiceGrpc.newBlockingStub(channel);
Userinfo.GetUserInfoRes res = stub.getUserInfo(
Userinfo.GetUserInfoReq.newBuilder()
.setId("1")
.build());
logger.info("用户id: " + res.getId() + "\\t用户姓名:"+ res.getName()
+"\\t用户年龄:"+ res.getAge());
channel.shutdown();
}
}
(3)go 服务端
package serviceimpl
import (
"context"
"errors"
"grpc-in-action/part1/go/server/pb"
"log"
)
type UserInfo struct {
Id string
Name string
Age int32
}
type UserInfoServiceImpl struct {
UserInfoData map[string]*UserInfo
pb.UnimplementedUserInfoServiceServer
}
func (server *UserInfoServiceImpl) GetUserInfo(ctx context.Context, in *pb.GetUserInfoReq) (*pb.GetUserInfoRes, error) {
log.Printf("go server收到请求")
//初始化一个map
if server.UserInfoData == nil{
server.initUserInfoData()
}
data:= server.UserInfoData[in.Id]
if data == nil{
return nil,errors.New("该id不存在")
}
res := &pb.GetUserInfoRes{
Id: data.Id,
Name: data.Name,
Age: data.Age,
}
return res,nil
}
func (server *UserInfoServiceImpl) initUserInfoData (){
server.UserInfoData = make(map[string]*UserInfo)
server.UserInfoData["1"] = &UserInfo{
Id: "1",
Name: "小美",
Age: 18,
}
server.UserInfoData["2"] = &UserInfo{
Id: "2",
Name: "小刚",
Age: 28,
}
server.UserInfoData["3"] = &UserInfo{
Id: "3",
Name: "小王",
Age: 20,
}
}
package main
import (
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"grpc-in-action/part1/go/server/pb"
"grpc-in-action/part1/go/server/serviceimpl"
"log"
"net"
)
func main() {
lis, err := net.Listen("tcp", "localhost:10080")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
ser := &serviceimpl.UserInfoServiceImpl{}
pb.RegisterUserInfoServiceServer(s,ser)
log.Printf("start")
reflection.Register(s)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
(4)go 客户端
package main
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"grpc-in-action/part1/go/client/pb"
"log"
)
func main() {
// Set up a connection to the server.
conn, err := grpc.Dial("localhost:10080",grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewUserInfoServiceClient(conn)
req:= &pb.GetUserInfoReq{Id: "1"}
res,err :=c.GetUserInfo(context.Background(),req)
if err != nil {
log.Fatalf("err:%+v",err)
}else {
log.Printf("res:%+v",res)
}
}