java使用grpc框架demo代码示例protobuf

文章目录

  • java使用grpc框架
  • 一、gRPC是什么
  • 二、使用步骤
    • 1.父工程搭建
      • maven引入
    • 2.服务端模块搭建
      • 1.maven引入grpc包和protobuf插件
      • 2.使用protobuf生成代码
      • 3.继承自生成的代码实现并重写方法
      • 4.启动服务端代码
    • 3.客户端搭建
      • service实现类代码
    • 4.启动服务端,客户端进行通信测试
  • 总结


java使用grpc框架


一、gRPC是什么

RPC是Remote Procedure Call的简称,中文叫远程过程调用。
那么gRPC就是google使用GO语言开发的RPC框架
而且gRPC基于 HTTP/2协议传输

二、使用步骤

1.父工程搭建

maven引入

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>cdwxgrpc</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>server</module>
    </modules>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <grpc.version>1.34.1</grpc.version>
        <protobuf.version>3.12.0</protobuf.version>
        <protoc.version>3.12.0</protoc.version>
        <maven.cpmplier.source>1.8</maven.cpmplier.source>
        <maven.cpmplier.target>1.8</maven.cpmplier.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-bom</artifactId>
                <version>${grpc.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.google.protobuf</groupId>
                <artifactId>protobuf-java-util</artifactId>
                <version>${protobuf.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>

    </dependencyManagement>

    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.2</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
                    <protoSourceRoot>src/main/resources/proto</protoSourceRoot>
                </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>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.服务端模块搭建

1.maven引入grpc包和protobuf插件

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cdwxgrpc</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>server</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.5.2</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java-util</artifactId>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
        </dependency>
    </dependencies>
    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.2</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
                    <protoSourceRoot>./src/main/resources/proto</protoSourceRoot>
                </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>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

protobuf插件可以install生成grpc代码

2.使用protobuf生成代码

// 申明语法版本 *必要* (否则默认proto2)
syntax = "proto3";

package server;
// java代码的生成包路径
option java_package = "com.example.server";
// java生成的classname
option java_outer_classname = "SearchServiceProto";
//option java_multiple_files = true;

// 定义服务
// 例如下面这个search服务,rpc声明他是rpc服务方法,search是其中一个方法名(可以声明多个方法),searchrequest是请求参数
// searchresponse是返回结果
service SearchService{
  rpc Search (SearchRequest) returns (SearchResponse) {}
}
// 声明消息(有点像java对象)里面是他的一些属性,注意后面的=1这些是表明他的参数index而不是赋值(可以去了解一下protobuf语法)
message SearchRequest {
  // 默认reversed
  string query = 1;
  int32 pageNumber = 2;
  int32 resultPerPage = 3;
  enum Corpus {
    UNIVERSAL = 0;
    WEB = 1;
    IMAGES = 2;
    LOCAL = 3;
    NEWS = 4;
    PRODUCTS = 5;
    VIDEO = 6;
  }
  Corpus corpus = 4;
}
// 模拟globalresult的data
message Data {
  int32 dataInt = 1;
  string dataStr = 2;
}

message SearchResponse {
  int32 code = 1;
  string msg = 2;
  // 类似数组结构  Data[]
  repeated Data data = 3;
}

maven-install会生成代码在target目录下,后续可使用代码

3.继承自生成的代码实现并重写方法

package com.example.server.service.impl;

import com.example.server.SearchServiceGrpc;
import com.example.server.SearchServiceGrpc.*;
import com.example.server.SearchServiceProto;
import com.example.server.SearchServiceProto.*;
import io.grpc.BindableService;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Tequila
 * @date 2022/5/7 14:56
 */
public class SearchServiceImpl extends SearchServiceImplBase {

    private final int port = 9999;
    private Server server;

    @Override
    public void search(SearchRequest request, StreamObserver<SearchResponse> responseObserver) {
        if (request.isInitialized()) {
            System.out.println("true");
        }
        int value = request.getCorpusValue();
        int pageNumber = request.getPageNumber();
        String query = request.getQuery();
        int resultPerPage = request.getResultPerPage();
        System.out.println(request.toString());
        /*
        * proto Data
        * */
        List<Data> datas = new ArrayList<>();
        datas.add(Data.newBuilder().setDataInt(1).setDataStr("一").build());

        SearchResponse build = SearchResponse.newBuilder()
                // 如果用到了repeated修饰的proto message则不可使用set进行赋值用add
                .setCode(200)
                .setMsg("通信成功")
                .addAllData(datas)
                .build();

        responseObserver.onNext(build);
        // 结束
        responseObserver.onCompleted();
    }

    public void start() throws IOException {
        server = ServerBuilder.forPort(port)
                .addService(new SearchServiceImpl())
                .build()
                .start();
        System.out.println("service start...at port" + port);
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                SearchServiceImpl.this.stop();
                System.out.println("程序出错或正常退出!");
            }
        });
    }

    private void stop() {
        if (server != null) {
            server.shutdown();
        }
    }

    /**
     * 不让main线程断开
     * @throws InterruptedException
     */
    public void blockUntilShutdown() throws InterruptedException {
        if (server != null) {
            server.awaitTermination();
        }
    }

}

