java调用WebService(一)

这篇具有很好参考价值的文章主要介绍了java调用WebService(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文章目录

目录

文章目录

背景:

通过一个实例来认识webservice

服务端

客户端

WebService的一些概念

踩坑之旅

务必保证提供方的wsdl可以通过浏览器打开

sap提供的wsdl

wsdl鉴权问题

wsimport使用authfile

方法重名

解决方案

参数问题

鉴权:

参数:

注意点


背景:

因工作需要和一个Sap相关系统以WebService的方式进行接口联调,之前仅听过这种技术,但并没有实操过,所以将本次开发相关的踩坑进行记录

通过一个实例来认识webservice

服务端

首先我们先写一个简单的接口,不同于一般的接口就是我们要使用@WebService,以及需要将这个接口进行发布

public interface ExampleService {
    String sayHi(String request);
}
@WebService
public class ExampleServiceImpl implements ExampleService{
    @Override
    public String sayHi(String request) {
        return "request:"+request+"response:hi";
    }
}
public class ExampleServe {
    public static void main(String[] args) {
        //接口发布的地址
        Endpoint.publish("http://localhost:8080/example",new ExampleServiceImpl());
        //查看WebService服务是否启动  url+?wsdl
        //http://localhost:8080/example?wsdl是否能显示
        System.err.println("服务发布成功");
    }
}

然后,通过请求http://localhost:8080/example?wsdl我们可以看到下面这个xml结构的文档

<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://summary.webservice.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="ExampleServiceImplService" targetNamespace="http://summary.webservice.com/">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://summary.webservice.com/" elementFormDefault="unqualified" targetNamespace="http://summary.webservice.com/" version="1.0">
<xs:element name="sayHi" type="tns:sayHi"/>
<xs:element name="sayHiResponse" type="tns:sayHiResponse"/>
<xs:complexType name="sayHi">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="sayHiResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="sayHiResponse">
<wsdl:part element="tns:sayHiResponse" name="parameters"> </wsdl:part>
</wsdl:message>
<wsdl:message name="sayHi">
<wsdl:part element="tns:sayHi" name="parameters"> </wsdl:part>
</wsdl:message>
<wsdl:portType name="ExampleServiceImpl">
<wsdl:operation name="sayHi">
<wsdl:input message="tns:sayHi" name="sayHi"> </wsdl:input>
<wsdl:output message="tns:sayHiResponse" name="sayHiResponse"> </wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ExampleServiceImplServiceSoapBinding" type="tns:ExampleServiceImpl">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="sayHi">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="sayHi">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="sayHiResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ExampleServiceImplService">
<wsdl:port binding="tns:ExampleServiceImplServiceSoapBinding" name="ExampleServiceImplPort">
<soap:address location="http://localhost:8080/example"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

客户端

接下来我们通过jdk自带的wsimport命令自动将wsdl解析为我们熟悉的java调用类

执行下述命令,wsimport具体参数见附录

wsimport -s ./src/main/java/ -p com.webservice.summary.client  -encoding utf-8 http://localhost:8080/example\?wsdl 

写一个客户端类,在确保上面编写的server启动的情况下,执行就会获得调用结果

public class ExampleClient {
    public static void main(String[] args) {
        ExampleServiceImplService exampleServiceImplService=new ExampleServiceImplService();
        ExampleServiceImpl exampleServiceImplPort = exampleServiceImplService.getExampleServiceImplPort();
        String result = exampleServiceImplPort.sayHi("这是参数");
        System.out.println(result);
    }
}

总的来说,其实很简单,甚至具体业务中我们作为调用方并不需要编写和发布service,只需要将服务方暴露的wsdl文件或者地址进行转换,进行调用就好了。

WebService的一些概念

官方的概念感兴趣的可以自己了解

https://en.wikipedia.org/wiki/Web_service

https://baike.baidu.com/item/Web%20Service/1215039?fromtitle=webservice&fromid=2342584&fr=aladdin

在我看来,其实就是一种通信的解决方案,如Dubbo一样,处理应用通信的问题。核心包含wsdl和soap;

wsdl文件其实就是xml格式的文件,它定义了服务的相关信息,而soap目前我只清楚是一种协议,包含soap1.1和soap1.2版本,这两个版本影响了我们服务发布和调用的版本

踩坑之旅

这次对接的系统,使用的sap管理和发布webservice服务的,由于我是初次应用webservice,加之他们内网鉴权限制、WSDL鉴权以及接口鉴权,中间一度很不美妙,

务必保证提供方的wsdl可以通过浏览器打开

sap提供的wsdl

sap提供的wsdl不是普通的以?wsdl结尾的链接,而是一个结构类似于下面这个链接的格式http://*******.com:8001/sap/bc/srt/wsdl/flv_10002A111AD1/bndg_url/sap/bc/srt/rfc/sap/yws_get_str/200/yws_get_str/yws_get_str?sap-client=200(网上随便找的)

当时我直接拿着这个链接替换了上面wsimport命令最后的链接,结果竟然报错了;不过好在对方还提供了wsdl文件,结果我将链接替换为文件仍然还是这个错

无法读取 WSDL 文档:*******
原因为 1) 找不到文档; 2) 无法读取文档; 3) 文档的根元素不是 <wsdl:definitions>。
[ERROR] failed.noservice=在提供的 WSDL 中找不到 wsdl:service: 
需要至少提供一个 WSDL, 该 WSDL 至少具有一个服务定义。

