分享

WebService学习笔记2

 孙中熙——路 2011-03-14
WebService学习笔记2.txt
2007年04月30日 星期一 08:59
2。用及时发布(把.java改名为.jws)的结果和过程与在Tomcat上是一样的,完全可用。

在Eclipse中,改把.java改名为.jws后,.java文件的一些突出显示就没有了。Eclipse认为.jws不是.java文件了。
     可以通过窗口->首选项->工作台->文件关联.
     添加*.jws文件类型,指定相关编辑器是.java一样的,就可以解决的这个问题了.
     这样.jws文件的编辑方式和突出显示等就都和.java完全一样了
     .wsdd文件的编辑也可以和.xml一样.

详细阅读。Axis自带的文档,那是第一手,也是最好的学习资料。

自IIWeb:
当WebService 的输入或输出是XML文档时
可以直接使用org.w3c.dom.Element输入作为参数输入,做输出的时候强制转行。
在ie地址栏请求的时候看到的也是标准的xml文挡。

经典文章:
桌面\Axis\3步把您的java程序转换为webserviceJava与XMLJSP技术在线教程.htm
桌面\Axis\AxisDevelopGuide.doc
桌面\Axis\AxisDevelopGuide.htm
桌面\Axis\Tomcat5_0_28下AXIS完全安装手册 中华网络安全联盟 www_77941_com.htm
桌面\Axis\zh_CN from Hu Hao Java-_NET Archives.htm
桌面\Axis\中文java技术网用Axis 1_1 for Java进行Web Services开发(1).htm
桌面\WebService\基于Web Service的系统集成技术在网络教育平台中的应用.htm
桌面\Axis_Client_Stub\成长的路上.htm->关于axis1.2中对象的序列化和发序列化
桌面\CSDN_AXIS学习笔记\CSDN 文档中心:AXIS学习笔记(一).htm 至 (五) 都挺好。重点是(五)对与Axis中对象序列化做了一个经典的例子。

遗留问题:
Axis是否支持配置多个server-config.wsdd文件?如何配置?


实施阶段:主要是Element作为返回的服务器和客户端遇到的问题。,
注意:Element作为输入是完全没有异常的,服务器能正确的解析Element参数,客户端也能正常提交。
   那么客户端应该也有不用自己手写序列化程序的方法。

问题1。同样的代码的 Element 对象,在别的普通的java项目里的 Element.toString能把Element的内容全都输出。
在cuss里就不行,输出是[根标签名:null]
环境:cuss里想使用webservice,把一个web服务的返回值设置为Element,服务器端就发现这个问题但并不影响web服务的运行——在ie中可以正常访问,
但在在java客户端中有异常。
异常详细情况见:WSClient异常.txt

测试把关键的类的类型都打印出来:
代码:
   System.out.println("USER:"+user);
   System.out.println("DocumentBuilderFactory:factory.getClass().getName() : "+factory.getClass().getName());
   System.out.println("DocumentBuilder:build.getClass().getName() : "+build.getClass().getName());
   System.out.println("Document:doc.getClass().getName() : "+doc.getClass().getName());
   System.out.println("Element:user.getClass().getName() : "+user.getClass().getName());
结果1:客户端
USER:user.toString() : <USER><ID>idw</ID><NAME>笑纹</NAME><STATE>1</STATE><DEPT>项目开发</DEPT></USER>
DocumentBuilderFactory:factory.getClass().getName() : org.apache.crimson.jaxp.DocumentBuilderFactoryImpl
DocumentBuilder:build.getClass().getName() : org.apache.crimson.jaxp.DocumentBuilderImpl
Document:doc.getClass().getName() : org.apache.crimson.tree.XmlDocument
Element:user.getClass().getName() : org.apache.crimson.tree.ElementNode
结果2:服务器(cuss)
USER:user.toString() : [USER: null]
DocumentBuilderFactory:factory.getClass().getName() : org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
DocumentBuilder:build.getClass().getName() : org.apache.xerces.jaxp.DocumentBuilderImpl
Document:doc.getClass().getName() : org.apache.xerces.dom.DocumentImpl
Element:user.getClass().getName() : org.apache.xerces.dom.ElementImpl

