HttpURLConnection

277 阅读8分钟

一,HttpURLConnection介绍

HttpURLConnection一个抽象类是标准的JAVA接口,该类位于java.net包中,它提供了基本的URL请求,响应等功能。

HttpURLConnection是基于http协议的,支持GET、POST、PUT、DELETE等各种请求方式。如果使用HTTPS协议请求,可以使用它的子类HttpsURLConnection完成更安全的请求操作。

二,使用步骤

  1. 创建连接

    URL url = new URL("https://example.com/api");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    
  2. 设置请求方法

    conn.setRequestMethod("GET"); // 支持 GET、POST、PUT、DELETE 等
    
  3. 添加请求头

    conn.setRequestProperty("Content-Type", "application/json");
    conn.setRequestProperty("User-Agent", "MyApp/1.0");
    
  4. 处理请求参数

    • GET 请求参数:直接附加到 URL 后,如 ?key1=value1&key2=value2

    • POST 请求参数:通过输出流发送:

      conn.setDoOutput(true); // 允许写入请求体
      try (OutputStream os = conn.getOutputStream()) {
          String data = "key1=value1&key2=value2";
          os.write(data.getBytes(StandardCharsets.UTF_8));
      }
      
  5. 处理响应

    int statusCode = conn.getResponseCode(); // 200、404、500 等
    
    if (statusCode == HttpURLConnection.HTTP_OK) {
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(conn.getInputStream()))) {
            String line;
            StringBuilder response = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            System.out.println("Response: " + response.toString());
        }
    } else {
        // 处理错误流(如 4xx/5xx)
        try (BufferedReader errorReader = new BufferedReader(
                new InputStreamReader(conn.getErrorStream()))) {
            // 读取错误信息...
        }
    }
    
  6. 释放资源

    conn.disconnect(); // 释放资源(但 Java 通常会自动处理)
    
  • 超时设置

    conn.setConnectTimeout(5000); // 连接超时(毫秒)
    conn.setReadTimeout(10000);    // 读取超时(毫秒)
    

三,HttpURLConnection方法详解

3.1 设置连接参数方法

方法说明
setAllowUserInteraction(boolean allowuserinteraction)如果为 true,则在允许用户交互(例如弹出一个身份验证对话框)的上下文中对此 URL 进行检查,默认false
setDoInput (boolean doinput)用于设置是否从HTTP连接读取数据。默认情况下,这个值是 true,表示连接会用于输入操作。
setDoOutput(boolean dooutput)用于设置是否使用此连接进行输出操作。通常用于需要向服务器发送数据的请求,比如POST请求,如果设置为 true,表示将使用此连接进行输出操作;如果设置为 false,表示不进行输出操作,默认false
setIfModifiedSince(long ifmodifiedsince)用于设置If-Modified-Since请求头,该请求头是HTTP协议中的一种条件请求头。它告诉服务器只有在指定的时间之后资源被修改时,才返回资源。如果资源自指定时间以来没有被修改,服务器将返回304 Not Modified响应,并且不返回资源内容。
setUseCaches(boolean useCaches)用于设置是否允许使用缓存。如果设置为 true,则允许从缓存中获取资源;如果设置为 false,则不使用缓存,每次都从服务器获取资源。默认为true
setDefaultAllowUserInteraction(boolean defaultallowuserinteraction)用于设置所有后续的连接对象是否允许用户交互。它设置的是一个全局默认值,影响所有通过HttpURLConnection类创建的新连接,如果设置为 true,表示允许用户交互;如果设置为 false,表示不允许用户交互。默认false
setDefaultUseCaches(boolean defaultusecaches)用于设置所有后续创建的HttpURLConnection实例的缓存使用策略。它设置的是一个全局默认值,影响所有通过HttpURLConnection类创建的新连接,如果设置为 true,表示允许使用缓存;如果设置为 false,表示不使用缓存。

3.2 设置请求头

