前言: 使用ICE不用写slice了,很开心吧!虽然不用写slice文件,但得写客户端的哦
mlcs-ice是ICE的底层消息通讯封装,让java开发人员摆脱ice底层的消息通讯细节,直接支持javabean和原生类型的数据传递
好了,废话不多说,现在看看如何来做这些后续的操作吧!
步骤:
1、在maven工程的pom.xml文件中添加如下依赖:
<dependency>
<groupId>com.mlcs.core</groupId>
<artifactId>mlcs-ice</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
2、编写服务端程序(如HelloService.java,必须要继承 DefaultBaseServiceImpl.java;service中对外提供的方法必须满足两个条件:修饰符为public、第一个参数为JsonObject):
package com.mlcs.demo.service.impl;
public class HelloService extends DefaultBaseServiceImpl {
public void watch(JsonObject resultObj, HelloWorld hello, int aaa){
System.out.println("watch msg : " + hello + "====" + aaa);
}
public synchronized void handleArray(JsonObject resultObj, int[] ids){
System.out.println("handleArray msg : " + ids);
}
public static void handleList(JsonObject resultObj, List<HelloWorld> hwList){
System.out.println("handleList msg : " + hwList);
}
public void login(JsonObject resultObj, String userName, String passwd){
System.out.println(userName + "," + passwd);
JSONTool.addToResult(true, resultObj); //有返回值的情况,可以借助于工具类JSONTool的addToResult*方法来返回数据
}
}
3、编写服务端spring配置文件(例如 applicationContext.xml,放置在src/main/resources/conf/spring目录下):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://cxf.apache.org/core"
xmlns:p="http://cxf.apache.org/policy" xmlns:ss="http://www.springframework.org/schema/security"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="hw"
class="com.mlcs.demo.service.impl.HelloService"> <!-- 注意:这个id将被在客户端使用,如果HelloService使用了注解@Service,则无需在这配置 -->
</bean>
<!-- defaultSecurityInterp这个bean不是必须要配置的,这个主要用作安全访问限制,某个类的方法只能被指定的IP或者服务访问 -->
<bean id="defaultSecurityInterp"
class="com.mlcs.core.ice.service.impl.DefaultSecurityInterceptor">
</bean>
</beans>
4、使用zookeeper客户端工具(点击zk_tool.tar.gz下载,如果双击zookeeper-dev-ZooInspector.jar不能成功运行,则使用命令行 java -Djava.ext.dirs=lib -jar zookeeper-dev-ZooInspector.jar 运行)连接 10.249.15.194:2181,建立业务线的zk配置文件根节点(比如:/mlcsconf), 然后在 /mlcsconf 节点下建立自己的模块名节点(比如demo),然后在该模块名下建立配置文件节点 ice_config.xml ,在 ice_config.xml 节点中编写如下内容:
<?xml version="1.0" encoding="UTF-8"?>
<ice-config>
<springConfig>
<config>conf/spring/applicationContext.xml</config> <!-- 注意:这个文件路径是相对/WEB-INF/classes 的路径 ,与第3步放置的位置相关;这里配置有误,有可能导致启动时抛FileNotFoundException异常-->
</springConfig>
<services>
<service identity="testService" <!-- 这个是ice的配置文件里边配置的replica-group的子节点object的identity -->
replicaGroup="testIceBoxReplicaGroup" <!-- 这是ice的配置文件里边配置的replica-group的id -->
connectMode="debug" <!-- 这个模式共有4种,debug: 在本地调试的时候使用;dev:在开发环境中使用, test:在测试环境中使用;prod:在线上环境中使用 -->
localHost="10.249.9.234" <!-- 这个给客户端使用的连接服务器的IP,默认为127.0.0.1,这个便于多人进行组合调试,这个只在debug模式下有用,其它模式下可以省略 -->
localPort="10005"/> <!-- 在本地调试时,service将以这个值作为监听端口,client将读取这个端口来连接本地对应的service服务,其它connectMode模式下,这个属性可以省略 -->
</services>
</ice-config>
5、(如果iceintf节点已存在,则这一步可以忽略)使用zookeeper客户端工具连接 10.249.15.194:2181, 建立全局ice配置文件,在 /mlcsconf 下建立iceintf目录,然后在iceintf目录下建立 ice_config.xml 节点,编写内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<ice-config>
<locators>
<dev connectUrl="tcp -h 10.249.15.194 -p 4061" />
<test connectUrl="tcp -h 10.249.15.201 -p 4061" />
<prod connectUrl="tcp -h 10.14.16.134 -p 4061:tcp -h 10.14.16.51 -p 4061" />
</locators>
</ice-config>
6、编写服务端的本地zk连接的配置文件commons.properties(位置在 src/main/resources/conf 目录下),内容如下:
zk.quorum=10.249.15.194:2181,10.249.15.195:2181,10.249.15.196:2181 #这里是zk的ip信息
#zk.session.timeout=25000
projectName=demo #这个projectName的名字就是第4步中在zk上建立的/mlcsconf目录下的目录名称,在这里就是demo
zk.config.prefix=/mlcsconf #这个是第4步建立的配置文件根节点名称
is_server_endpoint=true #如果当前模块为ice的service,则需要配置一下这个属性
7、在本地启动刚才的service服务(即HelloIntfImpl.java服务):
点击eclipse工具栏中 Run 按钮边上的三角符号,选择 Run Configurations... 菜单项,在弹出的对话框中的左侧 Java Application 下新建一个运行项, 然后在右侧的 Main class 选择 com.meiliwan.emall.icetool.IceServerTester 类,点击 Run 按钮,即可将本地服务启动
8、编写ice的客户端类(例如:HelloClient.java)
package com.mlcs.demo.client;
public class HelloClient {
public static void watchHello(HelloWorld helloworld, int index){
IceClientTool.sendMsg(IceClientTool.TEST_ICE_SERVICE, JSONTool.buildParams("hw/watch", helloworld, index)); //注意标红的地方,不懂的往上边的内容里找;“/” 后边的为HelloService的方法名;
//如果HelloService.java是通过注解@Service注入的,hw需换成helloService;这是spring给注解类生产id的默认规则
}
public static void handleArray(int[] ids){
IceClientTool.sendMsg(IceClientTool.TEST_ICE_SERVICE, JSONTool.buildParams("hw/handleArray", ids));
}
public static void handleList(List<HelloWorld> list){
IceClientTool.sendMsg(IceClientTool.TEST_ICE_SERVICE, JSONTool.buildParams("hw/handleList", list));
}
public static boolean login(String username, String passwd){
JsonObject resultObj = IceClientTool.sendMsg(IceClientTool.TEST_ICE_SERVICE, JSONTool.buildParams("hw/login", username, passwd));
return resultObj.get(BaseService.RESULT_OBJ).getAsBoolean(); //如果返回值为基本类型,则可以如例子一样操作;如果为其它复杂类型,
//可以使用如下方法来转换成目标对象 new Gson().fromJson(resultObj.get(BaseService.RESULT_OBJ), new TypeToken<List<UserCart>>() {}.getType()) ; 注意标颜色的地方为目标类型
}
}
9、编写客户端的本地zk连接的配置文件commons.properties(位置在 src/main/resources/conf 目录下),内容如下:
zk.quorum=10.249.15.194:2181,10.249.15.195:2181,10.249.15.196:2181 #这里是zk的ip信息
#zk.session.timeout=25000
projectName=demo #这个projectName的名字就是第4步中在zk上建立的/mlwconfig目录下的目录名称,在这里就是demo
zk.config.prefix=/mlcsconf #这个是第4步建立的配置文件根节点名称
10、编写客户端的javabean(比如: HelloWorld.java)
package com.mlcs.demo.model;
public class HelloWorld {
private String prefix;
private String suffix; //注意生成getter和setter方法
}
11、编写客户端测试类 IceTester.java:
package com.mlcs.demo.client;
public class IceTester {
public static void main(String[] args) {
HelloWorld helloworld = new HelloWorld();
helloworld.setPrefix("hello ");
helloworld.setSuffix(" world");
HelloClient.watchHello(helloworld, 4);
HelloClient.handleArray(new int[]{1, 2, 3, 4, 5});
List<HelloWorld> hwList = new ArrayList<HelloWorld>();
hwList.add(helloworld);
HelloWorld helloworld1 = new HelloWorld();
helloworld1.setPrefix("hello1 ");
helloworld1.setSuffix(" world1");
hwList.add(helloworld1);
HelloClient.handleList(hwList);
HelloClient.login("hahaha", "sdfsfdj");
}
}
12、运行一下IceTester.java类,看看是否能在HelloService的服务窗口看到输出的信息,如果能看到,那恭喜您,这个demo已经完成了
目前还存在的问题:
1、在与spring的aspectj结合使用的时候,带有泛型的参数解析不正常,(例如:List<HelloWorld>将被解析成List<LinkedHashMap>, List<Integer>将被解析成List<String>)
2、不支持service方法的重载
3、json数据与对象之间的转换,需要用Gson工具进行
4、客户端和服务器端的数据传输,默认最大支持1M的数据,如果超过该值,将会抛出异常(解决方案,可以在ice服务配置文件中添加 <property name="Ice.MessageSizeMax" value="40960" /> 这样的一个属性)