一、创建项目
创建模块
二、父项目:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zoomy</groupId>
<artifactId>springboot-grpc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-grpc</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-boot.version>2.5.3</spring-boot.version>
<net-devh-grpc.version>2.0.1.RELEASE</net-devh-grpc.version>
</properties>
<!--引入的子模块-->
<modules>
<module>grpc-client</module>
<module>grpc-proto</module>
<module>grpc-server</module>
</modules>
<dependencies>
<dependency>
<groupId>com.zoomy</groupId>
<artifactId>grpc-proto</artifactId>
<version>${project.version}</version>
</dependency>
<!--核心grpc-spring-boot依赖-->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
<version>${net-devh-grpc.version}</version>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
<version>${net-devh-grpc.version}</version>
</dependency>
</dependencies>
</project>
三、grpc-proto
pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zoomy</groupId>
<artifactId>grpc-proto</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>grpc-proto</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<grpc.version>1.14.0</grpc.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.5.1-1:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.14.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
在grpc-proto下创建.proto文件
syntax = "proto3";
option java_package = "com.zoomy.grpc.proto";
option java_multiple_files = true;
service HelloService{
rpc hello (HelloRequest) returns (HelloResponse) {
}
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
使用插件生成java代码
右键Run protobuf:compile插件
先运行ptorobuf:compile,再运行ptotobuf:compile-custom
四、grpc-server 模块
pom 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zoomy</groupId>
<artifactId>grpc-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>grpc-server</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- 接口依赖 -->
<dependency>
<groupId>com.zoomy</groupId>
<artifactId>grpc-proto</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
</dependency>
</dependencies>
</project>
GrpcService:
package com.zoomy.grpcserver.annotation;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface GrpcService {
}
HelloService :
package com.zoomy.grpcserver.service;
import com.zoomy.grpc.proto.HelloRequest;
import com.zoomy.grpc.proto.HelloResponse;
import com.zoomy.grpc.proto.HelloServiceGrpc;
import com.zoomy.grpcserver.annotation.GrpcService;
import io.grpc.stub.StreamObserver;
@GrpcService
public class HelloService extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void hello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
System.out.println(" HelloService 接收到的参数,name:" + request.getName());
String greeting = "Hi " + request.getName();
HelloResponse response = HelloResponse.newBuilder().setMessage(greeting).build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
GrpcServerApplication:
package com.zoomy.grpcserver;
import com.zoomy.grpcserver.annotation.GrpcService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import java.io.IOException;
import java.util.Map;
@SpringBootApplication
public class GrpcServerApplication {
public static void main(String[] args) throws IOException, InterruptedException {
// 启动SpringBoot web
ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(GrpcServerApplication.class, args);
Map<String, Object> grpcServiceBeanMap = configurableApplicationContext.getBeansWithAnnotation(GrpcService.class);
ServiceManager serviceManager = configurableApplicationContext.getBean(ServiceManager.class);
serviceManager.loadService(grpcServiceBeanMap);
}
}
ServiceManager:
package com.zoomy.grpcserver;
import io.grpc.BindableService;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Map;
@Component
public class ServiceManager {
private Server server;
private int grpcServerPort = 9091;
public void loadService(Map<String, Object> grpcServiceBeanMap) throws IOException, InterruptedException {
ServerBuilder serverBuilder = ServerBuilder.forPort(grpcServerPort);
// 采用注解扫描方式,添加服务
for (Object bean : grpcServiceBeanMap.values()) {
serverBuilder.addService((BindableService) bean);
System.out.println(bean.getClass().getSimpleName() + " is regist in Spring Boot!");
}
server = serverBuilder.build().start();
System.out.println("grpc server is started at " + grpcServerPort);
// 增加一个钩子,当JVM进程退出时,Server 关闭
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.err.println("*** shutting down gRPC server since JVM is shutting down");
if (server != null) {
server.shutdown();
}
System.err.println("*** server shut down!!!!");
}
});
server.awaitTermination();
}
}
application.yml:
server:
port: 8081
spring:
application:
name: grpc-server
五、grpc-client
pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zoomy</groupId>
<artifactId>grpc-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>grpc-client</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- 接口依赖 -->
<dependency>
<groupId>com.zoomy</groupId>
<artifactId>grpc-proto</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
</dependency>
</dependencies>
</project>
GrpcServiceConfig:
package com.zoomy.grpcclient.annotation;
import com.zoomy.grpc.proto.HelloServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GrpcServiceConfig {
@Bean
public ManagedChannel getChannel() {
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 9091)
.usePlaintext()
.build();
return channel;
}
@Bean
public HelloServiceGrpc.HelloServiceBlockingStub getStub1(ManagedChannel channel) {
return HelloServiceGrpc.newBlockingStub(channel);
}
}
UserController:
package com.zoomy.grpcclient.controller;
import com.zoomy.grpc.proto.HelloRequest;
import com.zoomy.grpc.proto.HelloResponse;
import com.zoomy.grpc.proto.HelloServiceGrpc;
import lombok.SneakyThrows;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class UserController {
@Resource
HelloServiceGrpc.HelloServiceBlockingStub helloServiceBlockingStub;
/**
* http://localhost:8098/hello
*/
@SneakyThrows
@RequestMapping("/hello")
public String hello() {
HelloRequest request = HelloRequest.newBuilder()
.setName("zoomy")
.build();
HelloResponse helloResponse = helloServiceBlockingStub.hello(request);
String result = helloResponse.getMessage();
System.out.println(result);
return result;
}
}
application.yml
server:
port: 8082
六、测试
启动服务端,客户端
启动postman测试:http://localhost:8082/hello