Http方式调用WebService,直接发送soap消息到服务端,然后自己解析服务端返回的结果,这种方式比较简单粗暴,也很好用;soap消息可以通过SoapUI来生成,也很方便。文中所使用到的软件版本:Java 1.8.0_191、Commons-HttpClient 3.1、HttpClient 4.5.10、HttpAsyncClient 4.1.4、Spring 5.1.9、dom4j 2.1.1、jackson 2.9.9、netty-all 4.1.33。

1、准备

参考Java调用WebService方法总结(1)--准备工作

2、调用

2.1、HttpURLConnection方式

该方式利用JDK自身提供的API来调用,不需要额外的JAR包。

public static void httpURLConnection(String soap) {
    HttpURLConnection connection = null;
    try {
        URL url = new URL(urlWsdl);
        connection = (HttpURLConnection)url.openConnection();
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
        connection.setRequestProperty("SOAPAction", targetNamespace + "toTraditionalChinese");
        connection.connect();
        
        setBytesToOutputStream(connection.getOutputStream(), soap.getBytes());
        if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            byte[] b = getBytesFromInputStream(connection.getInputStream());
            String back = new String(b);
            System.out.println("httpURLConnection返回soap:" + back);
            System.out.println("httpURLConnection结果:" + parseResult(back));
        } else {
            System.out.println("httpURLConnection返回状态码:" + connection.getResponseCode());
        }
        
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        connection.disconnect();
    }
}

2.2、Commons-HttpClient方式

利用Apache Commons项目下的Commons-HttpClient组件调用,目前该组件已被HttpComponents项目所取代。

