登录
首页 >  文章 >  java教程

Java发送HTTP请求的几种方式

时间:2025-07-20 08:33:34 142浏览 收藏

知识点掌握了,还需要不断练习才能熟练运用。下面golang学习网给大家带来一个文章开发实战,手把手教大家学习《Java发送HTTP请求的几种方法》,在实现功能的过程中也带大家重新温习相关知识点,温故而知新,回头看看说不定又有不一样的感悟!

Java中发送HTTP请求的主流方式有四种,分别是:1. 使用 java.net.HttpURLConnection(适用于简单请求或无法引入第三方库的项目);2. 使用 Java 11 引入的 java.net.http.HttpClient(推荐用于Java 11及以上版本,支持HTTP/2和异步请求);3. 使用 Apache HttpClient(功能强大,适合复杂企业级场景);4. 使用 OkHttp(高效简洁,适合Android或微服务项目)。每种方式各有优劣,选择取决于项目需求、Java版本及开发偏好。

如何在Java中发送HTTP请求 Java实现HTTP通信的方法

在Java中发送HTTP请求,核心在于选择合适的API或库来构建、发送请求并处理响应。这并不是一个单一的“最佳”方案,更多的是根据项目需求、Java版本以及个人偏好来权衡。你可以使用Java自带的HttpURLConnection(虽然有点老旧但依然可用),Java 11引入的HttpClient(现代且功能强大),或者Apache HttpClient、OkHttp这类业界广泛使用的第三方库。选择哪种,往往决定了你代码的简洁性、可维护性和功能丰富度。

如何在Java中发送HTTP请求 Java实现HTTP通信的方法

解决方案

要在Java中实现HTTP通信,我通常会根据项目所用的Java版本和对功能复杂度的需求来决定。

1. 使用 java.net.HttpURLConnection (Java SE 1.1 及更高版本)

如何在Java中发送HTTP请求 Java实现HTTP通信的方法

这是Java内置的API,无需额外依赖。它功能完备,但用起来确实有点啰嗦,尤其是在处理复杂的请求头、参数或响应体时。我个人觉得,如果只是发个简单的GET请求,或者项目环境限制不能引入第三方库,它还能勉强用用。

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