在我将自己的文件和他们给的文件多次对比后发现,他们所提供的文件,很多<wsdl前面都有一个-,网络上只找到一个类似的案例,但并没有什么参考意义,本能的我认为这像是注释一样的符号应该删掉,于是我将所有-删除,再次尝试

-<wsdl

结果出现了新的错误,在这里这个错误先按下不表,下面还会出现

(这里我在写这篇文档复现时,报的错和上图不一样,错误: 类重复: com.webservice.summary.client.TESTTESTNew,但很相似,不清楚是不是jdk版本的缘故)

在和对面几次沟通之后,对方提供了一套账号密码,同时提供了代理ip(之前都是无法通过浏览器打开的),但是文件里为什么有-,他们确实不清楚

wsdl鉴权问题

由于存在账号密码,所以我们必须使用指定的参数

wsimport使用authfile

wsimport -Xauthfile sap.txt  http://*******.com:8001/sap/bc/srt/wsdl/flv_10002A111AD1/bndg_url/sap/bc/srt/rfc/sap/yws_get_str/200/yws_get_str/yws_get_str?sap-client=200

其中,sap.txt内容为 http[s]://user:password@host:port//<url-path>,例如,账号名为:test,密码为:123456,那内容就是

test:123456@http://*******.com:8001/sap/bc/srt/wsdl/flv_10002A111AD1/bndg_url/sap/bc/srt/rfc/sap/yws_get_str/200/yws_get_str/yws_get_str?sap-client=200

然后报错了,我猜测是因为对方提供的密码中带有@字符,导致格式识别失败了;但由于我并没有查询到怎么给服务端wsdl生成账号密码,所以我无法自己复现实例

****************不是有效的授权信息格式。格式应为 http[s]://user:pa
ssword@host:port//<url-path>。
*************
需要授权, 请在C:\Us
ers\****\.metro\auth中提供具有读取访问权限的授权文件, 或者使用 -Xauthfile 指定授权文
件并在每一行上使用以下格式提供授权信息: http[s]://user:password@host:port//<url-path>

不过好在,在浏览器输入对方的wsdl,会自动弹出账号密码输入框,输入之后,就可以正常看到wsdl文件内容了。因此,我们可以选择将wsdl文件下载下来并通过文件生成命令。比如,我将内容保存在example.wsdl文件

wsimport example.wsdl

方法重名

不出所料,又报错了

[WARNING] 忽略 SOAP 端口 "example_interface_12": 它使用非标准 SOAP 1.2 绑定。
必须指定 "-extension" 选项以使用此绑定。
正在生成代码...                                                                                
                                                                                         
[ERROR] 无法生成 SEI, 类com.sap.document.sap.soap.functions.mc_style.example_interface已存在
。请使用 JAX-WS 定制设置重命名 wsdl:portType "{urn:sap-com:document:sap:soap:functions:mc-style}ZC  
example_interface"                                                               

