1.导入maven依赖
<!-- grpc 开始 -->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>${grpc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
</dependency>
<!-- grpc 结束 -->
版本号为:
<protobuf.version>3.5.0</protobuf.version>
<grpc.version>1.16.0</grpc.version>
导入相应的编译插件
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.0</version>
</extension>
</extensions>
<plugins>
<!--编译插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<!-- 发布插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
<!-- 单元测试 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}
</protocArtifact>
<!-- Place these in a location that compiler-plugin is already looking -->
<outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
<!-- With multiple executions, this must be `false` otherwise we wipe out the previous execution -->
<clearOutputDirectory>false</clearOutputDirectory>
</configuration>
<executions>
<execution>
<id>compile-protobuf</id>
<phase>generate-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>compile-grpc</id>
<phase>generate-sources</phase>
<goals>
<goal>compile-custom</goal>
</goals>
<configuration>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
2.编写proto文件
ArDeviceService.proto
syntax = "proto3";
option java_multiple_files = true;
package cn.cloudwalk.aros.device;
message CwArDeviceQueryParam {
/**
* 设备类型
*/
string deviceType = 1;
/**
* 设备名称
*/
string deviceName = 2;
/**
* 来源平台名称
*/
string platformName = 3;
/**
* 系列号
*/
string sn = 4;
/**
* 国标编码
*/
string gbCode = 5;
/**
* 区域ID
*/
string regionId = 6;
string businessId = 7;
}
message CloudwalkArDeviceResult{
/**
* 编码
*/
string code = 1 ;
/**
* 是否成功
*/
bool success = 2;
/**
* 消息
*/
string message = 3;
/**
* 返回结果
*/
repeated CwArDeviceResult data = 4;
}
message CwArDeviceResult {
/**
* 设备类型
*/
string deviceType = 1;
/**
* 设备名称
*/
string deviceName = 2;
/**
* 来源平台名称
*/
string platformName = 3;
/**
* 系列号
*/
string sn = 4;
/**
* IP地址
*/
string ipAddress = 5;
/**
* 端口
*/
int32 port = 6;
/**
* 用户名
*/
string userName = 7;
/**
* 密码
*/
string userPassword = 8;
/**
* 国标编码
*/
string gbCode = 9;
/**
* 区域ID
*/
string regionId = 10;
/**
* 租户ID
*/
string businessId = 11;
}
service CwArDeviceService {
rpc query (CwArDeviceQueryParam) returns (CloudwalkArDeviceResult);
}
执行mvn clean compile
3.服务端实现grpc接口
@Lazy(true)
@Service("arDeviceServiceImpl")
public class ArDeviceServiceImpl extends CwArDeviceServiceGrpc.CwArDeviceServiceImplBase {
@Autowired
CwArDeviceManager cwArDeviceManager;
@Override
public void query(CwArDeviceQueryParam request, StreamObserver<CloudwalkArDeviceResult> responseObserver) {
CwArDeviceQueryDTO dto = new CwArDeviceQueryDTO();
BeanCopyUtils.copyProperties(request, dto);
//cn.cloudwalk.aros.client.device.param.CwArDeviceQueryParam param = BeanCopyUtils.copyProperties(request, cn.cloudwalk.aros.client.device.param.CwArDeviceQueryParam.class);
cn.cloudwalk.aros.device.CwArDeviceResult cwArDeviceResult = null;
try {
if(cwArDeviceManager==null) {
cwArDeviceManager= (CwArDeviceManager)SpringContextHolder.getBean("cwArDeviceManager");
}
List<CwArDeviceResultDTO> list = this.cwArDeviceManager.query(dto);
CloudwalkArDeviceResult.Builder rpcResponseBuilder = CloudwalkArDeviceResult.newBuilder();
CloudwalkArDeviceResult rpcResponse = null ;
for(int i = 0; i< list.size();i++){
CwArDeviceResultDTO item = list.get(i);
cwArDeviceResult = cn.cloudwalk.aros.device.CwArDeviceResult.newBuilder().setBusinessId(item.getBusinessId()).setDeviceName(item.getDeviceName()).build();
rpcResponseBuilder.addData(cwArDeviceResult);
}
rpcResponse = rpcResponseBuilder.setCode("00000000").setSuccess(true).build();
responseObserver.onNext( rpcResponse );
} catch (Exception e) {
CloudwalkArDeviceResult rpcErrorResponse = CloudwalkArDeviceResult.newBuilder().setCode("10000000000").setMessage("查询失败").setSuccess(false).build();
responseObserver.onNext( rpcErrorResponse );
}
responseObserver.onCompleted();
}
}
SpringContextHolder工具类
package cn.cloudwalk.service.common.util;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
/**
* 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候取出ApplicaitonContext.
*
*/
@Service
@Lazy(false)
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
private static ApplicationContext applicationContext = null;
/**
* 取得存储在静态变量中的ApplicationContext.
*/
public static ApplicationContext getApplicationContext() {
assertContextInjected();
return applicationContext;
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T cwArDeviceManager(String name) {
assertContextInjected();
return (T) applicationContext.getBean(name);
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBean(String requiredType) {
assertContextInjected();
return (T)applicationContext.getBean(requiredType);
}
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
public static void clearHolder() {
applicationContext = null;
}
/**
* 实现ApplicationContextAware接口, 注入Context到静态变量中.
*/
@Override
public void setApplicationContext(ApplicationContext appContext) {
applicationContext = appContext;
}
/**
* 实现DisposableBean接口, 在Context关闭时清理静态变量.
*/
@Override
public void destroy() throws Exception {
SpringContextHolder.clearHolder();
}
/**
* 检查ApplicationContext不为空.
*/
private static void assertContextInjected() {
Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
}
}
4.启动类中启动grpc服务器
//grpc启动
Server server = null ;
try {
server = ServerBuilder.
forPort(port)
.addService( new ArDeviceServiceImpl () )
.build().start();
System.out.println( "grpc服务端启动成功, 端口=" + port );
server.awaitTermination();
}catch (Exception e){
System.out.println( "grpc服务端异常关闭:"+e);
server.shutdown();
}
启动客户端
public class GrpcClient {
private static final String host = "localhost";
private static final int serverPort = 9999;
public static void main( String[] args ) throws Exception {
ManagedChannel managedChannel = ManagedChannelBuilder.forAddress( host, serverPort ).usePlaintext().build();
try {
CwArDeviceServiceGrpc.CwArDeviceServiceBlockingStub rpcDateService = CwArDeviceServiceGrpc.newBlockingStub( managedChannel );
CwArDeviceQueryParam cwArDeviceQueryParam = CwArDeviceQueryParam
.newBuilder()
.setBusinessId("1")
.build();
CloudwalkArDeviceResult rpcDateResponse = rpcDateService.query( cwArDeviceQueryParam );
System.out.println( rpcDateResponse.getDataList());
} finally {
managedChannel.shutdown();
}
}
}