httpclient作为客户端调用webservice

1.个人观点

webservice框架有很多,比如axis、axis2、cxf、xFire等等,做服务端和做客户端都可行,个人感觉使用这些框架的好处是减少了对于接口信息的解析,最主要的是减少了对于传递于网络中XML的解析,代价是你不得不在你的框架中添加对于这些框架的依赖。个人观点是:服务端使用这些框架还行,如果做客户端,没必要使用这些框架,只需使用httpclient即可。

2.需求场景

已经拿到对于接口的描述文件WebServiceFromB.wsdl,需要建立客户端进行调用,WebServiceFromB.wsdl内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?xml version="1.0" encoding="UTF-8"?> 
<!--WSDL created by Apache Axis version: 1.4 
Built on Apr 22, 2006 (06:55:48 PDT)--> 
 <wsdl:types
  <schema targetNamespace="https://webservices.b.com" xmlns="https://www.w3.org/2001/XMLSchema"
   <import namespace="https://schemas.xmlsoap.org/soap/encoding/"/> 
   <complexType name="OrderRequest"
    <sequence
     <element name="mobile" nillable="true" type="soapenc:string"/> 
     <element name="orderStatus" type="xsd:int"/> 
     <element name="productCode" nillable="true" type="soapenc:string"/> 
    </sequence
   </complexType
   <complexType name="OrderResponse"
    <sequence
     <element name="status" type="xsd:int"/> 
    </sequence
   </complexType
   <complexType name="QueryRequest"
    <sequence
     <element name="endTime" nillable="true" type="xsd:dateTime"/> 
     <element name="mobile" nillable="true" type="soapenc:string"/> 
     <element name="startTime" nillable="true" type="xsd:dateTime"/> 
    </sequence
   </complexType
   <complexType name="QueryResponse"
    <sequence
     <element name="product" nillable="true" type="soapenc:string"/> 
     <element name="status" type="xsd:int"/> 
    </sequence
   </complexType
  </schema
 </wsdl:types
   <wsdl:message name="queryRequest"
      <wsdl:part name="in0" type="impl:QueryRequest"/> 
   </wsdl:message
   <wsdl:message name="orderResponse"
      <wsdl:part name="orderReturn" type="impl:OrderResponse"/> 
   </wsdl:message
   <wsdl:message name="queryResponse"
      <wsdl:part name="queryReturn" type="impl:QueryResponse"/> 
   </wsdl:message
   <wsdl:message name="orderRequest"
      <wsdl:part name="in0" type="impl:OrderRequest"/> 
   </wsdl:message
   <wsdl:portType name="WebServiceFromB"
      <wsdl:operation name="order" parameterOrder="in0"
         <wsdl:input message="impl:orderRequest" name="orderRequest"/> 
         <wsdl:output message="impl:orderResponse" name="orderResponse"/> 
      </wsdl:operation
      <wsdl:operation name="query" parameterOrder="in0"
         <wsdl:input message="impl:queryRequest" name="queryRequest"/> 
         <wsdl:output message="impl:queryResponse" name="queryResponse"/> 
      </wsdl:operation
   </wsdl:portType
   <wsdl:binding name="WebServiceFromBSoapBinding" type="impl:WebServiceFromB"
      <wsdlsoap:binding style="rpc" transport="https://schemas.xmlsoap.org/soap/http"/> 
      <wsdl:operation name="order"
         <wsdlsoap:operation soapAction=""/> 
         <wsdl:input name="orderRequest"
            <wsdlsoap:body encodingStyle="https://schemas.xmlsoap.org/soap/encoding/" namespace="https://webservices.b.com" use="encoded"/> 
         </wsdl:input
         <wsdl:output name="orderResponse"
            <wsdlsoap:body encodingStyle="https://schemas.xmlsoap.org/soap/encoding/" namespace="https://webservices.b.com" use="encoded"/> 
         </wsdl:output
      </wsdl:operation
      <wsdl:operation name="query"
         <wsdlsoap:operation soapAction=""/> 
         <wsdl:input name="queryRequest"
            <wsdlsoap:body encodingStyle="https://schemas.xmlsoap.org/soap/encoding/" namespace="https://webservices.b.com" use="encoded"/> 
         </wsdl:input
         <wsdl:output name="queryResponse"
            <wsdlsoap:body encodingStyle="https://schemas.xmlsoap.org/soap/encoding/" namespace="https://webservices.b.com" use="encoded"/> 
         </wsdl:output
      </wsdl:operation
   </wsdl:binding
   <wsdl:service name="WebServiceFromBService"
      <wsdl:port binding="impl:WebServiceFromBSoapBinding" name="WebServiceFromB"
         <wsdlsoap:address location="https://localhost:8080/services/WebServiceFromB"/> 
      </wsdl:port
   </wsdl:service
