使用cxf的wsdl2java调用外部webservice提供的wsdl的步骤,使用过程中的问题与注意事项也做了相关总结。
一、可用的请求wsdl的webservice路径
服务器提供一个外部可调用的webservice的wsdl路径,在浏览器中可直接反问道wsdl文件,在soapUI中可测试每个请求的有效的路径(该webservice是已发布可工外部调用的有效请求)
二、下载配置Apache CXF提供的生成Client的工具
1.下载:
http://cxf.apache.org/download.html官网 下载apache-cxf-3.0.10.zip(或者别的压缩包,建议使用较新的工具包),将下载到的zip解压到本地某个文件下,如我解压到D盘的tool文件夹下
2.配置环境变量:
将cxf所在路径配置到环境变量中,如CXF_HOME=D:\tools\apache-cxf-3.0.10,在Path变量中添加;%CXF_HOME%\bin(讲cxf的bin目录配置到path中)。
运行cmd dos命令,输入wsdl2java -v,输出为wsdl2java - Apache CXF 3.0.10这种版本信息表示安装配置成功,否则则可能安装失败
三、使用wsdl2java的命令生成客户端代码
1,简单使用命令生成代码到某目录下:
可在本地手动切换到需要生成代码的目录下,在路径中输入cmd回车即转到该目录下——》wsdl2java -p '包名' -encoding UTF-8 https://XXX.XX.XXXService?wsdl 回车即可生成
-p 生成代码放置的包,命令中建议加上,方便直接放到项目目录下,默认的包可能不符java包的命名规则(如可能生成以java、org等包)
-encoding 建议加上,不指定编码可能导致生成的文件产生编码冲突的错误而无法直接使用
-autoNameResolution当有两个或者多个wsdl需要生成到同一个目录下时,再次运行命令行需加入此参数,如果wsdl中有相似相同的方法名或者引用了相同名称的类会提示“具有相同名称 "XXXX" 的类/接口已在使用。请使用类定制设置来解决此冲突。”,无法正常生成,在wsdl2java的命令中加上这段标示,标示每个wsdl生成类时都会生成一个唯一的Number,让同名的类也可生成。注意事项或出现ObjectFactory的错误时参考下面使用难点中的2即可解决。
四、使用难点
注意1:cxf所依赖的包比较坑爹,包引用的版本不对会出现非常多的问题
(ws的插件可以使用比较新的版本)
cxf的jar包依赖的版本如果出现问题会导致各种奇怪的报错:(因为cxf2.3.3所依赖的cxf-rt-frontend-jaxws、cxf-rt-transports-http-jetty都是2.2以上,如果这两个包是2.1hi报错)
jaxb-api使用的版本也不可过高
注意2:ObjectFactory conflicts
生成多个wsdl文档代码时,-autoNameResolution解决ObjectFactory类名称相同产生冲突时,会导致生成的ObjectFactory中只存在后执行生成命令的wsdl
的相关节点与方法,当再次调用之前生成的方法时,会报错说XXX,XX.XXService?wsdl 无法调用的错,简单的解决方式是讲之间生成的ObjectFactory的相关节
点与方法在被覆盖掉的ObjectFactory中粘贴一遍即可
参照解决方法:http://www.codeproject.com/Tips/145051/Apache-CXF-wsdl-java-Error
注意3:The lifecycle method [finalizeConfig] must not throw a checked exception
当想要在应用中调用service来完成相关逻辑,如果直接调用会报错类似The lifecycle method [finalizeConfig] must not throw a checked exception的错误,是因为在依赖中加入了
当使用main函数或者junit测试代码时可以加上这段,但调用时不可加入这段依赖
问题参考:https://issues.apache.org/jira/browse/CXF-5483
注意4:javax.xml.ws.WebServiceException: Unsupported endpoint address的错误
解决方法是在service中加入endpoint的设置或者在port中设置Provider的endpoint参数
参见:http://tugdualgrall.blogspot.jp/2009/02/jax-ws-how-to-configure-service-end_17.html
注意5:...can`t create a instance of XXX
http://stackoverflow.com/questions/7415659/instantiationexception-during-jaxb-unmarshalling-abstract-base-class-with-xml
五、成功案例
通过三生成的service可直接调用(XXXservice的注解为@WebServiceClient,注释中各种需要的参数都是已经生成的)
XXXService service=new XXXService(XXX.Service.WSDL_LOCATION);//WSDL_LOCATION是生成的类中已经赋值的路径http://XXX.XXX.XXService?wsdl
XXXPortType port=service.getXXXEndpoint();
//如果请求的wsdl有Bisic Authentication的认证,需要加下面这段
((BindingProvider) port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "username");
((BindingProvider) port).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "password");
//然后直接调用port中的方法,即可拿到数据
port.getCaptcha().getImagePath().getValue();
---------------------案例中使用的是wso2提供的的webservice
wsdl:
https://ids-dev.zhishinet.com:9443/services/UserInformationRecoveryService?wsdl
https://ids-dev.zhishinet.com:9443/services/RemoteUserStoreManagerService?wsdl
用户:admin
密码:admin
忘记密码:
getUserList("http://wso2.org/claims/mobile",18666666666,null)
有用户名,验证验证码
VerificationBean ver = user.verifyUser(userName, null);
VerificationBean ver2 = user.sendRecoveryNotification(userName, ver.key, "");
VerificationBean ver3 = user.verifyConfirmationCode(userName, ver2.notificationData.notificationCode, null);
VerificationBean ver4 = user.updatePassword(userName, ver3.key, password);
修改密码:
updateCredential