紧接着前2篇关于PHPRPC的实践,最近试了下服务器端返回带泛型的的集合以及作为参数传递,特总结如下:
首先是需要注意的是:不管是在服务器端定义发布方法时,还是在客户端定义代理接口时,都不建议用接口类型来声明返回值和参数类型。因为接口是抽象的不能被实例化,因此对于容器类型的参数和返回结果来说,接口并不能表明究竟该转换为何种具体类型。不过对于自定义类型可以用接口,只要传递的类型实现了该接口即可。
不过在 3.0.2 版之后,对 List
、Map
、Set
、Collection
这四个容器接口也提供了支持,如果使用这四个接口类型来接收数据,那么 List
、Collection
会被转换成 ArrayList
类型,Set
会被转换成 HashSet
类型,Map
会被转成 HashMap
类型。
以上说明均来自于文档,那么我们可以得知,一旦PHPRPC在进行反序列化而又无法获得类型时,就会将类型当作HashMap 或ArrayList 来处理,其中的数据则用byte[]形式传递.这个时候要么自己来将byte[]转为想要的类型,要么直接使用org.phprpc.util.Cast将HashMap/ArrayList转化为自己想要的类型.如果不想这么麻烦的话,就需要遵循一些规则,即当服务器端的自定义类型JAVA对象想要和其他语言的对象做转换时,需要注意:
1.对于有包机制的语言,例如FLEX,要注意包名和类名都完全和JAVA对象的一样,具体请参看之前FLEX作为客户端的例子;
2.对于没有包机制的语言,例如JS,则要注意用_代替.,同样实现类似包名点类名的形式.
例如如果你的服务器端的User类的全名为:
model.User,那么你客户端应该这样定义:
var User = function model_User(name,password){
this.name = name;
this.password = password;
}
===============================我是分割线==========================
OK.接下来我们用实际例子来演示JAVA自定义集合类型作为参数以及返回类型的RMI:
首先服务器类不变,在之前的TestService以及TestServiceImpl中添加代码
public List<User> getUsers();
public void showUsers(List<User> list);
public List<User> getUsers(){
List<User> list = new ArrayList<User>();
list.add(new User("fw"));
list.add(new User("jr"));
return list;
}
public void showUsers(List<User> list) {
for(User u:list){
System.out.println(u.getName()+" "+u.getPassword());
}
}
这2个方法分别为测试List<User>作为参数和返回类型的情况
接下来在发布服务的时候将这2个方法也一起发布
然后JS作为客户调用:
var rpc_client = new PHPRPC_Client(URL,["showUsers","getUsers"]); //调用getUsers rpc_client.getUsers(function(result, args, output, warning){ var str=""; for(var i=0;i<result.length;i++){ var user = result[i]; str+=user.name+" "; } alert(str); }); var User = function model_User(name,password){ this.name = name; this.password = password; } var users=[new User("fw","123"),new User("jr","123")]; rpc_client.showUsers(users);//调用showUsers
最终得到结果:
1.调用getUsers方法后得到服务器端返回的List<User>类型,客户端是转换为json数组接收的;
2.如果根据1的结论想当然地在调用showUsers时以json数组的形式传递数据的话,则会因为泛型中的User类型不能在运行时被获取从而导致服务器端得到的实际上是List<HashMap>或者List<AssocArray>,需要手动转换(话说Hessian也不支持泛型,真的是觉得这个东东越来越没实际意义了);
3.如果想要让JS这边自定义对象能够和JAVA的User对象进行转换,则不能够以工厂方式创建JS对象(JSON实际上就是工厂方式的一种快捷表示方法),而必须采用构造函数的方式创建.并且还需要注意服务器端的User类在包model下,即model.User,那么按照前面所提到的几点注意,需要在创建JS对象时用_代替.来表示包名点类名,因此是model_User.
打完收工,基本上PHPRPC针对JAVA的支持除了泛型这个鸡助之外还是非常好的.