随笔-95  评论-31  文章-10  trackbacks-0
     最近完成一个与IBM的医院融合项目,使用webservice特此总结。从axis2、xfire、cxf框架中选择了axis2原因是之前一个项目也使用axis2。
1、首先从http://axis.apache.org/axis2/java/core/download.cgi下载最新的axis2,下载Binary Distribution zip | MD5 | PGP  和  WAR Distribution zip | MD5 | PGP 。其中WAR文件必须放入web容器的webapps里(专业点就是放入servlet engine里)因为发布的webservice都构建在此基础上,就好比web项目要运行在J2EE容器里面一样。文章结尾将会说明不需要部署该WAR文件,在一个自己的项目里面部署axis2并发布webservice。
2、使用axis2让人难于理解的地方,(个人感觉)不是写services代码,也不是写Client测试代码。而是如何配置services.xml文件,以及发布成aar文件。在说明这个问题前首先要说明下axis2处理xml的机制,Axis1.x使用DOM作为其XML表示机制,但使用DOM的缺点是:需要在内存中保存完整的对象层次结构,对于小消息,这将不是问题,但对于大型消息就是问题了。为解决这个问题,Axis2引入了新的XML表示形式即AXIOM(Axis2 Object Model),任何SOAP消息在Axis2中都表示为AXIOM。它基于Pull解析器技术,即调用者对解析器具有完全控制权,可以要求触发下一个事件,因此具有“随需应变构建”功能,仅在被要求时才会构建对象模型。
      下面对services,xml文件以及如何发布成aar进行简单说明(代码均来自官方网站)首先创建一个简单的java类(用于发布成webservice)
 1package samples.quickstart.service.pojo;
 2
 3import java.util.HashMap;
 4
 5public class StockQuoteService {
 6    private HashMap map = new HashMap();
 7
 8    public double getPrice(String symbol) {
 9        Double price = (Double) map.get(symbol);
10        if(price != null){
11            return price.doubleValue();
12        }

13        return 42.00;
14    }

15
16    public void update(String symbol, double price) {
17        map.put(symbol, new Double(price));
18    }

19}
上面代码很简单接着给出services.xml文件
 1<service name="StockQuoteService" scope="application">
 2    <description>
 3        Stock Quote Sample Service
 4    </description>
 5    <messageReceivers>
 6        <messageReceiver 
 7            mep="http://www.w3.org/2004/08/wsdl/in-only"
 8    class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
 9        <messageReceiver
10            mep="http://www.w3.org/2004/08/wsdl/in-out"
11    class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
12    </messageReceivers>
13    <parameter name="ServiceClass">
14        samples.quickstart.service.pojo.StockQuoteService
15    </parameter>
16</service>
service元素里面的name属性代表该webservice的访问名字
messageReceivers元素定义用于处理此操作的消息接收器。
打包:
Axis2服务是作为Axis Archive(.aar)打包的 。这是一个jar文件,打包后具有以下结构:
1./stock/StockQuoteService.class
2
3./META-INF/services.xml
使用MyEclipse,首先选中StockQuoteService和META-INF/services.xml然后Export成.aar文件后,里面的META-INF文件夹里面不存在services.xml需要将WebRoot/META-INF里面的services挪进aar根目录的META-INF里面。
最后将该aar文件放入web容器webapps/axis2/WEB-INF/services里面,启动web容器,访问
http://localhost:8080/axis2/services/StockQuoteService?wsdl
这样webservice服务发布成功,但是以上发布没有基于SOAP标准。

      下面给出的services代码以及Client代码都基于AXIOM的API(代码均来自官方网站示例)首先还是构建一个java类(使用AXIOM用于发布成webservice)
 1package samples.quickstart.service.axiom;
 2
 3import javax.xml.stream.XMLStreamException;
 4import org.apache.axiom.om.OMAbstractFactory;
 5import org.apache.axiom.om.OMElement;
 6import org.apache.axiom.om.OMFactory;
 7import org.apache.axiom.om.OMNamespace;
 8
 9import java.util.HashMap;
10public class StockQuoteService {
11    private HashMap map = new HashMap();
12
13    public OMElement getPrice(OMElement element) throws XMLStreamException {
14        element.build();
15        element.detach();
16
17        OMElement symbolElement = element.getFirstElement();
18        String symbol = symbolElement.getText();
19
20        String returnText = "42";
21        Double price = (Double) map.get(symbol);
22        if(price != null){
23            returnText  = "" + price.doubleValue();
24        }

25        OMFactory fac = OMAbstractFactory.getOMFactory();
26        OMNamespace omNs =
27            fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd""tns");
28        OMElement method = fac.createOMElement("getPriceResponse", omNs);
29        OMElement value = fac.createOMElement("price", omNs);
30        value.addChild(fac.createOMText(value, returnText));
31        method.addChild(value);
32        return method;
33    }

34
35    public void update(OMElement element) throws XMLStreamException {
36        element.build();
37        element.detach();
38
39        OMElement symbolElement = element.getFirstElement();
40        String symbol = symbolElement.getText();
41
42        OMElement priceElement = (OMElement)symbolElement.getNextOMSibling();
43        String price = priceElement.getText();
44
45        map.put(symbol, new Double(price));
46    }

47}
上面17-18行代码表示获取请求参数
25-31行代码表示创建响应消息
update方法里面的代码类似。
下面是services.xml文件内容
 1<service name="StockQuoteService" scope="application">
 2    <description>
 3        Stock Quote Service
 4    </description>
 5    <operation name="getPrice">
 6        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
 7    </operation>
 8    <operation name="update">
 9        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/>
