公司做的系统之间的交互用到了webservice做交互,现在对webservice做一个总结。

1.配置已有的webservice

webservice主要包括

  • xml/json:作为传输数据的格式
  • soap:(simple object access protocol)对于http做的封装,是webservice用的服务协议。也有一种说法是:http+xml+soap = webservice
  • wsdl:webservice define language:这是webservice的规范文件。

一般webservice的访问包括四种格式:

  1. http-get
  2. http-post
  3. soap-get
  4. soap-post

java对webservice的支持没有.net做的那么好,只能支持其中一种(soap-post),下面就用http-get使用HttpURLConnection做的webservice的调用

java 利用wsdl文件 java解析wsdl文件_json

这里用中文<>英文双向翻译web服务作为例子,打开页面点击其中的服务说明,如图所示(不好意思,qq截图不知道怎么的打不了中文,我就用简单的英文代替了)

java 利用wsdl文件 java解析wsdl文件_java 利用wsdl文件_02

 

打开:是关于这个webservice的WSDL文件,这个文件我们等下再去分析,我们此时只需要拖到最下面,找到http-get 所需要用的URL,最下面应该会有四种访问方式的URL,我们只需要http-get的就可以了。

java 利用wsdl文件 java解析wsdl文件_xml_03

url应该是:http://fy.webxml.com.cn/webservices/EnglishChinese.asmx,然后我们回到上一个页面,选择:TranslatorSentenceString 

这里不选上一个是因为java对webservice没有.net支持的那么好,没法用dataset去接,如图所示:

java 利用wsdl文件 java解析wsdl文件_xml_04

打开之后,发现需要输入参数wordkey:

java 利用wsdl文件 java解析wsdl文件_json_05

我们可以开始写代码了,用HttpURLConnection写一个调用http-get方法的访问类。



