当前位置: 首页 > article >正文

【SpringBoot整合系列】HttpClient远程访问的示例

前言

  1. 使用Apache的HttpClient库,添加Apache HttpClient的依赖。
  2. 工具类的封装。通常,工具类需要处理GET、POST请求,可能还有其他方法如PUT、DELETE。需要设计一个工具类,提供静态方法,可以发送请求,并处理响应。同时要考虑连接超时、读取超时的设置,以及请求头的配置,比如Content-Type、User-Agent等
  3. 然后,需要处理请求参数的封装。对于GET请求,参数通常是查询字符串;对于POST,可能需要表单参数或者JSON body。因此,工具类可能需要支持不同的参数类型,比如使用Map<String, String>来传递表单参数,或者直接传入一个JSON字符串作为请求体。
  4. 异常处理也是关键。网络请求可能会抛出IOException等异常,工具类需要捕获这些异常,并可能转换成自定义异常,或者返回null,或者记录日志,具体取决于设计选择。需要灵活处理错误,所以可能需要将异常抛出让调用者处理,或者在工具类内部处理并返回错误信息。
  5. 另外,响应处理方面,需要将HttpEntity转换为字符串,并正确关闭连接,确保资源释放。使用EntityUtils.toString时要注意字符编码,通常使用UTF-8。同时,需要关闭HttpResponse和HttpClient,或者使用try-with-resources来自动管理资源,但Apache HttpClient 4.x版本的response关闭可能需要注意,需要确保正确关闭流。

注意事项

  1. 工具类可能包含sendGet和sendPost方法。例如,sendGet接收URL和参数Map,构造带查询参数的URL;sendPost接收URL和可能的表单参数或JSON body,并设置合适的Content-Type。此外,可能需要设置请求头,比如设置JSON的Content-Type为application/json。

  2. 工具类的设计要尽量简洁,可配置。比如,可以允许自定义连接超时时间、读取超时时间,或者设置默认的请求头。可能使用HttpClient的配置,比如RequestConfig来设置超时参数。

  3. 可能的陷阱包括:未正确处理参数编码,比如在GET请求中,参数需要进行URL编码;在POST发送表单时,需要将参数转换为UrlEncodedFormEntity;发送JSON时,要使用StringEntity,并设置Content-Type为application/json。

  4. 需要注意线程安全,HttpClient通常建议重用实例,所以工具类中可能使用静态的CloseableHttpClient实例,并通过静态代码块初始化,确保线程安全。但需确认是否每次请求需要新的实例,或者可以共享。根据Apache HttpClient文档,建议重复使用同一个实例,因为它是线程安全的,并且管理连接池更高效。所以工具类中可以创建一个单例的HttpClient实例。

  5. 另外,工具类可能需要处理不同的Content-Type,比如POST发送JSON时,需要设置对应的头信息,并处理不同的数据体。因此,sendPost可能需要参数来指定发送的数据类型,或者通过方法重载来处理不同情况。

    • 例如,提供sendPostForm用于发送表单,sendPostJson用于发送JSON。或者,在方法中传递一个contentType参数,并根据类型构造不同的HttpEntity。

    • 或者,更灵活的方式是让调用者传入一个HttpEntity对象,这样工具类更通用,但使用起来可能不够方便。所以需要在易用性和灵活性之间权衡。

    • 这里工具类可以提供两个方法:一个处理表单参数(Map类型),另一个处理JSON字符串。

整体思路

  1. 引入Apache HttpClient依赖。

  2. 创建HttpClientUtil类,封装创建HttpClient实例的方法,配置超时等参数。

  3. 实现sendGet方法,处理参数拼接和编码。

  4. 实现sendPost方法,处理表单或JSON数据的提交。

  5. 处理响应,将结果转换为字符串。

  6. 异常处理,关闭资源。

  7. 提供使用示例。

代码示例

Maven依赖

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>

