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. java框架之Spring(1)-入门

    介绍 概述 Spring 是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用.Spring 是于 2003 年兴起的一个轻量级的 J ...

  2. 利用StateListDrawable给button动态设置背景

    项目中,遇到相同样式的Button,只是stroke颜色不一样.为了实现一个,就得写两个shape文件,一个selector文件:多个还得重复写. 解决方法: 结合StateListDrawable给 ...

  3. cocos2d JS-(JavaScript) 冒泡排序

    思想: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 针对所有的元素重复以上的步骤,除了最 ...

  4. Treap仿set 模板

    Treap仿set 模板 蓝书232 &代码: #include <cstdio> #include <bitset> #include <iostream> ...

  5. C#中的装箱(inboxing)和拆箱(unboxing)(简单理解)

    装箱和拆箱是值类型和引用类型之间相互转换是要执行的操作.  装箱:将一个值类型隐式地转换成一个object类型,或把这个值类型转换成一个被该值类型应用的接口类型,把一个值类型的值装箱,就是创建一个ob ...

  6. [openjudge-搜索]城堡问题(The Castle)

    题目描述 描述 图1是一个城堡的地形图.请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大.城堡被分割成mn(m≤50,n≤50)个方块,每个方块可以有0~4面墙. 输入 程序从标准输入设备 ...

  7. windows 如何创建硬链接

    输入代码:mklink /d F:\ D:\pdf mklink /d 是命令语句,空格,接着是放置硬链接的位置,空格,再是目标文件夹.

  8. j2ee高级开发技术课程第六周

    一.jsf(java server faces)的运行原理(工作方式) 1.jsf应用是事件驱动的,当一个事件发生时(比如用户单击一个按钮),事件通知通过HTTP发往服务器,服务器端使用叫做Faces ...

  9. Hdu2039 三角形

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2039 三角形 Time Limit: 2000/1000 MS (Java/Others)    Me ...

  10. 大话npm,cnpm和yarn

    npm:基于node.js的包管理工具; 常用命令 npm install 包名; 缺点:因服务器在国外,所以下载包的速度超级慢,所以出现了cnpm和yarn cnpm:跟npm是一样的,这是淘宝出的 ...