1、参考资料
  (1)grpc-java官网QuickStart: https://grpc.io/docs/quickstart/java.html
  (2)grpc-java的github: https://github.com/grpc/grpc-java
  (3)grpc-java的tutorial: https://grpc.io/docs/tutorials/basic/java.html
  (4)Protocol Buffers:https://developers.google.com/protocol-buffers/
 
2、grpc helloworld案例
  2.1、需求:我在项目a中UserServiceImpl中写了一个getUserById(Integer id)方法,然后想在项目b中使用,怎么办?
  2.2、定义想要调用的方法
  首先新建一个springboot项目(springboot版本2.1.3.RELEASE),项目名为 grpc007_server,按照传统做法,编写实体类、dao层和service层。为了方便,dao省略,service使用模拟数据。
  实体类:
package com.oy.model;
public class User {
private Integer id;
private String name;
private Integer age;
private Double salary;
}
package com.oy.model;
public class Book {
private Integer id;
private String name;
private Double price;
}

  service接口:

package com.oy.service;
import com.oy.model.User;
public interface UserService {
User getUserById(Integer id);
}
package com.oy.service;
import com.oy.model.Book;
public interface BookService {
int addBook(Book book);
}

  service实现类:

package com.oy.service.impl;

import org.springframework.stereotype.Service;
import com.oy.model.User;
import com.oy.service.UserService; @Service
public class UserServiceImpl implements UserService {
@Override
public User getUserById(Integer id) {
User user = null;
if (id.equals(1)) {
user = new User();
user.setAge(25);
user.setId(1);
user.setName("张无忌");
user.setSalary(10000.0);
} else {
user = new User();
user.setAge(20);
user.setId(2);
user.setName("周芷若");
user.setSalary(10000.0);
}
return user;
}
}
package com.oy.service.impl;

import org.springframework.stereotype.Service;
import com.oy.model.Book;
import com.oy.service.BookService; @Service
public class BookServiceImpl implements BookService{
@Override
public int addBook(Book book) {
return 1;
}
}

  

  2.3、定义服务
  为了在另外一个项目使用上面定义的两个service方法。我们需要定义服务。新建一个新springboot项目,名为grpc007_proto,用来专门定义方法。在src/main/proto目录下,创建文件hello.proto,内容为:
 
syntax = "proto3";

option java_multiple_files = false;
option java_package = "com.oy.grpc";
option java_outer_classname = "GrpcLib";
//option objc_class_prefix = "HLW"; package grpc; // The service definition.
service UserService {
rpc getUserById (getUserByIdRequest) returns (GrpcReply) {}
} service BookService {
rpc addBook (addBookRequest) returns (GrpcReply) {}
} /************************************************************/ message GrpcReply {
int32 code = 1;
string data = 2;
} message getUserByIdRequest {
int32 id = 1;
} message addBookRequest {
int32 id = 1;
string name = 2;
double price = 3;
}

  hello.proto定义了服务的方法名、入参和返回值。通过hello.proto可以生成我们需要的代码,但是首先要在项目grpc007_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 http://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.1.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.oy</groupId>
<artifactId>grpc007_proto</artifactId>
<version>0.0.1</version>
<name>grpc007_proto</name>
<description>grpc007_proto for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<grpc.version>1.14.0</grpc.version>
</properties> <dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</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> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</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: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>
</plugins>
</build>
</project>

  选中项目grpc007_proto,右键/Run As/Maven build...,输入clean compile命令进行编译。

  

  选中项目,使用F5更新项目,可以看到生成的代码如下:

  2.4、发布服务

  尽管我们定义了服务,但是客户端并不能直接使用,我们还需要在服务端对服务进一步包装处理,然后才能发布服务。

  首先将项目grpc007_proto生成的3个类复制到 grpc007_server。然后要将我们想要调用的方法进行包装。

  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 http://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.1.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.oy</groupId>
<artifactId>grpc007_server</artifactId>
<version>0.0.1</version>
<name>grpc007_server</name>
<description>grpc007_server for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<grpc.version>1.14.0</grpc.version>
</properties> <dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</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> <dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

  UserGrpc类:(最好命名为UserServiceImpl)

package com.oy.service.grpc;

