[b][size=x-large]通过代理接口进行同步调用[/size][/b]
看完通过invoke进行同步调用的方式后,再来看一下通过接口进行同步调用的方式。通过接口方式进行同步调用更加直观,方便,但是不支持动态调用和引用参数传递。
[b][size=large]接口定义[/size][/b]
为了调用上面的方法,我们需要先定义接口,下面是接口的定义:
package hprose.exam;
import java.util.List;
import java.util.Map;
public interface IExam1 {
String getId();
int sum(int[] nums);
int sum(short[] nums);
int sum(long[] nums);
int sum(double[] nums);
int sum(String[] nums);
double sum(List nums);
Map<String, String> swapKeyAndValue(Map<String, String> strmap);
}
这个是与Exam1对应的接口,其中除了跟Exam1声明相同的方法签名以外,还有另外一些重载的方法,它们都能在调用过程中自动转换为正确的类型进行调用。
package hprose.exam;
public interface IExam2 {
User[] getUserList();
}
这个接口与Exam2对应,返回类型我们改成了User[]类型。
从上面的接口我们可以看出,在hprose中,客户端和服务器端的接口不必完全一致,这就大大增加了灵活性,也更加方便了跟弱类型语言进行交互。
[b][size=large]带名称空间(别名前缀)方法[/size][/b]
在使用invoke时,对带有名称空间(别名前缀)的方法在调用时,需要将方法名写为带有前缀形式的,但是使用接口调用时,在生成代理对象时,这个工作可以自动帮您完成,看下面的例子:
package hprose.exam;
import hprose.client.HproseHttpClient;
import java.io.IOException;
public class ClientExam5 {
public static void main(String[] args) throws IOException {
HproseHttpClient client = new HproseHttpClient();
client.useService("http://localhost:8084/HproseExamServer/Methods");
IExam1 exam1 = (IExam1) client.useService(IExam1.class, "ex1");
IExam1 exam2 = (IExam1) client.useService(IExam1.class, "ex2");
System.out.println(exam1.getId());
System.out.println(exam2.getId());
}
}
在这个例子中,exam1和exam2都是IExam1的接口对象,但是它们被指定了不同的名称空间(别名前缀),因此在后面对它们上面的getId方法调用时,调用的就是两个不同的方法了。
运行结果如下:
[quote]Exam1
Exam2
[/quote]
[b][size=large]可变的参数和结果类型[/size][/b]
下面我们再来看对sum方法的调用:
package hprose.exam;
import hprose.client.HproseHttpClient;
import java.io.IOException;
import java.util.ArrayList;
public class ClientExam6 {
public static void main(String[] args) throws IOException {
HproseHttpClient client = new HproseHttpClient();
client.useService("http://localhost:8084/HproseExamServer/Methods");
IExam1 exam = (IExam1) client.useService(IExam1.class, "ex1");
System.out.println(exam.sum(new int[] {1,2,3,4,5}));
System.out.println(exam.sum(new short[] {6,7,8,9,10}));
System.out.println(exam.sum(new long[] {11,12,13,14,15}));
System.out.println(exam.sum(new double[] {16,17,18,19,20}));
System.out.println(exam.sum(new String[] {"21","22","23","24","25"}));
ArrayList intList = new ArrayList();
intList.add(26);
intList.add(27);
intList.add(28);
intList.add(29);
intList.add(30);
System.out.println(exam.sum(intList));
}
}
这个程序运行结果跟前面用invoke实现的ClientExam2是相同的,这个程序看上去更简洁一些,不过需要事先将接口定义好才可以。用接口方式就不需要在调用时指定返回值类型了,Hprose自动从接口声明中就可以获取返回值类型。
[b][size=large]泛型参数和结果[/size][/b]
下面继续来看对swapKeyAndValue方法的调用:
package hprose.exam;
import hprose.client.HproseHttpClient;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class ClientExam7 {
public static void main(String[] args) throws IOException {
HproseHttpClient client = new HproseHttpClient();
client.useService("http://localhost:8084/HproseExamServer/Methods");
IExam1 exam = (IExam1) client.useService(IExam1.class, "ex1");
Map<String, String> map = new HashMap<String, String>();
map.put("January", "Jan");
map.put("February", "Feb");
map.put("March", "Mar");
map.put("April", "Apr");
map.put("May", "May");
map.put("June", "Jun");
map.put("July", "Jul");
map.put("August", "Aug");
map.put("September", "Sep");
map.put("October", "Oct");
map.put("November", "Nov");
map.put("December", "Dec");
Map<String, String> map2 = exam.swapKeyAndValue(map);
System.out.println(map);
System.out.println(map2);
}
}
运行结果如下:
[quote]{October=Oct, January=Jan, April=Apr, February=Feb, August=Aug, June=Jun, November=Nov, July=Jul, May=May, December=Dec, March=Mar, September=Sep}
{Sep=September, Feb=February, Mar=March, Apr=April, Oct=October, Jan=January, May=May, Nov=November, Dec=December, Jul=July, Aug=August, Jun=June}
[/quote]
泛型要注意的问题在前一章介绍本方法的发布时已经做过说明啦,这里就不再重复了。
[b][size=large]自定义类型[/size][/b]
下面代码中您会发现接口中的方法签名虽然跟服务器的方法签名不同,但是仍然可以正常调用:
package hprose.exam;
import hprose.client.HproseHttpClient;
import java.io.IOException;
public class ClientExam8 {
public static void main(String[] args) throws IOException {
HproseHttpClient client = new HproseHttpClient();
client.useService("http://localhost:8084/HproseExamServer/Methods");
IExam2 exam2 = (IExam2) client.useService(IExam2.class, "ex2");
User[] users = exam2.getUserList();
for (User user : users) {
System.out.printf("name: %s, ", user.getName());
System.out.printf("age: %d, ", user.getAge());
System.out.printf("sex: %s, ", user.getSex());
System.out.printf("birthday: %s, ", user.getBirthday());
System.out.printf("married: %s.", user.isMarried());
System.out.println();
}
}
}
运行结果如下:
[quote]name: Amy, age: 26, sex: Female, birthday: 1983-12-03, married: true.
name: Bob, age: 20, sex: Male, birthday: 1989-06-12, married: false.
name: Chris, age: 29, sex: Unknown, birthday: 1980-03-08, married: true.
name: Alex, age: 17, sex: InterSex, birthday: 1992-06-14, married: false.[/quote]
同样,这个例子已经很好的说明了Hprose使用的易用性和灵活性,不用多做解释相信您也已经看懂了,所以这里就不再多作解释啦。