使用HttpClient发送Http请求详细示例

目录

一、GET无参,HTTP发送示例

二、GET有参(方式一:拼接URL参数)

三、GET有参(方式二:使用URI方式)

四、POST有参(对象+普通参数)

五、application/x-www-form-urlencoded表单请求(示例)

知识补充:application/x-www-form-urlencoded和multipart/form-data

(1)application/x-www-urlencoded

(3)multipart/form-data

六、发送文件示例

七、发送流示例


HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。

HTTP和浏览器有点像,但却不是浏览器。很多人觉得既然HttpClient是一个HTTP客户端编程工具,很多人把他当做浏览器来理解,但是其实HttpClient不是浏览器,它是一个HTTP通信库,因此它只提供一个通用浏览器应用程序所期望的功能子集,最根本的区别是HttpClient中没有用户界面,浏览器需要一个渲染引擎来显示页面,并解释用户输入,例如鼠标点击显示页面上的某处,有一个布局引擎,计算如何显示HTML页面,包括级联样式表和图像。javascript解释器运行嵌入HTML页面或从HTML页面引用的javascript代码。来自用户界面的事件被传递到javascript解释器进行处理。除此之外,还有用于插件的接口,可以处理Applet,嵌入式媒体对象(如pdf文件,Quicktime电影和Flash动画)或ActiveX控件(可以执行任何操作)。HttpClient只能以编程的方式通过其API用于传输和接受HTTP消息。

在使用HttpClient前,首先需要导入其maven依赖,另外还引入了fastjson的依赖,在示例中会用到


   org.apache.httpcomponents
   httpclient
   4.5.6


   com.alibaba
   fastjson
   1.2.58

本文示例使用springboot的运行环境,springboot运行环境的搭建请参照我的这篇文章:快速构建一个springboot项目。

在运行测试案例前需要先启动springboot项目,然后再启动测试类进行测试,如果不知道怎样搭建springboot的单元测试,可以参照我的这篇文章:编写springboot单元测试类

以下所有示例亲测有效。

一、GET无参,HTTP发送示例

代码示例:

