实现HttpURLConnection调用.NET WebService的指南

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在Android开发中,使用 HttpURLConnection 与.NET平台上的WebService进行交互是一种常见的需求。本文将介绍 HttpURLConnection 的基础知识,解释WebService的工作原理,并通过详细的步骤指导如何通过 HttpURLConnection 发起SOAP请求以调用.NET WebService。文章还将提供实际代码示例,并强调错误处理、资源管理和安全性等方面的注意事项。 HttpURLConnection

1. HttpURLConnection简介和优势

1.1 HttpURLConnection简介

HttpURLConnection 是Java标准库中提供的用于发送HTTP请求和接收HTTP响应的类。它是一个基于RFC 2616标准实现的可扩展的HTTP客户端,能够进行基本的HTTP协议操作,如GET、POST等。它是网络编程中经常用到的类之一,广泛应用于与Web服务交互的场景中。

1.2 HttpURLConnection优势

相比于其他HTTP客户端库,如Apache的HttpClient和OkHttp, HttpURLConnection 的优势在于它作为Java标准库的一部分,无需额外添加依赖,开箱即用。它具有较强的跨平台性,并且能够很好地与Java的其他部分,例如输入输出流,安全机制等协同工作。由于其简洁性和可靠性,对于需要快速构建和部署HTTP服务的开发者来说, HttpURLConnection 是一个非常合适的选择。

2. WebService调用原理

2.1 WebService技术概述

2.1.1 WebService的定义和架构

WebService是一种Web应用,它允许应用程序通过Web发布、定位和调用远程服务。它基于标准化的通信协议,通常是HTTP,实现了系统之间不同编程语言和平台的透明互操作性。从架构上看,WebService主要由服务提供者(Service Provider)、服务请求者(Service Requester)和服务注册中心(Service Registry)组成。服务提供者负责发布服务,服务请求者通过网络发现并调用服务,而服务注册中心则用于存放服务的元数据,使得服务可以被发现。

2.1.2 WebService的优势和应用场景

WebService的一个核心优势在于它的松耦合特性,这意味着软件组件可以独立于其他组件进行开发和更新。此外,WebService可以利用现有的网络基础设施,支持跨平台和不同语言的通信。它的应用场景包括但不限于电子商务、集成企业应用程序、系统间的远程过程调用(RPC)等。例如,一个使用Java编写的前端应用程序可能需要与一个使用.NET开发的后端服务进行通信,WebService使得这种跨平台的通信成为可能。

2.2 WebService的交互模式

2.2.1 请求/响应模式

请求/响应模式是WebService中最基本的交互方式,它类似于日常生活中的查询和响应过程。服务请求者发送一个请求消息到服务提供者,然后等待并接收响应消息。这种模式是最常见的一种,适用于大多数需要服务提供者返回数据的场景。例如,一个天气查询服务,用户提交一个城市名称的查询请求,然后接收包含该城市当前天气状况的响应。

2.2.2 发布/订阅模式

发布/订阅模式是一种多对多的交互方式,其中一个服务发布信息供多个服务订阅者接收。这种模式通常用于信息共享、事件通知等场景。例如,股票交易系统可以发布实时的股票价格变动信息,而订阅者则可以是需要这些信息的其他应用程序或服务。

graph LR
A[发布者] -->|发布信息| M[消息队列]
B[订阅者] -->|订阅| M
C[订阅者] -->|订阅| M
M -->|通知| B
M -->|通知| C

上图展示了发布/订阅模式的一个简化的流程,其中发布者将信息推送到消息队列,而订阅者则从消息队列中拉取信息。

2.2.3 代码块示例:发送SOAP请求

// 创建URL对象
URL url = new URL("***");
// 打开连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置请求方法
connection.setRequestMethod("POST");
// 添加必要的请求头
connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
connection.setRequestProperty("SOAPAction", "***");

// 发送POST请求必须设置如下两行
connection.setDoOutput(true);
connection.setDoInput(true);

// 获取输出流
OutputStream os = connection.getOutputStream();
// 发送请求到服务器
os.write(soapRequest.getBytes());
os.flush();
os.close();

在上述代码块中,我们创建了一个指向WebService的URL,并通过 HttpURLConnection 建立了连接。然后我们设置了请求方法为POST,并设置了必要的HTTP头信息,包括内容类型和SOAP动作。最后我们获取输出流并发送SOAP请求。

SOAP请求头的设置

