加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

天气预报

发布时间:2020-12-17 00:07:27 所属栏目:安全 来源:网络整理
导读:实战 CXF 调用 Webxml 天气预报服务 今晚群里的 kasasis 同学问我会不会使用 CXF 调用 http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl 这个天气预报的 WebService 服务 ; 我也是初学者 ,? 在尝试调用的过程中发现不少问题 ,? 也有一些小

实战CXF调用Webxml天气预报服务

今晚群里的kasasis同学问我会不会使用CXF调用

http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

这个天气预报的WebService服务;

我也是初学者,?在尝试调用的过程中发现不少问题,?也有一些小心得,?希望与大家分享,?更希望大家可以帮我解惑.

.初探:通过wsdl2java生成调用远程服务所需要的java

因为还没有成功使用dynamic-clients(http://cxf.apache.org/docs/dynamic-clients.html)的方式动态调用过WebService服务,?所以决定使用CXF提供的wsdl2java来生成调用WebService服务所必须的java,?进而使用JaxWsServerFactoryBean来调用WebService服务:

遗憾的是,?CXF?wsdl2java报错了:

?

view source
print ?
1 undefined element declaration 's:schema'
2 ??
3 at line 85 column 41 of schema

?http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

将该wsdl下载下来,?使用MyEclipse?9.0打开并查看,?也提示了这一错误:

view source
print ?
1 src-resolve.4.2: Error resolving component 's:schema'.?
2 ??
3 It was detected that 's:schema' is in namespace 'http://www.w3.org/2001/XMLSchema',but components from this namespace are not referenceable from schema document 'file:///D:/workspace/workspace_j2ee/CXFWeatherTest/src/WeatherWebService.asmx.original.wsdl'.?
4 ??
5 If this is the incorrect namespace,perhaps the prefix of 's:schema' needs to be changed.?
6 ??
7 If this is the correct namespace,then an appropriate 'import' tag should be added to 'file:///D:/workspace/workspace_j2ee/CXFWeatherTest/src/WeatherWebService.asmx.original.wsdl'.

wsdl报错部分内容如下(下边代码红色部分):

view source
print ?
01 <s:element name="getSupportDataSetResponse">
02 ??
03 ????<s:complexType>
04 ??
05 ????????<s:sequence>
06 ??
07 ????????????<s:element?
08 ??
09 ????????????????minOccurs="0"?
10 ??
11 ????????????????maxOccurs="1"
12 ??
13 ????????????????name="getSupportDataSetResult">
14 ??
15 ????????????????<s:complexType>
16 ??
17 ????????????????????<s:sequence>

view source
print ?
1 ????????????????????????<s:element ref="s:schema" />
view source
print ?
01 ????????????????????????<s:any />
02 ??
03 ????????????????????</s:sequence>
04 ??
05 ????????????????</s:complexType>
06 ??
07 ????????????</s:element>
08 ??
09 ????????</s:sequence>
10 ??
11 ????</s:complexType>
12 ??
13 </s:element>

作为初学者,?曾在风中叶老师的视频中学习过关于schemaDTD的一些知识,?但还没修炼到能解决这一错误的程度,?也期待各位同学的积极探索并给出答案;

问题催人奋进,?折衷的办法总是有的:

<s:any/>既然可以代表任何元素,?为什么不能代表<s:element?ref="xxx"/>元素呢??于是乎,?愤然删除<s:element?ref="s:schema"?/>,?勉强算是通过了CXF提供的wsdl验证工具wsdlvalidator的验证;

Ok,?继续之前的步骤,?通过wsdl2java来生成调用远程WebService服务所需要的java;

一切顺利,?生成的类的目录结构如下:

?

.使用JaxWsProxyFactoryBean调用天气服务

本工程使用的jar包如下图示:

通过JaxWsProxyFactoryBean调用webService服务的过程相信大家都很熟悉了,?具体代码如下:

view source
print ?
01 package cn.com.client;
02 ??
03 import java.util.List;
04 ??
05 import org.apache.cxf.interceptor.LoggingInInterceptor;
06 ??
07 import org.apache.cxf.interceptor.LoggingOutInterceptor;
08 ??
09 import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
10 ??
11 import cn.com.webxml.ArrayOfString;
12 ??
13 import cn.com.webxml.WeatherWebServiceSoap;
14 ??
15 public class Test {
16 ??
17 ????public static void main(String[] args) throws Exception {
18 ??
19 ????????JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
20 ??
21 ????????factory.getInInterceptors().add(new LoggingInInterceptor());
22 ??
23 ????????factory.getOutInterceptors().add(new LoggingOutInterceptor());?
24 ??
25 ????????factory.setAddress(
26 ??
27 ????????????????"http://www.webxml.com.cn/WebServices/WeatherWebService.asmx");
28 ??
29 ????????factory.setServiceClass(WeatherWebServiceSoap.class);?
30 ??
31 ????????WeatherWebServiceSoap client =
32 ??
33 ????????????????(WeatherWebServiceSoap) factory.create();
34 ??
35 ????????ArrayOfString o = client.getWeatherbyCityName("南阳");
36 ??
37 ????????List<String> strList = o.getString();
38 ??
39 ????????for (String str : strList) {
40 ??
41 ????????????System.out.println(str);
42 ??
43 ????????}
44 ??
45 ????}
46 ??
47 }

?运行还算顺利,?得到的结果如下:

信息:?Outbound?Message

---------------------------

ID:?1

Address:?http://www.webxml.com.cn/WebServices/WeatherWebService.asmx

Encoding:?UTF-8

Content-Type:?text/xml

Headers:?{Accept=[*/*],?SOAPAction=["http://WebXml.com.cn/getWeatherbyCityName"]}

Payload:

<soap:Envelope?xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

<soap:Body>

<getWeatherbyCityName?xmlns="http://WebXml.com.cn/">

<theCityName>南阳</theCityName>

</getWeatherbyCityName>

</soap:Body>

</soap:Envelope>

河南

南阳

57178

57178.jpg

2012-4-5?22:58:11

11℃/24℃

46日?晴

无持续风向微风

0.gif

0.gif

今日天气实况:气温:16℃;风向/风力:北风?0级;湿度:53%;空气质量:较差;紫外线强度:中等

穿衣指数:建议着薄型套装等春秋过渡装。年老体弱者宜着套装。但昼夜温差较大,注意适当增减衣服。

感冒指数:昼夜温差较大,较易发生感冒,请适当增减衣服。体质较弱的朋友请注意防护。

运动指数:天气较好,赶快投身大自然参与户外运动,尽情感受运动的快乐吧。

洗车指数:适宜洗车,未来持续两天无雨天气较好,适合擦洗汽车,蓝天白云、风和日丽将伴您的车子连日洁净。

晾晒指数:天气不错,适宜晾晒。赶紧把久未见阳光的衣物搬出来吸收一下太阳的味道吧!

旅游指数:天气晴朗,风和日丽,温度适宜,是个好天气哦。这样的天气很适宜旅游,您可以尽情地享受大自然的风光。

路况指数:天气较好,路面比较干燥,路况较好。

舒适度指数:温度适宜,风力不大,您在这样的天气条件下,会感到比较清爽和舒适。

空气污染指数:气象条件较不利于空气污染物稀释、扩散和清除,请适当减少室外活动时间。

紫外线指数:属中等强度紫外线辐射天气,外出时建议涂擦SPF高于15PA+的防晒护肤品,戴帽子、太阳镜。

11℃/24℃

47日?晴

无持续风向微风

0.gif

0.gif

10℃/23℃

48日?阴转多云

无持续风向微风

2.gif

1.gif

南阳市位于河南省西南部,北靠伏牛山,东扶桐柏山,西依秦岭,南临汉江。气候属南北过渡带,四季分明。这里土地肥沃,雨量充沛。现辖1210县,总面积266万平方公里,人口1055万。南阳是历史文化名城。早在南召猿人就在这里生息繁衍。战国时期,是全国著名的冶铁中心,西汉时为全国六大都会之一,商遍天下,富冠海内,东汉为光武帝刘秀发迹之地,故称南都…‘帝乡。南阳曾培养和造就出著名谋略家、商圣范蠢,科圣张衡,医圣张仲景,杰出的政治家、军事家诸葛亮等举世间名的历史人物。1948年,毛泽东主席为庆祝南阳解放,亲笔写下《中原我军占领南阳》的光辉篇章。今日的南阳,是一座现代化新城。南阳市中心城区建成区面积为40平方公里,人口43万。城市环境优美,街道清洁宽敞,高楼大厦林立。北京大道、工业路、人民路、新华路等主于道纵横交错,道路成网;南阳宾馆。梅溪宾馆、豫宛宾馆等各类星级宾馆为八方宾客提供优美舒适的服务;南阳商场、金汉丰商厦、南阳亚细亚商厦等大型购物中心,向海内外朋友显示出南阳商贸发达的新景象。被称为中国之最的南阳沼气工程,日产沼气40万立方米,可满足2万用户居民用气。全市具有较高审美价值和文化价值的名胜古迹40多处,每天吸引着大量中外游人。景观:武候祠,内乡,天心洞,内乡县衙,张仲景墓与医圣祠张衡墓,汉画像石馆,桐柏淮源,宝天墁自然保护区,九龙沟,丹江口水库,西峡,伏牛山,水帘洞,白河

.使用JaxWsDynamicClientFactory调用天气服务

CXF关于Dynamic-clients的介绍文档见:

http://cxf.apache.org/docs/dynamic-clients.html;

很简洁的一段官方示例代码:

view source
print ?
1 JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
2 ???
3 Client client = dcf.createClient("echo.wsdl");
4 ???
5 Object[] res = client.invoke("echo","test echo");
6 ???
7 System.out.println("Echo response: " + res[0]);

但具体的调用过程并非一帆风顺;?让人不解的是,?即使调用自己所创建的WebService,?使用动态方式调用也不能成功,?总会提示一个异常:

view source
print ?
01 Exception in thread "main" java.lang.IllegalStateException: Unable to write generated Java files for schemas: null
02 ???
03 at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:351)
04 ???
05 at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:234)
06 ???
07 at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:227)
08 ???
09 at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:182)
10 ???
11 at com.client.Test.dynamicStudent(Test.java:30)
12 ???
13 at com.client.Test.main(Test.java:38)
14 ???
15 Caused by: java.lang.reflect.UndeclaredThrowableException
16 ???
17 at $Proxy29.build(Unknown Source)
18 ???
19 at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:349)
20 ???
21 ... 5 more
22 ???
23 Caused by: java.lang.NoSuchMethodException:?
24 ???
25 com.sun.codemodel.internal.JCodeModel.build(java.lang.Object)
26 ???
27 at java.lang.Class.getMethod(Class.java:1605)
28 ???
29 at org.apache.cxf.common.util.ReflectionInvokationHandler.invoke(ReflectionInvokationHandler.java:50)
30 ???
31 ... 7 more

异常信息的最后一个Caused?by给了我线索:

java.lang.NoSuchMethodException:?

com.sun.codemodel.internal.JCodeModel.build(java.lang.Object)

遍历工程所用jar文件,?居然没有找到internal包下的类JCodeModel;

但报的异常是NoSuchMethodException,?而不是ClassNotFoundException,?表明该类是存在的,?可能包路径发生了变化,?STFG(search?the?fUcking?google.?陈皓老师的博文学到的?-?-?),?最终发现该类现存在于jaxb-xjc-2.2.4-1.jar,?包路径为com.sun.codemodel,?而不是异常中所提示的com.sun.codemodel.internal;

为什么会这样??难道是我的jaxb-xjc?jar包的版本不对??

遂通过http://jaxb.java.net/,?对比jaxb2.0.1?--?2.2.5之间的所有版本,?均没有找到包com.sun.codemodel.internal...

Ok,?让我们继续查找jaxb1.x版本的jar;

幸运的是,?在页面http://jaxb.java.net/nonav/2.0.1/docs/jaxb-1_0.html?,?终于有所发现:

JAXB?2.0?is?backwards?compatible?with?JAXB?1.0?-?you?can?deploy?your?existing?1.0?applications?on?the?2.0?runtime?(provided?that?you?also?bundle?the?jaxb1-impl.jar)?and?they?should?run?without?modification.?

查看我的项目的类库,?刚好缺少了这么一个jaxb-impl.jar,?加上该包(我使用的是jaxb-impl-2.2.4-1.jar),?再次运行动态调用天气预报WebService的服务,?Congratulations!?这个异常被干掉了!?

但是,?不要高兴的太早,?服务并没有调用成功,?因为又回到了最开始遇到的问题:

<s:element?ref="s:schema"?/>,

undefined?element?declaration?'s:schema'

?at?line?85?column?41?of?schema?

http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

具体调用代码如下:

view source
print ?
01 package com.client;
02 ???
03 import org.apache.cxf.endpoint.Client;
04 ???
05 import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
06 ???
07 public class Test {
08 ???
09 ????public static void main(String[] args) throws Exception {
10 ???
11 ????????JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
12 ???
13 ????????Client client = dcf.createClient(
14 ???
15 ????????????"http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl");
16 ???
17 ????????Object[] res = client.invoke("getSupportProvince");
18 ???
19 ????????System.out.println("Echo response: " + res[0]);?
20 ??
21 ????}
22 ???
23 }

值得欣慰的是,?在补充了jaxb-impl-2.2.4-1.jar之后,?可以通过动态方式成功调用自己创建的WebService服务了,?详见下节;

.使用JaxWsDynamicClientFactory动态调用自己创建的WebService服务

服务接口及实现类很简单:

接口?com.service.StudentService:

view source
print ?
01 package com.service;
02 ???
03 import javax.jws.WebParam;
04 ???
05 import javax.jws.WebService;
06 ???
07 @WebService
08 ???
09 public interface StudentService {
10 ???
11 ????String helloStudent(@WebParam(name="text")String name);
12 ???
13 }

实现类?com.service.impl.StudentServiceImpl:

view source
print ?
01 package com.service.impl;
02 ???
03 import javax.jws.WebService;
04 ???
05 import com.service.StudentService;
06 ???
07 @WebService(endpointInterface="com.service.StudentService",targetNamespace="http://service.com/")
08 ???
09 public class StudentServiceImpl implements StudentService{
10 ???
11 ????public String helloStudent(String name) {
12 ???
13 ????????return "hello " + name;
14 ???
15 ????}
16 ???
17 }

server:?com.jettyServer.ServerForJetty:

view source
print ?
01 package com.jettyServer;
02 ???
03 import javax.xml.ws.Endpoint;
04 ???
05 import com.service.impl.StudentServiceImpl;
06 ???
07 public class ServerForJetty {
08 ???
09 ????public static void main(String[] args) throws InterruptedException {
10 ???
11 ????????StudentServiceImpl implementor = new StudentServiceImpl();
12 ???
13 ????????String address = "http://localhost:9000/student";
14 ???
15 ????????Endpoint.publish(address,implementor);
16 ???
17 ????}
18 ???
19 }

client:com.client.Test?

view source
print ?
01 package com.client;
02 ???
03 import org.apache.cxf.endpoint.Client;
04 ???
05 import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
06 ???
07 public class Test {
08 ???
09 ????public static void main(String[] args) throws Exception {
10 ???
11 ????????JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
12 ???
13 ?????????
view source
print ?
1 ????????Client client = dcf.createClient("http://localhost:9000/student?wsdl");?
2 ??
3 ????????Object[] res = client.invoke("helloStudent","LeeThinker");?
4 ??
5 ????????System.out.println("Echo response: " + res[0]);
6 ???
7 ????}
8 ???
9 }

先启动JettyServer,?后访问http://localhost:9000/student?wsdl,?成功刷新出wsdl,?Ok,?服务顺利启动!

再执行Testmain方法,?Congratulations!?这次真正使用Dynamic的方式,?在不需要通过wsdl2java生成客户端java类文件的情况下,?成功调用WebService服务!

至于不能通过这种方式成功调用

http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

的问题,?还需要在进一步学习SchemaDTD的知识才能解答;

.小结:

虽未能通过Dynamic的方式成功调用天气预报服务,?好歹wsdl2java生成客户端调用类

的方式是可行的.

.其他问题:

6.1.@WebService声明问题

".使用JaxWsDynamicClientFactory调用自己创建的WebService服务"

自定义服务接口的实现类com.service.impl.StudentServiceImpl的类声明之前,?仅注释声明了@WebService,?没有后边(endpointInterface="com.service.StudentService",?

targetNamespace="http://service.com/"),?这时使用动态代理方式调用该服务时,?会发生异常:

Exception?in?thread?"main"?

org.apache.cxf.common.i18n.UncheckedException:?No?operation?was? found?with?the?name?{http://impl.service.com/}helloStudent.

大概还是因为WSDL的基础知识不够过硬吧,?STFG,?

http://lost-alien.iteye.com/blog/1175859?找到答案:

com.service.impl.StudentServiceImpl的类声明之前,?正确注释了

@WebService(

endpointInterface="com.service.StudentService",? targetNamespace="http://service.com/")之后,

再使用动态方式调用该服务,?一切顺利!

具体原因还有待分析,?认识和理解!

6.2.关于CXF?wsdl2java生成的调用远程服务的客户端java类文件

".使用JaxWsDynamicClientFactory调用自己创建的WebService服务"中所描述的自定义WebService服务中,?若使用JaxWsServerFactoryBean的调用方式,?那么首先需要通过wsdl2java生成客户端必需的java类文件;

将通过自己的wsdl生成的客户端java类文件的目录结构&类名称,?

wsdl2java?http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl?

这个wsdl文件后生成的java类文件的目录结构&类名称,?对比之后,?发现差距明显:

对比可以清楚的看到,?自己的wsdl生成的客户端类文件,?java类文件名及其混乱,?始终没能弄懂为什么会这样??还请各位同学多多指教!?

http://my.oschina.net/bayer/blog/52490

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读