/**
     * GET---无参测试
     */
    @Test
    public void doGetNoParam() {
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        // 创建Get请求
        HttpGet httpGet = new HttpGet("http://localhost:8080/http/doGetNoParam");
        // 响应模型
        CloseableHttpResponse response = null;
        try {
            // 由客户端执行(发送)Get请求
            response = httpClient.execute(httpGet);
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("响应内容长度为:" + responseEntity.getContentLength());
                System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

对应的接收示例:

@RequestMapping("doGetNoParam")
public String doGetNoParam(){
        return "doGetNoParam...";
    }

执行结果:

使用HttpClient发送Http请求详细示例_第1张图片

二、GET有参(方式一:拼接URL参数)

代码示例:

/**
     * GET---有参测试 (方式一:手动在url后面加上参数)
     */
    @Test
    public void doGetAppendUrl() {
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        // 参数
        StringBuffer params = new StringBuffer();
        try {
            // 字符数据最好encoding以下;这样一来,某些特殊字符才能传过去(如:某人的名字就是“&”,不encoding的话,传不过去)
            params.append("name=" + URLEncoder.encode("&&", "utf-8"));
            params.append("&");
            params.append("age=24");
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        }

        // 创建Get请求
        HttpGet httpGet = new HttpGet("http://localhost:8080/http/doGetAppendUrl" + "?" + params);
        // 响应模型
        CloseableHttpResponse response = null;
        try {
            // 配置信息
            RequestConfig requestConfig = RequestConfig.custom()
                    // 设置连接超时时间(单位毫秒)
                    .setConnectTimeout(5000)
                    // 设置请求超时时间(单位毫秒)
                    .setConnectionRequestTimeout(5000)
                    // socket读写超时时间(单位毫秒)
                    .setSocketTimeout(5000)
                    // 设置是否允许重定向(默认为true)
                    .setRedirectsEnabled(true).build();

            // 将上面的配置信息 运用到这个Get请求里
            httpGet.setConfig(requestConfig);

            // 由客户端执行(发送)Get请求
            response = httpClient.execute(httpGet);

            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("响应内容长度为:" + responseEntity.getContentLength());
                System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

对应接收示例:

@GetMapping("/doGetAppendUrl")
    public String doGetAppendUrl(String name,Integer age){
        return name + ",ta的年龄为" + age + "岁了";
    }

执行结果:

使用HttpClient发送Http请求详细示例_第2张图片

三、GET有参(方式二:使用URI方式)

代码示例:

/**
     * GET---有参测试 (方式二:将参数放入键值对类中,再放入URI中,从而通过URI得到HttpGet实例)
     */
    @Test
    public void doGetByURI() {
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        // 参数
        URI uri = null;
        try {
            // 将参数放入键值对类NameValuePair中,再放入集合中
            List params = new ArrayList<>();
            params.add(new BasicNameValuePair("name", "&&"));
            params.add(new BasicNameValuePair("age", "18"));
            // 设置uri信息,并将参数集合放入uri;
            // 注:这里也支持一个键值对一个键值对地往里面放setParameter(String key, String value)
            uri = new URIBuilder().setScheme("http").setHost("localhost")
                    .setPort(8080).setPath("/http/doGetAppendUrl")
                    .setParameters(params).build();
        } catch (URISyntaxException e1) {
            e1.printStackTrace();
        }
        // 创建Get请求
        HttpGet httpGet = new HttpGet(uri);

        // 响应模型
        CloseableHttpResponse response = null;
        try {
            // 配置信息
            RequestConfig requestConfig = RequestConfig.custom()
                    // 设置连接超时时间(单位毫秒)
                    .setConnectTimeout(5000)
                    // 设置请求超时时间(单位毫秒)
                    .setConnectionRequestTimeout(5000)
                    // socket读写超时时间(单位毫秒)
                    .setSocketTimeout(5000)
                    // 设置是否允许重定向(默认为true)
                    .setRedirectsEnabled(true).build();

            // 将上面的配置信息 运用到这个Get请求里
            httpGet.setConfig(requestConfig);

            // 由客户端执行(发送)Get请求
            response = httpClient.execute(httpGet);

            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("响应内容长度为:" + responseEntity.getContentLength());
                System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

对应的接收示例跟上边方法一是一样的,在此就不过多描述了。

四、POST有参(对象+普通参数)

POST无参基本上跟GET传参差不多,就是new HttpPost()而已。Post传基本参数,可以通过拼接Url的方式,也可以使用URI的方式,此示例把对象传参和基本传参结合在一起,以便囊括常用的传参方式。

使用URI传递普通参数,使用Entity传递对象参数,其中用到的User对象是自己创建的简单对象类型,里边有一些Get和Set方法,在此就不一一列举了。

代码示例:

/**
     * POST---有参测试(普通参数 + 对象参数)
     */
    @Test
    public void doPostUseParam() {
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        // 创建Post请求
        // 参数
        URI uri = null;
        try {
            // 将参数放入键值对类NameValuePair中,再放入集合中
            List params = new ArrayList<>();
            params.add(new BasicNameValuePair("flag", "8"));
            params.add(new BasicNameValuePair("meaning", "哈哈哈"));
            // 设置uri信息,并将参数集合放入uri;
            // 注:这里也支持一个键值对一个键值对地往里面放setParameter(String key, String value)
            uri = new URIBuilder().setScheme("http").setHost("localhost").setPort(8080)
                    .setPath("/http/doPostUseParam").setParameters(params).build();
        } catch (URISyntaxException e1) {
            e1.printStackTrace();
        }
        HttpPost httpPost = new HttpPost(uri);
        // 创建user参数
        User user = new User();
        user.setUserName("Merry");
        user.setUserSex("女");
        // 将user对象转换为json字符串,并放入entity中
        StringEntity entity = new StringEntity(JSON.toJSONString(user), "UTF-8");
        // post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
        httpPost.setEntity(entity);
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        // 响应模型
        CloseableHttpResponse response = null;
        try {
            // 由客户端执行(发送)Post请求
            response = httpClient.execute(httpPost);
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();

            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("响应内容长度为:" + responseEntity.getContentLength());
                System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

防止响应乱码,可以主动设置编码

String response = EntityUtils.toString(responseEntity, UTF_8);

对应接收示例:

@PostMapping("/doPostUseParam")
    public String doPostUseParam(@RequestBody User user, String meaning, Integer flag) {
        return user.getUserName() + ",ta是" + user.getUserSex() + "生。这意味着" + meaning + flag;
    }

执行结果:

使用HttpClient发送Http请求详细示例_第3张图片

五、application/x-www-form-urlencoded表单请求(示例)

代码示例:

/**
     * POST---application/x-www-form-urlencoded 表单请求
     */
    @Test
    public void doPostUseForm() {
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpPost httpPost = new HttpPost("http://localhost:8080/http/doPostUseForm");
        httpPost.setHeader("Content-Type","application/x-www-form-urlencoded");

        // 将参数放入键值对类NameValuePair中,再放入集合中
        List params = new ArrayList<>();
        params.add(new BasicNameValuePair("bookName", "语文"));
        params.add(new BasicNameValuePair("message", "这是一本好书"));
        UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params, UTF_8);
        httpPost.setEntity(formEntity);

        CloseableHttpResponse response = null;
        try {
            // 由客户端执行(发送)Post请求
            response = httpClient.execute(httpPost);
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("响应内容长度为:" + responseEntity.getContentLength());
                System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

对应接收示例:

@PostMapping("/doPostUseForm")
    public String doPostUseForm(String bookName, String message) {
        return bookName + ":" + message;
    }

知识补充:application/x-www-form-urlencoded和multipart/form-data

一个 HTML 表单中的 enctype 有三种类型

  • application/x-www-urlencoded
  • multipart/form-data
  • text-plain

默认情况下是 application/x-www-urlencoded,当表单使用 POST 请求时,数据会被以 x-www-urlencoded 方式编码到 Body 中来传送,而如果 GET 请求,则是附在 url 链接后面来发送。GET 请求只支持 ASCII 字符集,因此,如果我们要发送更大字符集的内容,我们应使用 POST 请求。
如果要发送大量的二进制数据(non-ASCII),application/x-www-form-urlencoded 显然是低效的,因为它需要用 3 个字符来表示一个 non-ASCII 的字符。因此,这种情况下,应该使用 “multipart/form-data” 格式。

application / x-www-form-urlencoded对于发送大量二进制数据或包含非ASCII字符的文本效率低下

multipart / form-data应该用于提交包含文件,非ASCII数据和二进制数据的表单

(1)application/x-www-urlencoded

我们在通过 HTTP 向服务器发送 POST 请求提交数据,都是通过 form 表单形式提交的,代码如下:

提交时会向服务器端发出这样的数据(已经去除部分不相关的头信息),数据如下:

POST / HTTP/1.1
Content-Type:application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: w.sohu.com
Content-Length: 21
Connection: Keep-Alive
Cache-Control: no-cache

txt1=hello&txt2=world

对于普通的 HTML Form POST请求,它会在头信息里使用 Content-Length 注明内容长度。请求头信息每行一条,空行之后便是 Body,即“内容”(entity。内容的格式是在头信息中的 Content-Type 指定的,如上是 application/x-www-form-urlencoded,这意味着消息内容会经过 URL 格式编码,就像在 GET请 求时 URL 里的 QueryString 那样。如:txt1=hello&txt2=world。

(3)multipart/form-data

multipart/form-data 定义在 rfc2388 中,最早的 HTTP POST 是不支持文件上传的,给编程开发带来很多问题。但是在1995年,ietf 出台了 rfc1867,也就是《RFC 1867 -Form-based File Upload in HTML》,用以支持文件上传。所以 Content-Type 的类型扩充了multipart/form-data 用以支持向服务器发送二进制数据。因此,发送 POST 请求时候,表单 属性 enctype 共有二个值可选,这个属性管理的是表单的 MIME 编码:

  • ① application/x-www-form-urlencoded (默认值)
  • ② multipart/form-data

注:form 表单中 enctype 的默认值是 enctype="application/x- www-form-urlencoded".
通过 form 表单提交文件操作如下:

浏览器将会发送以下数据:

POST /t2/upload.do HTTP/1.1
User-Agent: SOHUWapRebot
Accept-Language: zh-cn,zh;q=0.5
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Content-Length: 60408
Content-Type:multipart/form-data; boundary=ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
Host: w.sohu.com

--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
Content-Disposition: form-data; name="city"

Santa colo
--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
Content-Disposition: form-data;name="desc"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
 
...
--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
Content-Disposition: form-data;name="pic"; filename="photo.jpg"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
 
... binary data of the jpg ...
--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC--

从上面的 multipart/form-data 格式发送的请求的样式来看,它包含了多个 Parts,每个 Part 都包含头信息部分,
Part 头信息中必须包含一个 Content-Disposition 头,其他的头信息则为可选项, 比如 Content-Type 等。
Content-Disposition 包含了 type 和 一个名字为 name 的 parameter,type 是 form-data,name 参数的值则为表单控件(也即 field)的名字,如果是文件,那么还有一个 filename 参数,值就是文件名。对于可选的 Content-Type(如果没有的话),默认就是 text/plain。

注意:
如果文件内容是通过填充表单来获得,那么上传的时候,Content-Type 会被自动设置(识别)成相应的格式,如果没法识别,那么就会被设置成 application/octet-stream”。

六、发送文件示例

如果想要灵活方便的传输文件的话,除了引入org.apache.httpcomponents基本的httpclient依赖外再额外引入org.apache.httpcomponents的httpmime依赖。
P.S.:即便不引入httpmime依赖,也是能传输文件的,不过功能不够强大。

在pom.xml中额外引入:


        
            org.apache.httpcomponents
            httpmime
            4.5.5
        

代码示例:

/**
     *
     * 发送文件
     *
     * multipart/form-data传递文件(及相关信息)
     *
     * 注:如果想要灵活方便的传输文件的话,
     *    除了引入org.apache.httpcomponents基本的httpclient依赖外
     *    再额外引入org.apache.httpcomponents的httpmime依赖。
     *    追注:即便不引入httpmime依赖,也是能传输文件的,不过功能不够强大。
     *
     */
    @Test
    public void doPostUseFile() {
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpPost httpPost = new HttpPost("http://localhost:8080/http/doPostUseFile");
        CloseableHttpResponse response = null;
        try {
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            // 第一个文件
            String filesKey = "files";
            File file1 = new File("D:\\MyFiles\\poi\\picture.jpg");
            multipartEntityBuilder.addBinaryBody(filesKey, file1);
            // 第二个文件(多个文件的话,使用同一个key就行,后端用数组或集合进行接收即可)
            File file2 = new File("D:\\MyFiles\\poi\\图片.jpg");
            // 防止服务端收到的文件名乱码。 我们这里可以先将文件名URLEncode,然后服务端拿到文件名时在URLDecode。就能避免乱码问题。
            // 文件名其实是放在请求头的Content-Disposition里面进行传输的,如其值为form-data; name="files"; filename="头像.jpg"
            multipartEntityBuilder.addBinaryBody(filesKey, file2, ContentType.DEFAULT_BINARY, URLEncoder.encode(file2.getName(), "utf-8"));
            // 其它参数(注:自定义contentType,设置UTF-8是为了防止服务端拿到的参数出现乱码)
            ContentType contentType = ContentType.create("text/plain", Charset.forName("UTF-8"));
            multipartEntityBuilder.addTextBody("name", "邓沙利文", contentType);
            multipartEntityBuilder.addTextBody("age", "25", contentType);

            HttpEntity httpEntity = multipartEntityBuilder.build();
            httpPost.setEntity(httpEntity);

            response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            System.out.println("HTTPS响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("HTTPS响应内容长度为:" + responseEntity.getContentLength());
                // 主动设置编码,来防止响应乱码
                String responseStr = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
                System.out.println("HTTPS响应内容为:" + responseStr);
            }
        } catch (ParseException | IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

对应的接收示例:

@PostMapping("/doPostUseFile")
    public String doPostUseFile(@RequestParam("name") String name,
                                @RequestParam("age") Integer age,
                                @RequestParam("files") List multipartFiles) throws UnsupportedEncodingException {
        StringBuilder sb = new StringBuilder();
        sb.append("\n");
        sb.append("name=").append(name)
                .append("\tage=").append(age);
        String fileName;
        for(MultipartFile file : multipartFiles){
            sb.append("\n文件信息:\n");
            fileName = file.getOriginalFilename();
            if(fileName == null){
                continue;
            }
            // 防止中文乱码问题
            fileName = URLDecoder.decode(fileName, "utf-8");
            sb.append("\t文件名:").append(fileName);
            sb.append("\t文件大小:").append(file.getSize() * 1.0 /1024).append("KB");
            sb.append("\tContentType:").append(file.getContentType());
            sb.append("\n");
        }
        return sb.toString();
    }

执行结果:

使用HttpClient发送Http请求详细示例_第4张图片

七、发送流示例

代码示例:

/**
     * 发送流
     */
    @Test
    public void doPostUseStream() {
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpPost httpPost = new HttpPost("http://localhost:8080/http/doPostUseStream?name=邓沙利文");
        CloseableHttpResponse response = null;
        try {
            InputStream stream = new ByteArrayInputStream("流啊流~".getBytes());
            InputStreamEntity InputStream = new InputStreamEntity(stream);
            httpPost.setEntity(InputStream);

            response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            System.out.println("HTTPS响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("HTTPS响应内容长度为:" + responseEntity.getContentLength());
                // 主动设置编码,来防止响应乱码
                String responseStr = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
                System.out.println("HTTPS响应内容为:" + responseStr);
            }
        } catch (ParseException | IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

接收端示例:

@PostMapping("/doPostUseStream")
    public String doPostUseStream(@RequestParam("name") String name,
                                  InputStream stream) throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append("\nname值为:").append(name);
        sb.append("\n输入数据流内容为:");
        BufferedReader bf = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
        String line;
        while((line = bf.readLine()) != null){
            sb.append(line);
        }
        return sb.toString();
    }

执行结果:

使用HttpClient发送Http请求详细示例_第5张图片

最后总结一下:使用HttpClient发送HTTP请求基本分为四步:

  1. 创建Http客户端
  2. 创建request请求
  3. 执行Reuest请求
  4. 关闭资源

你可能感兴趣的:(网络协议,HttpClient,http,http请求)