可见:在不同的项目里,通过工厂方法得到的对象的实际类型不同,导致了相同的代码在不同的项目里产生了不同的结果。
工厂方法封装了,返回不同的类型。
到底是什么导致了,返回值的不同?
解决:在cuss的webservice类里
用:
DocumentBuilderFactory factory = new org.apache.crimson.jaxp.DocumentBuilderFactoryImpl();
代替原来的:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         避免生成DocumentBuilderFactoryImpl类型的factory,运行结果就相同了。
关键:工厂类得到的DocumentBuilderFactory的类型不同造成的。
为什么会有这种类型不同那。因为:cuss生成的一系列的org.apache.xerces.dom类,在java项目里不可见。所以java项目里就会生成org.apache.crimson系列类。
把xerces-2.4.0.jar加入到java项目的类路径中得到结果如下。
DocumentBuilderFactory:factory.getClass().getName() : org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
得到的结果与cuss是一个类,但在构件DocumentBuilder的实例时发生java.lang.NoClassDefFoundError: org/w3c/dom/ranges/DocumentRange异常,
因为只导入了这一个包,还有包含org/w3c/dom/ranges/DocumentRange的包没有导进来。

 

问题2。通过TransformerFactory,把目标设置成System.out,可以把Element的内容输出到控制台。但有乱码。如果到文件里就没有乱码了。

问题3。在返回值是Element的情况下,为什么IE可以正常解析,而.java的客户端就会报错那
是因为没有正确的配置返回值的参数。

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
※解决返回值是org.w3c.dom.Element的最终解决方法:
※代码的获得方式:
※先建立测试的web项目,发布到tomcat上
※通过client stub,中的java org.apache.axis.wsdl.WSDL2Java -p client http://localhost:8080/WSServer/Fws2.jws?wsdl命令得到的
※得到client包,其中有4个文件,主要从Fws2SoapBindingStub.java里摘抄的代码:

   客户端正确的代码片段:
   Service sv = new Service();
   Call call = (Call) sv.createCall();
   call.setTargetEndpointAddress("http://localhost:7001/cuss/services/dlsstReportWS");

    //返回值是Element时需要添加的代码    开始
   call.setOperationName(new javax.xml.namespace.QName(
           "http://DefaultNamespace", "getReport"));
   call.setReturnQName(new javax.xml.namespace.QName(
           "http://xml./xml-soap", "Element"));
   call.setReturnClass(org.w3c.dom.Element.class);
   call.addParameter("op1", XMLType.XSD_STRING, ParameterMode.IN);
    //返回值是Element时需要添加的代码    结束

   Object[] wsargs = new Object[1];
   wsargs[0] = "00000";
   Object o = call.invoke(wsargs);
   System.out.println("o.getClass().getName() : "+o.getClass().getName());
   System.out.println(o);

其中
   call.setOperationName(new javax.xml.namespace.QName(
           "http://DefaultNamespace", "getReport"));
   call.setReturnQName(new javax.xml.namespace.QName(
           "http://xml./xml-soap", "Element"));
   call.setReturnClass(org.w3c.dom.Element.class);
   call.addParameter("op1", XMLType.XSD_STRING, ParameterMode.IN);
是以前没有的,调用invoke方法就不出
org.xml.sax.SAXException: SimpleDeserializer encountered a child element, which is NOT expected, in something it was trying to deserialize.
异常了,并能正确的获得对象。

其中
call.setReturnQName(new javax.xml.namespace.QName(
                     "http://xml./xml-soap", "Element"));
不是必须的,去掉了程序仍然可以运行成功
并且服务器端不需要显示声明(通过new 指定具体的类)DocumentBuilderFactory,还可以工厂方法。
虽然服务器的Element类与客户端的Element类型是不同的,但因为他们都实现了Element接口,所以可以运行通过。
cuss服务器端的Element类的实际类型:
user.getClass().getName():weblogic.apache.xerces.dom.ElementImpl
USER:[USER: null]
客户端得到的类型:
o.getClass().getName() : org.apache.crimson.tree.ElementNode2
<USER><ID>idw</ID><NAME>成功</NAME><STATE>1</STATE><DEPT>项目开发</DEPT></USER>
完全可以通过。
※※※※※※※※※※※※※※※※※※※※※※※
client stub封装了webservice的调用,从应用速度和减少学习坡度的角度讲,是非常有用的。

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
注意Axis的客户端调用和ie直接调用webservice是WebService客户端的不同实现。但都是符合规范的客户端。

注意:如果Element是参数那么setReturnClass和addParameter不是必须的。可以不写。
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

参考资料:
Nemo@Nona_name ? Blog Archive ? 关于Axis的client的一个例子.htm  
\Axis_Client获得复杂对象如ArrayList或org.w3c.Element\Nemo.htm    ——对call前参数设置比较详细的讲解

客户端异常

发生条件:WS返回值是org.w3c.dom.Element,在客户断调用就会出现这个问题。
    注意:1与返回值的声明没有关系。声明为Object实际返回的只要是Element就会出这个错误。
     2。返回值实际类型是String时读取完全正常。通过ie请求可以看到getReportReturn标记有xsi:type="soapenc:string" 属性。
      但是Element时则没有。
     3。WS在IE中的调用是完全正常的只是在.java写的客户端才会出现这个问题。