方法说明
setRequestProperty(key,value)设置一般请求属性。如果已存在具有该关键字的属性,则覆盖。注:HTTP 要求所有能够合法拥有多个具有相同键的实例的请求属性,使用以逗号分隔的列表语法,这样可实现将多个属性添加到一个属性中。
addRequestProperty(key,value)添加由键值对指定的一般请求属性。此方法不会改写与相同键关联的现有值

3.3 传递参数给服务器

方法说明
public OutputStream getOutputStream() throws IOException用于获取连接的输出流,允许将数据发送到服务器。这个方法通常用于需要将数据发送到服务器的请求,比如 HTTP POST 或 PUT 请求。

3.4 获取响应内容

方法说明
public Object getContent() throws IOException用于获取HTTP响应的内容。该方法的返回值是一个Object,通常是一个流对象,如InputStreamReader,根据具体的内容类型而定。这个方法提供了一个简便的方式来获取响应体,而不需要直接处理底层的流操作。
public String getHeaderField(String name)用于获取响应头中指定字段的值。你可以通过该方法来检索HTTP响应头中某个字段的值,如 Content-TypeContent-Length 等。
public InputStream getInputStream() throws IOException用于获取连接的输入流,以便读取从服务器返回的响应数据。这个方法适用于处理响应体内容,例如读取网页内容、API 返回的数据等。getInputStream 方法会抛出 IOException 异常,如果服务器响应状态码不是成功状态码(如404或500),则可能需要调用 getErrorStream 来读取错误信息。
public int getResponseCode() throws IOException用于获取服务器响应的HTTP状态码。HTTP状态码是服务器对客户端请求的响应代码,指示请求的结果或状态。
public String getResponseMessage() throws IOException用于获取与HTTP响应状态码相关的描述性消息。这个方法返回的消息是对状态码的简短描述,比如 "OK""Not Found""Internal Server Error"

3.5 获取响应头

方法说明
public String getContentEncoding()用于获取响应体的内容编码类型。如果该字段在响应头中存在,它会返回编码类型的字符串。
public int getContentLength()用于获取HTTP响应体的内容长度。该方法返回的长度以字节为单位,通常用于确定响应体的大小,帮助处理和管理响应数据。
public String getContentType()用于获取HTTP响应头中的 Content-Type 字段。这个字段表示响应体的媒体类型(MIME类型),用于描述响应内容的类型,例如 text/htmlapplication/jsonimage/png 等。
public long getDate()用于获取HTTP响应头中的 Date 字段。这个字段表示响应被发送的日期和时间。返回的日期和时间是标准的 HTTP 日期格式,通常用于记录和处理服务器响应的时间信息。
public long getExpiration()用于获取HTTP响应头中 Expires 字段的时间戳值,以毫秒为单位,表示响应的过期时间。这个方法提供了一种简便的方式来获取响应的过期时间,而无需手动解析日期字符串。

四,代码示例

4.1 GET 请求示例

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class GetExample {
    public static void main(String[] args) throws Exception {
        String url = "https://jsonplaceholder.typicode.com/posts/1";
        URL obj = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
        
        // 设置请求方法
        conn.setRequestMethod("GET");
        // 添加请求头(可选)
        conn.setRequestProperty("User-Agent", "Java Client");
        
        //处理响应
        int responseCode = conn.getResponseCode();
        System.out.println("GET Response Code: " + responseCode);
        
        if (responseCode == HttpURLConnection.HTTP_OK) {
            try (BufferedReader in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()))) {
                String inputLine;
                StringBuilder response = new StringBuilder();
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                System.out.println("Response Body: " + response);
            }
        } else {
            System.out.println("GET Request Failed");
        }
        conn.disconnect();
    }
}

4.2 POST 请求示例