package com.mz.webservice.b;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class TransLatorService {
    public void translate(String keyWord) {
        //我们要调用的webservice的url地址,我们用拼接字符串的形式用?wordKey=xxx来进行拼接
        String httpUrl = "http://fy.webxml.com.cn/webservices/EnglishChinese.asmx/Translator?wordKey="+keyWord;
        
        try {
            URL url = new URL(httpUrl);
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
            //设置访问时间
            conn.setConnectTimeout(5000);
            //访问方式为get
            conn.setRequestMethod("GET");
            //如果连接成功,则把返回的数据读入buffer中
            if(conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream is = conn.getInputStream();
                ByteArrayOutputStream boas = new ByteArrayOutputStream();
                byte[] buffer = new byte[10240];
                int len = -1;
                while((len = is.read(buffer)) != -1) {
                    boas.write(buffer, 0, len);
                }
                System.out.println("the output is:" + boas.toString("UTF-8"));
                boas.close();
                is.close();
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        TransLatorService ts = new TransLatorService();
        ts.translate("death");
    }
}



返回值应该是一个关于单词“death”的xml



the output is:<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://WebXml.com.cn/">
  <xs:schema id="Dictionary" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="Dictionary" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="Trans">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="WordKey" type="xs:string" minOccurs="0" />
                <xs:element name="Pron" type="xs:string" minOccurs="0" />
                <xs:element name="Info" type="xs:string" minOccurs="0" />
                <xs:element name="Translation" type="xs:string" minOccurs="0" />
                <xs:element name="Mp3" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
          <xs:element name="Refer">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="Rel" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
          <xs:element name="Sentence">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="Orig" type="xs:string" minOccurs="0" />
                <xs:element name="Trans" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
    <Dictionary xmlns="">
      <Trans diffgr:id="Trans1" msdata:rowOrder="0">
        <WordKey>death</WordKey>
        <Pron>deθ</Pron>
        <Info />
        <Translation>n. 死,死亡;死神</Translation>
        <Mp3>1694.mp3</Mp3>
      </Trans>
      <Sentence diffgr:id="Sentence1" msdata:rowOrder="0">
        <Orig>That motorbike will be the death of you.</Orig>
        <Trans>那辆摩托车就会要了你的命。</Trans>
      </Sentence>
      <Sentence diffgr:id="Sentence2" msdata:rowOrder="1">
        <Orig>That defeat meant the death of all my hopes.</Orig>
        <Trans>那次失败毁灭了我所有的希望。</Trans>
      </Sentence>
      <Sentence diffgr:id="Sentence3" msdata:rowOrder="2">
        <Orig>Car accident caused many deaths.</Orig>
        <Trans>车祸造成很多人死亡。</Trans>
      </Sentence>
    </Dictionary>
  </diffgr:diffgram>
</DataSet>



我们剩下需要做的就是对这个xml进行解析,自己封装一个解析类和方法,这样做是很费时费力的,所以java提供了一套自己的机制。

我们可以直接封装成实体类,直接调用方法,传递实体类返回实体类的方法来进行调用。

通过wsimport 命令进行生成相应的webservice的实体类。(提醒:必须配置java的环境变量,请自行上网参考,如果不会配置,并且需要jdk1.6_21的版本以上,否则会报错!并且,请保持项目中的jre和控制台版本的一致性!)

语法 wsimport [opations] <wsdl_uri>
- wsdl_uri:wsdl 的统一资源标识符
- d :指定要输出的文件的位置
- s :表示要解析java的源码 ,默认解析出的是class字节码
- p : 指定输出的包名

好比我们如果要把刚刚的webservice服务进行相应的实体类的转换,就是:

wsimport http://fy.webxml.com.cn/webservices/EnglishChinese.asmx?WSDL

这里只会生成字节码文件,没有.java文件,并且字节码文件会出现在你控制台目前的路径下,所以这里先cd到了桌面,如图所示:

java 利用wsdl文件 java解析wsdl文件_json_06

这里报错了,说明不能把相应的WSDL转为我们需要的代理类,那么我们就可以把相应的网页的xml报错到本地,命名随意,我就命名的a.xml(因为其实命令是解析一个wsdl文件,那么不管是解析网页的还是本地的其实是一样的)

找到相应的错误的地方(line 19 line 105)如图所示

java 利用wsdl文件 java解析wsdl文件_java 利用wsdl文件_07

既然没有办法解析,那么就把这一行删除掉,然后重新解析,命令如下:

cd Desktop(先转移到桌面,因为xml文件是报错在桌面的)

wsimport a.xml

java 利用wsdl文件 java解析wsdl文件_json_08

warning是对其他几种方式的不能解析,所以没有error就算是解析成功了,如图所示:

java 利用wsdl文件 java解析wsdl文件_实体类_09

如果需要相应的指定,需要:
wsimport -s ./ -p com.hp.webservice.getTranslatorInfo a.xml

这里的-s是指的要生成的源码地址,-p是包名,如下图所示:

java 利用wsdl文件 java解析wsdl文件_xml_10

这个时候就可以新建一个项目,然后把上面生成的java文件拷到src目录下(此处不截图了,因为我们要分析一个最重要的东西,就是WSDL文件)

首先必须说明WSDL文件是从下往上看的:

java 利用wsdl文件 java解析wsdl文件_实体类_11

往回找,如图所示:

java 利用wsdl文件 java解析wsdl文件_xml_12

接着往上找:

java 利用wsdl文件 java解析wsdl文件_xml_13

接着向上找

java 利用wsdl文件 java解析wsdl文件_实体类_14

最后找到参数类型:

java 利用wsdl文件 java解析wsdl文件_json_15

tips:我知道有人会说那上面有的地方有中文解释为什么还要找,我只想说很多时候很多公司内部的WSDL文件没那么友好,至少我们公司就没有!所以还是一步一步的

找上去吧,还有一个是最后的返回类型是TranlatorResult,有人说找不到,这个是定义在别的xml文件里的,就不去找了,反正知道返回的是一个List就可以了,下一篇我们自己来创建webservice项目会再说明的

综上的WSDL文档所述:

  • 这个webservice的service name:EnglishChinese
  • 我们所用的soap:EnglishChineseSoap
  • 调用方法名:TranslatorString
  • 输入类型:String
  • 输出类型:TransLatorResult(在生成的代理文件里是AraayOfString)

 好了,下面我们写一个测试类:

 



package com.hp.webservice.getTranslatorInfo.test;

import java.util.List;

import com.hp.webservice.getTranslatorInfo.ArrayOfString;
import com.hp.webservice.getTranslatorInfo.EnglishChinese;
import com.hp.webservice.getTranslatorInfo.EnglishChineseSoap;

public class GetTranslatorTest {
    public static void main(String[] args) {
        //首先先获得一个服务
        EnglishChinese eng = new EnglishChinese();
        //通过服务获取其中一种的soap方式
        EnglishChineseSoap soap = eng.getEnglishChineseSoap();
        //调用translatorString方法,并且传递一个英文单词作为参数
        ArrayOfString arrays = soap.translatorString("death");
        //返回是一个webservice自定义的类型,我们需要通过getString方法获得List
        List<String> infos = arrays.getString();
        //通过xml文档分析,list中的第四个元素是单词释义,输出单词释义
        System.out.println(infos.get(3));
    }
}



 

 输出结果应该是:

n. 死,死亡;死神

好了,到这里我们基本可以去使用别人的webservice了,自己建一个webservice项目下次再讲