原因:初步估计是反序列化(Deserializer)的问题
   通过阅读\Axis_Client_Stub\成长的路上.htm->关于axis1.2中对象的序列化和发序列化 一文得知。AXIS的WS客户端在遇到Element这种对象的时候,就得自己编写serializer和deserializer
   不知道黄明伟当时怎么试出来的的。
解决:初步的解决方法是让ws返回Element转换成的String。
   但web中直接使用DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
   得到的Element的toString方法的输出值是错误的。用
   DocumentBuilderFactory factory = new org.apache.crimson.jaxp.DocumentBuilderFactoryImpl();
   代替。
   如果指定DocumentBuilderFactory后,不toString方法,客户端的问题依然存在。
   后可以使用Element.toString方法了。

   代替后客户端可以正常运行了。但结果有所变化:先边有比较。
   注意返回值的类型都发生了变化。
  

- Exception:
org.xml.sax.SAXException: SimpleDeserializer encountered a child element, which is NOT expected, in something it was trying to deserialize.
   at org.apache.axis.encoding.ser.SimpleDeserializer.onStartChild(SimpleDeserializer.java:145)
   at org.apache.axis.encoding.DeserializationContext.startElement(DeserializationContext.java:1035)
   at org.apache.axis.message.SAX2EventRecorder.replay(SAX2EventRecorder.java:165)
   at org.apache.axis.message.MessageElement.publishToHandler(MessageElement.java:1141)
   at org.apache.axis.message.RPCElement.deserialize(RPCElement.java:345)
   at org.apache.axis.message.RPCElement.getParams(RPCElement.java:384)
   at org.apache.axis.client.Call.invoke(Call.java:2467)
   at org.apache.axis.client.Call.invoke(Call.java:2366)
   at org.apache.axis.client.Call.invoke(Call.java:1812)
   at client.AxisClientT.main(AxisClientT.java:41)
