簡介
更多內容參考:https://www.grpc.io/docs/guides/
gRPC 是一個高性能、開源和通用的 RPC 框架,面向移動和 HTTP/2 設計。目前提供 C、Java 和 Go 語言版本,分別是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持.
gRPC 基於 HTTP/2 標准設計,帶來諸如雙向流、流控、頭部壓縮、單 TCP 連接上的多復用請求等特。這些特性使得其在移動設備上表現更好,更省電和節省空間占用。
gRPC 是什么?
在 gRPC 里客戶端應用可以像調用本地對象一樣直接調用另一台不同的機器上服務端應用的方法 ,使得您能夠更容易地創建分布式應用和服務。與許多 RPC 系統類似,
gRPC 也是基於以下理念 :
定義一個服務,指定其能夠被遠程調用的方法(包含參數和返回類型)。在服務端實現這個接口 ,並運行一個 gRPC 服務器來處理客戶端調用。在客戶端擁有一個存根能夠像服務端一樣的方法。
gRPC 客戶端和服務端可以在多種環境中運行和交互 - 從 google 內部的服務器到你自己的筆記本 ,並且可以用任何 gRPC 支持的語言(#quickstart)來編寫。所以,你可以很容易地用 Java 創建一 個 gRPC 服務端,用 Go、Python、Ruby 來創建客戶端。此外,Google 最新 API 將有 gRPC 版 本的接口,使你很容易地將 Google 的功能集成到你的應用里。
使用 protocol buffers
gRPC 默認使用 protocol buffers,這是 Google 開源的一套成熟的結構數據序列化機制(當然也 可以使用其他數據格式如 JSON)。
正如你將在下方例子里所看到的,你用 proto files 創建 gRPC 服務,用 protocol buffers 消息類型來定義方法參數和返回類型。
你可以在 Protocol Buffers 文檔 (
https://developers.google.com/protocol-buffers/docs/overview
)找到更多關於 Protocol Buffers 的資料。
Protocol buffers 版本
盡管 protocol buffers 對於開源用戶來說已經存在了一段時間,例子內使用的卻一種名叫 proto3 的新風格的 protocol buffers,它擁有輕量簡化的語法、一些有用的新功能,並且支持更多新語言 。
當前針對 Java 和 C++ 發布了 beta 版本,針對 JavaNano(即 Android Java)發布 alpha 版 本,
在protocol buffers Github 源碼庫里(https://github.com/google/protobuf/releases)有 Ruby 支持,
在golang/protobuf Github 源碼庫(https://github.com/golang/protobuf)里還 有針對 Go 語言的生成器, 對更多語言的支持正在開發中。
你可以在 proto3 語言指南 (https://developers.google.com/protocol-buffers/docs/proto3)里找到更多內容,
在與當前 默認版本的發布說明(https://github.com/google/protobuf/releases)比較,看到兩者的主要不 同點。更多關於 proto3 的文檔很快就會出現。
雖然你可以使用 proto2 (當前默認的 protocol buffers 版本), 我們通常建議你在 gRPC 里使用 proto3,因為這樣你可以使用 gRPC 支持全部范 圍的的語言,
並且能避免 proto2 客戶端與 proto3 服務端交互時出現的兼容性問題,反之亦然。
安裝gRPC
Java 例子代碼在 GitHub 源碼庫里。你可以運行如下命令克隆源碼到本地:
git clone -b v1.24.0 https://github.com/grpc/grpc-java
切換當前目錄到grpc-java/examples
cd grpc-java/examples
Run a gRPC application
From the examples
directory:
- Compile the client and server
./gradlew installDist
- Run the server
./build/install/examples/bin/hello-world-server
- In another terminal, run the client
./build/install/examples/bin/hello-world-client
Congratulations! You’ve just run a client-server application with gRPC.
Go獲取例子:
go get -u github.com/grpc/grpc-go/examples/helloworld/greeter_client
go get -u github.com/grpc/grpc-go/examples/helloworld/greeter_server
切換當前目錄到 examples/helloworld
// Copyright 2015 The gRPC Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; option java_multiple_files = true; option java_package = "io.grpc.examples.helloworld"; option java_outer_classname = "HelloWorldProto"; option objc_class_prefix = "HLW"; package helloworld; // The greeting service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; }
構建gRPC-Java
僅當您要更改gRPC-Java或測試/使用gRPC-Java庫的未發行版本(例如主HEAD)時,才需要構建。
構建需要JDK 8,因為我們的測試使用TLS。
grpc-java有一個用於protoc的C ++代碼生成插件。由於許多Java開發人員沒有安裝C編譯器,也不需要運行或修改代碼生成,因此該構建可以跳過它。要跳過,請創建文件 <project-root>/gradle.properties
並添加skipCodegen=true
。
然后,要構建,運行:
$ ./gradlew build
要將工件安裝到您的Maven本地存儲庫中以在您自己的項目中使用,請運行:
$ ./gradlew publishToMavenLocal
IntelliJ的注意事項
當您將項目作為Gradle項目導入並將IDE生成/運行操作委托給Gradle時,以IntelliJ進行構建的效果最佳。
您可以在以下位置找到此設置:
-> Build Tools -> Gradle -> Runner
-> Delegate IDE build/run actions to gradle.
如何構建代碼生成插件
僅當您要更改代碼生成時,才需要此部分。大多數用戶只需要skipCodegen=true
如上所述使用即可。
建立Protobuf
codegen插件是C ++代碼,需要protobuf 3.0.0或更高版本。
對於Linux,Mac和MinGW:
git clone https://github.com/google/protobuf.git cd protobuf git checkout v3.9.0 ./autogen.sh ./configure --disable-shared make make check sudo make install
如果您熟悉C ++編譯和自動工具,你可以指定 --prefix
為的Protobuf和使用-I
中CXXFLAGS
,-L
在 LDFLAGS
引用它。在構建grpc-java時將使用環境變量。
Protobuf /usr/local
默認安裝到。
對於Visual C ++,請參閱Protobuf自述文件, 以了解如何編譯Protobuf。gRPC-java假定為Release版本。
Linux和MinGW
如果/usr/local/lib
不在您的庫搜索路徑中,則可以通過運行以下命令添加它:
sudo sh -c 'echo /usr/local/lib >> /etc/ld.so.conf' sudo ldconfig
蘋果電腦
Mac OS X的某些版本(例如10.10)沒有/usr/local
默認文件頭文件和庫的搜索路徑。它將使代碼生成的構建失敗。要解決此問題,您將需要設置環境變量:
export CXXFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib"
Visual C ++的注意事項
在Windows和VC ++上構建時,需要為Gradle指定項目屬性以找到protobuf:
.\gradlew publishToMavenLocal ^ -PvcProtobufInclude=C:\path\to\protobuf-3.9.0\src ^ -PvcProtobufLibs=C:\path\to\protobuf-3.9.0\vsprojects\Release ^ -PtargetArch=x86_32
由於指定每個構建的那些屬性很麻煩,因此您可以<project-root>\gradle.properties
使用如下內容創建:
vcProtobufInclude=C:\\path\\to\\protobuf-3.9.0\\src vcProtobufLibs=C:\\path\\to\\protobuf-3.9.0\\vsprojects\\Release targetArch=x86_32
默認情況下,構建腳本將為與系統上安裝的Java運行時相同的體系結構構建代碼生成。如果您使用的是64位JVM,則會將代碼生成為64位編譯。由於Protobuf默認情況下僅針對32位構建,因此這targetArch=x86_32
是必需的。
Windows上MinGW的注意事項
如果您在Windows上同時安裝了MinGW和VC ++,則默認情況下將使用VC ++。要覆蓋此默認設置並使用MinGW,請添加-PvcDisable=true
到您的Gradle命令行或添加vcDisable=true
到中 <project-root>\gradle.properties
。
不支持的操作系統的注意事項
protoc
默認情況下,構建腳本從Maven Central 提取預編譯的。我們已經protoc
為流行的系統構建了二進制文件,但是它們可能不適用於您的系統。如果protoc
無法下載或無法運行,則可以通過將以下屬性添加到來使用自己構建的版本 <project-root>/gradle.properties
:
protoc=/path/to/protoc
生成代碼:
或者在build.gradle中配置好插件

group 'com.mikey' version '1.0-SNAPSHOT' //加入grpc插件 apply plugin: 'java' apply plugin: 'com.google.protobuf' //源編譯和目標編譯 sourceCompatibility = 1.8 targetCompatibility = 1.8 repositories { // maven庫 def cn = "http://maven.aliyun.com/nexus/content/groups/public/" def abroad = "http://central.maven.org/maven2/" // 先從url中下載jar若沒有找到,則在artifactUrls中尋找 maven { url cn artifactUrls abroad } } dependencies { compile group: 'io.netty', name: 'netty-all', version: '4.1.10.Final' //protobuf用到的庫 compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.3.1' compile group: 'com.google.protobuf', name: 'protobuf-java-util', version: '3.3.1' //thrift的庫 compile group: 'org.apache.thrift', name: 'libthrift', version: '0.12.0' //grpc用到的庫 compile 'io.grpc:grpc-netty-shaded:1.20.0' compile 'io.grpc:grpc-protobuf:1.20.0' compile 'io.grpc:grpc-stub:1.20.0' } /** *以下都是grpc所使用到的gradle插件 */ buildscript { repositories { mavenCentral() } dependencies { classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.8' } } protobuf { //生成的java代碼路徑 generatedFilesBaseDir = "$projectDir/src" // protoc { artifact = "com.google.protobuf:protoc:3.7.1" } plugins { grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.20.0' } } generateProtoTasks { all()*.plugins { grpc { // 生成的 service 文件路徑 setOutputSubDir 'java' } } } }
簡單Demo
參考:https://www.grpc.io/docs/tutorials/basic/java/
proto文件:StudentProto.proto
syntax="proto3"; package com.mikey.grpc; option java_package = "com.mikey.grpcstream"; option java_outer_classname = "StudentProto"; option java_multiple_files = true; service StudentService { //message 2 message rpc GetRealNameByUserName(Request) returns (Response){} } message Request { string username = 1; } message Response { string realname = 2; }
生成代碼:

// Generated by the protocol buffer compiler. DO NOT EDIT! // source: Student.proto package com.mikey.grpc; /** * Protobuf type {@code com.mikey.grpc.Request} */ public final class Request extends com.google.protobuf.GeneratedMessageV3 implements // @@protoc_insertion_point(message_implements:com.mikey.grpc.Request) RequestOrBuilder { private static final long serialVersionUID = 0L; // Use Request.newBuilder() to construct. private Request(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) { super(builder); } private Request() { username_ = ""; } @Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } private Request( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); if (extensionRegistry == null) { throw new NullPointerException(); } int mutable_bitField0_ = 0; com.google.protobuf.UnknownFieldSet.Builder unknownFields = com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { int tag = input.readTag(); switch (tag) { case 0: done = true; break; case 10: { String s = input.readStringRequireUtf8(); username_ = s; break; } default: { if (!parseUnknownField( input, unknownFields, extensionRegistry, tag)) { done = true; } break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return com.mikey.grpc.StudentProto.internal_static_com_mikey_grpc_Request_descriptor; } @Override protected FieldAccessorTable internalGetFieldAccessorTable() { return com.mikey.grpc.StudentProto.internal_static_com_mikey_grpc_Request_fieldAccessorTable .ensureFieldAccessorsInitialized( Request.class, Builder.class); } public static final int USERNAME_FIELD_NUMBER = 1; private volatile Object username_; /** * <code>string username = 1;</code> */ public String getUsername() { Object ref = username_; if (ref instanceof String) { return (String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; String s = bs.toStringUtf8(); username_ = s; return s; } } /** * <code>string username = 1;</code> */ public com.google.protobuf.ByteString getUsernameBytes() { Object ref = username_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (String) ref); username_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } private byte memoizedIsInitialized = -1; @Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; if (isInitialized == 0) return false; memoizedIsInitialized = 1; return true; } @Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (!getUsernameBytes().isEmpty()) { com.google.protobuf.GeneratedMessageV3.writeString(output, 1, username_); } unknownFields.writeTo(output); } @Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; size = 0; if (!getUsernameBytes().isEmpty()) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, username_); } size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } @Override public boolean equals(final Object obj) { if (obj == this) { return true; } if (!(obj instanceof Request)) { return super.equals(obj); } Request other = (Request) obj; if (!getUsername() .equals(other.getUsername())) return false; if (!unknownFields.equals(other.unknownFields)) return false; return true; } @Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + USERNAME_FIELD_NUMBER; hash = (53 * hash) + getUsername().hashCode(); hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } public static Request parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static Request parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static Request parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static Request parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static Request parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static Request parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static Request parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } public static Request parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } public static Request parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } public static Request parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } public static Request parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } public static Request parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } @Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } public static Builder newBuilder(Request prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } @Override protected Builder newBuilderForType( BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** * Protobuf type {@code com.mikey.grpc.Request} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements // @@protoc_insertion_point(builder_implements:com.mikey.grpc.Request) com.mikey.grpc.RequestOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return com.mikey.grpc.StudentProto.internal_static_com_mikey_grpc_Request_descriptor; } @Override protected FieldAccessorTable internalGetFieldAccessorTable() { return com.mikey.grpc.StudentProto.internal_static_com_mikey_grpc_Request_fieldAccessorTable .ensureFieldAccessorsInitialized( Request.class, Builder.class); } // Construct using com.mikey.grpc.Request.newBuilder() private Builder() { maybeForceBuilderInitialization(); } private Builder( BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessageV3 .alwaysUseFieldBuilders) { } } @Override public Builder clear() { super.clear(); username_ = ""; return this; } @Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return com.mikey.grpc.StudentProto.internal_static_com_mikey_grpc_Request_descriptor; } @Override public Request getDefaultInstanceForType() { return Request.getDefaultInstance(); } @Override public Request build() { Request result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } @Override public Request buildPartial() { Request result = new Request(this); result.username_ = username_; onBuilt(); return result; } @Override public Builder clone() { return super.clone(); } @Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, Object value) { return super.setField(field, value); } @Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { return super.clearField(field); } @Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { return super.clearOneof(oneof); } @Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, int index, Object value) { return super.setRepeatedField(field, index, value); } @Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, Object value) { return super.addRepeatedField(field, value); } @Override public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof Request) { return mergeFrom((Request)other); } else { super.mergeFrom(other); return this; } } public Builder mergeFrom(Request other) { if (other == Request.getDefaultInstance()) return this; if (!other.getUsername().isEmpty()) { username_ = other.username_; onChanged(); } this.mergeUnknownFields(other.unknownFields); onChanged(); return this; } @Override public final boolean isInitialized() { return true; } @Override public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { Request parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { parsedMessage = (Request) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { mergeFrom(parsedMessage); } } return this; } private Object username_ = ""; /** * <code>string username = 1;</code> */ public String getUsername() { Object ref = username_; if (!(ref instanceof String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; String s = bs.toStringUtf8(); username_ = s; return s; } else { return (String) ref; } } /** * <code>string username = 1;</code> */ public com.google.protobuf.ByteString getUsernameBytes() { Object ref = username_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (String) ref); username_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } /** * <code>string username = 1;</code> */ public Builder setUsername( String value) { if (value == null) { throw new NullPointerException(); } username_ = value; onChanged(); return this; } /** * <code>string username = 1;</code> */ public Builder clearUsername() { username_ = getDefaultInstance().getUsername(); onChanged(); return this; } /** * <code>string username = 1;</code> */ public Builder setUsernameBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); username_ = value; onChanged(); return this; } @Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { return super.setUnknownFields(unknownFields); } @Override public final Builder mergeUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { return super.mergeUnknownFields(unknownFields); } // @@protoc_insertion_point(builder_scope:com.mikey.grpc.Request) } // @@protoc_insertion_point(class_scope:com.mikey.grpc.Request) private static final Request DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new Request(); } public static Request getDefaultInstance() { return DEFAULT_INSTANCE; } private static final com.google.protobuf.Parser<Request> PARSER = new com.google.protobuf.AbstractParser<Request>() { @Override public Request parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return new Request(input, extensionRegistry); } }; public static com.google.protobuf.Parser<Request> parser() { return PARSER; } @Override public com.google.protobuf.Parser<Request> getParserForType() { return PARSER; } @Override public Request getDefaultInstanceForType() { return DEFAULT_INSTANCE; } }

// Generated by the protocol buffer compiler. DO NOT EDIT! // source: Student.proto package com.mikey.grpc; public interface RequestOrBuilder extends // @@protoc_insertion_point(interface_extends:com.mikey.grpc.Request) com.google.protobuf.MessageOrBuilder { /** * <code>string username = 1;</code> */ String getUsername(); /** * <code>string username = 1;</code> */ com.google.protobuf.ByteString getUsernameBytes(); }

// Generated by the protocol buffer compiler. DO NOT EDIT! // source: Student.proto package com.mikey.grpc; /** * Protobuf type {@code com.mikey.grpc.Response} */ public final class Response extends com.google.protobuf.GeneratedMessageV3 implements // @@protoc_insertion_point(message_implements:com.mikey.grpc.Response) ResponseOrBuilder { private static final long serialVersionUID = 0L; // Use Response.newBuilder() to construct. private Response(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) { super(builder); } private Response() { realname_ = ""; } @Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } private Response( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); if (extensionRegistry == null) { throw new NullPointerException(); } int mutable_bitField0_ = 0; com.google.protobuf.UnknownFieldSet.Builder unknownFields = com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { int tag = input.readTag(); switch (tag) { case 0: done = true; break; case 18: { String s = input.readStringRequireUtf8(); realname_ = s; break; } default: { if (!parseUnknownField( input, unknownFields, extensionRegistry, tag)) { done = true; } break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return com.mikey.grpc.StudentProto.internal_static_com_mikey_grpc_Response_descriptor; } @Override protected FieldAccessorTable internalGetFieldAccessorTable() { return com.mikey.grpc.StudentProto.internal_static_com_mikey_grpc_Response_fieldAccessorTable .ensureFieldAccessorsInitialized( Response.class, Builder.class); } public static final int REALNAME_FIELD_NUMBER = 2; private volatile Object realname_; /** * <code>string realname = 2;</code> */ public String getRealname() { Object ref = realname_; if (ref instanceof String) { return (String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; String s = bs.toStringUtf8(); realname_ = s; return s; } } /** * <code>string realname = 2;</code> */ public com.google.protobuf.ByteString getRealnameBytes() { Object ref = realname_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (String) ref); realname_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } private byte memoizedIsInitialized = -1; @Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; if (isInitialized == 0) return false; memoizedIsInitialized = 1; return true; } @Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (!getRealnameBytes().isEmpty()) { com.google.protobuf.GeneratedMessageV3.writeString(output, 2, realname_); } unknownFields.writeTo(output); } @Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; size = 0; if (!getRealnameBytes().isEmpty()) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, realname_); } size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } @Override public boolean equals(final Object obj) { if (obj == this) { return true; } if (!(obj instanceof Response)) { return super.equals(obj); } Response other = (Response) obj; if (!getRealname() .equals(other.getRealname())) return false; if (!unknownFields.equals(other.unknownFields)) return false; return true; } @Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + REALNAME_FIELD_NUMBER; hash = (53 * hash) + getRealname().hashCode(); hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } public static Response parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static Response parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static Response parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static Response parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static Response parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } public static Response parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } public static Response parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } public static Response parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } public static Response parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } public static Response parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } public static Response parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } public static Response parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } @Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } public static Builder newBuilder(Response prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } @Override protected Builder newBuilderForType( BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** * Protobuf type {@code com.mikey.grpc.Response} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements // @@protoc_insertion_point(builder_implements:com.mikey.grpc.Response) com.mikey.grpc.ResponseOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return com.mikey.grpc.StudentProto.internal_static_com_mikey_grpc_Response_descriptor; } @Override protected FieldAccessorTable internalGetFieldAccessorTable() { return com.mikey.grpc.StudentProto.internal_static_com_mikey_grpc_Response_fieldAccessorTable .ensureFieldAccessorsInitialized( Response.class, Builder.class); } // Construct using com.mikey.grpc.Response.newBuilder() private Builder() { maybeForceBuilderInitialization(); } private Builder( BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessageV3 .alwaysUseFieldBuilders) { } } @Override public Builder clear() { super.clear(); realname_ = ""; return this; } @Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return com.mikey.grpc.StudentProto.internal_static_com_mikey_grpc_Response_descriptor; } @Override public Response getDefaultInstanceForType() { return Response.getDefaultInstance(); } @Override public Response build() { Response result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } @Override public Response buildPartial() { Response result = new Response(this); result.realname_ = realname_; onBuilt(); return result; } @Override public Builder clone() { return super.clone(); } @Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, Object value) { return super.setField(field, value); } @Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { return super.clearField(field); } @Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { return super.clearOneof(oneof); } @Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, int index, Object value) { return super.setRepeatedField(field, index, value); } @Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, Object value) { return super.addRepeatedField(field, value); } @Override public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof Response) { return mergeFrom((Response)other); } else { super.mergeFrom(other); return this; } } public Builder mergeFrom(Response other) { if (other == Response.getDefaultInstance()) return this; if (!other.getRealname().isEmpty()) { realname_ = other.realname_; onChanged(); } this.mergeUnknownFields(other.unknownFields); onChanged(); return this; } @Override public final boolean isInitialized() { return true; } @Override public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { Response parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { parsedMessage = (Response) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { mergeFrom(parsedMessage); } } return this; } private Object realname_ = ""; /** * <code>string realname = 2;</code> */ public String getRealname() { Object ref = realname_; if (!(ref instanceof String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; String s = bs.toStringUtf8(); realname_ = s; return s; } else { return (String) ref; } } /** * <code>string realname = 2;</code> */ public com.google.protobuf.ByteString getRealnameBytes() { Object ref = realname_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( (String) ref); realname_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } /** * <code>string realname = 2;</code> */ public Builder setRealname( String value) { if (value == null) { throw new NullPointerException(); } realname_ = value; onChanged(); return this; } /** * <code>string realname = 2;</code> */ public Builder clearRealname() { realname_ = getDefaultInstance().getRealname(); onChanged(); return this; } /** * <code>string realname = 2;</code> */ public Builder setRealnameBytes( com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); realname_ = value; onChanged(); return this; } @Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { return super.setUnknownFields(unknownFields); } @Override public final Builder mergeUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { return super.mergeUnknownFields(unknownFields); } // @@protoc_insertion_point(builder_scope:com.mikey.grpc.Response) } // @@protoc_insertion_point(class_scope:com.mikey.grpc.Response) private static final Response DEFAULT_INSTANCE; static { DEFAULT_INSTANCE = new Response(); } public static Response getDefaultInstance() { return DEFAULT_INSTANCE; } private static final com.google.protobuf.Parser<Response> PARSER = new com.google.protobuf.AbstractParser<Response>() { @Override public Response parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return new Response(input, extensionRegistry); } }; public static com.google.protobuf.Parser<Response> parser() { return PARSER; } @Override public com.google.protobuf.Parser<Response> getParserForType() { return PARSER; } @Override public Response getDefaultInstanceForType() { return DEFAULT_INSTANCE; } }

// Generated by the protocol buffer compiler. DO NOT EDIT! // source: Student.proto package com.mikey.grpc; public interface ResponseOrBuilder extends // @@protoc_insertion_point(interface_extends:com.mikey.grpc.Response) com.google.protobuf.MessageOrBuilder { /** * <code>string realname = 2;</code> */ String getRealname(); /** * <code>string realname = 2;</code> */ com.google.protobuf.ByteString getRealnameBytes(); }

// Generated by the protocol buffer compiler. DO NOT EDIT! // source: Student.proto package com.mikey.grpc; public final class StudentProto { private StudentProto() {} public static void registerAllExtensions( com.google.protobuf.ExtensionRegistryLite registry) { } public static void registerAllExtensions( com.google.protobuf.ExtensionRegistry registry) { registerAllExtensions( (com.google.protobuf.ExtensionRegistryLite) registry); } static final com.google.protobuf.Descriptors.Descriptor internal_static_com_mikey_grpc_Request_descriptor; static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_com_mikey_grpc_Request_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor internal_static_com_mikey_grpc_Response_descriptor; static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_com_mikey_grpc_Response_fieldAccessorTable; public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { return descriptor; } private static com.google.protobuf.Descriptors.FileDescriptor descriptor; static { String[] descriptorData = { "\n\rStudent.proto\022\016com.mikey.grpc\"\033\n\007Reque" + "st\022\020\n\010username\030\001 \001(\t\"\034\n\010Response\022\020\n\010real" + "name\030\002 \001(\t2^\n\016StudentService\022L\n\025GetRealN" + "ameByUserName\022\027.com.mikey.grpc.Request\032\030" + ".com.mikey.grpc.Response\"\000B \n\016com.mikey." + "grpcB\014StudentProtoP\001b\006proto3" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { public com.google.protobuf.ExtensionRegistry assignDescriptors( com.google.protobuf.Descriptors.FileDescriptor root) { descriptor = root; return null; } }; com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] { }, assigner); internal_static_com_mikey_grpc_Request_descriptor = getDescriptor().getMessageTypes().get(0); internal_static_com_mikey_grpc_Request_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_com_mikey_grpc_Request_descriptor, new String[] { "Username", }); internal_static_com_mikey_grpc_Response_descriptor = getDescriptor().getMessageTypes().get(1); internal_static_com_mikey_grpc_Response_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_com_mikey_grpc_Response_descriptor, new String[] { "Realname", }); } // @@protoc_insertion_point(outer_class_scope) }
服務類:

package com.mikey.grpc; import static io.grpc.MethodDescriptor.generateFullMethodName; import static io.grpc.stub.ClientCalls.asyncBidiStreamingCall; import static io.grpc.stub.ClientCalls.asyncClientStreamingCall; import static io.grpc.stub.ClientCalls.asyncServerStreamingCall; import static io.grpc.stub.ClientCalls.asyncUnaryCall; import static io.grpc.stub.ClientCalls.blockingServerStreamingCall; import static io.grpc.stub.ClientCalls.blockingUnaryCall; import static io.grpc.stub.ClientCalls.futureUnaryCall; import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall; import static io.grpc.stub.ServerCalls.asyncClientStreamingCall; import static io.grpc.stub.ServerCalls.asyncServerStreamingCall; import static io.grpc.stub.ServerCalls.asyncUnaryCall; import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall; import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; /** */ //@javax.annotation.Generated( // value = "by gRPC proto compiler (version 1.20.0)", // comments = "Source: Student.proto") public final class StudentServiceGrpc { private StudentServiceGrpc() {} public static final String SERVICE_NAME = "com.mikey.grpc.StudentService"; // Static method descriptors that strictly reflect the proto. private static volatile io.grpc.MethodDescriptor<com.mikey.grpc.Request, com.mikey.grpc.Response> getGetRealNameByUserNameMethod; @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "GetRealNameByUserName", requestType = com.mikey.grpc.Request.class, responseType = com.mikey.grpc.Response.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) public static io.grpc.MethodDescriptor<com.mikey.grpc.Request, com.mikey.grpc.Response> getGetRealNameByUserNameMethod() { io.grpc.MethodDescriptor<com.mikey.grpc.Request, com.mikey.grpc.Response> getGetRealNameByUserNameMethod; if ((getGetRealNameByUserNameMethod = StudentServiceGrpc.getGetRealNameByUserNameMethod) == null) { synchronized (StudentServiceGrpc.class) { if ((getGetRealNameByUserNameMethod = StudentServiceGrpc.getGetRealNameByUserNameMethod) == null) { StudentServiceGrpc.getGetRealNameByUserNameMethod = getGetRealNameByUserNameMethod = io.grpc.MethodDescriptor.<com.mikey.grpc.Request, com.mikey.grpc.Response>newBuilder() .setType(io.grpc.MethodDescriptor.MethodType.UNARY) .setFullMethodName(generateFullMethodName( "com.mikey.grpc.StudentService", "GetRealNameByUserName")) .setSampledToLocalTracing(true) .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( com.mikey.grpc.Request.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( com.mikey.grpc.Response.getDefaultInstance())) .setSchemaDescriptor(new StudentServiceMethodDescriptorSupplier("GetRealNameByUserName")) .build(); } } } return getGetRealNameByUserNameMethod; } /** * Creates a new async stub that supports all call types for the service */ public static StudentServiceStub newStub(io.grpc.Channel channel) { return new StudentServiceStub(channel); } /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ public static StudentServiceBlockingStub newBlockingStub( io.grpc.Channel channel) { return new StudentServiceBlockingStub(channel); } /** * Creates a new ListenableFuture-style stub that supports unary calls on the service */ public static StudentServiceFutureStub newFutureStub( io.grpc.Channel channel) { return new StudentServiceFutureStub(channel); } /** */ public static abstract class StudentServiceImplBase implements io.grpc.BindableService { /** */ public void getRealNameByUserName(com.mikey.grpc.Request request, io.grpc.stub.StreamObserver<com.mikey.grpc.Response> responseObserver) { asyncUnimplementedUnaryCall(getGetRealNameByUserNameMethod(), responseObserver); } @Override public final io.grpc.ServerServiceDefinition bindService() { return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) .addMethod( getGetRealNameByUserNameMethod(), asyncUnaryCall( new MethodHandlers< com.mikey.grpc.Request, com.mikey.grpc.Response>( this, METHODID_GET_REAL_NAME_BY_USER_NAME))) .build(); } } /** */ public static final class StudentServiceStub extends io.grpc.stub.AbstractStub<StudentServiceStub> { private StudentServiceStub(io.grpc.Channel channel) { super(channel); } private StudentServiceStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { super(channel, callOptions); } @Override protected StudentServiceStub build(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { return new StudentServiceStub(channel, callOptions); } /** */ public void getRealNameByUserName(com.mikey.grpc.Request request, io.grpc.stub.StreamObserver<com.mikey.grpc.Response> responseObserver) { asyncUnaryCall( getChannel().newCall(getGetRealNameByUserNameMethod(), getCallOptions()), request, responseObserver); } } /** */ public static final class StudentServiceBlockingStub extends io.grpc.stub.AbstractStub<StudentServiceBlockingStub> { private StudentServiceBlockingStub(io.grpc.Channel channel) { super(channel); } private StudentServiceBlockingStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { super(channel, callOptions); } @Override protected StudentServiceBlockingStub build(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { return new StudentServiceBlockingStub(channel, callOptions); } /** */ public com.mikey.grpc.Response getRealNameByUserName(com.mikey.grpc.Request request) { return blockingUnaryCall( getChannel(), getGetRealNameByUserNameMethod(), getCallOptions(), request); } } /** */ public static final class StudentServiceFutureStub extends io.grpc.stub.AbstractStub<StudentServiceFutureStub> { private StudentServiceFutureStub(io.grpc.Channel channel) { super(channel); } private StudentServiceFutureStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { super(channel, callOptions); } @Override protected StudentServiceFutureStub build(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { return new StudentServiceFutureStub(channel, callOptions); } /** */ public com.google.common.util.concurrent.ListenableFuture<com.mikey.grpc.Response> getRealNameByUserName( com.mikey.grpc.Request request) { return futureUnaryCall( getChannel().newCall(getGetRealNameByUserNameMethod(), getCallOptions()), request); } } private static final int METHODID_GET_REAL_NAME_BY_USER_NAME = 0; private static final class MethodHandlers<Req, Resp> implements io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>, io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>, io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>, io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> { private final StudentServiceImplBase serviceImpl; private final int methodId; MethodHandlers(StudentServiceImplBase serviceImpl, int methodId) { this.serviceImpl = serviceImpl; this.methodId = methodId; } @Override @SuppressWarnings("unchecked") public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) { switch (methodId) { case METHODID_GET_REAL_NAME_BY_USER_NAME: serviceImpl.getRealNameByUserName((com.mikey.grpc.Request) request, (io.grpc.stub.StreamObserver<com.mikey.grpc.Response>) responseObserver); break; default: throw new AssertionError(); } } @Override @SuppressWarnings("unchecked") public io.grpc.stub.StreamObserver<Req> invoke( io.grpc.stub.StreamObserver<Resp> responseObserver) { switch (methodId) { default: throw new AssertionError(); } } } private static abstract class StudentServiceBaseDescriptorSupplier implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier { StudentServiceBaseDescriptorSupplier() {} @Override public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { return com.mikey.grpc.StudentProto.getDescriptor(); } @Override public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() { return getFileDescriptor().findServiceByName("StudentService"); } } private static final class StudentServiceFileDescriptorSupplier extends StudentServiceBaseDescriptorSupplier { StudentServiceFileDescriptorSupplier() {} } private static final class StudentServiceMethodDescriptorSupplier extends StudentServiceBaseDescriptorSupplier implements io.grpc.protobuf.ProtoMethodDescriptorSupplier { private final String methodName; StudentServiceMethodDescriptorSupplier(String methodName) { this.methodName = methodName; } @Override public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() { return getServiceDescriptor().findMethodByName(methodName); } } private static volatile io.grpc.ServiceDescriptor serviceDescriptor; public static io.grpc.ServiceDescriptor getServiceDescriptor() { io.grpc.ServiceDescriptor result = serviceDescriptor; if (result == null) { synchronized (StudentServiceGrpc.class) { result = serviceDescriptor; if (result == null) { serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) .setSchemaDescriptor(new StudentServiceFileDescriptorSupplier()) .addMethod(getGetRealNameByUserNameMethod()) .build(); } } } return result; } }
實現類:

package com.mikey.grpc; import io.grpc.stub.StreamObserver; /** * @ProjectName netty * @Author 麥奇 * @Email biaogejiushibiao@outlook.com * @Date 10/2/19 10:55 AM * @Version 1.0 * @Description: **/ public class StudentServiceImpl extends StudentServiceGrpc.StudentServiceImplBase{ @Override public void getRealNameByUserName(Request request, StreamObserver<Response> responseObserver) { System.out.println("接收到客戶端信息:"+request.getUsername()); responseObserver.onNext(Response.newBuilder().setRealname(request.getUsername()).build()); responseObserver.onCompleted(); } }
客戶端:

package com.mikey.grpc; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.stub.ClientCalls; import java.util.logging.Logger; /** * @ProjectName netty * @Author 麥奇 * @Email biaogejiushibiao@outlook.com * @Date 10/2/19 11:02 AM * @Version 1.0 * @Description: **/ public class GrpcClient { private static final Logger logger = Logger.getLogger(GrpcClient.class.getName()); public static final String HOST_ADDRESS = "localhost"; public static final Integer PORT = 8899; public static void main(String[] args) throws Exception{ //構建配置 ManagedChannelBuilder<?> builder = ManagedChannelBuilder.forAddress(HOST_ADDRESS, PORT).usePlaintext(true); //傳輸管道 ManagedChannel channel = builder.build(); //構建請求 Request request = Request.newBuilder().setUsername("麥奇").build(); //構建非阻塞服務調用 StudentServiceGrpc.StudentServiceBlockingStub blockingStub = StudentServiceGrpc.newBlockingStub(channel); //服務調用並接收返回參數 Response response = blockingStub.getRealNameByUserName(request); //打印信息 logger.info(response.getRealname()); //關閉資源 channel.shutdown(); } }
服務器:

package com.mikey.grpc; import io.grpc.Server; import io.grpc.ServerBuilder; import java.util.logging.Logger; /** * @ProjectName netty * @Author 麥奇 * @Email biaogejiushibiao@outlook.com * @Date 10/2/19 11:02 AM * @Version 1.0 * @Description: **/ public class GrpcServer { private static final Logger logger = Logger.getLogger(GrpcServer.class.getName()); public static void main(String[] args) throws Exception{ Server start = ServerBuilder.forPort(8899) .addService(new com.mikey.grpc.StudentServiceImpl()) .build() .start(); //阻塞 start.awaitTermination(); logger.info("Server started, listening on " + start.getPort()); 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"); start.shutdown(); System.err.println("*** server shut down"); } }); } }
定義不同的服務方法
gRPC lets you define four kinds of service method:
- Unary RPCs where the client sends a single request to the server and gets a single response back, just like a normal function call.
rpc SayHello(HelloRequest) returns (HelloResponse){}
- Server streaming RPCs where the client sends a request to the server and gets a stream to read a sequence of messages back. The client reads from the returned stream until there are no more messages. gRPC guarantees message ordering within an individual RPC call.
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){}
- Client streaming RPCs where the client writes a sequence of messages and sends them to the server, again using a provided stream. Once the client has finished writing the messages, it waits for the server to read them and return its response. Again gRPC guarantees message ordering within an individual RPC call.
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {}
- Bidirectional streaming RPCs where both sides send a sequence of messages using a read-write stream. The two streams operate independently, so clients and servers can read and write in whatever order they like: for example, the server could wait to receive all the client messages before writing its responses, or it could alternately read a message then write a message, or some other combination of reads and writes. The order of messages in each stream is preserved.
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){}
We’ll look at the different types of RPC in more detail in the RPC life cycle section below.

package com.mikey.grpcstream; import io.grpc.stub.ServerCallStreamObserver; import io.grpc.stub.StreamObserver; import java.util.logging.Logger; /** * @ProjectName netty * @Author 麥奇 * @Email biaogejiushibiao@outlook.com * @Date 10/2/19 12:28 PM * @Version 1.0 * @Description: **/ public class StudentGrpcImpl extends com.mikey.grpcstream.StudentServiceGrpc.StudentServiceImplBase { private static final Logger logger = Logger.getLogger(StudentGrpcImpl.class.getName()); @Override public void getRealNameByUserName(Request request, StreamObserver<Response> responseObserver) { logger.info("參數:"+request.getUsername()); responseObserver.onNext(Response.newBuilder().setRealname("阿姆斯特朗").build()); responseObserver.onCompleted(); } @Override public void getStudentByAge(Request request, StreamObserver<StudentResponse> responseObserver) { logger.info("參數:"+request.getUsername()); responseObserver.onNext(StudentResponse.newBuilder().setName("里奧").setAge(20).setCity("北京").build()); responseObserver.onNext(StudentResponse.newBuilder().setName("麥奇").setAge(20).setCity("柳州").build()); responseObserver.onNext(StudentResponse.newBuilder().setName("達芬奇").setAge(20).setCity("深圳").build()); responseObserver.onCompleted(); } @Override public StreamObserver<StudentResponseList> getStudentByStream(StreamObserver<StudentResponse> responseObserver) { StudentResponse build1 = StudentResponse.newBuilder().setName("1111111111").setAge(111111111).setCity("11111111111").build(); StudentResponse build2 = StudentResponse.newBuilder().setName("1111111111").setAge(111111111).setCity("11111111111").build(); StudentResponse build3 = StudentResponse.newBuilder().setName("1111111111").setAge(111111111).setCity("11111111111").build(); return new StreamObserver<StudentResponseList>() { @Override public void onNext(StudentResponseList value) { } @Override public void onError(Throwable t) { } @Override public void onCompleted() { responseObserver.onNext(build1); responseObserver.onNext(build2); responseObserver.onNext(build3); responseObserver.onCompleted(); } }; } @Override public StreamObserver<StreamRequest> biTalk(StreamObserver<StreamResponse> responseObserver) { return new StreamObserver<StreamRequest>() { @Override public void onNext(StreamRequest value) { } @Override public void onError(Throwable t) { } @Override public void onCompleted() { } }; } }
跨語言調用服務
node.js

syntax="proto3"; package com.mikey.grpc; option java_package = "com.mikey.grpcstream"; option java_outer_classname = "StudentProto"; option java_multiple_files = true; service StudentService { //message 2 message rpc GetRealNameByUserName(Request) returns (Response){} //message 2 stream message rpc GetStudentByAge(Request) returns (stream StudentResponse){} //stream message 2 message rpc GetStudentByStream(stream StudentResponseList) returns (StudentResponse){} //stream message 2 stream message rpc BiTalk(stream StreamRequest) returns (stream StreamResponse){} } message Request { string username = 1; } message Response { string realname = 2; } message StudentResponse { string name = 1; int32 age =2; string city = 3; } message StudentRequest { string key = 1; } message StudentResponseList { repeated StudentResponse studentResponse = 1; } message StreamRequest { string request_info = 1; } message StreamResponse { string response_info = 1; }
動態生成服務代碼

var PROTO_FILE_PATH = '/home/mikey/WebstormProjects/node-grpc/proto/Student.proto'; var grpc = require('grpc'); var grpcService = grpc.load(PROTO_FILE_PATH).com.mikey.grpc var client = new grpcService.StudentService('localhost:8899',grpc.credentials.createInsecure()) client.GetRealNameByUserName({username:'mikey'}, function(error,respData) { console.log(respData) });

var PROTO_FILE_PATH = '/home/mikey/WebstormProjects/node-grpc/proto/Student.proto'; var grpc = require('grpc'); var grpcService = grpc.load(PROTO_FILE_PATH).com.mikey.grpc; var server = new grpc.Server(); server.addService(grpcService.StudentService.service,{ GetRealNameByUserName: GetRealNameByUserName }) server.bind('localhost:8899',grpc.ServerCredentials.createInsecure()); server.start(); function GetRealNameByUserName(call,callback) { console.log("call : "+call.request.username) callback(null,{realname: '張三'}); } function getStudentByAge() {} function getStudentByStream() {} function biTalk() {}
靜態生成服務代碼
參考:https://github.com/grpc/grpc/tree/master/examples/node/static_codegen
// 進入proto文件目錄
cd ../../protos
// 全局安裝grpc工具 npm install -g grpc-tools // 生成靜態代碼
grpc_tools_node_protoc --js_out=import_style=commonjs,binary:../node/static_codegen/ --grpc_out=../node/static_codegen --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` helloworld.proto grpc_tools_node_protoc --js_out=import_style=commonjs,binary:../node/static_codegen/route_guide/ --grpc_out=../node/static_codegen/route_guide/ --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` route_guide.proto
上面方法我通過 npm install -g grpc-tools 並未安裝 grpc_tools_node_protoc 所以通過下面方法來生成
npm install grpc-tools --save-dev
../node_modules/grpc-tools/bin/protoc --js_out=import_style=commonjs,binary:../static_codegen/ --plugin=protoc-gen-grpc=../node_modules/grpc-tools/bin/grpc_node_plugin --grpc_out=../static_codegen/ Student.proto
生成兩個pb.js文件

// GENERATED CODE -- DO NOT EDIT! 'use strict'; var grpc = require('grpc'); var Student_pb = require('./Student_pb.js'); function serialize_com_mikey_grpc_Request(arg) { if (!(arg instanceof Student_pb.Request)) { throw new Error('Expected argument of type com.mikey.grpc.Request'); } return Buffer.from(arg.serializeBinary()); } function deserialize_com_mikey_grpc_Request(buffer_arg) { return Student_pb.Request.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_com_mikey_grpc_Response(arg) { if (!(arg instanceof Student_pb.Response)) { throw new Error('Expected argument of type com.mikey.grpc.Response'); } return Buffer.from(arg.serializeBinary()); } function deserialize_com_mikey_grpc_Response(buffer_arg) { return Student_pb.Response.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_com_mikey_grpc_StreamRequest(arg) { if (!(arg instanceof Student_pb.StreamRequest)) { throw new Error('Expected argument of type com.mikey.grpc.StreamRequest'); } return Buffer.from(arg.serializeBinary()); } function deserialize_com_mikey_grpc_StreamRequest(buffer_arg) { return Student_pb.StreamRequest.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_com_mikey_grpc_StreamResponse(arg) { if (!(arg instanceof Student_pb.StreamResponse)) { throw new Error('Expected argument of type com.mikey.grpc.StreamResponse'); } return Buffer.from(arg.serializeBinary()); } function deserialize_com_mikey_grpc_StreamResponse(buffer_arg) { return Student_pb.StreamResponse.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_com_mikey_grpc_StudentResponse(arg) { if (!(arg instanceof Student_pb.StudentResponse)) { throw new Error('Expected argument of type com.mikey.grpc.StudentResponse'); } return Buffer.from(arg.serializeBinary()); } function deserialize_com_mikey_grpc_StudentResponse(buffer_arg) { return Student_pb.StudentResponse.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_com_mikey_grpc_StudentResponseList(arg) { if (!(arg instanceof Student_pb.StudentResponseList)) { throw new Error('Expected argument of type com.mikey.grpc.StudentResponseList'); } return Buffer.from(arg.serializeBinary()); } function deserialize_com_mikey_grpc_StudentResponseList(buffer_arg) { return Student_pb.StudentResponseList.deserializeBinary(new Uint8Array(buffer_arg)); } var StudentServiceService = exports.StudentServiceService = { // message 2 message getRealNameByUserName: { path: '/com.mikey.grpc.StudentService/GetRealNameByUserName', requestStream: false, responseStream: false, requestType: Student_pb.Request, responseType: Student_pb.Response, requestSerialize: serialize_com_mikey_grpc_Request, requestDeserialize: deserialize_com_mikey_grpc_Request, responseSerialize: serialize_com_mikey_grpc_Response, responseDeserialize: deserialize_com_mikey_grpc_Response, }, // message 2 stream message getStudentByAge: { path: '/com.mikey.grpc.StudentService/GetStudentByAge', requestStream: false, responseStream: true, requestType: Student_pb.Request, responseType: Student_pb.StudentResponse, requestSerialize: serialize_com_mikey_grpc_Request, requestDeserialize: deserialize_com_mikey_grpc_Request, responseSerialize: serialize_com_mikey_grpc_StudentResponse, responseDeserialize: deserialize_com_mikey_grpc_StudentResponse, }, // stream message 2 message getStudentByStream: { path: '/com.mikey.grpc.StudentService/GetStudentByStream', requestStream: true, responseStream: false, requestType: Student_pb.StudentResponseList, responseType: Student_pb.StudentResponse, requestSerialize: serialize_com_mikey_grpc_StudentResponseList, requestDeserialize: deserialize_com_mikey_grpc_StudentResponseList, responseSerialize: serialize_com_mikey_grpc_StudentResponse, responseDeserialize: deserialize_com_mikey_grpc_StudentResponse, }, // stream message 2 stream message biTalk: { path: '/com.mikey.grpc.StudentService/BiTalk', requestStream: true, responseStream: true, requestType: Student_pb.StreamRequest, responseType: Student_pb.StreamResponse, requestSerialize: serialize_com_mikey_grpc_StreamRequest, requestDeserialize: deserialize_com_mikey_grpc_StreamRequest, responseSerialize: serialize_com_mikey_grpc_StreamResponse, responseDeserialize: deserialize_com_mikey_grpc_StreamResponse, }, }; exports.StudentServiceClient = grpc.makeGenericClientConstructor(StudentServiceService);

/** * @fileoverview * @enhanceable * @suppress {messageConventions} JS Compiler reports an error if a variable or * field starts with 'MSG_' and isn't a translatable message. * @public */ // GENERATED CODE -- DO NOT EDIT! var jspb = require('google-protobuf'); var goog = jspb; var global = Function('return this')(); goog.exportSymbol('proto.com.mikey.grpc.Request', null, global); goog.exportSymbol('proto.com.mikey.grpc.Response', null, global); goog.exportSymbol('proto.com.mikey.grpc.StreamRequest', null, global); goog.exportSymbol('proto.com.mikey.grpc.StreamResponse', null, global); goog.exportSymbol('proto.com.mikey.grpc.StudentRequest', null, global); goog.exportSymbol('proto.com.mikey.grpc.StudentResponse', null, global); goog.exportSymbol('proto.com.mikey.grpc.StudentResponseList', null, global); /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.com.mikey.grpc.Request = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.com.mikey.grpc.Request, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.com.mikey.grpc.Request.displayName = 'proto.com.mikey.grpc.Request'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.com.mikey.grpc.Request.prototype.toObject = function(opt_includeInstance) { return proto.com.mikey.grpc.Request.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.com.mikey.grpc.Request} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.Request.toObject = function(includeInstance, msg) { var f, obj = { username: jspb.Message.getFieldWithDefault(msg, 1, "") }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.com.mikey.grpc.Request} */ proto.com.mikey.grpc.Request.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.com.mikey.grpc.Request; return proto.com.mikey.grpc.Request.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.com.mikey.grpc.Request} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.com.mikey.grpc.Request} */ proto.com.mikey.grpc.Request.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); msg.setUsername(value); break; default: reader.skipField(); break; } } return msg; }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.com.mikey.grpc.Request.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); proto.com.mikey.grpc.Request.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. * @param {!proto.com.mikey.grpc.Request} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.Request.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = message.getUsername(); if (f.length > 0) { writer.writeString( 1, f ); } }; /** * optional string username = 1; * @return {string} */ proto.com.mikey.grpc.Request.prototype.getUsername = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** @param {string} value */ proto.com.mikey.grpc.Request.prototype.setUsername = function(value) { jspb.Message.setProto3StringField(this, 1, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.com.mikey.grpc.Response = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.com.mikey.grpc.Response, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.com.mikey.grpc.Response.displayName = 'proto.com.mikey.grpc.Response'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.com.mikey.grpc.Response.prototype.toObject = function(opt_includeInstance) { return proto.com.mikey.grpc.Response.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.com.mikey.grpc.Response} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.Response.toObject = function(includeInstance, msg) { var f, obj = { realname: jspb.Message.getFieldWithDefault(msg, 2, "") }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.com.mikey.grpc.Response} */ proto.com.mikey.grpc.Response.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.com.mikey.grpc.Response; return proto.com.mikey.grpc.Response.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.com.mikey.grpc.Response} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.com.mikey.grpc.Response} */ proto.com.mikey.grpc.Response.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 2: var value = /** @type {string} */ (reader.readString()); msg.setRealname(value); break; default: reader.skipField(); break; } } return msg; }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.com.mikey.grpc.Response.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); proto.com.mikey.grpc.Response.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. * @param {!proto.com.mikey.grpc.Response} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.Response.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = message.getRealname(); if (f.length > 0) { writer.writeString( 2, f ); } }; /** * optional string realname = 2; * @return {string} */ proto.com.mikey.grpc.Response.prototype.getRealname = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; /** @param {string} value */ proto.com.mikey.grpc.Response.prototype.setRealname = function(value) { jspb.Message.setProto3StringField(this, 2, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.com.mikey.grpc.StudentResponse = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.com.mikey.grpc.StudentResponse, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.com.mikey.grpc.StudentResponse.displayName = 'proto.com.mikey.grpc.StudentResponse'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.com.mikey.grpc.StudentResponse.prototype.toObject = function(opt_includeInstance) { return proto.com.mikey.grpc.StudentResponse.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.com.mikey.grpc.StudentResponse} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.StudentResponse.toObject = function(includeInstance, msg) { var f, obj = { name: jspb.Message.getFieldWithDefault(msg, 1, ""), age: jspb.Message.getFieldWithDefault(msg, 2, 0), city: jspb.Message.getFieldWithDefault(msg, 3, "") }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.com.mikey.grpc.StudentResponse} */ proto.com.mikey.grpc.StudentResponse.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.com.mikey.grpc.StudentResponse; return proto.com.mikey.grpc.StudentResponse.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.com.mikey.grpc.StudentResponse} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.com.mikey.grpc.StudentResponse} */ proto.com.mikey.grpc.StudentResponse.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); msg.setName(value); break; case 2: var value = /** @type {number} */ (reader.readInt32()); msg.setAge(value); break; case 3: var value = /** @type {string} */ (reader.readString()); msg.setCity(value); break; default: reader.skipField(); break; } } return msg; }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.com.mikey.grpc.StudentResponse.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); proto.com.mikey.grpc.StudentResponse.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. * @param {!proto.com.mikey.grpc.StudentResponse} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.StudentResponse.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = message.getName(); if (f.length > 0) { writer.writeString( 1, f ); } f = message.getAge(); if (f !== 0) { writer.writeInt32( 2, f ); } f = message.getCity(); if (f.length > 0) { writer.writeString( 3, f ); } }; /** * optional string name = 1; * @return {string} */ proto.com.mikey.grpc.StudentResponse.prototype.getName = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** @param {string} value */ proto.com.mikey.grpc.StudentResponse.prototype.setName = function(value) { jspb.Message.setProto3StringField(this, 1, value); }; /** * optional int32 age = 2; * @return {number} */ proto.com.mikey.grpc.StudentResponse.prototype.getAge = function() { return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); }; /** @param {number} value */ proto.com.mikey.grpc.StudentResponse.prototype.setAge = function(value) { jspb.Message.setProto3IntField(this, 2, value); }; /** * optional string city = 3; * @return {string} */ proto.com.mikey.grpc.StudentResponse.prototype.getCity = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); }; /** @param {string} value */ proto.com.mikey.grpc.StudentResponse.prototype.setCity = function(value) { jspb.Message.setProto3StringField(this, 3, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.com.mikey.grpc.StudentRequest = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.com.mikey.grpc.StudentRequest, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.com.mikey.grpc.StudentRequest.displayName = 'proto.com.mikey.grpc.StudentRequest'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.com.mikey.grpc.StudentRequest.prototype.toObject = function(opt_includeInstance) { return proto.com.mikey.grpc.StudentRequest.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.com.mikey.grpc.StudentRequest} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.StudentRequest.toObject = function(includeInstance, msg) { var f, obj = { key: jspb.Message.getFieldWithDefault(msg, 1, "") }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.com.mikey.grpc.StudentRequest} */ proto.com.mikey.grpc.StudentRequest.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.com.mikey.grpc.StudentRequest; return proto.com.mikey.grpc.StudentRequest.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.com.mikey.grpc.StudentRequest} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.com.mikey.grpc.StudentRequest} */ proto.com.mikey.grpc.StudentRequest.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); msg.setKey(value); break; default: reader.skipField(); break; } } return msg; }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.com.mikey.grpc.StudentRequest.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); proto.com.mikey.grpc.StudentRequest.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. * @param {!proto.com.mikey.grpc.StudentRequest} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.StudentRequest.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = message.getKey(); if (f.length > 0) { writer.writeString( 1, f ); } }; /** * optional string key = 1; * @return {string} */ proto.com.mikey.grpc.StudentRequest.prototype.getKey = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** @param {string} value */ proto.com.mikey.grpc.StudentRequest.prototype.setKey = function(value) { jspb.Message.setProto3StringField(this, 1, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.com.mikey.grpc.StudentResponseList = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, proto.com.mikey.grpc.StudentResponseList.repeatedFields_, null); }; goog.inherits(proto.com.mikey.grpc.StudentResponseList, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.com.mikey.grpc.StudentResponseList.displayName = 'proto.com.mikey.grpc.StudentResponseList'; } /** * List of repeated fields within this message type. * @private {!Array<number>} * @const */ proto.com.mikey.grpc.StudentResponseList.repeatedFields_ = [1]; if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.com.mikey.grpc.StudentResponseList.prototype.toObject = function(opt_includeInstance) { return proto.com.mikey.grpc.StudentResponseList.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.com.mikey.grpc.StudentResponseList} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.StudentResponseList.toObject = function(includeInstance, msg) { var f, obj = { studentresponseList: jspb.Message.toObjectList(msg.getStudentresponseList(), proto.com.mikey.grpc.StudentResponse.toObject, includeInstance) }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.com.mikey.grpc.StudentResponseList} */ proto.com.mikey.grpc.StudentResponseList.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.com.mikey.grpc.StudentResponseList; return proto.com.mikey.grpc.StudentResponseList.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.com.mikey.grpc.StudentResponseList} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.com.mikey.grpc.StudentResponseList} */ proto.com.mikey.grpc.StudentResponseList.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = new proto.com.mikey.grpc.StudentResponse; reader.readMessage(value,proto.com.mikey.grpc.StudentResponse.deserializeBinaryFromReader); msg.addStudentresponse(value); break; default: reader.skipField(); break; } } return msg; }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.com.mikey.grpc.StudentResponseList.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); proto.com.mikey.grpc.StudentResponseList.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. * @param {!proto.com.mikey.grpc.StudentResponseList} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.StudentResponseList.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = message.getStudentresponseList(); if (f.length > 0) { writer.writeRepeatedMessage( 1, f, proto.com.mikey.grpc.StudentResponse.serializeBinaryToWriter ); } }; /** * repeated StudentResponse studentResponse = 1; * @return {!Array<!proto.com.mikey.grpc.StudentResponse>} */ proto.com.mikey.grpc.StudentResponseList.prototype.getStudentresponseList = function() { return /** @type{!Array<!proto.com.mikey.grpc.StudentResponse>} */ ( jspb.Message.getRepeatedWrapperField(this, proto.com.mikey.grpc.StudentResponse, 1)); }; /** @param {!Array<!proto.com.mikey.grpc.StudentResponse>} value */ proto.com.mikey.grpc.StudentResponseList.prototype.setStudentresponseList = function(value) { jspb.Message.setRepeatedWrapperField(this, 1, value); }; /** * @param {!proto.com.mikey.grpc.StudentResponse=} opt_value * @param {number=} opt_index * @return {!proto.com.mikey.grpc.StudentResponse} */ proto.com.mikey.grpc.StudentResponseList.prototype.addStudentresponse = function(opt_value, opt_index) { return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.com.mikey.grpc.StudentResponse, opt_index); }; proto.com.mikey.grpc.StudentResponseList.prototype.clearStudentresponseList = function() { this.setStudentresponseList([]); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.com.mikey.grpc.StreamRequest = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.com.mikey.grpc.StreamRequest, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.com.mikey.grpc.StreamRequest.displayName = 'proto.com.mikey.grpc.StreamRequest'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.com.mikey.grpc.StreamRequest.prototype.toObject = function(opt_includeInstance) { return proto.com.mikey.grpc.StreamRequest.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.com.mikey.grpc.StreamRequest} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.StreamRequest.toObject = function(includeInstance, msg) { var f, obj = { requestInfo: jspb.Message.getFieldWithDefault(msg, 1, "") }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.com.mikey.grpc.StreamRequest} */ proto.com.mikey.grpc.StreamRequest.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.com.mikey.grpc.StreamRequest; return proto.com.mikey.grpc.StreamRequest.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.com.mikey.grpc.StreamRequest} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.com.mikey.grpc.StreamRequest} */ proto.com.mikey.grpc.StreamRequest.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); msg.setRequestInfo(value); break; default: reader.skipField(); break; } } return msg; }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.com.mikey.grpc.StreamRequest.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); proto.com.mikey.grpc.StreamRequest.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. * @param {!proto.com.mikey.grpc.StreamRequest} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.StreamRequest.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = message.getRequestInfo(); if (f.length > 0) { writer.writeString( 1, f ); } }; /** * optional string request_info = 1; * @return {string} */ proto.com.mikey.grpc.StreamRequest.prototype.getRequestInfo = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** @param {string} value */ proto.com.mikey.grpc.StreamRequest.prototype.setRequestInfo = function(value) { jspb.Message.setProto3StringField(this, 1, value); }; /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a * server response, or constructed directly in Javascript. The array is used * in place and becomes part of the constructed object. It is not cloned. * If no data is provided, the constructed object will be empty, but still * valid. * @extends {jspb.Message} * @constructor */ proto.com.mikey.grpc.StreamResponse = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; goog.inherits(proto.com.mikey.grpc.StreamResponse, jspb.Message); if (goog.DEBUG && !COMPILED) { proto.com.mikey.grpc.StreamResponse.displayName = 'proto.com.mikey.grpc.StreamResponse'; } if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto suitable for use in Soy templates. * Field names that are reserved in JavaScript and will be renamed to pb_name. * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. * For the list of reserved names please see: * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. * @param {boolean=} opt_includeInstance Whether to include the JSPB instance * for transitional soy proto support: http://goto/soy-param-migration * @return {!Object} */ proto.com.mikey.grpc.StreamResponse.prototype.toObject = function(opt_includeInstance) { return proto.com.mikey.grpc.StreamResponse.toObject(opt_includeInstance, this); }; /** * Static version of the {@see toObject} method. * @param {boolean|undefined} includeInstance Whether to include the JSPB * instance for transitional soy proto support: * http://goto/soy-param-migration * @param {!proto.com.mikey.grpc.StreamResponse} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.StreamResponse.toObject = function(includeInstance, msg) { var f, obj = { responseInfo: jspb.Message.getFieldWithDefault(msg, 1, "") }; if (includeInstance) { obj.$jspbMessageInstance = msg; } return obj; }; } /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. * @return {!proto.com.mikey.grpc.StreamResponse} */ proto.com.mikey.grpc.StreamResponse.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); var msg = new proto.com.mikey.grpc.StreamResponse; return proto.com.mikey.grpc.StreamResponse.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. * @param {!proto.com.mikey.grpc.StreamResponse} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. * @return {!proto.com.mikey.grpc.StreamResponse} */ proto.com.mikey.grpc.StreamResponse.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; } var field = reader.getFieldNumber(); switch (field) { case 1: var value = /** @type {string} */ (reader.readString()); msg.setResponseInfo(value); break; default: reader.skipField(); break; } } return msg; }; /** * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ proto.com.mikey.grpc.StreamResponse.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); proto.com.mikey.grpc.StreamResponse.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. * @param {!proto.com.mikey.grpc.StreamResponse} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ proto.com.mikey.grpc.StreamResponse.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = message.getResponseInfo(); if (f.length > 0) { writer.writeString( 1, f ); } }; /** * optional string response_info = 1; * @return {string} */ proto.com.mikey.grpc.StreamResponse.prototype.getResponseInfo = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** @param {string} value */ proto.com.mikey.grpc.StreamResponse.prototype.setResponseInfo = function(value) { jspb.Message.setProto3StringField(this, 1, value); }; goog.object.extend(exports, proto.com.mikey.grpc);
客戶端

var service = require('../static_codegen/Student_grpc_pb'); var message = require('../static_codegen/Student_pb'); var grpc = require('grpc'); var client = new service.StudentServiceClient('localhost:8899', grpc.credentials.createInsecure()); var request = new message.Request(); request.setUsername('麥奇'); client.getRealNameByUserName(request, function(error, respData) { console.log(respData.getRealname()); })
服務器

var service = require('../static_codegen/Student_grpc_pb'); var message = require('../static_codegen/Student_pb'); var grpc = require('grpc'); var server = new grpc.Server(); server.addService( service.StudentServiceService, { getRealNameByUserName:getRealNameByUserName, getStudentByAge:getStudentByAge(), getStudentByStream:getStudentByStream(), biTalk:biTalk() } ) server.bind('localhost:8899', grpc.ServerCredentials.createInsecure()); server.start(); function getRealNameByUserName(call,callback) { console.log('request:'+call.request.getUsername()); var response = new message.Response(); response.setRealname('麥奇蜀素'); callback(null, response); } function getStudentByAge() {} function getStudentByStream() {} function biTalk() {}