目录
三 项目git https://github.com/HandsomeMars/springboot-ice-demo
一 前言
1、基于上篇ice简单使用,本篇文章讲讲如何实现客户端与服务端之间双向调用
2、本文列举两种实现:
- java main方法调用
- 结合spring IOC容器管理
二 实现
1、目录结构
├─main
│ ├─java
│ │ │ .depend
│ │ │
│ │ ├─com
│ │ │ └─zyj
│ │ │ │ SpringbootIceCallClientApplication.java #springweb启动类
│ │ │ │
│ │ │ ├─ice
│ │ │ │ ├─java
│ │ │ │ │ ├─client
│ │ │ │ │ │ IceClient.java #java客户端
│ │ │ │ │ │
│ │ │ │ │ └─server
│ │ │ │ │ IceService.java #java服务端
│ │ │ │ │
│ │ │ │ ├─servant
│ │ │ │ │ ClientServant.java #客户端实现
│ │ │ │ │ ServerServant.java #服务端实现
│ │ │ │ │
│ │ │ │ └─spring
│ │ │ │ ├─client
│ │ │ │ │ IceClient.java #srping客户端
│ │ │ │ │
│ │ │ │ └─server
│ │ │ │ IceService.java #srping服务端
│ │ │ │
│ │ │ └─util
│ │ │ SpringContextUtil.java
│ │ │
│ │ └─slice2java
│ │ Callback_IServerCallBack_response.java
│ │ Callback_IServer_request.java
│ │ Callback_IServer_setCallBack.java
│ │ IServer.java
│ │ IServerCallBack.java
│ │ IServerCallBackHolder.java
│ │ IServerCallBackPrx.java
│ │ IServerCallBackPrxHelper.java
│ │ IServerCallBackPrxHolder.java
│ │ IServerHolder.java
│ │ IServerPrx.java
│ │ IServerPrxHelper.java
│ │ IServerPrxHolder.java
│ │ _IServerCallBackDisp.java
│ │ _IServerCallBackOperations.java
│ │ _IServerCallBackOperationsNC.java
│ │ _IServerDisp.java
│ │ _IServerOperations.java
│ │ _IServerOperationsNC.java
│ │
│ └─resources
│ │ application.properties #springweb项目
│ ├─lib
│ │
│ │ Identity.ice #ice公共文件 拷贝至此解除软件环境依赖
│ └─slice
│ call.ice #ice协议文件
│
└─test
└─java
└─com
└─zyj
SpringbootIceCallClientApplicationTests.java
2、公共代码
call.ice
#include <E:\SpringWorkSpace\springboot-ice-demo\springboot-ice-call\src\main\resources\lib\Identity.ice>
module slice2java{
/****************
ice客户端
*****************/
interface IServerCallBack {
/****************
客户端处理服务端返回
*****************/
bool response(string msg);
};
/***************
ice服务端
****************/
interface IServer {
/***************
服务端设置客户端回调对象
****************/
bool setCallBack(Ice::Identity id);
/***************
服务端处理客户端请求
****************/
bool request(string msg);
};
};
ice文件解释
#include 标识当前ice文件包含其他文件
E:\SpringWorkSpace\springboot-ice-demo\springboot-ice-call\src\main\resources\lib\Identity.ice 为ice公共文件
/****************
注释内容
*****************/
ClientServant.java
扫描二维码关注公众号,回复:
13466879 查看本文章