</wsdl:definitions>

3.获取调用报文

1.首先得安装soapUI 4.5.2,安装后打开,截图如下:

\

2.右键点击“Projects”创建工程,截图如下:

\

3.双击展开左侧创建的工程下所有节点,最后双击“Request 1”节点,在右侧即可拿到soap格式消息,这个就是我们后面作为客户端调用服务端的报文内容,截图如下:

\

拿到的调用order的soap消息为:

1
2
3
4
5
6
7
8
9
10
11
12
   <soapenv:Header/> 
   <soapenv:Body
      <web:order soapenv:encodingStyle="https://schemas.xmlsoap.org/soap/encoding/"
         <in0 xsi:type="web:OrderRequest"
            <mobile xsi:type="soapenc:string" xmlns:soapenc="https://schemas.xmlsoap.org/soap/encoding/">?</mobile
            <orderStatus xsi:type="xsd:int">?</orderStatus
            <productCode xsi:type="soapenc:string" xmlns:soapenc="https://schemas.xmlsoap.org/soap/encoding/">?</productCode
         </in0
      </web:order
   </soapenv:Body
</soapenv:Envelope>

拿到的调用query的soap消息为:

1
2
3
4
5
6
7
8
9
10
11
12
   <soapenv:Header/> 
   <soapenv:Body
      <web:query soapenv:encodingStyle="https://schemas.xmlsoap.org/soap/encoding/"
         <in0 xsi:type="web:QueryRequest"
            <endTime xsi:type="xsd:dateTime">?</endTime
            <mobile xsi:type="soapenc:string" xmlns:soapenc="https://schemas.xmlsoap.org/soap/encoding/">?</mobile
            <startTime xsi:type="xsd:dateTime">?</startTime
         </in0
      </web:query
   </soapenv:Body
</soapenv:Envelope>

4.用httpclient发送soap消息

直接上代码,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import java.nio.charset.Charset; 
import org.apache.http.HttpEntity; 
import org.apache.http.client.config.RequestConfig; 
import org.apache.http.client.methods.CloseableHttpResponse; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.entity.StringEntity; 
import org.apache.http.impl.client.CloseableHttpClient; 
import org.apache.http.impl.client.HttpClientBuilder; 
import org.apache.http.util.EntityUtils; 
import org.apache.log4j.Logger; 
   
public class HttpClientCallSoapUtil { 
    static int socketTimeout = 30000;// 请求超时时间 
    static int connectTimeout = 30000;// 传输超时时间 
    static Logger logger = Logger.getLogger(HttpClientCallSoapUtil.class); 
   