import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.oy.grpc.UserServiceGrpc;
import com.oy.grpc.GrpcLib.GrpcReply;
import com.oy.grpc.GrpcLib.getUserByIdRequest;
import com.oy.model.User;
import com.oy.service.UserService;
import com.oy.utils.Utils;
import io.grpc.stub.StreamObserver; @Component
public class UserGrpc extends UserServiceGrpc.UserServiceImplBase { @Resource
private UserService userService; @Override
public void getUserById(getUserByIdRequest request, StreamObserver<GrpcReply> responseObserver) {
Utils.log.info("UserGrpc#getUserById, id:{}", request.getId()); // 调用service层的方法
User user = userService.getUserById(request.getId()); String data = JSONObject.toJSONString(user);
GrpcReply reply = GrpcReply.newBuilder().setCode(0).setData(data).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}

  BookGrpc类:(最好命名为BookServiceImpl)

package com.oy.service.grpc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import com.alibaba.fastjson.JSONObject;
import com.oy.grpc.BookServiceGrpc;
import com.oy.grpc.GrpcLib.GrpcReply;
import com.oy.grpc.GrpcLib.addBookRequest;
import com.oy.model.Book;
import com.oy.service.BookService;
import com.oy.utils.Utils; import io.grpc.stub.StreamObserver; @Component
public class BookGrpc extends BookServiceGrpc.BookServiceImplBase { @Autowired
private BookService bookService; @Override
public void addBook(addBookRequest request, StreamObserver<GrpcReply> responseObserver) {
Integer id = request.getId();
String name = request.getName();
Double price = request.getPrice();
Utils.log.info("BookGrpc#addBook, id:{}, name:{}, price:{}", id, name, price); // 调用service层的方法
Book book = new Book();
book.setId(id);
book.setName(name);
book.setPrice(price);
int result = bookService.addBook(book); JSONObject jsonObj = new JSONObject(); if (result == 1) {
jsonObj.put("msg", "add book succ");
} else {
jsonObj.put("msg", "add book failed");
} String data = jsonObj.toJSONString();
GrpcReply reply = GrpcReply.newBuilder().setCode(0).setData(data).build();
responseObserver.onNext(reply);
// onCompleted() method to specify that we’ve finished dealing with the RPC
responseObserver.onCompleted();
}
}

  定义grpc服务端,GrpcServer类:

package com.oy;

import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.oy.service.grpc.BookGrpc;
import com.oy.service.grpc.UserGrpc;
import com.oy.utils.Utils;
import io.grpc.Server;
import io.grpc.ServerBuilder; @Component
public class GrpcServer {
private int port = 23333;
private Server server; @Autowired
private UserGrpc userGrpc; @Autowired
private BookGrpc bookGrpc; private void start() throws IOException {
server = ServerBuilder.forPort(port)
.addService(userGrpc)
.addService(bookGrpc)
.build().start(); Utils.log.info(("grpc service start...")); Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
Utils.log.error(("shutting down gRPC server since JVM is shutting down"));
GrpcServer.this.stop();
Utils.log.error("gRPC server shut down");
}
});
} private void stop() {
if (server != null) {
server.shutdown();
}
} // block
private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
} public void init(String[] args) throws IOException, InterruptedException {
start();
blockUntilShutdown();
}
}

  

  springboot启动类,实现CommandLineRunner接口,重写run()方法。spring容器加载完毕后会调用run()方法,从而启动grpc服务。可以通过springboot启动类的main方法启动grpc007_server,也可以将项目grpc007_server打成可执行jar再运行。

package com.oy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class Grpc007ServerMainApplication implements CommandLineRunner { public static void main(String[] args) throws Exception {
SpringApplication.run(Grpc007ServerMainApplication.class, args);
} @Autowired
private GrpcServer grpcServer; @Override
public void run(String... args) throws Exception {
grpcServer.init(args);
} }

  将项目grpc007_server打成可执行jar:选中项目grpc007_proto,右键/Run As/Maven build...,输入clean package命令进行打包,进入项目grpc007_proto的target目录,可以将jar包重命名为a.jar,shift+右键,在此处打开Powershell窗口。输入java -jar a.jar,回车。 输入clean package命令进行打包如果报错,可能是因为src/test/java里面代码的问题,删除src/test/java里面的内容。

 
   2.5、客户端
  新建一个springboot项目,名为grpc007_client。
 

  客户端程序,GrpcClient类:

package com.oy.grpc.client;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit; import com.oy.grpc.BookServiceGrpc;
import com.oy.grpc.GrpcClientPool;
import com.oy.grpc.GrpcLib.GrpcReply;
import com.oy.grpc.GrpcLib.addBookRequest;
import com.oy.grpc.GrpcLib.getUserByIdRequest;
import com.oy.grpc.UserServiceGrpc;
import com.oy.utils.UtilFunctions; import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException; public class GrpcClient {
public static String host = "localhost";
private final ManagedChannel channel;
private final UserServiceGrpc.UserServiceBlockingStub userBlockingStub;
private final BookServiceGrpc.BookServiceBlockingStub bookBlockingStub; public GrpcClient(String host, int port) {
channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
userBlockingStub = UserServiceGrpc.newBlockingStub(channel);
bookBlockingStub = BookServiceGrpc.newBlockingStub(channel);
} public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
} @SuppressWarnings({ "rawtypes" })
public static Object call(String rpcMethoddName, Object... args) throws Exception {
UtilFunctions.log.info("=========== GrpcClient#call begin ===========");
GrpcClient client = null;
try {
// client = GrpcClientPool.borrowObject();
client = new GrpcClient(host, 23333); Class[] argsTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
UtilFunctions.log.info("args types: {}", args[i].getClass());
argsTypes[i] = args[i].getClass();
}
Method method = client.getClass().getMethod(rpcMethoddName, argsTypes);
Object result = method.invoke(client, args);
return result;
} catch (Exception e) {
UtilFunctions.log.error("GrpcClient#call Exception: {}", e.toString());
return null;
} finally {
if (client != null) {
// GrpcClientPool.returnObject(client);
client.shutdown();
}
}
} // ============= User module =============
public Object getUserById(Integer id) {
UtilFunctions.log.info("=========== GrpcClient#getUserById begin ===========");
getUserByIdRequest request = getUserByIdRequest.newBuilder().setId(id).build();
GrpcReply response;
try {
response = userBlockingStub.getUserById(request);
UtilFunctions.log.info("GrpcClient#getUserById response, code:{}, data:{}", response.getCode(),
response.getData());
} catch (StatusRuntimeException e) {
UtilFunctions.log.error("GrpcClient#getUserById error, StatusRuntimeException:{}", e);
return null;
}
return response;
} // ============= Book module =============
public Object addBook(Integer id, String name, Double price) {
UtilFunctions.log.info("=========== GrpcClient#addBook begin ===========");
addBookRequest request = addBookRequest.newBuilder().setId(id).setName(name).setPrice(price).build();
GrpcReply response;
try {
response = bookBlockingStub.addBook(request);
UtilFunctions.log.info("GrpcClient#addBook response, code:{}, data:{}", response.getCode(),
response.getData());
} catch (StatusRuntimeException e) {
UtilFunctions.log.error("GrpcClient#addBook error, StatusRuntimeException:{}", e);
return null;
}
return response;
} }

  测试类:

package com.oy.grpc.client;

import com.oy.grpc.GrpcLib.GrpcReply;
import com.oy.utils.UtilFunctions; public class TestService { public static void main(String[] args) throws Exception { for (int i = 0; i < 1; i++) {
new Thread(new Runnable() { @Override
public void run() {
GrpcReply result = null;
try {
//result = (GrpcReply) GrpcClient.call("getUserById", Integer.valueOf("1"));
//result = (GrpcReply) GrpcClient.call("getUserById", 2);
result = (GrpcReply) GrpcClient.call("addBook", 1, "thinking in java", 50.0);
} catch (Exception e) {
e.printStackTrace();
}
UtilFunctions.log.info("client call interface, get code:{}, data:{}", result.getCode(),
result.getData()); }
}).start();
} }
}

grpc(一)grpc-java之helloworld的更多相关文章

  1. JAVA的helloworld

    java环境设置------------- 在环境变量中设置以下三个变量:JAVA_HOME=C:\j2sdk1.4.1 //可以改为相应的目录CLASSPATH=%JAVA_HOME%\lib\to ...

  2. Java的HelloWorld程序

    Java的HelloWorld程序 1.新建文本文档,编写HelloWorld程序,最后保存时记得保存成.java格式 2.在D盘新建一个HelloJava文件夹用于保存java程序 3.使用WIN+ ...

  3. JAVA_SE基础——5.第一个Java程序HelloWorld&注释的应用

    配置完JDK&环境变量后,我们就可以开始写程序了,那么程序怎么写呢,用什么工具呢,我建议 为了方便学习,我们最好在一个磁盘下建立一个专门的文件来写java程序,比如就在D盘下建立一个名为&qu ...

  4. Java RMI HelloWorld

    Java RMI HelloWorld   RMI 远程方法调用. 顾名思义就是可以像调用本地程序方法一样调用远程(其他JVM)的程序方法.   分为3个部分: Stub:中介,代理. 封装了远程对象 ...

  5. 带入gRPC:gRPC Streaming, Client and Server

    带入gRPC:gRPC Streaming, Client and Server 原文地址:带入gRPC:gRPC Streaming, Client and Server 前言 本章节将介绍 gRP ...

  6. Java Learning 001 新建一个Java工程 HelloWorld程序

    Java Learning 001 新建一个Java工程 HelloWorld程序 Step 1 . 在Eclipse 软件里,点击: File -> New -> Java Projec ...

  7. 带入gRPC:gRPC Deadlines

    带入gRPC:gRPC Deadlines 原文地址:带入gRPC:gRPC Deadlines项目地址:https://github.com/EDDYCJY/go... 前言 在前面的章节中,已经介 ...

  8. Go gRPC进阶-gRPC转换HTTP(十)

    前言 我们通常把RPC用作内部通信,而使用Restful Api进行外部通信.为了避免写两套应用,我们使用grpc-gateway把gRPC转成HTTP.服务接收到HTTP请求后,grpc-gatew ...

  9. gRPC Motivation and Design Principles | gRPC https://grpc.io/blog/principles/

    gRPC Motivation and Design Principles | gRPC https://grpc.io/blog/principles/

  10. Go语言入门篇-gRPC基于golang & java简单实现

    一.什么是RPC 1.简介: RPC:Remote Procedure Call,远程过程调用.简单来说就是两个进程之间的数据交互. 正常服务端的接口服务是提供给用户端(在Web开发中就是浏览器)或者 ...

随机推荐

  1. 微信小游戏跳一跳简单手动外挂(基于adb 和 python)

    只有两个python文件,代码很简单. shell.py: #coding:utf-8 import subprocess import math import os def execute_comm ...

  2. 基于UVM的verilog验证

    Abstract 本文介绍UVM框架,并以crc7为例进行UVM的验证,最后指出常见的UVM验证开发有哪些坑,以及怎么避免. Introduction 本例使用环境:ModelSim 10.2c,UV ...

  3. python列表常用内建方法

    python列表常用内建方法: abc = ['a',1,3,'a'] #abc.pop(1) #删除索引1的值.结果['a', 3] #abc.append([123]) #结果:['a', 1, ...

  4. nuxtJs中直接使用自带的@nuxtjs/axios

    最初我以为在nuxtjs中是需要重新npm install axios,但是其实nuxtjs自己集成了这个数据渲染方法 你只需在nuxt.config.js中配置一下就可以了 modules: [ / ...

  5. #WEB安全基础 : HTTP协议 | 0x0 TCP/IP四层结构

    学完HTML/CSS了? 做了这么多网页,但是你知道它们是怎么工作的吗? 作为你的朋友,我也对这些东西感兴趣,在写博客的同时也在和你一起学. 废话少说,进入正题 网络中的通信包括两个端分别为:客户端( ...

  6. [ Python ] OpenGL

    pyOpenGL Installation Package Version------------------- -------numpy 1.14.2 PyOpenGL 3.1.0 PyOpenGL ...

  7. pageresponse.min.js自动缩放页面改写

    /* * 名称 :移动端响应式框架 * 作者 :白树 http://peunzhang.cnblogs.com * 版本 :v2.1 * 日期 :2015.10.13 * 兼容 :ios 5+.and ...

  8. Maven 的41种骨架功能介绍(转)

    Maven 的41种骨架: ...>mvn archetype:generate 1: internal -> appfuse-basic-jsf (创建一个基于Hibernate,Spr ...

  9. oracle 误删除数据,回退表数据

    select * from sh_gonghuo_renyuan as of timestamp to_timestamp('2017-11-17 16:00:00','yyyy-mm-dd hh24 ...

  10. c#高级编程第七版 学习笔记 第三章 对象和类型

    第三章 对象和类型 本章的内容: 类和结构的区别 类成员 按值和按引用传送参数 方法重载 构造函数和静态构造函数 只读字段 部分类 静态类 Object类,其他类型都从该类派生而来 3.1 类和结构 ...