bboyjing's blog

尝试ZeorC ICE之【改造Hello World】

上一篇我们跑通了简单的Ice小例子,这一篇我们把hello项目改造下,主要涉及两个方面:

  1. 引入针对Slice语言的gradle插件
  2. 参照官网例子,重写Hello World

首先在attempt_ice目录下新建一个项目ice_better_hello,步骤参照上一篇的新建项目章节。

引入gradle插件

首先思考一个问题,当项目中*.ice文件多了之后,总能每次都手动slice2java去执行吧。ZeroC github上开源了一个项目ice-builder-gradle,在编译的时候基于gradle的task去执行slice2java命令,这就方便许多了。
同样在/src/main目录下新建slice目录,并且在其中新建HelloWorld.ice文件:

1
2
3
4
5
6
7
8
9
// 指定上层包名
[["java:package:cn.didadu.generate"]]
// module和Java的Package对应
module helloworld {
interface Hello{
idempotent void sayHello(int delay);
void shutdown();
};
};

注意sayHello()方法前多了个idempotent关键字,表示该方法是幂等的。
修改build.gradle,添加如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//可以在buildscrip中添加第三方插件源
buildscript {
repositories {
maven {
url 'https://repo.zeroc.com/nexus/content/repositories/releases'
}
}
dependencies {
classpath group: 'com.zeroc.gradle.ice-builder', name: 'slice', version: '1.0.5'
}
}
//通过apply,引入插件
apply plugin: 'slice'
//更改slice插件的属性
slice{
//更改将slice文件编译成java文件的路径
output = file('src/main/java')
}

在ice_better_hello项目根目录执行gradle build命令之后,会在指定目录生成HelloWorld.ice对应的Java文件,这样就爽多了。

重写Hello World

浏览ZeroC github仓库发现一个demo项目ice-demos,把其java目录下的hello模块直接拿过来。

实现Service

我们还是在cn.didadu下新建service包,存放我们将要实现的service类,新建HelloImpl.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class HelloImpl extends _HelloDisp {
@Override
public void sayHello(int delay, Current __current) {
if (delay > 0) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Hello World!");
}
}
@Override
public void shutdown(Current __current) {
System.out.println("Server Shutting down...");
// 关闭服务
__current.adapter.getCommunicator().shutdown();
}
}

实现提供服务逻辑

  1. 在cn.didadu下新建Server.java,用于启动服务:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class Server extends Application{
    @Override
    public int run(String[] args) {
    // 通过config.server配置文件初始化服务站点
    ObjectAdapter adapter = communicator().createObjectAdapter("Hello");
    adapter.add(new HelloImpl(), Ice.Util.stringToIdentity("hello"));
    adapter.activate();
    communicator().waitForShutdown();
    return 0;
    }
    public static void main(String[] args) {
    Server app = new Server();
    int status = app.main("Server", args, "config.server");
    System.exit(status);
    }
    }
  2. 在/src/main/resources目录下新建config.server文件,目前配下面两个配置就可以了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #
    # The server creates one single object adapter with the name
    # "Hello". The following line sets the endpoints for this
    # adapter.
    #
    Hello.Endpoints=tcp -p 10000
    #
    # Only listen on the localhost interface by default.
    #
    Ice.Default.Host=localhost

实现客户端调用

官网demo的客户端实现略复杂,我们先简化下,以后再研究。

  1. 在cn.didadu下新建Client.java,用于调用服务:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    public class Client extends Application {
    // 自定义ShutdownHook
    class ShutdownHook extends Thread {
    @Override
    public void run() {
    communicator().destroy();
    System.out.println("destroy communicator");
    }
    }
    @Override
    public int run(String[] args) {
    // 注册ShutdownHook,关闭应用时销毁Communicator实例
    setInterruptHook(new ShutdownHook());
    // 通过config.client中的Hello.Proxy,构造通用Proxy对象
    Ice.ObjectPrx base = communicator().propertyToProxy("Hello.Proxy");
    HelloPrx prxy = HelloPrxHelper.checkedCast(base);
    prxy.sayHello(0);
    // shutdown()方法可以关闭服务...
    prxy.shutdown();
    // 测试ShutdownHook
    communicator().waitForShutdown();
    return 0;
    }
    public static void main(String[] args) {
    Client app = new Client();
    int status = app.main("Client", args, "config.client");
    System.exit(status);
    }
    }
  2. 在/src/main/resources目录下新建config.client文件,目前配下面两个配置就可以了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #
    # The client reads this property to create the reference to the
    # "hello" object in the server.
    #
    Hello.Proxy=hello:tcp -p 10000
    #
    # Only connect to the localhost interface by default.
    #
    Ice.Default.Host=localhost

说是改造,其实也就小改了一下,本章最大的收获是在gradle中引入了slice插件,项目的小改动,好像现在看来意义也不是很大。