然后我在wsimport [ERROR] 无法生成 SEI, 类com.xx.XX 已存在。请使用JAX-WS定制设置重命名 wsdl:portType..._bnmnba的博客-CSDN博客 这篇博客中,看到了类似的情况以及处理方式。

为什么重?

根据实验可知,wsimport命令在生成时,对于接口内的方法会生成java类,接口也会生成java类。

报错的原因是猜测是因为提供的提供的这个接口里,有一个和接口名一模一样的方法。所以无法生成两个同名的类。但是,我自己在测试的时候,发现重名的话其实会生成一个_Type的类,于是,这又变成的一个未知项

解决方案

好吧,我并没有成功,也没有去研究

但是柳暗花明又一村,万能的互联网告诉我,我可以用apache-cxf来生成java类,于是我在idea配置了cxf的路徑

然后在idea的工具栏tools-webservice-Generate java code from wsdl,然后就成功了

参数问题

至此,起码代码生成成功了,下面的问题就是调用了。

通过cxf生成的代码中,会有一个测试类,可以方便去调用;

鉴权:

public final class ExampleServiceImpl_ExampleServiceImplPort_Client {

    private static final QName SERVICE_NAME = new QName("http://summary.webservice.com/", "ExampleServiceImplService");

    private ExampleServiceImpl_ExampleServiceImplPort_Client() {
    }

    public static void main(String args[]) throws java.lang.Exception {
        URL wsdlURL = ExampleServiceImplService.WSDL_LOCATION;
        if (args.length > 0 && args[0] != null && !"".equals(args[0])) { 
            File wsdlFile = new File(args[0]);
            try {
                if (wsdlFile.exists()) {
                    wsdlURL = wsdlFile.toURI().toURL();
                } else {
                    wsdlURL = new URL(args[0]);
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
        }
      
        ExampleServiceImplService ss = new ExampleServiceImplService(wsdlURL, SERVICE_NAME);
        ExampleServiceImpl port = ss.getExampleServiceImplPort();  
        
        {
        System.out.println("Invoking sayHi...");
        java.lang.String _sayHi_arg0 = "";
        java.lang.String _sayHi__return = port.sayHi(_sayHi_arg0);
        System.out.println("sayHi.result=" + _sayHi__return);


        }

        System.exit(0);
    }

}

直接执行测试类,会报如下的错误

Server returned HTTP response code: 401 for URL

是因为我们的接口是带着账号密码的,然后我首先查到的是通过下面这种方式指定账号密码:

ExampleServiceImpl.java

url = new URL("*******");
Authenticator.setDefault( new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(
                "username",
                "passwd".toCharArray());
    }
});
WSDL_LOCATION = url;

运行报错为:

None of the policy alternatives can be satisfied.

在stack搜了一下发现了这篇文章,Apache CXF - None of the policy alternatives can be satisfied,看了好多篇,指定账号密码都大同小异,我采用的是下面这种方式

final String username = "";
final String password = "";
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setAddress(address);
factory.setServiceClass(ExampleServiceImpl.class);
factory.setUsername(username);
factory.setPassword(password);
ExampleServiceImpl bean = (ExampleServiceImpl) factory.create();
//组装参数
...
//组装参数结束
bean.hi(参数)

参数:

执行上面的代码,如果参数没有问题,那么就可以正常返回调用结果了,但如果你要是出现下述的错误,很大可能是因为参数问题

Web service processing error; more details in the web service error log on provider side

普通的参数问题我这里就不提了,需要和提供方联调;需要特别注意的是时间、日期类型会被自动转为XMLGregorianCalendar文章来源地址https://www.toymoban.com/news/detail-755715.html

注意点

  1. 如果本来将代码放在A包下,因某些业务将代码迁移到B包下之后,记得修改interface类的@RequestWrapper和@ResponseWrapper后的className里的包名
  2. 在对应的serviceImpl里面:url = new URL("x"); x是wsdl的地址,如果是sap的话,那就是浏览器可以打开的那个地址
  3. factory.setAddress(address); 这里的address不是wsdl地址,而是你的wsdl和下图位置一样的地方的值

