ICE java實現服務雙向調用

目錄

一 前言

二 實現

1、目錄結構

2、公共代碼

3、java實現

4、spring實現(spring啓動ice)

三 項目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

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: 啓動

三 項目git  https://github.com/HandsomeMars/springboot-ice-demo

https://github.com/HandsomeMars/springboot-ice-demo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章