import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public class PostExample {
    public static void main(String[] args) throws Exception {
        String url = "https://jsonplaceholder.typicode.com/posts";
        URL obj = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
        
        // 设置请求方法
        conn.setRequestMethod("POST");
        // 添加请求头(JSON 格式)
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setRequestProperty("Accept", "application/json");
        // 允许写入请求体
        conn.setDoOutput(true);
        
        // 构造请求体
        String jsonBody = "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}";
        byte[] postData = jsonBody.getBytes(StandardCharsets.UTF_8);
        
        // 发送请求体
        try (OutputStream os = conn.getOutputStream()) {
            os.write(postData);
            os.flush();
        }
        //处理响应
        int responseCode = conn.getResponseCode();
        System.out.println("POST Response Code: " + responseCode);
        
        if (responseCode == HttpURLConnection.HTTP_CREATED) { // 201 表示创建成功
            try (BufferedReader in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()))) {
                String inputLine;
                StringBuilder response = new StringBuilder();
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                System.out.println("Response Body: " + response);
            }
        } else {
            System.out.println("POST Request Failed");
        }
        conn.disconnect();
    }
}

4.3 PUT 请求示例

import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public class PutExample {
    public static void main(String[] args) throws Exception {
        String url = "https://jsonplaceholder.typicode.com/posts/1";
        URL obj = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
        
        // 设置请求方法
        conn.setRequestMethod("PUT");
        // 添加请求头
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setRequestProperty("Accept", "application/json");
        conn.setDoOutput(true);
        
        // 构造请求体
        String jsonBody = "{\"id\":1,\"title\":\"updated title\",\"body\":\"updated body\"}";
        byte[] putData = jsonBody.getBytes(StandardCharsets.UTF_8);
        
        // 发送请求体
        try (OutputStream os = conn.getOutputStream()) {
            os.write(putData);
            os.flush();
        }
        
        int responseCode = conn.getResponseCode();
        System.out.println("PUT Response Code: " + responseCode);
        //处理响应
        if (responseCode == HttpURLConnection.HTTP_OK) { // 200 表示成功
            try (BufferedReader in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()))) {
                String inputLine;
                StringBuilder response = new StringBuilder();
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                System.out.println("Response Body: " + response);
            }
        } else {
            System.out.println("PUT Request Failed");
        }
        conn.disconnect();
    }
}

4.4 DELETE 请求示例

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class DeleteExample {
    public static void main(String[] args) throws Exception {
        String url = "https://jsonplaceholder.typicode.com/posts/1";
        URL obj = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
        
        // 设置请求方法
        conn.setRequestMethod("DELETE");
        //处理响应
        int responseCode = conn.getResponseCode();
        System.out.println("DELETE Response Code: " + responseCode);
        
        if (responseCode == HttpURLConnection.HTTP_OK) { // 200 表示成功
            try (BufferedReader in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()))) {
                String inputLine;
                StringBuilder response = new StringBuilder();
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                System.out.println("Response Body: " + response);
            }
        } else {
            System.out.println("DELETE Request Failed");
        }
        conn.disconnect();
    }
}

4.5 关键说明

  1. 请求方法设置:通过 setRequestMethod() 指定 GET/POST/PUT/DELETE
  2. 请求体处理
    • POST/PUT:必须设置 setDoOutput(true),并通过 getOutputStream() 写入数据。
    • GET/DELETE:通常无需请求体(但 DELETE 可以有请求体,具体取决于 API 设计)。
  3. 响应处理
    • 使用 getInputStream() 读取成功响应(如 200/201)。
    • 使用 getErrorStream() 读取错误响应(如 4xx/5xx)。
  4. 资源释放:通过 conn.disconnect() 主动关闭连接(尽管 Java 会自动处理,但显式调用更安全)。

4.6 注意事项

  • 异常处理:实际代码中需用 try-catch 处理 IOException
  • 字符编码:始终明确指定字符编码(如 StandardCharsets.UTF_8)。
  • HTTPS 支持:默认支持 HTTPS,但自签名证书需额外配置 SSLContext
  • 性能优化:频繁请求时建议复用连接或使用更高级库(如 OkHttp)。