10    </operation>
11    <parameter name="ServiceClass">samples.quickstart.service.axiom.StockQuoteService</parameter>
12</service>
service元素里面name属性代表webservice的访问名
operation元素里面的name属性代表方法
parameter元素里面的name属性(固定值ServiceClass)代表自定义的包名.类名
messageReceiver元素定义用于处理此操作的消息接收器。Axis针对In-Only和In-Out操作提供了两个无数据绑定的内置MessageReceivers;
org.apache.axis2.reveivers.RawXMLINOnlyMessageReceiver用于In-Only操作
org.apache.axis2.reveivers.RawXMLOutOnlyMessageReceiver用于In-Out操作
如果没有指定messageReceiver,则Axis2将尝试使用org.apache.axis2.reveivers.RawXMLINOutMessageReceiver作为缺省的messageReceiver。
上述RAWXML消息接收器将传入SOAP消息的<Body>的内容作为OMElement传递给服务实现。此操作应作为OMElement返回SOAP响应的<Body>元素包含的XML内容。这就解释了上述方法返回值为什么是OMElement了
打包过程同上。启动web容器,访问http://localhost:8080/axis2/services/StockQuoteService?wsdl即可访问
客户端测试代码:
 1package samples.quickstart.clients;
 2
 3import org.apache.axiom.om.OMAbstractFactory;
 4import org.apache.axiom.om.OMElement;
 5import org.apache.axiom.om.OMFactory;
 6import org.apache.axiom.om.OMNamespace;
 7import org.apache.axis2.Constants;
 8import org.apache.axis2.addressing.EndpointReference;
 9import org.apache.axis2.client.Options;
10import org.apache.axis2.client.ServiceClient;
11
12public class AXIOMClient {
13
14    private static EndpointReference targetEPR = 
15        new EndpointReference("http://localhost:8080/axis2/services/StockQuoteService");
16
17    public static OMElement getPricePayload(String symbol) {
18        OMFactory fac = OMAbstractFactory.getOMFactory();
19        OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd""tns");
20
21        OMElement method = fac.createOMElement("getPrice", omNs);
22        OMElement value = fac.createOMElement("symbol", omNs);
23        value.addChild(fac.createOMText(value, symbol));
24        method.addChild(value);
25        return method;
26    }

27
28    public static OMElement updatePayload(String symbol, double price) {
29        OMFactory fac = OMAbstractFactory.getOMFactory();
30        OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd""tns");
31
32        OMElement method = fac.createOMElement("update", omNs);
33
34        OMElement value1 = fac.createOMElement("symbol", omNs);
35        value1.addChild(fac.createOMText(value1, symbol));
36        method.addChild(value1);
37
38        OMElement value2 = fac.createOMElement("price", omNs);
39        value2.addChild(fac.createOMText(value2,
40                                         Double.toString(price)));
41        method.addChild(value2);
42        return method;
43    }

44
45    public static void main(String[] args) {
46        try {
47            OMElement getPricePayload = getPricePayload("WSO");
48            OMElement updatePayload = updatePayload("WSO"123.42);
49            Options options = new Options();
50            options.setTo(targetEPR);
51            options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
52
53            ServiceClient sender = new ServiceClient();
54            sender.setOptions(options);
55
56            sender.fireAndForget(updatePayload);
57            System.err.println("price updated");
58            OMElement result = sender.sendReceive(getPricePayload);
59
60            String response = result.getFirstElement().getText();
61            System.err.println("Current price of WSO: " + response);
62
63        }
 catch (Exception e) {
64            e.printStackTrace();
65        }

66    }

67    
68}

最后如果想得到某个已经写好的服务类的wsdl描述文件,使用java2wsdl工具。
首先配置Axis2_HOME路径(名字必须是这样,否则配置较麻烦),然后配置PATH添加%Axis2_HOME%\bin,最后打开dos窗口(如果需要对test.class文件生成wsdl描述符),那么进入该Test.class根目录下一般就是在classes目录,输入java2wsdl -cp . -cn 包名.Test -of Test.wsdl执行成功后会在classes根目录生成wsdl文件,可以交给对方生成客户端测试代码,此次与IBM融合就使用这种方法。

未完待续。。。
posted on 2011-03-04 17:08 朔望魔刃 阅读(2972) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: