杰瑞科技汇

Java如何调用HTTP接口?

java.net.HttpURLConnection (JDK 内置)

这是 Java 标准库自带的方式,无需添加任何依赖,但它比较底层,用起来相对繁琐,不推荐在新项目中使用,但了解其基本原理是有益的。

特点:

  • 优点:JDK 内置,无需引入外部库。
  • 缺点:API 繁琐,功能有限(如连接池、异步支持等),处理 JSON/XML 等数据需要手动转换。

示例:GET 请求

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpURLConnectionExample {
    public static void main(String[] args) {
        String urlString = "https://jsonplaceholder.typicode.com/posts/1";
        try {
            URL url = new URL(urlString);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            // 设置请求方法
            connection.setRequestMethod("GET");
            // 设置请求头
            connection.setRequestProperty("Accept", "application/json");
            // 获取响应码
            int responseCode = connection.getResponseCode();
            System.out.println("Response Code: " + responseCode);
            if (responseCode == HttpURLConnection.HTTP_OK) { // 200
                // 读取响应数据
                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: " + response.toString());
            } else {
                System.out.println("GET request failed");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Apache HttpClient (功能强大,工业级标准)

这是 Apache 基金会提供的 HTTP 客户端库,功能非常强大,支持连接池、重试、异步请求等,是许多大型项目和企业级应用的首选。

特点:

  • 优点:功能全面,稳定可靠,性能优秀(尤其是连接池),社区活跃。
  • 缺点:需要引入第三方依赖。

Maven 依赖

<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.3.1</version> <!-- 请使用最新版本 -->
</dependency>
<!-- 如果需要处理 JSON,可以添加 Jackson 或 Gson 依赖 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version> <!-- 请使用最新版本 -->
</dependency>

示例:GET 和 POST 请求

import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.StringEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.net.URIBuilder;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
public class ApacheHttpClientExample {
    private static final String BASE_URL = "https://jsonplaceholder.typicode.com";
    public static void main(String[] args) {
        // 1. GET 请求示例
        System.out.println("--- GET Request ---");
        getPosts();
        // 2. POST 请求示例
        System.out.println("\n--- POST Request ---");
        createPost();
    }
    public static void getPosts() {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 构建带查询参数的 URL
            URI uri = new URIBuilder(BASE_URL + "/posts")
                    .addParameter("userId", "1")
                    .build();
            HttpGet request = new HttpGet(uri);
            request.addHeader("Accept", "application/json");
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                System.out.println("Response Code: " + response.getCode());
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    String result = EntityUtils.toString(entity);
                    System.out.println("Response Body: " + result);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void createPost() {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(BASE_URL + "/posts");
            // 设置请求头
            httpPost.setHeader("Content-Type", "application/json");
            httpPost.setHeader("Accept", "application/json");
            // 设置请求体 (JSON)
            String jsonPayload = "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}";
            StringEntity entity = new StringEntity(jsonPayload, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                System.out.println("Response Code: " + response.getCode());
                HttpEntity responseEntity = response.getEntity();
                if (responseEntity != null) {
                    String result = EntityUtils.toString(responseEntity);
                    System.out.println("Response Body: " + result);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

OkHttp (现代、高效、易于使用)

OkHttp 是目前非常流行的 HTTP 客户端库,由 Square 公司(现已移交 OpenJS 基金会)开发,它以其简洁的 API、出色的性能(自动处理 GZIP、缓存、连接池)和对现代网络协议(HTTP/2, SPDY)的支持而闻名。

特点:

  • 优点:API 设计简洁易用,性能卓越,支持同步和异步请求,是 Android 开发的推荐库。
  • 缺点:需要引入第三方依赖。

Maven 依赖

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.12.0</version> <!-- 请使用最新版本 -->
</dependency>
<!-- 如果需要处理 JSON,可以添加 Jackson 或 Gson 依赖 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version> <!-- 请使用最新版本 -->
</dependency>

示例:GET 和 POST 请求

import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class OkHttpExample {
    private static final String BASE_URL = "https://jsonplaceholder.typicode.com";
    private static final OkHttpClient httpClient = new OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .build();
    private static final ObjectMapper objectMapper = new ObjectMapper();
    public static void main(String[] args) {
        // 1. GET 请求示例
        System.out.println("--- GET Request ---");
        getPost();
        // 2. POST 请求示例
        System.out.println("\n--- POST Request ---");
        createPost();
    }
    public static void getPost() {
        Request request = new Request.Builder()
                .url(BASE_URL + "/posts/1")
                .header("Accept", "application/json")
                .build();
        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            // 获取响应体
            String responseBody = response.body().string();
            System.out.println("Response Code: " + response.code());
            System.out.println("Response Body: " + responseBody);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void createPost() {
        // 构建请求体 (JSON)
        Post post = new Post();
        post.setTitle("foo");
        post.setBody("bar");
        post.setUserId(1);
        try {
            String jsonPayload = objectMapper.writeValueAsString(post);
            RequestBody body = RequestBody.create(
                    jsonPayload,
                    MediaType.parse("application/json; charset=utf-8")
            );
            Request request = new Request.Builder()
                    .url(BASE_URL + "/posts")
                    .post(body)
                    .header("Content-Type", "application/json")
                    .build();
            try (Response response = httpClient.newCall(request).execute()) {
                if (!response.isSuccessful()) {
                    throw new IOException("Unexpected code " + response);
                }
                String responseBody = response.body().string();
                System.out.println("Response Code: " + response.code());
                System.out.println("Response Body: " + responseBody);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 用于 JSON 序列化的简单 POJO 类
    static class Post {
        private String title;
        private String body;
        private int userId;
        // Getters and Setters
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }
        public String getBody() { return body; }
        public void setBody(String body) { this.body = body; }
        public int getUserId() { return userId; }
        public void setUserId(int userId) { this.userId = userId; }
    }
}

Spring RestTemplate (Spring 生态专用)

如果你的项目是基于 Spring 或 Spring Boot 的,那么使用 RestTemplateWebClient 是最佳选择。RestTemplate 是一个同步的 HTTP 客户端,在 Spring 生态中非常方便,因为它可以自动将 JSON 转换为 Java 对象(反序列化)。

特点:

  • 优点:与 Spring 框架无缝集成,支持自动 JSON 序列化/反序列化,模板方法调用简单。
  • 缺点:仅适用于 Spring 项目,在 Spring Boot 3.0 中已标记为不推荐,推荐使用 WebClient

Maven 依赖 (Spring Boot 项目中通常已包含)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

示例:GET 和 POST 请求

import org.springframework.web.client.RestTemplate;
import org.springframework.http.*;
import java.util.Collections;
public class RestTemplateExample {
    private static final String BASE_URL = "https://jsonplaceholder.typicode.com";
    private static final RestTemplate restTemplate = new RestTemplate();
    public static void main(String[] args) {
        // 1. GET 请求示例
        System.out.println("--- GET Request ---");
        getPost();
        // 2. POST 请求示例
        System.out.println("\n--- POST Request ---");
        createPost();
    }
    public static void getPost() {
        String url = BASE_URL + "/posts/1";
        // 直接指定返回类型,RestTemplate 会自动处理 JSON 到 Post 对象的转换
        Post post = restTemplate.getForObject(url, Post.class);
        System.out.println("Retrieved Post: " + post);
    }
    public static void createPost() {
        String url = BASE_URL + "/posts";
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        // 创建请求体 (Java 对象)
        Post newPost = new Post();
        newPost.setTitle("foo");
        newPost.setBody("bar");
        newPost.setUserId(1);
        // 构建 HttpEntity
        HttpEntity<Post> request = new HttpEntity<>(newPost, headers);
        // 发送 POST 请求并指定返回类型
        Post createdPost = restTemplate.postForObject(url, request, Post.class);
        System.out.println("Created Post: " + createdPost);
    }
    // 用于 JSON 序列化的简单 POJO 类
    static class Post {
        private int id;
        private String title;
        private String body;
        private int userId;
        // Getters and Setters
        public int getId() { return id; }
        public void setId(int id) { this.id = id; }
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }
        public String getBody() { return body; }
        public void setBody(String body) { this.body = body; }
        public int getUserId() { return userId; }
        public void setUserId(int userId) { this.userId = userId; }
        @Override
        public String toString() {
            return "Post{" +
                    "id=" + id +
                    ", title='" + title + '\'' +
                    ", body='" + body + '\'' +
                    ", userId=" + userId +
                    '}';
        }
    }
}

Spring WebClient (响应式,未来趋势)

WebClient 是 Spring 5 引入的响应式、非阻塞 HTTP 客户端,是 RestTemplate 的现代替代品,它基于 Project Reactor,非常适合构建高性能、高并发的应用。

特点:

  • 优点:非阻塞,性能更高,支持流式处理,是 Spring 5+ 和 Spring Boot 3+ 的推荐客户端。
  • 缺点:学习曲线较陡峭,需要理解响应式编程(Mono, Flux)。

示例:GET 和 POST 请求

import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.http.MediaType;
import reactor.core.publisher.Mono;
public class WebClientExample {
    private static final String BASE_URL = "https://jsonplaceholder.typicode.com";
    private static final WebClient webClient = WebClient.create(BASE_URL);
    public static void main(String[] args) {
        // 1. GET 请求示例
        System.out.println("--- GET Request ---");
        getPost();
        // 2. POST 请求示例
        System.out.println("\n--- POST Request ---");
        createPost();
    }
    public static void getPost() {
        Mono<Post> postMono = webClient.get()
                .uri("/posts/1")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToMono(Post.class);
        // 阻塞式获取结果(在 main 方法中为了演示,实际异步应用中应使用 subscribe)
        Post post = postMono.block();
        System.out.println("Retrieved Post: " + post);
    }
    public static void createPost() {
        Post newPost = new Post();
        newPost.setTitle("foo");
        newPost.setBody("bar");
        newPost.setUserId(1);
        Mono<Post> createdPostMono = webClient.post()
                .uri("/posts")
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON)
                .bodyValue(newPost) // 直接传入 Java 对象
                .retrieve()
                .bodyToMono(Post.class);
        Post createdPost = createdPostMono.block();
        System.out.println("Created Post: " + createdPost);
    }
    // 用于 JSON 序列化的简单 POJO 类
    static class Post {
        private int id;
        private String title;
        private String body;
        private int userId;
        // Getters and Setters
        public int getId() { return id; }
        public void setId(int id) { this.id = id; }
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }
        public String getBody() { return body; }
        public void setBody(String body) { this.body = body; }
        public int getUserId() { return userId; }
        public void setUserId(int userId) { this.userId = userId; }
        @Override
        public String toString() {
            return "Post{" +
                    "id=" + id +
                    ", title='" + title + '\'' +
                    ", body='" + body + '\'' +
                    ", userId=" + userId +
                    '}';
        }
    }
}

总结与如何选择

库名称 优点 缺点 适用场景
HttpURLConnection JDK 内置,无依赖 API 繁琐,功能弱 简单脚本、无外部依赖的极小项目
Apache HttpClient 功能强大,稳定,工业级 依赖较多,API 相对复杂 企业级 Java 应用,需要高级特性的后端服务
OkHttp API 简洁,性能高,流行 需要引入依赖 新项目,特别是移动端(Android)和需要高性能的 Java 应用
RestTemplate Spring 生态集成好,使用方便 仅限 Spring,已被标记不推荐 所有 Spring/Spring Boot 项目(但建议迁移到 WebClient)
WebClient 非阻塞,高性能,响应式 学习曲线陡峭,需要理解响应式编程 新的 Spring 5+/Spring Boot 3+ 项目,特别是高并发、微服务架构

选择建议:

  • 新项目,非 Spring 环境:优先选择 OkHttp,它在易用性和性能之间取得了很好的平衡。
  • 新项目,Spring/Spring Boot 环境:直接选择 WebClient,它是未来的方向。
  • 维护旧项目,使用 Spring:继续使用 RestTemplate 即可,除非有性能或新功能需求再考虑迁移。
  • 企业级、复杂系统Apache HttpClient 是一个非常成熟和可靠的选择。
  • 快速原型或无依赖需求:可以使用 HttpURLConnection,但实际开发中不推荐。
分享:
扫描分享到社交APP
上一篇
下一篇