AxisFault
   faultCode: {http://schemas./soap/envelope/}Server.userException
   faultSubcode:
   faultString: org.xml.sax.SAXException: SimpleDeserializer encountered a child element, which is NOT expected, in something it was trying to deserialize.
   faultActor:
   faultNode:
   faultDetail:
   {http://xml./axis/}stackTrace:org.xml.sax.SAXException: SimpleDeserializer encountered a child element, which is NOT expected, in something it was trying to deserialize.
   at org.apache.axis.encoding.ser.SimpleDeserializer.onStartChild(SimpleDeserializer.java:145)
   at org.apache.axis.encoding.DeserializationContext.startElement(DeserializationContext.java:1035)
   at org.apache.axis.message.SAX2EventRecorder.replay(SAX2EventRecorder.java:165)
   at org.apache.axis.message.MessageElement.publishToHandler(MessageElement.java:1141)
   at org.apache.axis.message.RPCElement.deserialize(RPCElement.java:345)
   at org.apache.axis.message.RPCElement.getParams(RPCElement.java:384)
   at org.apache.axis.client.Call.invoke(Call.java:2467)
   at org.apache.axis.client.Call.invoke(Call.java:2366)
   at org.apache.axis.client.Call.invoke(Call.java:1812)
   at client.AxisClientT.main(AxisClientT.java:41)

   {http://xml./axis/}hostname:kangxiaoguang

org.xml.sax.SAXException: SimpleDeserializer encountered a child element, which is NOT expected, in something it was trying to deserialize.
   at org.apache.axis.AxisFault.makeFault(AxisFault.java:101)
   at org.apache.axis.client.Call.invoke(Call.java:2470)
   at org.apache.axis.client.Call.invoke(Call.java:2366)
   at org.apache.axis.client.Call.invoke(Call.java:1812)
   at client.AxisClientT.main(AxisClientT.java:41)
Caused by: org.xml.sax.SAXException: SimpleDeserializer encountered a child element, which is NOT expected, in something it was trying to deserialize.
   at org.apache.axis.encoding.ser.SimpleDeserializer.onStartChild(SimpleDeserializer.java:145)
   at org.apache.axis.encoding.DeserializationContext.startElement(DeserializationContext.java:1035)
   at org.apache.axis.message.SAX2EventRecorder.replay(SAX2EventRecorder.java:165)
   at org.apache.axis.message.MessageElement.publishToHandler(MessageElement.java:1141)
   at org.apache.axis.message.RPCElement.deserialize(RPCElement.java:345)
   at org.apache.axis.message.RPCElement.getParams(RPCElement.java:384)
   at org.apache.axis.client.Call.invoke(Call.java:2467)
   ... 3 more

Element通过IE的返回结果:
<?xml version="1.0" encoding="UTF-8" ?>
- <soapenv:Envelope xmlns:soapenv="http://schemas./soap/envelope/" xmlns:xsd="http://www./2001/XMLSchema" xmlns:xsi="http://www./2001/XMLSchema-instance">
- <soapenv:Body>
- <getReportResponse soapenv:encodingStyle="http://schemas./soap/encoding/">
- <getReportReturn>
- <USER>
    <ID>idw</ID>
    <NAME>笑纹</NAME>
    <STATE>1</STATE>
    <DEPT>项目开发</DEPT>
    </USER>
    </getReportReturn>
    </getReportResponse>
    </soapenv:Body>
    </soapenv:Envelope>

Element指定DocumentBuilderFactory,不使用工厂方法后,通过IE的返回结果:
      <?xml version="1.0" encoding="UTF-8" ?>
   - <soapenv:Envelope xmlns:soapenv="http://schemas./soap/envelope/" xmlns:xsd="http://www./2001/XMLSchema" xmlns:xsi="http://www./2001/XMLSchema-instance">
   - <soapenv:Body>
   - <getReportResponse soapenv:encodingStyle="http://schemas./soap/encoding/">
     <getReportReturn xsi:type="soapenc:string" xmlns:soapenc="http://schemas./soap/encoding/"><USER><ID>idw</ID><NAME>笑纹</NAME><STATE>1</STATE><DEPT>项目开发</DEPT></USER></getReportReturn>
     </getReportResponse>
     </soapenv:Body>
     </soapenv:Envelope>


QName的定义:


与spring整合:
网络上有现成的方法。但过于麻烦。由于时间比较紧,采用直连数据库的方式,没有经过spring框架。

通过阅读spring-reference.pdf(1.15版英文)和spring-reference.pdf(1.1版 中文),还有源代码\spring-framework-1.1.5\samples\jpetstore得知,
   WebService可以与Spring结合在一起。
   ——有时间应该深入研究下去。

通过IE请求,和Flashget下载的到的WebService响应里,中文并不是中文
例如:返回如下:
   <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas./soap/envelope/" xmlns:xsd="http://www./2001/XMLSchema" xmlns:xsi="http://www./2001/XMLSchema-instance"><soapenv:Body><getAgentInfoResponse soapenv:encodingStyle="http://schemas./soap/encoding/"><getAgentInfoReturn><AGENTS><AGENT><GONGHAO>1001</GONGHAO><USER_NAME>座席员1</USER_NAME></AGENT><AGENT><GONGHAO>1002</GONGHAO><USER_NAME>座席员2</USER_NAME></AGENT><AGENT><GONGHAO>1003</GONGHAO><USER_NAME>座席员3</USER_NAME></AGENT><AGENT><GONGHAO>1005</GONGHAO><USER_NAME>用户名称</USER_NAME></AGENT><AGENT><GONGHAO>34sq33332</GONGHAO><USER_NAME>12f</USER_NAME></AGENT></AGENTS></getAgentInfoReturn></getAgentInfoResponse></soapenv:Body></soapenv:Envelope>
在IE中显示如下:
     <?xml version="1.0" encoding="UTF-8" ?>
   - <soapenv:Envelope xmlns:soapenv="http://schemas./soap/envelope/" xmlns:xsd="http://www./2001/XMLSchema" xmlns:xsi="http://www./2001/XMLSchema-instance">
   - <soapenv:Body>
   - <getAgentInfoResponse soapenv:encodingStyle="http://schemas./soap/encoding/">
   - <getAgentInfoReturn>
   - <AGENTS>
   - <AGENT>
     <GONGHAO>1001</GONGHAO>
     <USER_NAME>座席员1</USER_NAME>
     </AGENT>
   - <AGENT>
     <GONGHAO>1002</GONGHAO>
     <USER_NAME>座席员2</USER_NAME>
     </AGENT>
   - <AGENT>
     <GONGHAO>1003</GONGHAO>
     <USER_NAME>座席员3</USER_NAME>
     </AGENT>
   - <AGENT>
     <GONGHAO>1005</GONGHAO>
     <USER_NAME>用户名称</USER_NAME>
     </AGENT>
   - <AGENT>
     <GONGHAO>34sq33332</GONGHAO>
     <USER_NAME>12f</USER_NAME>
     </AGENT>
     </AGENTS>
     </getAgentInfoReturn>
     </getAgentInfoResponse>
     </soapenv:Body>
     </soapenv:Envelope>


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多