HttpClient工具类编写

HttpClient

介绍

HttpClient是Apache Jakarta Common下的一个子项目,它提供了一个高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包。它支持HTTP协议最新的版本和建议,并实现了Http1.0和Http1.1协议。

HttpClient具有可扩展的面向对象的结构,实现了Http全部的方法,包括GET、POST、PUT、DELETE、HEAD、OPTIONS以及TRACE。它支持HTTPS协议,并允许通过Http代理建立透明的连接,以及利用CONNECT方法建立隧道的https连接。此外,它还支持多种认证方案,如Basic、Digest、NTLMv1、NTLMv2、NTLM2 Session以及SNPNEGO/Kerberos,并允许使用插件式的自定义认证方案。

在项目中,HttpClient的使用场景广泛,如爬虫、多系统之间的接口交互等。在分布式项目中,前端系统需要调用后台的数据并初始化时,可以使用HttpClient进行通信。

在使用HttpClient时,通常需要导入相关的依赖库,并根据具体需求配置HttpClient的行为,如设置连接超时、读取超时等。然后,可以使用HttpClient发送GET、POST等请求,并处理返回的响应。

在SpringBoot后端项目开发时,什么时候需要HttpClient?

调用第三方服务的时候

构造HTTP请求

HttpClient的maven坐标:

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

其实阿里云oss已经依赖了httpclient,所以无需再引入这个包

HttpClient的核心API:

  • HttpClient(HttpClient对象接口):Http客户端对象类型,使用该类型对象可发起Http请求。

  • HttpClients:可认为是构建器,可创建HttpClient对象。

  • CloseableHttpClient(HttpClient对象实现类):实现类,实现了HttpClient接口。

  • HttpGet(Http请求对象):Get方式请求类型。

  • HttpPost(Http请求对象):Post方式请求类型。

HttpClient发送请求步骤:

  • 创建HttpClient对象

  • 创建Http请求对象

  • 调用HttpClient的execute方法发送请求

 GET请求

实现步骤:

  1. 创建HttpClient对象

  2. 创建请求对象

  3. 发送请求,接受响应结果

  4. 解析结果

  5. 关闭资源

package com.sky.test;
​
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;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
​
@SpringBootTest
public class HttpClientTest {
​
    /**
     * 测试通过httpclient发送GET方式的请求
     */
    @Test
    public void testGET() throws Exception{
        //创建httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
​
        //创建请求对象
        HttpGet httpGet = new HttpGet("http://localhost:8080/user/shop/status");
​
        //发送请求,接受响应结果
        CloseableHttpResponse response = httpClient.execute(httpGet);
​
        //获取服务端返回的状态码
        int statusCode = response.getStatusLine().getStatusCode();
        System.out.println("服务端返回的状态码为:" + statusCode);
​
        HttpEntity entity = response.getEntity();
        String body = EntityUtils.toString(entity);
        System.out.println("服务端返回的数据为:" + body);
​
        //关闭资源
        response.close();
        httpClient.close();
    }
}

在访问http://localhost:8080/user/shop/status请求时,需要提前启动项目。

注意:

  • 创建HttpClient对象需要调用HttpClients.createDefault()方法,创建一个CloseableHttpClient对象
  • 创建请求对象:HttpGet httpGet = new HttpGet("请求url");
  • 利用HttpCliet对象执行execute请求对象,得到响应结果response:CloseableHttpResponse response = httpClient.execute(httpGet);
  • 解析响应结果:

            int statusCode = response.getStatusLine().getStatusCode();
            System.out.println("服务端返回的状态码为:" + statusCode);

            HttpEntity entity = response.getEntity();
            String body = EntityUtils.toString(entity);
            System.out.println("服务端返回的数据为:" + body);

  • 关闭资源:

        response.close();
        httpClient.close();

Post请求

在HttpClientTest中添加POST方式请求方法,相比GET请求来说,POST请求若携带参数需要封装请求体对象,并将该对象设置在请求对象中。