package com.zyj.ice.servant;
import Ice.Current;
import slice2java._IServerCallBackDisp;
/**
* @author by zyj
* @version V1.0
* @Description:
* @Date 2019/8/6 21:13
*/
@Service
//spring模式bean托管
public class ClientServant extends _IServerCallBackDisp {
/**
* 客户端处理服务端返回
*
* @param msg
* @param __current The Current object for the invocation.
**/
@Override
public boolean response(String msg, Current __current) {
System.out.println("serverCallBack:" + msg);
return false;
}
}
ServerServant.java
package com.zyj.ice.servant;
import Ice.*;
import org.springframework.stereotype.Service;
import slice2java.IServerCallBackPrx;
import slice2java.IServerCallBackPrxHelper;
import slice2java._IServerDisp;
/**
* @author by zyj
* @version V1.0
* @Description:
* @Date 2019/8/6 21:13
*/
@Service
//spring模式使用bean托管
public class ServerServant extends _IServerDisp {
/**
* 服务端设置客户端回调对象
*
* @param id
* @param __current The Current object for the invocation.
**/
@Override
public boolean setCallBack(Identity id, Current __current) {
IServerCallBackPrx iServerCallBackPrx = IServerCallBackPrxHelper.uncheckedCast(__current.con.createProxy(id));
iServerCallBackPrx.ice_getConnection().setCallback(new ConnectionCallback() {
@Override
public void heartbeat(Connection c) {
System.out.println("sn:" + " client heartbeat....");
}
@Override
public void closed(Connection c) {
System.out.println("sn:" + " " + "closed....");
}
});
// 每30/2 s向对方做心跳
// 客户端向服务端做心跳 服务端打印服务端的con.setCallback(new Ice.ConnectionCallback()
iServerCallBackPrx.ice_getConnection().setACM(new IntOptional(10), new Optional<ACMClose>(ACMClose.CloseOff),
new Optional<ACMHeartbeat>(ACMHeartbeat.HeartbeatAlways));
return true;
}
/**
* 服务端处理客户端请求
*
* @param msg
* @param __current The Current object for the invocation.
**/
@Override
public boolean request(String msg, Current __current) {
System.out.println("client:" + msg);
return false;
}
}
3、java实现
step1: ServerServant 实现服务端 如上
setp2:配置server
package com.zyj.ice.java.server;
import com.zyj.ice.servant.ServerServant;
/**
* @author by zyj
* @version V1.0
* @Description:
* @Date 2019/8/6 21:13
*/
public class IceService {
/**
* 服务名
*/
private static final String SERVER_NAME = "Hello";
/**
* 服务端点
*/
private static final String SERVER_ENDPOINT = "tcp -p 10006";
public static void main(String[] args) {
//获取实现类 SpringContextUtil.getBean(helloServant)
ServerServant serverServant = new ServerServant();
//ice通信器
Ice.Communicator communicator = null;
try {
//初始化ice通信器communicator,可以使用args传入一下ice初始化的参数如超时时间,线程池大小等
communicator = Ice.Util.initialize(args);
//创建一个名为queryEmployeeAdapter的适配器并且默认使用tcp协议 服务部署在10.4.30.81机器上 服务开启10006监听端口
Ice.ObjectAdapter adapter = communicator.createObjectAdapterWithEndpoints(SERVER_NAME, SERVER_ENDPOINT);
// 将servant与ice对象标识符建立映射关系,并添加到ice对象适配器中
adapter.add(serverServant, Ice.Util.stringToIdentity(SERVER_NAME));
// 激活对象适配器
adapter.activate();
System.out.println("服务启动");
// 服务在退出之前一直保持监听状态
communicator.waitForShutdown();
} catch (Exception e) {
e.printStackTrace();
} finally {
//异常销毁通信器
if (communicator != null) {
communicator.destroy();
}
}
}
}
step3:IceClient 实现ClientServant
step4:IceClient 连接server并设置回调
package com.zyj.ice.java.client;
import Ice.Identity;
import Ice.StringHolder;
import com.zyj.ice.servant.ClientServant;
import slice2java.IServerPrx;
import slice2java.IServerPrxHelper;
/**
* @author by zyj
* @version V1.0
* @Description:
* @Date 2019/8/6 21:13
*/
public class IceClient {
/**
* 服务名
*/
private static final String SERVER_NAME = "Hello";
/**
* 服务端点
*/
private static final String SERVER_ENDPOINT = "tcp -h 127.0.0.1 -p 10006";
public static void main(String[] args) {
//ice通信器
Ice.Communicator communicator = null;
try {
//初始化ice通信器communicator,可以使用args传入一下ice初始化的参数如超时时间,线程池大小等
communicator = Ice.Util.initialize(args);
//构建服务端的代理对象 服务端对象标识以 SERVER_NAME:SERVER_ENDPOINT 格式
Ice.ObjectPrx op = communicator.stringToProxy(SERVER_NAME + ":" + SERVER_ENDPOINT);
//检查通用客户端代理op 是不是queryServer对象标识符所关联的ice对象的代理
IServerPrx qp = IServerPrxHelper.checkedCast(op);
if (qp == null) {
throw new Exception("qp == null");
}
//测试发送信息到户无端
boolean result = qp.request("hello");
// 输出服务端返回结果
System.out.println("java:client请求结果:" + result + " 时间:" + System.currentTimeMillis());
//创建客户端服务
Ice.ObjectAdapter adapter = communicator.createObjectAdapter("");
Ice.Identity id = new Identity();
id.name = "client";
id.category = "";
ClientServant clientServant = new ClientServant();
adapter.add(clientServant, id);
adapter.activate();
//客户端服务设置服务端点
qp.ice_getConnection().setAdapter(adapter);
//设置回调对象
qp.setCallBack(id);
//设置心跳回调
qp.ice_getConnection().setCallback(new Ice.ConnectionCallback() {
@Override
public void heartbeat(Ice.Connection c) {
System.out.println("sn:" + " server heartbeat....");
}
@Override
public void closed(Ice.Connection c) {
System.out.println("sn:" + " " + "closed....");
}
});
// 每30/2 s向对方做心跳
// 客户端向服务端做心跳 服务端打印服务端的con.setCallback(new Ice.ConnectionCallback()
qp.ice_getConnection().setACM(new Ice.IntOptional(10), new Ice.Optional<Ice.ACMClose>(Ice.ACMClose.CloseOff),
new Ice.Optional<Ice.ACMHeartbeat>(Ice.ACMHeartbeat.HeartbeatAlways));
} catch (Exception e) {
e.printStackTrace();
}
}
}
step5:启动验证
启动server
启动client
4、spring实现(spring启动ice)
step1:改造ServerServant(添加@Service注解)同上
step2:改造server 主要防止ice阻塞,所以通过线程处理
package com.zyj.ice.spring.server;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author by zyj
* @version V1.0
* @Description:
* @Date 2019/8/6 21:13
*/
@Service
public class IceService implements Runnable{
/**服务名*/
private static final String SERVER_NAME="Hello";
/**服务端点*/
private static final String SERVER_ENDPOINT="tcp -p 10006";
@Autowired
private HelloServant helloServant;
@PostConstruct
private void startIceServer() {
//构造线程池启动当前任务
LinkedBlockingQueue<Runnable> runnableList=new LinkedBlockingQueue<Runnable>();
ThreadPoolExecutor threadPoolExecutor= new ThreadPoolExecutor(100,100,1L, TimeUnit.SECONDS,runnableList);
threadPoolExecutor.execute(this);
}
@Override
public void run() {
//ice通信器
Ice.Communicator communicator = null;
try {
//初始化ice通信器communicator,可以使用args传入一下ice初始化的参数如超时时间,线程池大小等
communicator = Ice.Util.initialize();
//创建一个名为queryEmployeeAdapter的适配器并且默认使用tcp协议 服务部署在10.4.30.81机器上 服务开启10006监听端口
Ice.ObjectAdapter adapter = communicator.createObjectAdapterWithEndpoints(SERVER_NAME,SERVER_ENDPOINT);
// 将servant与ice对象标识符建立映射关系,并添加到ice对象适配器中
adapter.add(helloServant, Ice.Util.stringToIdentity(SERVER_NAME));
// 激活对象适配器
adapter.activate();
System.out.println("服务启动");
// 服务在退出之前一直保持监听状态
communicator.waitForShutdown();
} catch (Exception e) {
e.printStackTrace();
} finally{
//异常销毁通信器
if(communicator != null){
communicator.destroy();
}
}
}
}
step3:IceClient 实现ClientServant(添加@Service注解)同上
step4:改造客户端(客户端连接服务端后,可以保持服务端xxxPrx对象持续调用)
package com.zyj.ice.spring.client;
import Ice.Identity;
import com.zyj.ice.servant.ClientServant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import slice2java.IServerPrx;
import slice2java.IServerPrxHelper;
import javax.annotation.PostConstruct;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author by zyj
* @version V1.0
* @Description:
* @Date 2019/8/6 21:13
*/
@Service
public class IceClient implements Runnable {
/**
* 服务名
*/
private static final String SERVER_NAME = "Hello";
/**
* 服务端点
*/
private static final String SERVER_ENDPOINT = "tcp -h 127.0.0.1 -p 10006";
@Autowired
private ClientServant clientServant;
@PostConstruct
private void startIceClient() {
//构造线程启动客户端
LinkedBlockingQueue<Runnable> runnableList = new LinkedBlockingQueue<Runnable>();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(100, 100, 1L, TimeUnit.SECONDS, runnableList);
threadPoolExecutor.execute(this);
}
@Override
public void run() {
//ice通信器
Ice.Communicator communicator = null;
try {
//初始化ice通信器communicator,可以使用args传入一下ice初始化的参数如超时时间,线程池大小等
communicator = Ice.Util.initialize();
//构建服务端的代理对象 服务端对象标识以 SERVER_NAME:SERVER_ENDPOINT 格式
Ice.ObjectPrx op = communicator.stringToProxy(SERVER_NAME + ":" + SERVER_ENDPOINT);
//检查通用客户端代理op 是不是queryServer对象标识符所关联的ice对象的代理
IServerPrx qp = IServerPrxHelper.checkedCast(op);
if (qp == null) {
throw new Exception("qp == null");
}
//测试发送信息到户无端
boolean result = qp.request("hello");
// 输出服务端返回结果
System.out.println("spring:client请求结果:" + result + " 时间:" + System.currentTimeMillis());
//创建客户端服务
Ice.ObjectAdapter adapter = communicator.createObjectAdapter("");
Ice.Identity id = new Identity();
id.name = "client";
id.category = "";
adapter.add(clientServant, id);
adapter.activate();
//客户端服务设置服务端点
qp.ice_getConnection().setAdapter(adapter);
//设置回调对象
qp.setCallBack(id);
//设置心跳回调
qp.ice_getConnection().setCallback(new Ice.ConnectionCallback() {
@Override
public void heartbeat(Ice.Connection c) {
System.out.println("sn:" + " server heartbeat....");
}
@Override
public void closed(Ice.Connection c) {
System.out.println("sn:" + " " + "closed....");
}
});
// 每30/2 s向对方做心跳
// 客户端向服务端做心跳 服务端打印服务端的con.setCallback(new Ice.ConnectionCallback()
qp.ice_getConnection().setACM(new Ice.IntOptional(10), new Ice.Optional<Ice.ACMClose>(Ice.ACMClose.CloseOff),
new Ice.Optional<Ice.ACMHeartbeat>(Ice.ACMHeartbeat.HeartbeatAlways));
} catch (Exception e) {
e.printStackTrace();
}
}
}
step:5: 启动