public static void commonsHttpClient(String soap) {
    try {
        org.apache.commons.httpclient.HttpClient httpclient = new org.apache.commons.httpclient.HttpClient();
        org.apache.commons.httpclient.methods.PostMethod post = new org.apache.commons.httpclient.methods.PostMethod(urlWsdl);
        post.addRequestHeader("Content-Type", "text/xml;charset=UTF-8");
        post.addRequestHeader("SOAPAction", targetNamespace + "toTraditionalChinese");
        org.apache.commons.httpclient.methods.RequestEntity entity = new org.apache.commons.httpclient.methods.InputStreamRequestEntity(new ByteArrayInputStream(soap.getBytes()));
        post.setRequestEntity(entity);
        int status = httpclient.executeMethod(post);
        if (status == org.apache.commons.httpclient.HttpStatus.SC_OK) {
            String back = post.getResponseBodyAsString();
            System.out.println("Commons-HttpClinet返回soap:" + back);
            System.out.println("commons-HttpClinet返回结果:" + parseResult(back));
        } else {
            System.out.println("commons-HttpClinet返回状态码:" + status);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

2.3、HttpClient方式

利用Apache HttpComponents项目下HttpClient组件调用,是Commons-HttpClient组件的升级版。

public static void httpClient(String soap) {
    try {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(urlWsdl);
        httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");
        httpPost.setHeader("SOAPAction", targetNamespace + "toTraditionalChinese");
        InputStreamEntity entity = new InputStreamEntity(new ByteArrayInputStream(soap.getBytes()));
        httpPost.setEntity(entity);
        CloseableHttpResponse response = httpClient.execute(httpPost);
        if (response.getStatusLine().getStatusCode() == org.apache.http.HttpStatus.SC_OK) {
            HttpEntity responseEntity = response.getEntity();
            String back = EntityUtils.toString(responseEntity);
            System.out.println("httpClient返回soap:" + back);
            System.out.println("httpClient返回结果:" + parseResult(back));
        } else {
            System.out.println("HttpClinet返回状态码:" + response.getStatusLine().getStatusCode());
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

2.4、HttpAsyncClient方式

HttpAsyncClient是HttpClient的异步版本,其用法跟HttpClient类似。

public static void httpAsyncClient(String soap) {
    CloseableHttpAsyncClient httpClient = HttpAsyncClients.createDefault();
    try {
        httpClient.start();
        HttpPost httpPost = new HttpPost(urlWsdl);
        httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");
        httpPost.setHeader("SOAPAction", targetNamespace + "toTraditionalChinese");
        InputStreamEntity entity = new InputStreamEntity(new ByteArrayInputStream(soap.getBytes()));
        httpPost.setEntity(entity);
        Future<HttpResponse> future = httpClient.execute(httpPost, null);
        HttpResponse response = future.get();
        if (response.getStatusLine().getStatusCode() == org.apache.http.HttpStatus.SC_OK) {
            HttpEntity responseEntity = response.getEntity();
            String back = EntityUtils.toString(responseEntity);
            System.out.println("HttpAsyncClient返回soap:" + back);
            System.out.println("HttpAsyncClient返回结果:" + parseResult(back));
        } else {
            System.out.println("HttpAsyncClient返回状态码:" + response.getStatusLine().getStatusCode());
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {httpClient.close();} catch (IOException e) {e.printStackTrace();}
    }
}

2.5、RestTemplate方式

利用Srping的RestTemplate工具调用。

public static void restTemplate(String soap) {
    RestTemplate template = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.add("SOAPAction", targetNamespace + "toTraditionalChinese");
    headers.add("Content-Type", "text/xml;charset=UTF-8");
    org.springframework.http.HttpEntity<String> entity = new org.springframework.http.HttpEntity<String>(soap, headers);
    ResponseEntity<String> response = template.postForEntity(urlWsdl, entity, String.class);
    if (response.getStatusCode() == org.springframework.http.HttpStatus.OK) {
        String back = template.postForEntity(urlWsdl, entity, String.class).getBody();
        System.out.println("restTemplate返回soap:" + back);
        System.out.println("restTemplate返回结果:" + parseResult(back));
    } else {
        System.out.println("restTemplate返回状态码:" + response.getStatusCode());
    }
}

2.6、WebClient方式

利用Spring的WebClient工具调用,它是RestTemplate的异步版本。

public static void webClient(String soap) {
    WebClient webClient = WebClient.create();
    ResponseSpec response = webClient.post().uri(urlWsdl)
            .header("SOAPAction", targetNamespace + "toTraditionalChinese")
            .header("Content-Type", "text/xml;charset=UTF-8")
            .syncBody(soap).retrieve();
    Mono<String> mono = response.bodyToMono(String.class);
    System.out.println("webClient返回soap:" + mono.block());
    System.out.println("webClient结果:" + parseResult(mono.block()));
}

这种方式会用到reactor及nettty相关包:

reactor-core-3.3.0.RELEASE.jar(https://search.maven.org/artifact/io.projectreactor/reactor-core/3.3.0.RELEASE/jar)

reactive-streams-1.0.3.jar(https://search.maven.org/artifact/org.reactivestreams/reactive-streams/1.0.3/jar)

reactor-netty-0.9.1.RELEASE.jar(https://search.maven.org/artifact/io.projectreactor.netty/reactor-netty/0.9.1.RELEASE/jar)

netty-all-4.1.33.Final.jar(https://search.maven.org/artifact/io.netty/netty-all/4.1.33.Final/jar)

2.7、OkHttp方式

利用OkHttp工具调用

public static void okHttp(String soap) {
    try {
        OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(soap, MediaType.get("text/xml;charset=UTF-8"));
        
        Request request = new Request.Builder().url(urlWsdl).post(body)
                .addHeader("SOAPAction", targetNamespace + "toTraditionalChinese").build();
        Response response = client.newCall(request).execute();
        String soapReturn = response.body().string();
        System.out.println("okHttp返回soap:" + soapReturn);
        System.out.println("okHttp结果:" + parseResult(soapReturn));
        response.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

该方式需引入OkHttp的依赖:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.8.1</version>
</dependency>

由于okHttp 4.x用到了kotline,所以需要kotline的环境;在IDEA中可以直接下载kotline的插件。

2.8、小结

几种方式其实差不多,主体思想是一样的就是发送soap报文,就是写法不一样而已。完整例子:

Java调用WebService方法总结(9,end)--Http方式调用WebService_JavaJava调用WebService方法总结(9,end)--Http方式调用WebService_Java_02
package com.inspur.ws;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClient.ResponseSpec;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import reactor.core.publisher.Mono;

/**
 * Http方式调用WebService
 *
 */
public class Http {
    private static String urlWsdl = "http://www.webxml.com.cn/WebServices/TraditionalSimplifiedWebService.asmx?wsdl";
    private static String targetNamespace = "http://webxml.com.cn/";
    
    /**
     * HttpURLConnection方式
     * @param soap
     */
    public static void httpURLConnection(String soap) {
        HttpURLConnection connection = null;
        try {
            URL url = new URL(urlWsdl);
            connection = (HttpURLConnection)url.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
            connection.setRequestProperty("SOAPAction", targetNamespace + "toTraditionalChinese");
            connection.connect();
            
            setBytesToOutputStream(connection.getOutputStream(), soap.getBytes());
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                byte[] b = getBytesFromInputStream(connection.getInputStream());
                String back = new String(b);
                System.out.println("httpURLConnection返回soap:" + back);
                System.out.println("httpURLConnection结果:" + parseResult(back));
            } else {
                System.out.println("httpURLConnection返回状态码:" + connection.getResponseCode());
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            connection.disconnect();
        }
    }
    
    /**
     * Commons-HttpClinet方式
     * @param soap
     */
    public static void commonsHttpClient(String soap) {
        try {
            org.apache.commons.httpclient.HttpClient httpclient = new org.apache.commons.httpclient.HttpClient();
            org.apache.commons.httpclient.methods.PostMethod post = new org.apache.commons.httpclient.methods.PostMethod(urlWsdl);
            post.addRequestHeader("Content-Type", "text/xml;charset=UTF-8");
            post.addRequestHeader("SOAPAction", targetNamespace + "toTraditionalChinese");
            org.apache.commons.httpclient.methods.RequestEntity entity = new org.apache.commons.httpclient.methods.InputStreamRequestEntity(new ByteArrayInputStream(soap.getBytes()));
            post.setRequestEntity(entity);
            int status = httpclient.executeMethod(post);
            if (status == org.apache.commons.httpclient.HttpStatus.SC_OK) {
                String back = post.getResponseBodyAsString();
                System.out.println("Commons-HttpClinet返回soap:" + back);
                System.out.println("commons-HttpClinet返回结果:" + parseResult(back));
            } else {
                System.out.println("commons-HttpClinet返回状态码:" + status);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * HttpClient方式
     * @param soap
     */
    public static void httpClient(String soap) {
        try {
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(urlWsdl);
            httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");
            httpPost.setHeader("SOAPAction", targetNamespace + "toTraditionalChinese");
            InputStreamEntity entity = new InputStreamEntity(new ByteArrayInputStream(soap.getBytes()));
            httpPost.setEntity(entity);
            CloseableHttpResponse response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == org.apache.http.HttpStatus.SC_OK) {
                HttpEntity responseEntity = response.getEntity();
                String back = EntityUtils.toString(responseEntity);
                System.out.println("httpClient返回soap:" + back);
                System.out.println("httpClient返回结果:" + parseResult(back));
            } else {
                System.out.println("HttpClinet返回状态码:" + response.getStatusLine().getStatusCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * HttpAsyncClient方式
     * @param soap
     */
    public static void httpAsyncClient(String soap) {
        CloseableHttpAsyncClient httpClient = HttpAsyncClients.createDefault();
        try {
            httpClient.start();
            HttpPost httpPost = new HttpPost(urlWsdl);
            httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");
            httpPost.setHeader("SOAPAction", targetNamespace + "toTraditionalChinese");
            InputStreamEntity entity = new InputStreamEntity(new ByteArrayInputStream(soap.getBytes()));
            httpPost.setEntity(entity);
            Future<HttpResponse> future = httpClient.execute(httpPost, null);
            HttpResponse response = future.get();
            if (response.getStatusLine().getStatusCode() == org.apache.http.HttpStatus.SC_OK) {
                HttpEntity responseEntity = response.getEntity();
                String back = EntityUtils.toString(responseEntity);
                System.out.println("HttpAsyncClient返回soap:" + back);
                System.out.println("HttpAsyncClient返回结果:" + parseResult(back));
            } else {
                System.out.println("HttpAsyncClient返回状态码:" + response.getStatusLine().getStatusCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {httpClient.close();} catch (IOException e) {e.printStackTrace();}
        }
    }
    
    /**
     * RestTemplate方式
     * @param soap
     */
    public static void restTemplate(String soap) {
        RestTemplate template = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.add("SOAPAction", targetNamespace + "toTraditionalChinese");
        headers.add("Content-Type", "text/xml;charset=UTF-8");
        org.springframework.http.HttpEntity<String> entity = new org.springframework.http.HttpEntity<String>(soap, headers);
        ResponseEntity<String> response = template.postForEntity(urlWsdl, entity, String.class);
        if (response.getStatusCode() == org.springframework.http.HttpStatus.OK) {
            String back = template.postForEntity(urlWsdl, entity, String.class).getBody();
            System.out.println("restTemplate返回soap:" + back);
            System.out.println("restTemplate返回结果:" + parseResult(back));
        } else {
            System.out.println("restTemplate返回状态码:" + response.getStatusCode());
        }
    }
    
    /**
     * WebClient方式
     * @param soap
     */
    public static void webClient(String soap) {
        WebClient webClient = WebClient.create();
        ResponseSpec response = webClient.post().uri(urlWsdl)
                .header("SOAPAction", targetNamespace + "toTraditionalChinese")
                .header("Content-Type", "text/xml;charset=UTF-8")
                .syncBody(soap).retrieve();
        Mono<String> mono = response.bodyToMono(String.class);
        System.out.println("webClient返回soap:" + mono.block());
        System.out.println("webClient结果:" + parseResult(mono.block()));
    }
    
    /**
     * OkHttp方式
     * @param soap
     */
    public static void okHttp(String soap) {
        try {
            OkHttpClient client = new OkHttpClient();
            RequestBody body = RequestBody.create(soap, MediaType.get("text/xml;charset=UTF-8"));
            
            Request request = new Request.Builder().url(urlWsdl).post(body)
                    .addHeader("SOAPAction", targetNamespace + "toTraditionalChinese").build();
            Response response = client.newCall(request).execute();
            String soapReturn = response.body().string();
            System.out.println("okHttp返回soap:" + soapReturn);
            System.out.println("okHttp结果:" + parseResult(soapReturn));
            response.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 从输入流获取数据
     * @param in
     * @return
     * @throws IOException
     */
    private static byte[] getBytesFromInputStream(InputStream in) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] b = new byte[1024];
        int len;
        while ((len = in.read(b)) != -1) {
            baos.write(b, 0, len);
        }
        byte[] bytes = baos.toByteArray();
        return bytes;
    }
    
    /**
     * 向输入流发送数据
     * @param out
     * @param bytes
     * @throws IOException
     */
    private static void setBytesToOutputStream(OutputStream out, byte[] bytes) throws IOException {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        byte[] b = new byte[1024];
        int len;
        while ((len = bais.read(b)) != -1) {
            out.write(b, 0, len);
        }
        out.flush();
    }
    
    /**
     * 解析结果
     * @param s
     * @return
     */
    private static String parseResult(String s) {
        String result = "";
        try {
            Reader file = new StringReader(s);
            SAXReader reader = new SAXReader();
            
            Map<String, String> map = new HashMap<String, String>();
            map.put("ns", "http://webxml.com.cn/");
            reader.getDocumentFactory().setXPathNamespaceURIs(map);
            Document dc = reader.read(file);
            result = dc.selectSingleNode("//ns:toTraditionalChineseResult").getText().trim();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    
    public static void main(String[] args) {
        String soap11 = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:web=\"http://webxml.com.cn/\">"
                       + "<soapenv:Header/>"
                       + "<soapenv:Body>"
                       +    "<web:toTraditionalChinese>"
                       +      "<web:sText>小学</web:sText>"
                       +    "</web:toTraditionalChinese>"
                       + "</soapenv:Body>"
                       + "</soapenv:Envelope>";
        String soap12 = "<soapenv:Envelope xmlns:soapenv=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:web=\"http://webxml.com.cn/\">"
                   + "<soapenv:Header/>"
                   + "<soapenv:Body>"
                   +    "<web:toTraditionalChinese>"
                   +      "<web:sText>大学</web:sText>"
                   +    "</web:toTraditionalChinese>"
                   + "</soapenv:Body>"
                   + "</soapenv:Envelope>";
        httpURLConnection(soap11);
        httpURLConnection(soap12);
        
        commonsHttpClient(soap11);
        commonsHttpClient(soap12);
        
        httpClient(soap11);
        httpClient(soap12);
        
        httpAsyncClient(soap11);
        httpAsyncClient(soap12);
        
        restTemplate(soap11);
        restTemplate(soap12);
        
        webClient(soap11);
        webClient(soap12);
        
        okHttp(soap11);
        okHttp(soap12);
    }
}
Http