实现步骤:

  1. 创建HttpClient对象

  2. 创建请求对象

  3. 发送请求,接收响应结果

  4. 解析响应结果

  5. 关闭资源

	/**
     * 测试通过httpclient发送POST方式的请求
     */
    @Test
    public void testPOST() throws Exception{
        // 创建httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();

        //创建请求对象
        HttpPost httpPost = new HttpPost("http://localhost:8080/admin/employee/login");

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("username","admin");
        jsonObject.put("password","123456");

        StringEntity entity = new StringEntity(jsonObject.toString());
        //指定请求编码方式
        entity.setContentEncoding("utf-8");
        //数据格式
        entity.setContentType("application/json");
        httpPost.setEntity(entity);

        //发送请求
        CloseableHttpResponse response = httpClient.execute(httpPost);

        //解析返回结果
        int statusCode = response.getStatusLine().getStatusCode();
        System.out.println("响应码为:" + statusCode);

        HttpEntity entity1 = response.getEntity();
        String body = EntityUtils.toString(entity1);
        System.out.println("响应数据为:" + body);

        //关闭资源
        response.close();
        httpClient.close();
    }

HttpPost请求对象需要利用setEntity方法补充json格式的请求体数据。

1、打包Json数据

       JSONObject jsonObject = new JSONObject();
        jsonObject.put("username","admin");
        jsonObject.put("password","123456");

        StringEntity entity = new StringEntity(jsonObject.toString());

2、设置请求编码方式和数据格式

        //指定请求编码方式
        entity.setContentEncoding("utf-8");
        //数据格式
        entity.setContentType("application/json");

3、setEntity打包Json数据

httpPost.setEntity(entity);

4、利用HttpClient对象的execute方法发送请求
        CloseableHttpResponse response = httpClient.execute(httpPost);

编写HttpClient工具类

/**
 * Http工具类
 */
public class HttpClientUtil {

    static final  int TIMEOUT_MSEC = 5 * 1000;

    /**
     * 发送GET方式请求
     * @param url
     * @param paramMap
     * @return
     */
    public static String doGet(String url,Map<String,String> paramMap){
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();

        String result = "";
        CloseableHttpResponse response = null;

        try{
            URIBuilder builder = new URIBuilder(url);
            if(paramMap != null){
                for (String key : paramMap.keySet()) {
                    builder.addParameter(key,paramMap.get(key));
                }
            }
            URI uri = builder.build();

            //创建GET请求
            HttpGet httpGet = new HttpGet(uri);

            //发送请求
            response = httpClient.execute(httpGet);

            //判断响应状态
            if(response.getStatusLine().getStatusCode() == 200){
                result = EntityUtils.toString(response.getEntity(),"UTF-8");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                response.close();
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return result;
    }

    /**
     * 发送POST方式请求
     * @param url
     * @param paramMap
     * @return
     * @throws IOException
     */
    public static String doPost(String url, Map<String, String> paramMap) throws IOException {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";

        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);

            // 创建参数列表
            if (paramMap != null) {
                List<NameValuePair> paramList = new ArrayList();
                for (Map.Entry<String, String> param : paramMap.entrySet()) {
                    paramList.add(new BasicNameValuePair(param.getKey(), param.getValue()));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
                httpPost.setEntity(entity);
            }

            httpPost.setConfig(builderRequestConfig());

            // 执行http请求
            response = httpClient.execute(httpPost);

            resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return resultString;
    }

    /**
     * 发送POST方式请求
     * @param url
     * @param paramMap
     * @return
     * @throws IOException
     */
    public static String doPost4Json(String url, Map<String, String> paramMap) throws IOException {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";

        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);

            if (paramMap != null) {
                //构造json格式数据
                JSONObject jsonObject = new JSONObject();
                for (Map.Entry<String, String> param : paramMap.entrySet()) {
                    jsonObject.put(param.getKey(),param.getValue());
                }
                StringEntity entity = new StringEntity(jsonObject.toString(),"utf-8");
                //设置请求编码
                entity.setContentEncoding("utf-8");
                //设置数据类型
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }

            httpPost.setConfig(builderRequestConfig());

            // 执行http请求
            response = httpClient.execute(httpPost);

            resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return resultString;
    }
    private static RequestConfig builderRequestConfig() {
        return RequestConfig.custom()
                .setConnectTimeout(TIMEOUT_MSEC)
                .setConnectionRequestTimeout(TIMEOUT_MSEC)
                .setSocketTimeout(TIMEOUT_MSEC).build();
    }

}

1. doGet(String url, Map<String,String> paramMap)

输入:

