Grpc 针对proto复杂对象转换传输DEMO,其中对象包含List、enum 、Map、Map中包含List等复杂对象转换。
proto 文件原文
syntax = "proto3";//指定proto版本为3.0
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";//生成API代码路径
option java_outer_classname = "HelloWorldProto";//文件名称
option objc_class_prefix = "HLW";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (Test) returns (HelloReply) {}//API接口其中参数为Test返回值为HelloReply
}
//定义返回HelloReply实体
message HelloReply {
string message = 1;
}
/**
*定义Test实体
*/
message Test{
string testStr = 1;//字段类型为String
repeated TestList testList = 2;//属性为TestList对象集合
map<string,TestMap> testMap = 3;//属性为map<string,TestMap>Map对象其中TestMap 包含集合属性
DocumentExtType type = 4;//枚举属性
}
message TestMap{
string testmap = 1;
repeated HelloReply helloReply = 2;
}
message TestList{
string testlist = 1;
}
enum DocumentExtType{
HTML = 0;
XML = 1;
JSON = 2;
PDF = 3;
IMAGETIFF = 4;
IMAGEGIF = 5;
IMAGEJPG = 6;
IMAGEJPEG = 7;
IMAGEPNG = 8;
MEDIAAU = 9;
MEDIAAIFF = 10;
MEDIAWAVE = 11;
MEDIAMIDI = 12;
MEDIAMP4 = 13;
MEDIAM4V = 14;
MEDIA3G2 = 15;
MEDIA3GP2 = 16;
MEDIA3GP = 17;
MEDIA3GPP = 18;
OTHER = 19;
}
定义GRPC服务端代码
package io.grpc.examples.hello.demo;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.Test;
import io.grpc.examples.helloworld.TestList;
import io.grpc.examples.zk.DistributedSystemServer;
import io.grpc.stub.StreamObserver;
import java.util.logging.Logger;
public class HelloWorldServer {
private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName());
private Server server;
private void start() throws Exception {
/* The port on which the server should run */
int port = 8888;
server = ServerBuilder.forPort(port)
.addService(new GreeterImpl())
.build()
.start();
logger.info("Server started, listening on " + port);
//该处是将GRPC服务注入到zookeeper中下篇帖子讲述DistributedSystemServer类得实现
// DistributedSystemServer distributedSystemServer = new DistributedSystemServer();
// distributedSystemServer.getZkClient();
// distributedSystemServer.connectZK("8888");
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
HelloWorldServer.this.stop();
System.err.println("*** server shut down");
}
});
}
private void stop() {
if (server != null) {
server.shutdown();
}
}
/**
* Await termination on the main thread since the grpc library uses daemon threads.
*/
private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
/**
* Main launches the server from the command line.
*/
public static void main(String[] args) throws Exception, InterruptedException {
final HelloWorldServer server = new HelloWorldServer();
server.start();
server.blockUntilShutdown();
}
static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
//API服务端接口实现
@Override
public void sayHello(Test req, StreamObserver<HelloReply> responseObserver) {
//解析Test对象复杂属性
System.out.println("集合数量"+req.getTestListList().size());
System.out.println("枚举获取:"+req.getType());
System.out.println("JSON".equals(req.getType().toString()));
for (TestList testList:req.getTestListList()){
System.out.println("集合内容:"+testList.getTestlist());
}
System.out.println("Map对象String内容:"+req.getTestMapMap().get("test").getTestmap());
for (String str: req.getTestMapMap().keySet()){
System.out.println("获取的MapKey值:"+str);
}
for(HelloReply helloReply:req.getTestMapMap().get("test").getHelloReplyList()){
System.out.println("Map对象集合内容:"+helloReply.getMessage());
}
//返回值回写
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getTestStr()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
GRPC客户端
package io.grpc.examples.hello.demo;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import io.grpc.examples.helloworld.*;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A simple client that requests a greeting from the {@link HelloWorldServer}.
*/
public class HelloWorldClient {
private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName());
private final ManagedChannel channel;
private final GreeterGrpc.GreeterBlockingStub blockingStub;
/** Construct client connecting to HelloWorld server at {@code host:port}. */
public HelloWorldClient(String host, int port) {
this(ManagedChannelBuilder.forAddress(host, port)
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
// needing certificates.
.usePlaintext(true)
.build());
}
/** Construct client for accessing RouteGuide server using the existing channel. */
HelloWorldClient(ManagedChannel channel) {
this.channel = channel;
blockingStub = GreeterGrpc.newBlockingStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
/** Say hello to server. */
public void greet(String name) {
logger.info("Will try to greet " + name + " ...");
Test.Builder builder = Test.newBuilder();
builder.setTestStr("复杂对象测试DEMO");
builder.setType(DocumentExtType.JSON);
TestMap.Builder mapBuilder = TestMap.newBuilder();
mapBuilder.setTestmap("MAP集合对象测试");
for (int i = 0;i<3;i++){
TestList.Builder testlistbuilder = TestList.newBuilder();
testlistbuilder.setTestlist("集合对象0"+i);
builder.addTestList(testlistbuilder);
HelloReply.Builder helloBuilder = HelloReply.newBuilder();
helloBuilder.setMessage("MAP中helloReply集合数据0"+i);
mapBuilder.addHelloReply(helloBuilder);
}
builder.putTestMap("test",mapBuilder.build());
Test request = builder.build();
HelloReply response;
try {
response = blockingStub.sayHello(request);
} catch (StatusRuntimeException e) {
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
return;
}
logger.info("Greeting: " + response.getMessage());
}
/**
* Greet server. If provided, the first element of {@code args} is the name to use in the
* greeting.
*/
public static void main(String[] args) throws Exception {
HelloWorldClient client = new HelloWorldClient("localhost", 8888);
try {
/* Access a service running on the local machine on port 50051 */
String user = "world";
if (args.length > 0) {
user = args[0]; /* Use the arg as the name to greet if provided */
}
client.greet(user);
} finally {
client.shutdown();
}
}
}
运行结果
"C:\Program Files\Java\jdk1.8.0_151\bin\java" -Didea.launcher.port=7534 "-Didea.launcher.bin.path=D:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_151\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\rt.jar;E:\demo\GRPC\target\classes;D:\m2\repository\io\grpc\grpc-netty\1.9.0\grpc-netty-1.9.0.jar;D:\m2\repository\io\grpc\grpc-core\1.9.0\grpc-core-1.9.0.jar;D:\m2\repository\io\grpc\grpc-context\1.9.0\grpc-context-1.9.0.jar;D:\m2\repository\com\google\guava\guava\19.0\guava-19.0.jar;D:\m2\repository\com\google\errorprone\error_prone_annotations\2.1.2\error_prone_annotations-2.1.2.jar;D:\m2\repository\com\google\code\findbugs\jsr305\3.0.0\jsr305-3.0.0.jar;D:\m2\repository\com\google\instrumentation\instrumentation-api\0.4.3\instrumentation-api-0.4.3.jar;D:\m2\repository\io\opencensus\opencensus-api\0.10.0\opencensus-api-0.10.0.jar;D:\m2\repository\io\opencensus\opencensus-contrib-grpc-metrics\0.10.0\opencensus-contrib-grpc-metrics-0.10.0.jar;D:\m2\repository\io\netty\netty-codec-http2\4.1.17.Final\netty-codec-http2-4.1.17.Final.jar;D:\m2\repository\io\netty\netty-codec-http\4.1.17.Final\netty-codec-http-4.1.17.Final.jar;D:\m2\repository\io\netty\netty-codec\4.1.17.Final\netty-codec-4.1.17.Final.jar;D:\m2\repository\io\netty\netty-transport\4.1.17.Final\netty-transport-4.1.17.Final.jar;D:\m2\repository\io\netty\netty-handler\4.1.17.Final\netty-handler-4.1.17.Final.jar;D:\m2\repository\io\netty\netty-buffer\4.1.17.Final\netty-buffer-4.1.17.Final.jar;D:\m2\repository\io\netty\netty-common\4.1.17.Final\netty-common-4.1.17.Final.jar;D:\m2\repository\io\netty\netty-handler-proxy\4.1.17.Final\netty-handler-proxy-4.1.17.Final.jar;D:\m2\repository\io\netty\netty-resolver\4.1.17.Final\netty-resolver-4.1.17.Final.jar;D:\m2\repository\io\netty\netty-codec-socks\4.1.17.Final\netty-codec-socks-4.1.17.Final.jar;D:\m2\repository\io\grpc\grpc-protobuf\1.9.0\grpc-protobuf-1.9.0.jar;D:\m2\repository\com\google\protobuf\protobuf-java\3.5.1\protobuf-java-3.5.1.jar;D:\m2\repository\com\google\protobuf\protobuf-java-util\3.5.1\protobuf-java-util-3.5.1.jar;D:\m2\repository\com\google\code\gson\gson\2.7\gson-2.7.jar;D:\m2\repository\com\google\api\grpc\proto-google-common-protos\1.0.0\proto-google-common-protos-1.0.0.jar;D:\m2\repository\io\grpc\grpc-protobuf-lite\1.9.0\grpc-protobuf-lite-1.9.0.jar;D:\m2\repository\io\grpc\grpc-stub\1.9.0\grpc-stub-1.9.0.jar;D:\m2\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar;D:\m2\repository\com\101tec\zkclient\0.7\zkclient-0.7.jar;D:\m2\repository\org\slf4j\slf4j-api\1.6.1\slf4j-api-1.6.1.jar;D:\m2\repository\org\slf4j\slf4j-log4j12\1.6.1\slf4j-log4j12-1.6.1.jar;D:\m2\repository\org\apache\zookeeper\zookeeper\3.4.6\zookeeper-3.4.6.jar;D:\m2\repository\jline\jline\0.9.94\jline-0.9.94.jar;D:\m2\repository\io\netty\netty\3.7.0.Final\netty-3.7.0.Final.jar;D:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.1\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain io.grpc.examples.hello.demo.HelloWorldServer
log4j:WARN No appenders could be found for logger (io.netty.util.internal.logging.InternalLoggerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
三月 02, 2018 3:00:14 下午 io.grpc.examples.hello.demo.HelloWorldServer start
信息: Server started, listening on 8888
收到事件通知:SyncConnected
集合数量3
枚举获取:JSON
true
集合内容:集合对象00
集合内容:集合对象01
集合内容:集合对象02
Map对象String内容:MAP集合对象测试
获取的MapKey值:test
Map对象集合内容:MAP中helloReply集合数据00
Map对象集合内容:MAP中helloReply集合数据01
Map对象集合内容:MAP中helloReply集合数据02