HttpClientUtil

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpClientUtil {

    // 超时配置(单位:毫秒)
    private static final int CONNECT_TIMEOUT = 5000;
    private static final int SOCKET_TIMEOUT = 5000;

    // 创建可复用的HttpClient实例
    private static final CloseableHttpClient httpClient = HttpClients.custom()
            .setDefaultRequestConfig(RequestConfig.custom()
                    .setConnectTimeout(CONNECT_TIMEOUT)
                    .setSocketTimeout(SOCKET_TIMEOUT)
                    .build())
            .build();

    /**
     * 发送GET请求
     * @param url 请求地址
     * @param params 请求参数
     * @return 响应内容
     */
    public static String sendGet(String url, Map<String, String> params) {
        HttpGet httpGet = new HttpGet(buildUri(url, params));
        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
            return handleResponse(response);
        } catch (IOException e) {
            throw new RuntimeException("GET请求失败", e);
        }
    }

    /**
     * 发送POST表单请求(application/x-www-form-urlencoded)
     * @param url 请求地址
     * @param formData 表单数据
     * @return 响应内容
     */
    public static String sendPostForm(String url, Map<String, String> formData) {
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> params = new ArrayList<>();
        formData.forEach((k, v) -> params.add(new BasicNameValuePair(k, v)));
        httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
        return executePost(httpPost);
    }

    /**
     * 发送POST JSON请求(application/json)
     * @param url 请求地址
     * @param json JSON字符串
     * @return 响应内容
     */
    public static String sendPostJson(String url, String json) {
        HttpPost httpPost = new HttpPost(url);
        StringEntity entity = new StringEntity(json, "UTF-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        return executePost(httpPost);
    }

    private static String executePost(HttpPost httpPost) {
        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            return handleResponse(response);
        } catch (IOException e) {
            throw new RuntimeException("POST请求失败", e);
        }
    }

    private static URI buildUri(String url, Map<String, String> params) {
        try {
            URIBuilder uriBuilder = new URIBuilder(url);
            if (params != null) {
                params.forEach(uriBuilder::addParameter);
            }
            return uriBuilder.build();
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException("URL格式错误", e);
        }
    }

    private static String handleResponse(CloseableHttpResponse response) throws IOException {
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200) {
            throw new RuntimeException("HTTP响应异常,状态码:" + statusCode);
        }
        HttpEntity entity = response.getEntity();
        return entity != null ? EntityUtils.toString(entity, "UTF-8") : null;
    }
}

使用示例

import java.util.HashMap;
import java.util.Map;

public class Example {
    public static void main(String[] args) {
        // GET请求示例
        String getUrl = "https://api.example.com/data";
        Map<String, String> params = new HashMap<>();
        params.put("key1", "value1");
        params.put("key2", "value2");
        String getResponse = HttpClientUtil.sendGet(getUrl, params);
        System.out.println("GET响应内容:" + getResponse);

        // POST表单示例
        String postFormUrl = "https://api.example.com/submit";
        Map<String, String> formData = new HashMap<>();
        formData.put("username", "testuser");
        formData.put("password", "testpass");
        String postFormResponse = HttpClientUtil.sendPostForm(postFormUrl, formData);
        System.out.println("POST表单响应:" + postFormResponse);

        // POST JSON示例
        String postJsonUrl = "https://api.example.com/submit-json";
        String jsonPayload = "{\"name\":\"John\", \"age\":30}";
        String postJsonResponse = HttpClientUtil.sendPostJson(postJsonUrl, jsonPayload);
        System.out.println("POST JSON响应:" + postJsonResponse);
    }
}

总结

工具类特点:

  • 线程安全: 使用单个共享的HttpClient实例,复用连接池资源
  • 超时配置: 统一设置5秒连接/读取超时
  • 编码处理: 统一使用UTF-8编码
  • 异常处理: 将检查异常转换为运行时异常,简化调用
  • 支持多种请求:
    • GET请求(带查询参数)
    • POST表单(application/x-www-form-urlencoded)
    • POST JSON(application/json)
  • 响应处理: 自动验证状态码并转换响应内容

注意事项:

  • 根据实际情况调整超时时间配置
  • 生产环境建议添加日志记录
  • 需要处理其他状态码(如3xx重定向)时可扩展handleResponse方法
  • 如需添加自定义请求头,可扩展方法参数
  • 注意及时释放资源,使用try-with-resources自动关闭响应

可根据实际需求进一步扩展支持:

  • 文件上传
  • HTTPS配置
  • 代理设置
  • 请求重试机制
  • 更完善的异常处理等

http://www.kler.cn/a/554744.html

相关文章:

  • ”将一维数组a中的n个数逆序存放到原数组“的算法时间和空间复杂度
  • UNIAPP开发之利用阿里RTC服务实现音视频通话后端THINKPHP5
  • 利用爬虫精准获取商品销量详情:实战案例指南
  • luci界面开发中的MVC架构——LuCI介绍(二)
  • ubuntu22.04桥接模式开代理
  • Mac M3/M4 本地部署Deepseek并集成vscode
  • 氧传感器芯片cj125驱动
  • XTOM-TRANSFORM自动化三维测量系统用于汽车零部件质量控制
  • Unity shader glsl着色器特效之 模拟海面海浪效果
  • Redis 存在线程安全问题吗?为什么?
  • 快速入门——Vue框架快速上手
  • 神经网络八股(1)
  • C++ 课程设计 汇总(含源码)
  • Ubuntu:wvp-GB28181-pro安装、运行
  • 记录一次部署PC端网址全过程
  • Java集合框架中常用类及其底层数据结构的详细分类
  • 使用ESP32与INMP441麦克风模块实现音频传输
  • MySQL执行计划Explain如何分析 SQL语句?
  • Spring Boot项目中实现Excel的导出功能
  • HC32F460_GPIO驱动库