在SOAP请求中,HTTP头的设置非常关键,它包含了关于消息的元数据信息。通过设置正确的HTTP头,可以确保请求被正确地路由和处理。例如,"Content-Type"指定了消息内容的类型,而"SOAPAction"则指定了SOAP消息的行动。

SOAP消息体的构建

SOAP消息体是实际包含请求数据的地方。构建SOAP消息体通常涉及到创建一个XML格式的字符串,这个字符串定义了消息的结构和包含的数据。该消息被序列化后写入到HTTP请求的输出流中,从而发送到远程服务。正确构建SOAP消息体是确保远程服务理解并正确处理请求的关键。

通过深入理解这些基础组件和如何将它们组合起来,开发者可以有效地利用WebService进行服务的发现、调用和交互,进而实现高效、跨平台的系统集成。在下一节中,我们将详细探讨如何构建SOAP请求,以及如何通过HttpURLConnection发送这些请求。

3. WebService的SOAP请求格式

3.1 SOAP协议简介

3.1.1 SOAP协议的工作原理

SOAP(Simple Object Access Protocol)是一种基于XML的消息传递协议,用于在网络上的应用程序之间交换信息。SOAP的出现主要是为了提供一个简单的、轻量级的机制来实现跨平台的分布式计算环境。其工作原理主要基于以下几个步骤:

  1. 消息创建 :客户端创建一个SOAP消息,通常包含一个请求的描述,并将其封装在HTTP请求中发送出去。
  2. 消息传输 :SOAP消息通过HTTP协议传输至服务器端。
  3. 消息解析 :服务器端解析HTTP包中的SOAP消息,并根据消息内容执行相应的处理。
  4. 响应生成 :服务器根据处理结果生成响应消息,并将该SOAP消息封装在HTTP响应中送回客户端。
  5. 响应解析 :客户端解析从服务器收到的SOAP响应消息,提取数据或状态信息。

SOAP消息具有自描述特性,这意味着消息体包含了描述消息格式和处理所需的所有信息。SOAP协议是Web服务技术的基础之一,它不依赖于传输协议,但在实际应用中,SOAP通常使用HTTP协议作为底层传输机制。

3.1.2 SOAP消息结构

SOAP消息的结构是一个严格的XML格式,主要包括以下几个部分:

  • Envelope :SOAP消息的根元素,它将整个SOAP消息定义为一个单元。任何SOAP消息都必须包含一个Envelope元素。
  • Header :(可选)包含了一个或多个Header条目,每个条目包含了一组信息,如认证数据、事务信息等。这些信息对于消息的处理可能有用,但不是必需的。
  • Body :包含了实际的请求或响应信息。每个SOAP消息必须包含一个Body元素。
  • Fault :(可选)当SOAP消息处理中出现错误时,可以在Body元素内包含一个Fault元素,提供错误信息。

3.2 构建SOAP请求

3.2.1 HTTP头的设置

构建SOAP请求时,HTTP头信息的设置是重要的一环。HTTP头信息会告诉服务器端如何处理请求,常见的HTTP头设置包括内容类型(Content-Type)和内容长度(Content-Length)等。

以Java中的 HttpURLConnection 为例,下面是设置HTTP头的代码示例:

URL url = new URL("***");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置请求方法为POST
connection.setRequestMethod("POST");
// 设置允许输入输出
connection.setDoInput(true);
connection.setDoOutput(true);
// 设置内容类型为SOAP
connection.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
// 设置SOAPAction,这是一个HTTP头,指定SOAP请求所要调用的服务方法
connection.setRequestProperty("SOAPAction", "***");

3.2.2 SOAP消息体的构建

SOAP消息体是实际发送给服务器的数据部分。构建SOAP消息体通常需要手动编写XML格式的内容,或者使用一些现成的库来生成。下面是一个简单的SOAP消息体构建的例子:

<soap:Envelope xmlns:soap="***"
    xmlns:web="***">
    <soap:Header/>
    <soap:Body>
        <web:SayHello>
            <web:name>John</web:name>
        </web:SayHello>
    </soap:Body>
</soap:Envelope>

在Java代码中,你可以使用字符串拼接的方式创建一个SOAP消息体,或者使用XML处理库如 JDOM DOM4J 来构建更加复杂的XML结构。之后,你需要将这个消息体通过 HttpURLConnection 输出流发送出去。

String soapMessage = ...
OutputStream out = connection.getOutputStream();
out.write(soapMessage.getBytes());
out.flush();

构建SOAP请求需要对XML和HTTP协议有一定的了解,同时确保SOAP消息格式正确和符合服务器端的要求。服务器端接收到SOAP请求后,会解析消息体内容并根据定义好的服务接口进行处理。

4. HttpURLConnection的使用步骤和代码示例

4.1 HttpURLConnection的初始化

4.1.1 创建HttpURLConnection对象

为了开始使用HttpURLConnection,首先我们需要创建一个HttpURLConnection实例。通常,这是通过打开一个URL对象,然后调用其 openConnection 方法来完成的。这个方法返回一个URLConnection对象,而我们通常将它强制转换为HttpURLConnection对象。

以下是如何创建HttpURLConnection对象的示例代码:

URL url = new URL("***");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

4.1.2 设置请求方法和URL

创建了HttpURLConnection实例后,接下来我们需要设置请求方法,如GET或POST。此外,我们还可以设置一些基本的请求属性,比如连接超时时间、读取超时时间以及是否允许自动重定向。

示例代码如下:

// 设置请求方法为GET
connection.setRequestMethod("GET");

// 设置连接超时时间为5秒
connection.setConnectTimeout(5000);

// 设置读取超时时间为10秒
connection.setReadTimeout(10000);

// 允许自动重定向
connection.setInstanceFollowRedirects(true);

4.2 HttpURLConnection的配置

4.2.1 配置请求头

请求头是HTTP请求的一部分,用于传达有关请求的额外信息。在使用HttpURLConnection时,我们可以通过 setRequestProperty 方法来设置请求头。

例如,如果我们需要添加一个用户代理头,可以这样做:

// 添加用户代理头
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MyBot/1.0)");

4.2.2 设置请求参数

对于GET请求,请求参数通常附加在URL的查询字符串中。而对于POST请求,这些参数会在请求体中发送。在Java中,我们可以使用 OutputStreamWriter 来写入请求体。

示例代码如下:

// 对于POST请求,我们需要设置请求体内容类型
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

// 获取请求体的输出流
OutputStream os = connection.getOutputStream();
Writer writer = new OutputStreamWriter(os, "UTF-8");
writer.write("param1=value1&param2=value2");
writer.flush();
writer.close();

4.3 HttpURLConnection代码示例

4.3.1 发送GET请求的代码示例

以下是使用HttpURLConnection发送GET请求的完整代码示例:

URL url = new URL("***");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

// 设置请求方法为GET
connection.setRequestMethod("GET");

// 设置连接超时和读取超时
connection.setConnectTimeout(5000);
connection.setReadTimeout(10000);

// 允许自动重定向
connection.setInstanceFollowRedirects(true);

// 打开连接并读取响应
connection.connect();
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
    response.append(line);
}
reader.close();
in.close();

// 打印响应内容
System.out.println(response.toString());

4.3.2 发送POST请求的代码示例

以下是使用HttpURLConnection发送POST请求的完整代码示例:

URL url = new URL("***");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

// 设置请求方法为POST
connection.setRequestMethod("POST");

// 设置连接超时和读取超时
connection.setConnectTimeout(5000);
connection.setReadTimeout(10000);

// 设置必要的请求头
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

// 获取请求体的输出流并写入数据
OutputStream os = connection.getOutputStream();
Writer writer = new OutputStreamWriter(os, "UTF-8");
writer.write("param1=value1&param2=value2");
writer.flush();
writer.close();

// 打开连接并读取响应
connection.connect();
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
    response.append(line);
}
reader.close();
in.close();

// 打印响应内容
System.out.println(response.toString());

在发送POST请求时,我们通常需要准备要发送的数据,这可以通过将参数拼接到一个字符串中来实现。然后,我们将这个字符串写入到连接的输出流中。注意,关闭输出流是必须的,以便发送数据并告诉服务器我们已经完成数据的发送。

接下来的章节中,我们将进一步讨论如何建立连接、发送数据以及如何从服务器接收和处理响应数据。

5. 连接建立和数据发送

5.1 连接的建立

5.1.1 连接的建立过程

在使用HttpURLConnection时,连接的建立涉及到几个关键步骤。首先,通过调用URL对象的 openConnection() 方法获取一个连接对象。随后,将这个连接对象转换为HttpURLConnection类型,以便进行进一步的配置和操作。

URL url = new URL("***");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

接下来,配置连接的相关参数,例如请求方法(GET、POST等)、超时时间以及需要发送的请求头信息:

connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.setRequestProperty("User-Agent", "Mozilla/5.0");

完成上述配置后,调用 connect() 方法实际建立连接。

connection.connect();

5.1.2 网络异常处理

在建立连接的过程中,可能会抛出多种异常,比如 MalformedURLException IOException 等。因此,使用try-catch结构来捕获这些异常是必要的,以确保程序的健壮性。

try {
    connection.connect();
} catch (IOException e) {
    // 处理网络异常,例如连接失败、读取超时等
    e.printStackTrace();
}

5.2 数据的发送

5.2.1 发送数据的过程

一旦连接建立,就可以开始发送数据。对于POST请求,通常需要在连接建立后设置请求体,并使用 OutputStream 进行数据的发送。

connection.setDoOutput(true); // 允许输出
try (OutputStream os = connection.getOutputStream()) {
    // 发送的数据需要转换为字节流
    byte[] input = "some data".getBytes(StandardCharsets.UTF_8);
    os.write(input, 0, input.length);
}

5.2.2 数据发送的优化方法

发送数据时,应注意几个优化点:

  • 合理设置缓存区大小 :避免过大的缓存导致内存占用过高,同时,过小的缓存会增加网络交互次数。
  • 流式发送数据 :大数据量时,可以边读取边发送,减少内存占用。
  • 关闭自动重定向 :有时服务器的自动重定向可能会导致不必要的网络开销,可以通过设置 setInstanceFollowRedirects(false) 来关闭自动重定向。
connection.setInstanceFollowRedirects(false);
  • 异步发送数据 :在支持多线程的环境中,可以考虑使用异步方式发送数据,减少阻塞时间。

通过上述步骤,我们可以完成HttpURLConnection的初始化、配置以及数据的发送,并且在过程中考虑了异常处理和优化方法,以确保数据传输过程既稳定又高效。

6. 响应读取和数据处理

6.1 响应的读取

6.1.1 读取响应的过程

在使用HttpURLConnection类与WebService进行交互的过程中,读取服务器响应是一个至关重要的步骤。这个过程通常涉及以下几个关键点:

  1. 连接服务器 - 首先,确保已经建立了连接。这通常是通过调用 HttpURLConnection.getInputStream() 方法来完成的,该方法会返回一个 InputStream 实例,用于从服务器读取响应数据。

  2. 读取输入流 - 接下来,从返回的输入流中读取数据。这通常是通过使用 InputStreamReader 将字节流转换为字符流,并使用 BufferedReader 来逐行读取响应内容。

  3. 处理数据 - 读取到的响应数据需要被适当地处理,这可能包括字符编码转换、格式解析等。

  4. 关闭流 - 在读取完数据后,必须确保释放资源。这通过调用输入流的 close() 方法实现。

以下是使用Java代码读取HTTP响应的基本步骤:

// 假设urlConnection是已经配置好的HttpURLConnection对象
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
    response.append(line).append("\n");
}
reader.close();

// 输出响应内容
System.out.println(response.toString());

6.1.2 字符编码和乱码处理

在网络编程中,字符编码是一个常被提及的问题。不同服务器可能会使用不同的字符集来编码响应数据,因此在读取响应时可能会遇到乱码问题。为了解决这个问题,应该在读取输入流之前正确地设置字符编码。

通常,服务器响应头中的 Content-Type 字段会指示响应的内容类型,其中可以包含字符编码信息。例如:

Content-Type: text/xml; charset=utf-8

开发者可以根据这个字段来设置字符编码。以下是如何在读取响应之前设置字符编码的示例:

if (urlConnection.getContentEncoding() != null) {
    reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), 
                                                    urlConnection.getContentEncoding()));
} else {
    // 如果响应头中没有指定字符编码,可以根据实际情况指定默认编码
    reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
}

6.2 数据的解析和处理

6.2.1 使用XML解析器解析SOAP响应

SOAP响应本质上是一个XML格式的字符串,因此可以使用XML解析器来解析这些响应内容。常见的XML解析库包括 javax.xml.parsers org.jdom org.w3c.dom 等。在Java中,通常使用 DocumentBuilder 来解析XML文档。

以下是使用 DocumentBuilder 解析SOAP响应的一个基本示例:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new StringReader(response.toString())));

// 获取指定元素,例如获取第一个<fault>元素
NodeList faultNodes = document.getElementsByTagName("fault");
Element faultElement = (Element) faultNodes.item(0);

6.2.2 JSON数据的解析和处理

随着RESTful API的流行,JSON数据格式也变得越来越常见。在Java中,处理JSON数据时可以使用 org.json 库、 com.fasterxml.jackson.databind 或者 com.google.gson 等库。

以下是一个使用Gson库来解析JSON响应的示例:

Gson gson = new Gson();
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> jsonResponse = gson.fromJson(response.toString(), type);
System.out.println(jsonResponse);

在处理JSON数据时,应当注意JSON的结构和字段,以正确地从响应中提取需要的信息。此外,异常处理也是必要的,因为JSON格式错误或解析问题都可能引发异常。

总结第六章的内容,我们介绍了如何从HttpURLConnection读取响应,并处理了字符编码的常见问题。我们还讨论了使用XML和JSON解析器来解析SOAP和RESTful API的响应数据。通过这些知识点,我们可以更好地处理从WebService交互中得到的复杂数据。

7. 异常处理和资源管理

在开发过程中,异常处理和资源管理是保证程序稳定性和健壮性的关键部分。特别是对于使用HttpURLConnection进行网络通信的应用程序,有效地处理各种可能发生的异常情况,以及确保网络资源被正确管理,是提高应用性能和用户体验的重要方面。

7.1 异常处理

7.1.1 常见异常及处理策略

在使用HttpURLConnection时,我们可能会遇到多种异常,比如 IOException ConnectException 等。合理地捕获和处理这些异常,能帮助我们诊断问题并给出恰当的用户反馈。

HttpURLConnection urlConnection = null;
BufferedReader reader = null;
try {
    URL url = new URL("***");
    urlConnection = (HttpURLConnection) url.openConnection();
    // 发送请求、读取响应等操作...
} catch (MalformedURLException e) {
    // 处理URL错误异常
    System.err.println("Malformed URL: " + e.getMessage());
} catch (IOException e) {
    // 处理其他网络相关的异常
    System.err.println("Network error: " + e.getMessage());
} finally {
    if (urlConnection != null) {
        urlConnection.disconnect();
    }
    if (reader != null) {
        try {
            reader.close();
        } catch (IOException e) {
            // 可以记录日志
        }
    }
}

7.1.2 异常捕获和日志记录

在实际开发中,除了基本的异常捕获,我们还需要对异常进行记录,以便于后续的问题排查和复现。通常会使用日志框架,如Log4j或者SLF4J,来实现这一功能。

try {
    // 网络请求和数据处理代码
} catch (Exception e) {
    // 使用日志框架记录异常信息
    Log.error("An error occurred during the network request", e);
    // 可以根据需要记录堆栈跟踪等信息
}

7.2 资源管理

7.2.1 使用try-catch-finally确保资源释放

在Java中,资源如文件流或网络连接,需要被显式关闭,以防内存泄漏和资源占用。使用try-catch-finally结构是一种保证资源释放的可靠方法。

BufferedReader reader = null;
try {
    URL url = new URL("***");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    // 初始化连接、发送请求等
    reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    // 读取响应数据
} catch (IOException e) {
    // 异常处理
    Log.error("Error while opening connection", e);
} finally {
    // 释放资源
    if (reader != null) {
        try {
            reader.close();
        } catch (IOException e) {
            Log.error("Error while closing reader", e);
        }
    }
}

7.2.2 使用AutoCloseable管理资源

从Java 7开始,引入了try-with-resources语句,它可以自动管理实现了AutoCloseable接口的资源,从而简化代码并避免资源泄露。

try (URL url = new URL("***");
     HttpURLConnection connection = (HttpURLConnection) url.openConnection();
     BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
    // 使用reader对象读取数据
} catch (IOException e) {
    // 异常处理
    Log.error("Error while processing the request", e);
}

try-with-resources结构保证了所有资源在try代码块执行完毕后自动关闭,无论是正常执行还是发生异常,都无需手动关闭资源,使代码更简洁且安全。

在这一章节中,我们了解了异常处理的重要性和使用try-catch-finally进行资源管理的传统方法,以及try-with-resources带来的便利。对于使用HttpURLConnection的开发者来说,掌握这些知识,能显著提高代码的质量和应用的稳定性。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在Android开发中,使用 HttpURLConnection 与.NET平台上的WebService进行交互是一种常见的需求。本文将介绍 HttpURLConnection 的基础知识,解释WebService的工作原理,并通过详细的步骤指导如何通过 HttpURLConnection 发起SOAP请求以调用.NET WebService。文章还将提供实际代码示例,并强调错误处理、资源管理和安全性等方面的注意事项。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值