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. git:当本地分支中的代码和develop分支上有很多冲突,希望删掉本地分支,重新建立新的分支,怎么解决?

    git:当本地分支中的代码和develop分支上有很多冲突,希望删掉本地分支,重新建立新的分支,但是git中说你需要先解决当前的冲突,这种情况怎么解决 这种情况可以在代码编辑器中点击commit,然后 ...

  2. JMeter已传值但是提示为空

    登录时已经传值了,可是一直提示为空 解决:在在请求的url中拼接上参数

  3. 爬虫出现Forbidden by robots.txt(转载 https://blog.csdn.net/zzk1995/article/details/51628205)

    先说结论,关闭scrapy自带的ROBOTSTXT_OBEY功能,在setting找到这个变量,设置为False即可解决. 使用scrapy爬取淘宝页面的时候,在提交http请求时出现debug信息F ...

  4. fiddler学习总结--通过Fiddler模拟弱网进行测试

    弱网测试的目的: 弱网测试可以发现一些因为网络问题导致的交互问题,从而更好的完善应用的性能. 关注点:1.卡死,崩溃,无响应,闪退.2.业务交互数据传输正确性. 通过Fiddler可以模拟弱网进行测试 ...

  5. 为archlinux终端ls不同类型文件设置不同显示颜色

    title: 为archlinux终端ls不同类型文件设置不同显示颜色 date: 2017-11-13 20:53:55 tags: linux categories: linux archlinu ...

  6. 机器学习【三】k-近邻(kNN)算法

    一.kNN算法概述 kNN算法是用来分类的,其依据测量不同特征值之间的距离,其核心思想在于用距离目标最近的k个样本数据的分类来代表目标的分类(这k个样本数据和目标数据最为相似).其精度高,对异常值不敏 ...

  7. DataTable插件报错:Uncaught TypeError: Cannot read property 'style' of undefined

    DataTable插件报错:Uncaught TypeError: Cannot read property 'style' of undefined 原因:table 中定义的列和aoColumns ...

  8. web前端开发常用组件

    web前端开发常用组件 1. 对话框(dialog):jbox(适合对话框等其它功能).colorbox(也很强大,可以弥补jbox图片轮播的落点),      这二者基本能搞定所有对话框的情况 2. ...

  9. git push 远程新分支

    git clone #从远程克隆 进行一些编辑后 git add . git commit -m "xxx" git push #将master推送到master git chec ...

  10. Linux环境sftp配置

    1.查看SSH版本,openssh版本必须大于4.8p1 ssh -V 2.创建用户组 groupadd sftp-users 3.在sftp-users用户组下创建admin,admin不用于登录系 ...