到了这里,关于java调用WebService(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java调用WebService接口,SOAP协议HTTP请求返回XML对象

    Java调用Web service接口SOAP协议HTTP请求,解析返回的XML字符串: 1. 使用Java的HTTP库发送SOAP请求,并接收返回的响应。 可以使用Java的HttpURLConnection、Apache HttpClient等库。 2. 将返回的响应转换为字符串。 3. 解析XML字符串 ,可以使用Java的DOM解析器或者其他第三方库,如JDOM、DOM4J等。

    2024年01月19日
    浏览(50)
  • 使用postman 调用 Webservice 接口

    使用postman 调用 Webservice 接口,postman,webService,接口,cxf

    2024年02月08日
    浏览(59)
  • springboot使用restTemplate调用webservice接口

    1.首先确定wsdl的http地址,使用postman测试接口是否成功  在浏览器输入webservice地址可以找到相应的请求和响应示例。    如果postman返回了正确的数据,就说明测试成功! 2.接下来代码:

    2024年01月16日
    浏览(60)
  • 用Restful方式调用WebService接口(需认证)

    一个可以调用的 WebService接口 调用WebService接口的 SoapUI工具 调用Rest接口的 Postman/Apipost工具 首先接口在浏览器里访问是这样的,一个需要认证的接口 打开SoapUI工具,new一个Project,自定义一下名称和粘贴你的wsdl地址    解析wsdl的时候弹出提示输入账号密码,跟浏览器那边一样

    2024年02月13日
    浏览(40)
  • 使用axis调用WebService,Java WebService调用工具类

    概述 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件,就可相互交换数据或集成。依据 WebService 规范实施的应用之间,无论它们所使用的语言、平台或内部协议是什么,都可以相互交换数据。 也就是说可以实现多语言、跨平台数据交互。 引入

    2024年01月17日
    浏览(45)
  • C# 调用SAP WebService接口(SoapUI Postman)

    SAP wsdl地址发放在浏览器中是需要输入用户名密码进行认证的 将wsdl地址放到SoapUI进行解析 输入用户名密码 左边就是请求的XML格式,右边是接口返回内容,点击运行就可以看到结果 Request1的地址就是我们需要调用的地址(这里提供的域名和wsdl 的域名不一致,需要换成wsdl的域

    2024年02月09日
    浏览(44)
  • SpringBoot调用第三方WebService接口的两种实现方式

    WebService接口的发布通常一般都是使用WSDL(web service descriptive language)文件的样式来发布的,该文档包含了请求的参数信息,返回的结果信息,我们需要根据WSDL文档的信息来编写相关的代码进行调用WebService接口。接下来我将采用常见的两种方式调用WebService接口。 目前我需要

    2024年02月12日
    浏览(69)
  • java调用WebService(一)

    目录 文章目录 背景: 通过一个实例来认识webservice 服务端 客户端 WebService的一些概念 踩坑之旅 务必保证提供方的wsdl可以通过浏览器打开 sap提供的wsdl wsdl鉴权问题 wsimport使用authfile 方法重名 解决方案 参数问题 鉴权: 参数: 注意点 因工作需要和一个Sap相关系统以WebServic

    2024年02月05日
    浏览(35)
  • SAP PO 接口配置1:连通WebService-通过PO调用第三方接口

    SAP 通过 PO 中间件进行接口调用,调用外部接口。 外部接口可以用任意方式生成,常见的REST类型接口即可,关于如何使用python生成接口,其他章节另述。 本教程的前置条件,PO中已配置Business Systems,并与SAP环境连通。 这里以常见的post接口做示例,如有其他类型接口,需要每

    2024年02月05日
    浏览(104)
  • C# .Net6 指定WSDL, 生成Webservice,调用该接口服务

    IDE: Microsoft Visual Studio Community 2022 (64 位) 平台:.Net6 协议:Soap协议 Xml格式 需要开发一个前置机程序, 用于和硬件程序交互, 已知条件是:嵌入式同事提供另一个约定好的*.wsdl文件作为双方通信的Webservice接口协议,对方是服务端,前置机是客户端 使用BasicHttpBinding 通过WS

    2024年02月04日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包