  • url: 要请求的URL地址。
  • paramMap: 一个包含请求参数的 Map 对象,键和值都是 String 类型。

输出:

  • 返回一个 String 类型的结果,表示 HTTP 响应的正文内容。

功能:

  • 该方法用于构造一个 HTTP GET 请求。它首先创建一个 HttpClient 对象,然后使用 URIBuilder 来添加请求参数。如果响应状态码为200,它将响应正文转换为字符串并返回。

2. doPost(String url, Map<String, String> paramMap) throws IOException

输入:

  • url: 要请求的URL地址。
  • paramMap: 一个包含请求参数的 Map 对象。

输出:

  • 返回一个 String 类型的结果,表示 HTTP 响应的正文内容。

功能:

  • 该方法用于构造一个 HTTP POST 请求,请求参数以表单形式发送。它创建一个 HttpPost 对象,并将参数作为 UrlEncodedFormEntity 设置到请求中。然后发送请求并返回响应正文。

3. doPost4Json(String url, Map<String, String> paramMap) throws IOException

输入:

  • url: 要请求的URL地址。
  • paramMap: 一个包含请求参数的 Map 对象。

输出:

  • 返回一个 String 类型的结果,表示 HTTP 响应的正文内容。

功能:

  • 该方法用于构造一个 HTTP POST 请求,请求参数以 JSON 格式发送。它创建一个 HttpPost 对象,并将参数构造为 JSON 对象,然后设置到请求的 StringEntity 中。请求的 Content-Type 被设置为 application/json,然后发送请求并返回响应正文。

4. builderRequestConfig()

输入:

  • 无。

输出:

  • 返回一个 RequestConfig 对象。

功能:

  • 这是一个私有方法,用于构建 RequestConfig 对象,它设置了连接超时、请求超时和套接字超时的默认值。

使用HttpClient工具类

以下是三个示例,展示如何使用 HttpClientUtil 类提供的前三个方法构造 HTTP 请求,并分析响应结果:

示例 1: 使用 doGet 方法发送 GET 请求

假设我们想要从 http://example.com/api/data 获取一些数据,并且有一些查询参数。

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

public class HttpClientUtilExample {
    public static void main(String[] args) {
        // 准备请求参数
        Map<String, String> params = new HashMap<>();
        params.put("param1", "value1");
        params.put("param2", "value2");

        // 发送 GET 请求
        String result = HttpClientUtil.doGet("http://example.com/api/data", params);

        // 分析响应结果
        if (result != null && !result.isEmpty()) {
            System.out.println("Response: " + result);
            // 这里可以根据需要解析 JSON 或 XML 响应体
        } else {
            System.out.println("No response received or error occurred.");
        }
    }
}

示例 2: 使用 doPost 方法发送表单 POST 请求

假设我们想要向 http://example.com/api/login 发送登录请求。

public class HttpClientUtilExample {
    public static void main(String[] args) {
        // 准备登录参数
        Map<String, String> params = new HashMap<>();
        params.put("username", "user123");
        params.put("password", "pass123");

        try {
            // 发送 POST 请求
            String result = HttpClientUtil.doPost("http://example.com/api/login", params);

            // 分析响应结果
            if (result != null && !result.isEmpty()) {
                System.out.println("Login Response: " + result);
                // 根据响应内容判断登录是否成功
            } else {
                System.out.println("Login failed or error occurred.");
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("An error occurred during the POST request.");
        }
    }
}

示例 3: 使用 doPost4Json 方法发送 JSON POST 请求

假设我们想要向 http://example.com/api/register 发送注册请求,并且请求体是 JSON 格式。

public class HttpClientUtilExample {
    public static void main(String[] args) {
        // 准备登录参数
        Map<String, String> params = new HashMap<>();
        params.put("username", "user123");
        params.put("password", "pass123");

        try {
            // 发送 POST 请求
            String result = HttpClientUtil.doPost("http://example.com/api/login", params);

            // 分析响应结果
            if (result != null && !result.isEmpty()) {
                System.out.println("Login Response: " + result);
                // 根据响应内容判断登录是否成功
            } else {
                System.out.println("Login failed or error occurred.");
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("An error occurred during the POST request.");
        }
    }
}

在每个示例中,我们首先创建了一个包含请求参数的 Map 对象,然后调用相应的方法发送请求。请求完成后,我们检查响应结果是否为 null 或者为空,如果不是,则打印出响应内容。在处理 POST 请求的示例中,我们还捕获了可能发生的 IOException

doPostdoPost4JsonHttpClientUtil 类中定义的两个发送 POST 请求的方法,它们的主要区别在于发送请求体的格式不同

doPost 方法:

  • 请求体格式doPost 方法发送的请求体是标准的表单格式(application/x-www-form-urlencoded)。
  • 参数构建:它使用 UrlEncodedFormEntity 来构建请求体,这适用于传统的表单提交,其中键值对被编码为字符串,并用 & 符号分隔。
  • 适用场景:当后端服务期望接收表单数据时,使用此方法。

doPost4Json 方法:

  • 请求体格式doPost4Json 方法发送的请求体是 JSON 格式(application/json)。
  • 参数构建:它使用 JSONObject 来构建请求体,然后将 JSON 对象转换为字符串,并设置到 StringEntity 中。
  • 适用场景:当后端服务期望接收 JSON 格式的请求体时,使用此方法。

代码层面的区别:

  • doPost 方法中,参数是通过遍历 paramMap 并使用 BasicNameValuePair 对象添加到 paramList 中,然后构建 UrlEncodedFormEntity 对象。
  • doPost4Json 方法中,参数是通过遍历 paramMap 并使用 JSONObject 的 put 方法添加到 JSON 对象中,然后构建 StringEntity 对象,并设置正确的 Content-Encoding 和 Content-Type

实际使用时的考虑因素:

  • 内容类型:客户端需要根据服务器端的期望来设置正确的 Content-Type
  • 编码:对于 JSON 请求体,需要确保字符编码正确设置为 UTF-8,以避免编码问题。
  • API 约定:不同的 API 可能对请求体的格式有不同的要求,选择正确的方法来满足这些要求是非常重要的。

在实际应用中,选择使用 doPost 还是 doPost4Json 取决于你要与之交互的 API 的具体要求。通常,现代的 RESTful API 更倾向于使用 JSON 格式,因为它结构化更好、更易于解析。然而,一些旧的或特定的系统可能仍然使用传统的表单数据格式。

传统的表单格式,通常指的是 application/x-www-form-urlencoded 格式,这是一种用于 HTTP 请求的编码方式,特别是用于表单数据的提交。在 Web 开发中,这是最常见的数据提交方式之一。

特点:

  1. 键值对:数据由键值对组成,其中键(key)和值(value)由等号(=)连接。
  2. 编码:所有键和值都必须进行百分比编码(也称为 URL 编码),以确保特殊字符可以安全地传输。
  3. 分隔:键值对之间通过和号(&)分隔。
  4. 兼容性:几乎所有的服务器端语言和框架都支持这种格式,因此它具有很好的兼容性。

示例:

假设有一个表单,包含用户名和密码字段,用户填写后提交到服务器:

<form action="/submit" method="post"> <input type="text" name="username" value="user123"> <input type="password" name="password" value="pass123"> <input type="submit" value="Submit"> </form>

当用户提交这个表单时,浏览器会将数据编码成以下格式:

username=user123&password=pass123

HTTP 请求示例:

POST /submit HTTP/1.1 Host: example.com Content-Type: application/x-www-form-urlencoded username=user123&password=pass123

与传统表单格式相比的 JSON:

  • 结构:JSON 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。
  • 格式:JSON 数据是自描述的,由键值对组成,键是字符串,值可以是字符串、数字、数组、布尔值或其他 JSON 对象。
  • 数据类型:JSON 支持更丰富的数据类型,如数组和嵌套对象。
  • 使用场景:JSON 通常用于 API 通信,特别是 RESTful API。

JSON 请求示例:

POST /api/register HTTP/1.1 Host: example.com Content-Type: application/json; charset=utf-8 { "username": "user123", "password": "pass123" }

在现代 Web 应用和 API 开发中,JSON 格式因其结构化和易于处理的特点而变得越来越流行,尤其是在需要传输复杂数据结构时。然而,传统的表单格式由于其简单性和广泛的支持,仍然在特定场景下被广泛使用。

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值