4.启动服务端代码

package com.example.server;

import com.example.server.service.impl.SearchServiceImpl;

import java.io.IOException;

/**
 * @author Tequila
 * @date 2022/5/7 15:07
 */
public class Server {

    public static void main(String[] args) {
        SearchServiceImpl searchService = new SearchServiceImpl();
            try {
                searchService.start();
                searchService.blockUntilShutdown();
            } catch (InterruptedException | IOException e) {
                e.printStackTrace();
            }
    }

}

这时候服务端就搭建好了

3.客户端搭建

java使用grpc框架demo代码示例protobuf_第1张图片

controller层来调用service然后返回数据给前端
controller代码就不写了下面看下serviceimpl代码就可

service实现类代码

package com.example.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.client.entity.Corpus;
import com.example.client.entity.GlobalData;
import com.example.client.service.DemoService;
import com.example.server.SearchServiceGrpc;
import com.example.server.SearchServiceGrpc.*;
import com.example.server.SearchServiceProto;
import com.example.server.SearchServiceProto.*;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;


/**
 * @author Tequila
 * @date 2022/5/7 14:11
 */
@Service
public class DemoServiceImpl implements DemoService {

    private final SearchServiceBlockingStub stub;
    private final ManagedChannel channel;



    public DemoServiceImpl() {
        channel = ManagedChannelBuilder
                .forAddress("127.0.0.1", 9999)
                .usePlaintext() //使用纯文本类型
                .build();
        stub = SearchServiceGrpc.newBlockingStub(channel);
    }

    @Override
    public String search(String query) {
        if (StringUtils.isEmpty(query)) {
            return null;
        }
        String[] split = query.split(",");
        SearchResponse response = stub.search(SearchRequest.newBuilder()
                .setCorpusValue(Integer.parseInt(split[0]))
                .setPageNumber(Integer.parseInt(split[1]))
                .setQuery(split[2])
                .setResultPerPage(Integer.parseInt(split[3]))
                .build());
        if (BeanUtil.isEmpty(response)) {
            return new JSONObject()
                    .set("code",200)
                    .set("msg","返回结果为空")
                    .set("data",GlobalData.builder().build()).toString();
        }
        int code = response.getCode();
        String msg = response.getMsg();
        List<Data> dataList = response.getDataList();
        List<GlobalData> collect = dataList.stream().map(data -> {
            // 转成自建对象不然json没法识别
            return GlobalData.builder().dataInt(data.getDataInt()).dataString(data.getDataStr()).build();
        }).collect(Collectors.toList());
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("code",code).set("msg",msg).set("data",collect);
        return jsonObject.toString();
    }
}

差不多就是这样的demo代码,后续的一些架构设计mapper层等自行添加就好

4.启动服务端,客户端进行通信测试

java使用grpc框架demo代码示例protobuf_第2张图片

总结

以上差不多就是简单得gRPC框架的使用demo代码示例了。
其中比较重要的点就是protobuf语法,插件生成代码,重写服务端方法,客户端连接请求获取返回结果。

你可能感兴趣的:(java学习笔记,java,rpc,golang)