1. Code first approach:可能不能完全发挥框架和web services的能量,但能完成目标。减少了学习曲线,不用非常透彻了解web services概念,只要对某个框架有一定了解就能完成任务。
2.Contract first approach:根据服务先写WSDL文件,写好之后使用框架的工具把WSDL转换为依赖框架的代码。
一 介绍
当客户端调用你的web service的时候,他会发送一个消息过来(可能是soap 消息),如:
<foo:concatRequest>
<s1>abc</s1>
<s2>123</s2>
</foo:concatRequest>
这时候如果有一个转换器把这个soap消息转换成java对象,然后调用你提供的java对象(方法)的话将会是非常方便的。几个最流行的库就是充当了这种转换器功能,比如CXF, Axis2 , Metro (jdk6自带的有)。
手动创建WSDL文件比较容易出错,可以使用eclipse进行可视化编辑。
二 生成服务代码
像CXF这样的 web service库可以创建转换器把进来的SOAP 消息转换为Java对象,然后作为参数传给方法。生成这些代码,只需创建一个main:
1 CXF方式:
public static void main(String[] args) {
WSDLToJava.main(new String[] {
"-server",
"-d", "src/main/java",
"src/main/resources/SimpleService.wsdl" });
System.out.println("Done!");
}
运行后会生成service endpoint interface(SEI),我们再写一个类(比如SimpleServiceImpl)来实现这个接口,写入自己的业务。还会生成传入消息对应的java对象。同时生成一个服务器类:
public class SimpleService_P1_Server {
protected SimpleService_P1_Server() throws Exception {
System.out.println("Starting Server");
Object implementor = new SimpleServiceImpl();
String address = "http://localhost:8080/ss/p1";
Endpoint.publish(address, implementor);
}
public static void main(String args[]) throws Exception {
new SimpleService_P1_Server();
System.out.println("Server ready...");
Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting");
System.exit(0);
}
}
运行这个类你的web service就可以服务了。
2 Axis2 方式
用类似的写main方法,或者配置eclipse的axis2插件可生成:在WSDL文件上,右键->web service->generate java bean skeleton
界面的上半部分针对服务端,可以根据需要调整生成的级别,下半部分是生成客户端。具体的级别可参考eclipse的帮助文档。一路下一步,最后根据命名空间生成包路径的文件,里面有XXSkeletonInterface.java 文件(如果生成的时候选择了生成接口的话),还有一个XXSkeleton实现了这个接口,也是我们需要修改这部分代码完成我们业务的地方。实际上有一个XXMessageReceiverInOut.java的类接收请求的消息,并调用XXSkeletonInterface。使用eclipse的axis2插件的时候,会自动在web-inf文件夹下生成service\xx(你的wsdl服务名),这下面还要一个meta-inf文件夹装有wsd文件和一个services.xml配置文件。services.xml文件可配置包括XXMessageReceiverInOut类在内的选项。
二 生成客户端代码
为了调用这些web service,同样可以用CXF这些库来生成在客户端运行的转换器(称为service stub)。当调用stub里的方法的时候,他会把你的数据/对象 转换为正确的XML格式,然后发送给真正的web service。当他收到响应的时候,又会把XML转回Java。
1 CXF 方式
和生成服务器端类似,使用方法
WSDLToJava.main(new String[] {
"-client",
"-d", "src/main/java",
"src/main/resources/SimpleService.wsdl" });
运行后会生成客户端代码:
public final class SimpleService_P1_Client {
private static final QName SERVICE_NAME = new QName("http://ttdev.com/ss",
"SimpleService");
private SimpleService_P1_Client() {}
public static void main(String args[]) throws Exception {
URL wsdlURL = SimpleService_Service.WSDL_LOCATION;
if (args.length > 0) {
File wsdlFile = new File(args[0]);
try {
if (wsdlFile.exists()) {
wsdlURL = wsdlFile.toURI().toURL();
} else {
wsdlURL = new URL(args[0]);
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
SimpleService_Service ss =
new SimpleService_Service(wsdlURL, SERVICE_NAME);
SimpleService port = ss.getP1();
{
System.out.println("Invoking concat...");
com.ttdev.ss.ConcatRequest _concat_parameters = null;
java.lang.String _concat__return = port.concat(_concat_parameters);
System.out.println("concat.result=" + _concat__return);
}
System.exit(0);
}
}
SimpleService_Service是创建的service stub,他模拟了客户端的服务。我们需要修改这个类中的_concat_parameters部分,加入参数:
com.ttdev.ss.ConcatRequest _concat_parameters = new ConcatRequest();
_concat_parameters.setS1("abc");
_concat_parameters.setS2("123");
现在就可以运行客户端代码了。SEI中有一些注解,可以修改,不细说。
2 Axis2 方式
和生成服务端类似,利用eclipse插件直接生成,包路径类似,有一个XXStub类,这个类里面有包括请求和应答消息在内的内部类。使用的时候,先对请求消息参数类按业务需求赋值,最后调用Stub的请求方法。可以使用Stub的构造函数指定目标endpoint。