    /**
     * 使用SOAP1.1发送消息
     
     * @param postUrl
     * @param soapXml
     * @param soapAction
     * @return
     */ 
    public static String doPostSoap1_1(String postUrl, String soapXml, 
            String soapAction) { 
        String retStr = ""
        // 创建HttpClientBuilder 
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); 
        // HttpClient 
        CloseableHttpClient closeableHttpClient = httpClientBuilder.build(); 
        HttpPost httpPost = new HttpPost(postUrl); 
                //  设置请求和传输超时时间 
        RequestConfig requestConfig = RequestConfig.custom() 
                .setSocketTimeout(socketTimeout) 
                .setConnectTimeout(connectTimeout).build(); 
        httpPost.setConfig(requestConfig); 
        try
            httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8"); 
            httpPost.setHeader("SOAPAction", soapAction); 
            StringEntity data = new StringEntity(soapXml, 
                    Charset.forName("UTF-8")); 
            httpPost.setEntity(data); 
            CloseableHttpResponse response = closeableHttpClient 
                    .execute(httpPost); 
            HttpEntity httpEntity = response.getEntity(); 
            if (httpEntity != null) { 
                // 打印响应内容 
                retStr = EntityUtils.toString(httpEntity, "UTF-8"); 
                logger.info("response:" + retStr); 
            
            // 释放资源 
            closeableHttpClient.close(); 
        } catch (Exception e) { 
            logger.error("exception in doPostSoap1_1", e); 
        
        return retStr; 
    
   
    /**
     * 使用SOAP1.2发送消息
     
     * @param postUrl
     * @param soapXml
     * @param soapAction
     * @return
     */ 
    public static String doPostSoap1_2(String postUrl, String soapXml, 
            String soapAction) { 
        String retStr = ""
        // 创建HttpClientBuilder 
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); 
        // HttpClient 
        CloseableHttpClient closeableHttpClient = httpClientBuilder.build(); 
        HttpPost httpPost = new HttpPost(postUrl); 
                // 设置请求和传输超时时间 
        RequestConfig requestConfig = RequestConfig.custom() 
                .setSocketTimeout(socketTimeout) 
                .setConnectTimeout(connectTimeout).build(); 
        httpPost.setConfig(requestConfig); 
        try
            httpPost.setHeader("Content-Type"
                    "application/soap+xml;charset=UTF-8"); 
            httpPost.setHeader("SOAPAction", soapAction); 
            StringEntity data = new StringEntity(soapXml, 
                    Charset.forName("UTF-8")); 
            httpPost.setEntity(data); 
            CloseableHttpResponse response = closeableHttpClient 
                    .execute(httpPost); 
            HttpEntity httpEntity = response.getEntity(); 
            if (httpEntity != null) { 
                // 打印响应内容 
                retStr = EntityUtils.toString(httpEntity, "UTF-8"); 
                logger.info("response:" + retStr); 
            
            // 释放资源 
            closeableHttpClient.close(); 
        } catch (Exception e) { 
            logger.error("exception in doPostSoap1_2", e); 
        
        return retStr; 
    
   
    public static void main(String[] args) { 
        String orderSoapXml = "<?xml version = \"1.0\" ?>" 
                + "<soapenv:Envelope xmlns:xsi=\"https://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"https://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"https://schemas.xmlsoap.org/soap/envelope/\" xmlns:web=\"https://webservices.b.com\">" 
                + "   <soapenv:Header/>" 
                + "   <soapenv:Body>" 
                + "      <web:order soapenv:encodingStyle=\"https://schemas.xmlsoap.org/soap/encoding/\">" 
                + "         <in0 xsi:type=\"web:OrderRequest\">" 
                + "            <mobile xsi:type=\"soapenc:string\" xmlns:soapenc=\"https://schemas.xmlsoap.org/soap/encoding/\">?</mobile>" 
                + "            <orderStatus xsi:type=\"xsd:int\">?</orderStatus>" 
                + "            <productCode xsi:type=\"soapenc:string\" xmlns:soapenc=\"https://schemas.xmlsoap.org/soap/encoding/\">?</productCode>" 
                + "         </in0>" + "      </web:order>" 
                + "   </soapenv:Body>" + "</soapenv:Envelope>"
        String querySoapXml = "<?xml version = \"1.0\" ?>" 
                + "<soapenv:Envelope xmlns:xsi=\"https://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"https://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"https://schemas.xmlsoap.org/soap/envelope/\" xmlns:web=\"https://webservices.b.com\">" 
                + "   <soapenv:Header/>" 
                + "   <soapenv:Body>" 
                + "      <web:query soapenv:encodingStyle=\"https://schemas.xmlsoap.org/soap/encoding/\">" 
                + "         <in0 xsi:type=\"web:QueryRequest\">" 
                + "            <endTime xsi:type=\"xsd:dateTime\">?</endTime>" 
                + "            <mobile xsi:type=\"soapenc:string\" xmlns:soapenc=\"https://schemas.xmlsoap.org/soap/encoding/\">?</mobile>" 
                + "            <startTime xsi:type=\"xsd:dateTime\">?</startTime>" 
                + "         </in0>" + "      </web:query>" 
                + "   </soapenv:Body>" + "</soapenv:Envelope>"
        String postUrl = "https://localhost:8080/services/WebServiceFromB"
        //采用SOAP1.1调用服务端,这种方式能调用服务端为soap1.1和soap1.2的服务 
        doPostSoap1_1(postUrl, orderSoapXml, ""); 
        doPostSoap1_1(postUrl, querySoapXml, ""); 
   
        //采用SOAP1.2调用服务端,这种方式只能调用服务端为soap1.2的服务 
        //doPostSoap1_2(postUrl, orderSoapXml, "order"); 
        //doPostSoap1_2(postUrl, querySoapXml, "query"); 
    
}

5.总结

优点:

1.使用httpclient作为客户端调用webservice,不用关注繁琐的webservice框架,只需找到SOAP消息格式,添加httpclient依赖就行。

2.使用httpclient调用webservice,建议采用soap1.1方式调用,经测试使用soap1.1方式能调用soap1.1和soap1.2的服务端。

缺点:

唯一的缺点是,你得自己解析返回的XML,找到你关注的信息内容。

 

转自:https://www.2cto.com/kf/201701/583039.html

posted @ 2018-06-01 00:32  N神3  阅读(88)  评论(0)    收藏  举报