public class HttpUrlConnectionExample {
    public static void main(String[] args) {
        try {
            URL url = new URL("https://jsonplaceholder.typicode.com/posts/1");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000); // 5秒连接超时
            connection.setReadTimeout(5000);    // 5秒读取超时

            int responseCode = connection.getResponseCode();
            System.out.println("GET Response Code :: " + responseCode);

            if (responseCode == HttpURLConnection.HTTP_OK) { // success
                BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String inputLine;
                StringBuilder response = new StringBuilder();

                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();
                System.out.println(response.toString());
            } else {
                System.out.println("GET request not worked");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 使用 java.net.http.HttpClient (Java 11 及更高版本)

如何在Java中发送HTTP请求 Java实现HTTP通信的方法

Java 11引入的HttpClient是现代Java HTTP客户端的首选。它支持HTTP/2、WebSocket,并且提供了同步和异步两种API。用起来比HttpURLConnection舒服太多了,链式调用让代码可读性大大提升。如果你的项目能用Java 11及以上版本,我强烈推荐这个。

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class JavaHttpClientExample {
    public static void main(String[] args) {
        HttpClient client = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_2)
                .followRedirects(HttpClient.Redirect.NORMAL)
                .connectTimeout(Duration.ofSeconds(5))
                .build();

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
                .GET() // 默认就是GET,也可以不写
                .build();

        try {
            HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());

            System.out.println("Status Code: " + response.statusCode());
            System.out.println("Response Body: " + response.body());

            // 异步请求示例
            client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                  .thenApply(HttpResponse::body)
                  .thenAccept(body -> System.out.println("Async Body: " + body))
                  .join(); // 等待异步完成,实际应用中通常不阻塞
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3. 使用 Apache HttpClient (第三方库)

Apache HttpClient是Java世界里非常成熟且功能强大的HTTP客户端库,它提供了丰富的特性,比如连接池、认证、代理、重试机制等。对于需要处理复杂HTTP场景的企业级应用来说,它依然是一个非常可靠的选择。需要引入Maven或Gradle依赖。



    org.apache.httpcomponents
    httpclient
    4.5.13
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class ApacheHttpClientExample {
    public static void main(String[] args) {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet request = new HttpGet("https://jsonplaceholder.typicode.com/posts/1");

            // 可以添加请求头
            request.addHeader("User-Agent", "Apache HttpClient Demo");

            try (CloseableHttpResponse response = httpClient.execute(request)) {
                System.out.println("Status Code: " + response.getStatusLine().getStatusCode());
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    System.out.println("Response Body: " + EntityUtils.toString(entity));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4. 使用 OkHttp (第三方库)

OkHttp是Square公司开源的一个高效HTTP客户端,在Android开发中尤为流行,但在后端服务中也常被使用。它支持HTTP/2、连接池、响应缓存等,API设计非常简洁流畅。



    com.squareup.okhttp3
    okhttp
    4.9.3
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;

public class OkHttpExample {
    public static void main(String[] args) {
        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
                .url("https://jsonplaceholder.typicode.com/posts/1")
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            System.out.println("Status Code: " + response.code());
            System.out.println("Response Body: " + response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Java中HTTP请求的几种主流实现方式有哪些?

谈到Java里发HTTP请求,选择确实不少,各有各的特点和适用场景。我个人在不同的项目里都用过,也踩过一些坑,所以对它们的优劣多少有些体会。

首先是 java.net.HttpURLConnection。这玩意儿是Java标准库自带的,你不需要引入任何第三方依赖就能用。它的好处是“开箱即用”,对于一些简单的GET或POST请求,比如请求一个静态资源或者提交一个简单的表单,它完全够用。但它的API设计确实比较老旧,用起来很“命令式”,代码会显得比较冗长,尤其是在你需要设置很多请求头、处理重定向、或者管理连接池的时候,你会发现它力不从心,写起来很费劲。在我看来,它更适合那些对依赖有严格限制的老项目,或者只是想快速验证一个HTTP请求的场景。

接着是 java.net.http.HttpClient,这是Java 11之后的新宠。我得说,Sun/Oracle终于在这方面做了些现代化改进。它的API设计非常符合现代编程习惯,支持链式调用,而且原生支持HTTP/2和WebSocket,这是很大的优势。它既能同步阻塞地发请求,也能异步非阻塞地发,这对于构建响应式服务非常有用。如果你正在开发基于Java 11或更高版本的新项目,或者有机会升级现有项目的Java版本,我强烈建议优先考虑它。它自带连接池管理,性能也相当不错,而且不用引入第三方依赖,很“干净”。

然后是 Apache HttpClient。这几乎是Java企业级应用中HTTP客户端的“老牌劲旅”了。在HttpClient出现之前,Apache HttpClient几乎是处理复杂HTTP请求的不二之选。它提供了非常丰富的功能,比如强大的连接池管理、多种认证机制、代理支持、请求重试策略等等。如果你需要对HTTP请求有非常精细的控制,或者你的应用场景非常复杂(比如需要处理大量的并发请求、复杂的认证流程),那么Apache HttpClient依然是一个非常稳健的选择。虽然它需要引入外部依赖,API也相对Java 11的HttpClient略显复杂,但它的稳定性和功能丰富度是经过时间考验的。

最后是 OkHttp。这个库在Android开发社区里非常流行,但它在后端服务中也越来越受欢迎。OkHttp的设计理念是高效和简洁。它默认支持HTTP/2,有非常优秀的连接池管理,并且提供了拦截器(Interceptor)机制,这让你可以非常方便地对请求和响应进行修改、日志记录、认证添加等操作。它的API非常简洁直观,用起来很舒服。如果你的项目追求性能、简洁的API设计,并且乐于引入一个高质量的第三方库,OkHttp是一个非常棒的选择。我个人在一些微服务项目里,因为它的简洁和高效,也倾向于使用它。

总结一下,如果你的项目是Java 11+,并且对依赖有洁癖,java.net.http.HttpClient是首选。如果需要处理非常复杂的企业级HTTP场景,或者项目Java版本较低,Apache HttpClient依然是可靠的伙伴。而如果追求简洁高效,尤其是在Android或某些微服务场景,OkHttp会让你爱不释手。

处理HTTP响应时常见的坑与解决方案?

在实际开发中,处理HTTP响应远不是拿到字符串那么简单。我踩过不少坑,也总结了一些经验,这里分享几个常见的“雷区”和我的处理方式。

一个最常见的坑是 超时问题。网络请求不是总能立刻得到响应的,如果服务器响应慢或者网络不稳定,你的程序可能会一直等下去,导致线程阻塞,甚至整个服务崩溃。我常遇到的是连接超时(Connect Timeout)和读取超时(Read Timeout)。连接超时是指客户端尝试与服务器建立连接的时间限制,如果超过这个时间还没连上,就放弃。读取超时是指连接建立后,客户端等待服务器发送数据的时间限制,如果数据传输中断或太慢,也会超时。

  • 解决方案: 务必设置合理的超时时间。
    • HttpURLConnection: connection.setConnectTimeout(milliseconds)connection.setReadTimeout(milliseconds)
    • HttpClient (Java 11+): HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5))HttpRequest.newBuilder().timeout(Duration.ofSeconds(10))。注意,HttpRequest上的timeout是整个请求的超时,包括连接和读取。
    • Apache HttpClient: 可以通过 RequestConfig 来设置,比如 RequestConfig.custom().setConnectTimeout(5000).setSocketTimeout(10000).build()
    • OkHttp: OkHttpClient.newBuilder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).build()

第二个大坑是 错误处理和HTTP状态码。很多人拿到响应后,只看有没有数据,不关心状态码。但HTTP状态码(2xx、3xx、4xx、5xx)是服务器告诉你的“语言”,它说明了请求的成功与否,以及失败的原因。比如404是资源未找到,500是服务器内部错误。不处理这些,你的程序可能会在不应该继续执行的时候继续,导致逻辑错误。

  • 解决方案: 总是检查响应状态码。
    • 对于2xx(成功),继续处理响应体。
    • 对于4xx(客户端错误)或5xx(服务器错误),应该抛出自定义异常或记录日志,并根据业务逻辑决定如何回滚或重试。我通常会封装一个方法,如果状态码不是2xx,就抛出 HttpClientErrorExceptionHttpServerErrorException 这样的异常。

第三个是 编码问题。HTTP响应体可能是UTF-8、GBK或者其他编码。如果你的程序没有正确地以服务器声明的编码去读取响应流,就会出现乱码。这在处理中文内容时尤其常见。

  • 解决方案: 优先使用响应头中Content-Type字段声明的编码。如果没有明确声明,或者声明不一致,UTF-8通常是安全的默认选择。
    • HttpURLConnection: new InputStreamReader(connection.getInputStream(), "UTF-8")
    • HttpClient (Java 11+): HttpResponse.BodyHandlers.ofString(Charset.forName("UTF-8"))
    • Apache HttpClient: EntityUtils.toString(entity, "UTF-8")
    • OkHttp: response.body().string() 默认会尝试从响应头中解析编码,如果没有则使用UTF-8。

第四个是 资源泄露。当你打开一个输入流(InputStream)或输出流(OutputStream),或者一个HttpURLConnectionCloseableHttpClient时,用完了一定要关闭它们。否则,连接资源会一直占用,导致系统资源耗尽,最终程序崩溃。

  • 解决方案: 使用 try-with-resources 语句。这是Java 7之后引入的语法糖,可以确保实现了 AutoCloseable 接口的资源在 try 块结束后自动关闭,即使发生异常也一样。
    • 所有现代HTTP客户端库(如Java 11 HttpClient、Apache CloseableHttpClient、OkHttp Response)都推荐或要求使用 try-with-resources 来管理它们的资源。
// 以Apache HttpClient为例,展示try-with-resources
try (CloseableHttpClient httpClient = HttpClients.createDefault();
     CloseableHttpResponse response = httpClient.execute(request)) {
    // 处理响应
    System.out.println("Status Code: " + response.getStatusLine().getStatusCode());
    HttpEntity entity = response.getEntity();
    if (entity != null) {
        System.out.println("Response Body: " + EntityUtils.toString(entity));
    }
} catch (IOException e) {
    e.printStackTrace();
}

这些坑,说起来简单,但实际写代码时一不留神就可能掉进去。养成良好的编程习惯,比如总是设置超时、检查状态码、正确处理编码和关闭资源,能省去你调试时的大量麻烦。

如何在HTTP请求中加入认证、头部信息或处理重定向?

在构建HTTP请求时,很多时候你需要更精细的控制,比如添加自定义头部、进行身份认证,或者处理服务器的重定向。这都是HTTP通信中非常常见的需求。

1. 添加头部信息 (Headers)

HTTP头部是客户端和服务器之间传递元数据的方式。比如User-Agent(标识客户端类型)、Content-Type(请求体类型)、Accept(期望的响应类型)、Authorization(认证凭证)等等。

  • HttpURLConnection: 相对繁琐,需要调用 connection.setRequestProperty("Header-Name", "Header-Value")
    connection.setRequestProperty("User-Agent", "MyJavaApp/1.0");
    connection.setRequestProperty("Content-Type", "application/json");
  • HttpClient (Java 11+): 链式调用非常方便。
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://example.com/api/data"))
            .header("User-Agent", "MyJavaHttpClient/1.0")
            .header("Content-Type", "application/json")
            .GET()
            .build();
  • Apache HttpClient: 同样直观。
    HttpGet request = new HttpGet("https://example.com/api/data");
    request.addHeader("User-Agent", "MyApacheHttpClient/1.0");
    request.addHeader("Content-Type", "application/json");
  • OkHttp: Request.Builder提供了header()addHeader()方法。
    Request request = new Request.Builder()
            .url("https://example.com/api/data")
            .header("User-Agent", "MyOkHttp/1.0")
            .addHeader("Content-Type", "application/json") // addHeader可以添加多个同名header
            .build();

2. 加入认证 (Authentication)

常见的认证方式有Basic认证和Bearer Token认证。

  • Basic认证: 这种方式是将用户名和密码用冒号连接,然后进行Base64编码,作为Authorization头部的值。
    String auth = "username:password";
    String encodedAuth = java.util.Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));
    // 在请求头中添加
    // .header("Authorization", "Basic " + encodedAuth)
  • Bearer Token认证: 这是OAuth 2.0等现代认证流程中常用的方式,将一个令牌(Token)放在Authorization头部,前面加上Bearer
    String token = "your_access_token_here";
    // 在请求头中添加
    // .header("Authorization", "Bearer " + token)

3. 处理重定向 (Redirects)

当服务器返回3xx状态码时,表示资源已移动或需要客户端重定向到另一个URL。大多数HTTP客户端默认会处理重定向,但有时你需要更精细的控制。

  • HttpURLConnection: 默认是跟随重定向的。你可以通过 connection.setInstanceFollowRedirects(false) 来禁用自动重定向,然后手动处理。
    connection.setInstanceFollowRedirects(false); // 禁用自动重定向
    // int responseCode = connection.getResponseCode();
    // if (responseCode == HttpURLConnection.HTTP_MOVED_TEMP || responseCode == HttpURLConnection.HTTP_MOVED_PERM) {
    //     String newUrl = connection.getHeaderField("Location");
    //     // 然后你就可以用newUrl再发一个请求
    // }
  • HttpClient (Java 11+): HttpClient.Builder提供了followRedirects()方法来控制重定向行为。
    • HttpClient.Redirect.NORMAL: 默认行为,跟随所有重定向。
    • HttpClient.Redirect.ALWAYS: 总是跟随重定向,包括POST到GET的重定向。
    • HttpClient.Redirect.NEVER: 从不跟随重定向。
      HttpClient client = HttpClient.newBuilder()
          .followRedirects(HttpClient.Redirect.NEVER) // 禁用自动重定向
          .build();
      // 如果响应是3xx,你可以从response.headers().firstValue("Location")获取新URL
  • Apache HttpClient: 默认是跟随重定向的。可以通过 RequestConfig 来配置。
    RequestConfig requestConfig

今天关于《Java发送HTTP请求的几种方式》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

相关阅读
更多>
最新阅读
更多>
课程推荐
更多>