一、.Net vs Java
相比较于java,.net体系下的WebService,选择更单一,用ms的就好,直接用ide导入webservice。玩java的话,axis1,axis2,ide导入,wsimport命令生成,还有wsdl2java命令。
二、厂商之争
就实战经验来看,不同的厂商对soap的实现,还有差异。.net发起的soap报文是开头,而java发起soap发起了soapenv报文。导致跨平台调用的时候出现问题。
方案一 ide导入
直接使用eclipse导入WebService,同样的方式导入,STS却导入不了。所以实操过程中,选择eclipse导入。针对java平台的WebService调用,调用正常。但是调用一个神秘的WebService,一直报soap报文格式不对。如果没有记错的话,当时eclipse导入WebService,生成的是axis1的实现。网查axis1对于soap请求头处理,就是一个Bug。所以方案一,被丢掉了。
方案二 前辈方案+axis2
想着axis1搞不了的事情,兴许axis2能做。当被告之有方案借鉴时,感觉看到了希望。不过,没有看到操作手册,也不知道代码是怎么生成的。从包引用上来讲,用的是axis2,这个就是为什么有axis2方案尝试的原因了。也是迷惑人的地方。因为引入的包,压根没有使用到。但是从代理类的生成风格上来讲,还是具备排版精良的影响。使用axis2的代理类生成工具,生成完代理类之后,吓死了,感觉生成的代码就是一团芝麻糊,于是,直接丢掉了。为什么别人生成的axis2代理类这么优秀,而我生成的惨不忍睹?
方案三 wsimport方案
绕了半圈,回到了java sdk自带的wsimport,直接在命令行输入wsimport,会有提示。存放代理类的文件夹不存在的话,还不给生成,这个有点小小的坑!
<span class="code-snippet_outer">D:\>wsimport</span><span class="code-snippet_outer">缺少 WSDL_URI</span><span class="code-snippet_outer"></span><span class="code-snippet_outer"></span><span class="code-snippet_outer">用法: wsimport [options] <span class="code-snippet__tag"><<span class="code-snippet__name">WSDL_URI</span>></span></span><span class="code-snippet_outer"></span><span class="code-snippet_outer">\其中 [options] 包括:</span><span class="code-snippet_outer"> -b <span class="code-snippet__tag"><<span class="code-snippet__name">path</span>></span> 指定 jaxws/jaxb 绑定文件或附加模式</span><span class="code-snippet_outer"> (每个 <span class="code-snippet__tag"><<span class="code-snippet__name">path</span>></span> 都必须具有自己的 -b)</span><span class="code-snippet_outer"> -B<span class="code-snippet__tag"><<span class="code-snippet__name">jaxbOption</span>></span> 将此选项传递给 JAXB 模式编译器</span><span class="code-snippet_outer"> -catalog <span class="code-snippet__tag"><<span class="code-snippet__name">file</span>></span> 指定用于解析外部实体引用的目录文件</span><span class="code-snippet_outer"> 支持 TR9401, XCatalog 和 OASIS XML 目录格式。</span><span class="code-snippet_outer"> -d <span class="code-snippet__tag"><<span class="code-snippet__name">directory</span>></span> 指定放置生成的输出文件的位置</span><span class="code-snippet_outer"> -encoding <span class="code-snippet__tag"><<span class="code-snippet__name">encoding</span>></span> 指定源文件所使用的字符编码</span><span class="code-snippet_outer"> -extension 允许供应商扩展 - 不按规范</span><span class="code-snippet_outer"> 指定功能。使用扩展可能会</span><span class="code-snippet_outer"> 导致应用程序不可移植或</span><span class="code-snippet_outer"> 无法与其他实现进行互操作</span><span class="code-snippet_outer"> -help 显示帮助</span><span class="code-snippet_outer"> -httpproxy:<span class="code-snippet__tag"><<span class="code-snippet__name">host</span>></span>:<span class="code-snippet__tag"><<span class="code-snippet__name">port</span>></span> 指定 HTTP 代理服务器 (端口默认为 8080)</span><span class="code-snippet_outer"> -keep 保留生成的文件</span><span class="code-snippet_outer"> -p <span class="code-snippet__tag"><<span class="code-snippet__name">pkg</span>></span> 指定目标程序包</span><span class="code-snippet_outer"> -quiet 隐藏 wsimport 输出</span><span class="code-snippet_outer"> -s <span class="code-snippet__tag"><<span class="code-snippet__name">directory</span>></span> 指定放置生成的源文件的位置</span><span class="code-snippet_outer"> -target <span class="code-snippet__tag"><<span class="code-snippet__name">version</span>></span> 按给定的 JAXWS 规范版本生成代码</span><span class="code-snippet_outer"> 默认为 2.2, 接受的值为 2.0, 2.1 和 2.2</span><span class="code-snippet_outer"> 例如, 2.0 将为 JAXWS 2.0 规范生成兼容的代码</span><span class="code-snippet_outer"> -verbose 有关编译器在执行什么操作的输出消息</span><span class="code-snippet_outer"> -version 输出版本信息</span><span class="code-snippet_outer"> -wsdllocation <span class="code-snippet__tag"><<span class="code-snippet__name">location</span>></span> @WebServiceClient.wsdlLocation 值</span><span class="code-snippet_outer"> -clientjar <span class="code-snippet__tag"><<span class="code-snippet__name">jarfile</span>></span> 创建生成的 Artifact 的 jar 文件以及</span><span class="code-snippet_outer"> 调用 Web 服务所需的 WSDL 元数据。</span><span class="code-snippet_outer"> -generateJWS 生成存根 JWS 实现文件</span><span class="code-snippet_outer"> -implDestDir <span class="code-snippet__tag"><<span class="code-snippet__name">directory</span>></span> 指定生成 JWS 实现文件的位置</span><span class="code-snippet_outer"> -implServiceName <span class="code-snippet__tag"><<span class="code-snippet__name">name</span>></span> 生成的 JWS 实现的服务名的本地部分</span><span class="code-snippet_outer"> -implPortName <span class="code-snippet__tag"><<span class="code-snippet__name">name</span>></span> 生成的 JWS 实现的端口名的本地部分</span><span class="code-snippet_outer"></span><span class="code-snippet_outer">\扩展:</span><span class="code-snippet_outer"> -XadditionalHeaders 映射标头不绑定到请求或响应消息不绑定到</span><span class="code-snippet_outer"> Java 方法参数</span><span class="code-snippet_outer"> -Xauthfile 用于传送以下格式的授权信息的文件:</span><span class="code-snippet_outer"> http://username:password@example.org/stock?wsdl</span><span class="code-snippet_outer"> -Xdebug 输出调试信息</span><span class="code-snippet_outer"> -Xno-addressing-databinding 允许 W3C EndpointReferenceType 到 Java 的绑定</span><span class="code-snippet_outer"> -Xnocompile 不编译生成的 Java 文件</span><span class="code-snippet_outer"> -XdisableAuthenticator 禁用由 JAX-WS RI 使用的验证程序,</span><span class="code-snippet_outer"> 将忽略 -Xauthfile 选项 (如果设置)</span><span class="code-snippet_outer"> -XdisableSSLHostnameVerification 在提取 wsdl 时禁用 SSL 主机名</span><span class="code-snippet_outer"> 验证</span><span class="code-snippet_outer"></span><span class="code-snippet_outer">\示例:</span><span class="code-snippet_outer"> wsimport stock.wsdl -b stock.xml -b stock.xjb</span><span class="code-snippet_outer"> wsimport -d generated http://example.org/stock?wsdl</span>
照着命令行的提示来,就能生成代理类了。
采用wsimport生成的代理类竟然跟4年前同事留下的对接项目代码是一样的,于是修改就有着落了。实战证明,前辈们留下的代码管用。关键的代码就是自己实现一个报文处理的Handler,然后在Soap代理类调用时,先设置Handler!
<span class="code-snippet_outer">wsInstance = <span class="code-snippet__keyword">new</span> WS();</span><span class="code-snippet_outer"> wsInstance.setHandlerResolver(portInfo -> {</span><span class="code-snippet_outer"> List<Handler> handlerList = <span class="code-snippet__keyword">new</span> ArrayList<>();</span><span class="code-snippet_outer"> handlerList.<span class="code-snippet__keyword">add</span>(<span class="code-snippet__keyword">new</span> SOAPEnvelopeHandler());</span><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> handlerList;</span><span class="code-snippet_outer"> });</span>
关注本公众号,输入soap获得SOAPEnvelopeHandler详细讲解。
方案不足之处
采用wsimport生成的代理类指定了wsdl位置,这个看起来怪怪,但是这种方案能修改soap请求报文,可以默认接受了这个让人心头有点痒痒的方案。
WebService优化
采用单例优先代练类的创建,能提升压测值。在未使用单例优化时,空接口也无法通过5000/min压测,采用单例优化后,可以通过。最终的优化方案为:
- 能缓存的,使用redis缓存60秒。过压测。
- 不能缓存的,过不了压测,限制每分钟调用频率。
受控环境下的WebService联调技术
如果开发机器不能直接调用对方的WebService,如何进行快速联调呢?关注本公众号,回复信息wsdebug,获取实战经验分享。
WebService与区服切换
回复信息switcharea,获取实战经验分享。
思考
今天的思考题:sonarqube报很多漏洞很多bug的代码是不是好代码?请留下您的思考答案。
结束语
WebService从诞生到现在,越来越不受待见了,越来越多的人喜欢采用更轻量级的WebAPI来代替WebService,采用JSON,采用更加透明的跨平台方案。但是WebService并没有死,因为生成代码还是一个优点。如果再次在java平台下对接WebService,请优先考虑jdk自带的wsimport进行代理类生成,可通过自定义SOAPHandler达到更好的兼容性。如有更好的方法,请留言告之。
关注公众号 看同行经验分享

发表回复
要发表评论,您必须先登录。