• httpclient


    1.什么是httpclient

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

    2.http请求(结合spring的注解)

    2-1GET请求

    添加添加@PathVariable  带占位符的 URL 

    添加@RequestParam  将请求参数区域的数据(url中参数)映射到控制层方法的参数上

    2-2 POST请求

    添加@RequestBody  JSON传参

     2-3.PUT请求

    添加@RequestBody  JSON传参

      2-4DELETE

    添加@RequestBody  JSON传参

    3.导入相关依赖

    lombok 和fastjson方便对数据进行处理

    1. <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
    2. <dependency>
    3. <groupId>org.apache.httpcomponents</groupId>
    4. <artifactId>httpclient</artifactId>
    5. <version>4.5.13</version>
    6. </dependency>
    7. <dependency>
    8. <groupId>com.alibaba</groupId>
    9. <artifactId>fastjson</artifactId>
    10. <version>1.2.46</version>
    11. </dependency>
    12. <dependency>
    13. <groupId>org.projectlombok</groupId>
    14. <artifactId>lombok</artifactId>
    15. <optional>true</optional>
    16. </dependency>

     4.准备工作

    在使用这个框架之前你需要明白 请求的组成部分 

     1.请求报文(请求行/请求头/请求数据/空行)

            请求行

                求方法字段、URL字段和HTTP协议版本

                例如:GET /index.html HTTP/1.1

                    get方法将数据拼接在url后面,传递参数受限

                请求方法:

                    GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT

            请求头(key value形式)

                User-Agent:产生请求的浏览器类型。

                Accept:客户端可识别的内容类型列表。

                Host:主机地址

            请求数据

                post方法中,会把数据以key value形式发送请求

            空行

                发送回车符和换行符,通知服务器以下不再有请求头

        2.响应报文(状态行、消息报头、响应正文)

            状态行

            消息报头

            响应正文

    请求头一般我们需要设置User-Agent,content-type 以及cookie  ,我们要的数据都存放在响应体内

    5.创建HttpClients实例

    创建HttpClients实例你可以理解为打开一个浏览器,发送请求 点开这个类

     5-1custom

    为构造自定义CloseableHttpClient实例创建构建器对象。

    1. public class Test01 {
    2. public static void main(String[] args) {
    3. CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(httpUtils()).build();
    4. }
    5. //设置连接池
    6. public static PoolingHttpClientConnectionManager httpUtils() {
    7. PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
    8. cm.setMaxTotal(200); //最大连接数
    9. cm.setDefaultMaxPerRoute(20); //设置每个主机的并发数
    10. return cm;
    11. }
    12. }

    5-2createDefault

    使用默认配置的实例。默认的无法设置连接池

    6.设置请求

    6-1不带参数  

     6-2带参数

    假设路径为 http://localhost:8081/?id=2 , 这里的id就是字段名,2就是字段的值,我们直接

    发送请求只会有http://localhost:8081/,现在我就是有吧参数带进去

    1. //get请求
    2. String url = "http://localhost:8081/";
    3. URI build = new URIBuilder(url).addParameter("id", "2").build();
    4. HttpGet httpGet = new HttpGet(build.toString());
    5. //post请求 form-data 表单提交
    6. HttpPost httpPost = new HttpPost(url);//
    7. List paramList = new ArrayList();
    8. paramList.add(new BasicNameValuePair("id","2"));
    9. UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
    10. httpPost.setEntity(entity);
    11. //post请求json表单
    12. HashMap param = new HashMap<>();
    13. param.put("id", "2");
    14. // 创建Http Post请求
    15. HttpPost httpPost1 = new HttpPost(url);
    16. // 创建请求内容
    17. String json = JSONObject.toJSON(param).toString();
    18. // 设置参数为Json,模拟表单
    19. StringEntity entity1 = new StringEntity(json, ContentType.APPLICATION_JSON);
    20. // 把参数赋值给请求
    21. httpPost1.setEntity(entity);

    7.设置请求头

    token也是在请求头中 ,可以直接设置  以get请求为列

    1. String url = "http://localhost:8081/";
    2. URI build = new URIBuilder(url).addParameter("id", "2").build();
    3. HttpGet httpGet = new HttpGet(build.toString());
    4. httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
    5. + "Chrome/104.0.0.0 Safari/537.36");
    6. httpGet.setHeader("content-type", "application/json");
    7. //假设tokeen:xsxsxs
    8. httpGet.setHeader("X-Access-Token", "xsxsxs");

     8.请求设置

    1. httpGet.setConfig(getConfig());
    2. }
    3. /**
    4. * @return 请求设置
    5. */
    6. private static RequestConfig getConfig() {
    7. //配置请求信息
    8. RequestConfig config = RequestConfig.custom().setConnectTimeout(1000000000)//创建连接最大时间,
    9. .setConnectionRequestTimeout(500000000) // 设置获取连接的最长时间 ,单位是毫秒
    10. .setSocketTimeout(10 * 100000) //设置传输的最长时间,单位是毫秒
    11. .build();
    12. return config;
    13. }

    9.设置代理

    1. //设置代理
    2. HttpHost proxy = new HttpHost("58.60.255.82",8118);
    3. RequestConfig requestConfig = RequestConfig.custom()
    4. .setProxy(proxy)
    5. .setConnectTimeout(10000)
    6. .setSocketTimeout(10000)
    7. .setConnectionRequestTimeout(3000)
    8. .build();
    9. httpGet.setConfig(requestConfig);

     10.工具类

    我这里没有设置请求头,也没有设置请求,代码也没有设置,主要展示带参数的

    1. package com.example.list.list;
    2. import com.alibaba.fastjson.JSONObject;
    3. import org.apache.http.HttpHost;
    4. import org.apache.http.NameValuePair;
    5. import org.apache.http.client.config.RequestConfig;
    6. import org.apache.http.client.entity.UrlEncodedFormEntity;
    7. import org.apache.http.client.methods.CloseableHttpResponse;
    8. import org.apache.http.client.methods.HttpGet;
    9. import org.apache.http.client.methods.HttpPost;
    10. import org.apache.http.client.utils.URIBuilder;
    11. import org.apache.http.entity.ContentType;
    12. import org.apache.http.entity.StringEntity;
    13. import org.apache.http.impl.client.CloseableHttpClient;
    14. import org.apache.http.impl.client.HttpClients;
    15. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    16. import org.apache.http.message.BasicNameValuePair;
    17. import org.apache.http.util.EntityUtils;
    18. import org.springframework.stereotype.Component;
    19. import java.io.IOException;
    20. import java.util.ArrayList;
    21. import java.util.List;
    22. import java.util.Map;
    23. @Component
    24. public class HttpClientUtils {
    25. /**
    26. * @return 请求设置
    27. */
    28. private RequestConfig getConfig(HttpHost proxy) {
    29. //配置请求信息
    30. RequestConfig config = RequestConfig.custom()
    31. .setConnectTimeout(1000000000)//创建连接最大时间,
    32. .setConnectionRequestTimeout(500000000) // 设置获取连接的最长时间 ,单位是毫秒
    33. .setSocketTimeout(10 * 100000) //设置传输的最长时间,单位是毫秒
    34. .setProxy(proxy)
    35. .build();
    36. return config;
    37. }
    38. /**
    39. * get 请求带参数
    40. *
    41. * @param url
    42. * @param param
    43. * @return
    44. */
    45. public Object doGet(String url, Map param) {
    46. //创建HttpClient对象
    47. CloseableHttpClient httpclient = HttpClients.createDefault();
    48. //返回的字符串
    49. String resultString = "";
    50. JSONObject jsonObject = new JSONObject();
    51. CloseableHttpResponse response = null;
    52. try {
    53. //创建url
    54. URIBuilder builder = new URIBuilder(url);
    55. if (param != null) {
    56. for (String key : param.keySet()) {
    57. builder.addParameter(key, param.get(key));
    58. }
    59. }
    60. //创建get请求
    61. HttpGet httpGet = new HttpGet(builder.toString());
    62. // 执行请求
    63. response = httpclient.execute(httpGet);
    64. //判断返回值是否为200
    65. if (response.getStatusLine().getStatusCode() == 200) {
    66. resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
    67. }
    68. //将字符串转JSONObject(可以获取里面得某个元素),也可以直接返回字符串
    69. jsonObject = JSONObject.parseObject(resultString);
    70. } catch (Exception e) {
    71. e.printStackTrace();
    72. }
    73. return jsonObject;
    74. }
    75. //设置连接池
    76. public PoolingHttpClientConnectionManager httpUtils() {
    77. PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
    78. cm.setMaxTotal(200); //最大连接数
    79. cm.setDefaultMaxPerRoute(20); //设置每个主机的并发数
    80. return cm;
    81. }
    82. /**
    83. * form表单 post请求
    84. *
    85. * @param url
    86. * @param param
    87. * @return
    88. */
    89. public String doPost(String url, Map param) {
    90. // 创建Httpclient对象
    91. CloseableHttpClient httpClient = HttpClients.createDefault();
    92. CloseableHttpResponse response = null;
    93. String resultString = "";
    94. try {
    95. // 创建Http Post请求
    96. HttpPost httpPost = new HttpPost(url);
    97. // 创建参数列表
    98. if (param != null) {
    99. List paramList = new ArrayList();
    100. for (String key : param.keySet()) {
    101. paramList.add(new BasicNameValuePair(key, param.get(key)));
    102. }
    103. // 模拟表单
    104. UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
    105. httpPost.setEntity(entity);
    106. }
    107. // 执行http请求
    108. response = httpClient.execute(httpPost);
    109. resultString = EntityUtils.toString(response.getEntity(), "utf-8");
    110. } catch (Exception e) {
    111. e.printStackTrace();
    112. } finally {
    113. try {
    114. response.close();
    115. } catch (IOException e) {
    116. e.printStackTrace();
    117. }
    118. }
    119. return resultString;
    120. }
    121. /**
    122. * post设置参数json
    123. *
    124. * @param url
    125. * @param param
    126. * @return
    127. */
    128. public String doPostJson(String url, Map param) {
    129. // 创建Httpclient对象
    130. CloseableHttpClient httpClient = HttpClients.createDefault();
    131. CloseableHttpResponse response = null;
    132. String resultString = "";
    133. try {
    134. // 创建Http Post请求
    135. HttpPost httpPost = new HttpPost(url);
    136. // 创建请求内容
    137. String json = JSONObject.toJSON(param).toString();
    138. // 设置参数为Json,模拟表单
    139. StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
    140. // 把参数赋值给请求
    141. httpPost.setEntity(entity);
    142. // 执行http请求
    143. response = httpClient.execute(httpPost);
    144. if (response.getStatusLine().getStatusCode() == 200) {
    145. resultString = EntityUtils.toString(response.getEntity(), "utf-8");
    146. }
    147. } catch (Exception e) {
    148. e.printStackTrace();
    149. } finally {
    150. try {
    151. response.close();
    152. } catch (IOException e) {
    153. e.printStackTrace();
    154. }
    155. }
    156. return resultString;
    157. }
    158. }

    11.文件下载

     下载HTML、图片、PDF和压缩等文件时,一种方法是使用HttpEntity类将响应实体转化成字节数组,再利用输出流的方式写入指定文件。另一种方法是使用HttpEntity类中的writeTo(OutputStream)方法,直接将响应实体写入指定的输出流中,这种方法简单且常用,使用writeTo(OutputStream)下载“.tar.gz”格式的压缩文件

    1. @Test
    2. void contextLoads() throws Exception {
    3. String url = "https://**.jd.com/";
    4. //初始化httpClient
    5. CloseableHttpClient httpClient = HttpClients.custom().build();
    6. final HttpGet httpGet = new HttpGet(url);
    7. //获取结果
    8. HttpResponse httpResponse = null;
    9. try {
    10. httpResponse = httpClient.execute(httpGet);
    11. } catch (IOException e) {
    12. e.printStackTrace();
    13. }
    14. final FileOutputStream out = new FileOutputStream("file/httpd-2.4.37.tar.gz");
    15. httpResponse.getEntity().writeTo(out);
    16. EntityUtils.consume(httpResponse.getEntity()); //消耗实体
    17. }

    12. HTTPS请求认证

    使用HttpClient直接请求以https://为前缀的URL,有时也会产生图4.11所示的错误信息,即找不到合法证书请求目标URL。

    首先,利用内部类SSL509TrustManager,创建X.509证书信任管理器;之后,使用SSLConnectionSocketFactory()方法创建SSL连接,并利用Registry注册http和https套接字工厂;接着,使用PoolingHttpClientConnectionManager()方法实例化连接池管理器;最后,基于实例化的连接池管理器和RequestConfig配置的信息,来实例化一个可以执行HTTPS请求的HttpClient。

    1. import org.apache.http.client.HttpClient;
    2. import org.apache.http.client.config.AuthSchemes;
    3. import org.apache.http.client.config.CookieSpecs;
    4. import org.apache.http.client.config.RequestConfig;
    5. import org.apache.http.config.Registry;
    6. import org.apache.http.config.RegistryBuilder;
    7. import org.apache.http.conn.socket.ConnectionSocketFactory;
    8. import org.apache.http.conn.socket.PlainConnectionSocketFactory;
    9. import org.apache.http.conn.ssl.NoopHostnameVerifier;
    10. import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    11. import org.apache.http.impl.client.HttpClients;
    12. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    13. import javax.net.ssl.SSLContext;
    14. import javax.net.ssl.X509TrustManager;
    15. import java.security.cert.CertificateException;
    16. import java.security.cert.X509Certificate;
    17. import java.util.Arrays;
    18. public class SSLClient {
    19. /**
    20. * 基于SSL配置 HttpClient
    21. * @param SSLProtocolVersion (SSL ,SSLv3 TLS TLSv1.1 TLSv1.2)
    22. * @return
    23. */
    24. public HttpClient initSSLClient(String SSLProtocolVersion) {
    25. RequestConfig defaultConfig = null;
    26. PoolingHttpClientConnectionManager pcm = null;
    27. try {
    28. SSL509TrustManager xtm = new SSL509TrustManager(); //创建信任管理
    29. SSLContext context = SSLContext.getInstance(SSLProtocolVersion);
    30. context.init(null, new X509TrustManager[]{xtm}, null);
    31. /**
    32. * 从 SSLContext 对象中得到SSLConnectionSocketFactory对象
    33. * NoopHostnameVerifier.INSTANCE 表示接收任何有效的符合目标
    34. */
    35. final SSLConnectionSocketFactory sslConnectionSocketFactory =
    36. new SSLConnectionSocketFactory(context, NoopHostnameVerifier.INSTANCE);
    37. defaultConfig = RequestConfig.custom().
    38. setCookieSpec(CookieSpecs.STANDARD_STRICT)
    39. .setExpectContinueEnabled(true)
    40. .setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST)
    41. ).build();
    42. //注册http和https套接字工厂
    43. Registry sfr = RegistryBuilder.create()
    44. .register("http", PlainConnectionSocketFactory.INSTANCE)
    45. .register("https", sslConnectionSocketFactory).build();
    46. //基于sfr创建连接管理器
    47. pcm = new PoolingHttpClientConnectionManager(sfr);
    48. } catch (Exception e) {
    49. e.printStackTrace();
    50. }
    51. //创建连接管理器和配置 ,实例化HttpClient
    52. HttpClient httpClient = HttpClients.custom()
    53. .setConnectionManager(pcm).setDefaultRequestConfig(defaultConfig).build();
    54. return httpClient;
    55. }
    56. private static class SSL509TrustManager implements X509TrustManager {
    57. //检查客户端证书
    58. @Override
    59. public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    60. }
    61. //检查服务端证书
    62. @Override
    63. public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    64. }
    65. //返回受信任的X50证书
    66. @Override
    67. public X509Certificate[] getAcceptedIssuers() {
    68. return new X509Certificate[0];
    69. }
    70. }
    71. }

     测试代码

    1. @Test
    2. void contextLoads() throws Exception {
    3. String url = "https://www.***.com";
    4. SSLClient sslClient = new SSLClient();
    5. HttpClient httpClientSSL = sslClient.initSSLClient("SSLv3");
    6. final HttpGet httpGet = new HttpGet(url);
    7. //获取结果
    8. HttpResponse httpResponse=null;
    9. try {
    10. httpResponse= httpClientSSL.execute(httpGet);
    11. } catch (IOException e) {
    12. e.printStackTrace();
    13. }
    14. if(httpResponse.getStatusLine().getStatusCode()== HttpStatus.SC_OK) { //状态码200表示响应成功
    15. //获取实体内容
    16. final String entity = EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
    17. //输出实体内容
    18. System.out.println(entity);
    19. EntityUtils.consume(httpResponse.getEntity());//消耗实体
    20. }else {
    21. //关闭HttpEntity的响应实体
    22. EntityUtils.consume(httpResponse.getEntity());//消耗实体
    23. }
    24. }

    13.请求重试

    使用HttpClient请求URL时,有时会出现请求异常的情况。针对一些非致命的异常,可以通过请求重试解决。HttpClient提供了默认重试策略DefaultHttpRequestRetryHandler。DefaultHttpRequestRetryHandler类实现了HttpRequestRetryHandler接口,重写了retryRequest()方法。DefaultHttpRequestRetryHandler类的一部分源码。由源码可以发现DefaultHttpRequestRetryHandler类定义的默认重试次数为3次;幂等方法(如GET和HEAD是幂等的)可以重试;如果网页请求失败,可以重试。另外,针对4种异常不进行重试,这四种异常分别是InterruptedIOException(线程中断异常)、UnknownHostException(未知的Host异常)、ConnectException(连接异常,如连接拒绝异常)和SSLException(HTTPS请求认证异常)。默认重试3次

     

     

    1. @Test
    2. void contextLoads() throws Exception {
    3. //默认重试3次
    4. HttpClient httpClient = HttpClients.custom()
    5. .setRetryHandler(new DefaultHttpRequestRetryHandler()).build();
    6. //自定义重试次数
    7. HttpClients.custom().
    8. setRetryHandler(new DefaultHttpRequestRetryHandler(5, true)).build();
    9. }

    14.多线程执行请求

    4.5版本的HttpClient中的连接池管理器PoolingHttpClientConnectionManager类实现了HTTP连接池化管理,其管理连接的单位为路由(Route),每个路由维护一定数量(默认是2)的连接;当给定路由的所有连接都被租用时,则新的连接请求将发生阻塞,直到某连接被释放回连接池。另外,PoolingHttpClientConnectionManager维护的连接次数也受总数MaxTotal(默认是20)的限制。当HttpClient配置了PoolingHttpClientConnectionManager时,其可以同时执行多个HTTP请求,即实现多线程操作。

    1. package com.example.jsoup;
    2. import lombok.SneakyThrows;
    3. import org.apache.http.Consts;
    4. import org.apache.http.ParseException;
    5. import org.apache.http.client.HttpClient;
    6. import org.apache.http.client.config.AuthSchemes;
    7. import org.apache.http.client.config.CookieSpecs;
    8. import org.apache.http.client.config.RequestConfig;
    9. import org.apache.http.client.methods.CloseableHttpResponse;
    10. import org.apache.http.client.methods.HttpGet;
    11. import org.apache.http.client.protocol.HttpClientContext;
    12. import org.apache.http.config.ConnectionConfig;
    13. import org.apache.http.config.SocketConfig;
    14. import org.apache.http.impl.client.CloseableHttpClient;
    15. import org.apache.http.impl.client.HttpClients;
    16. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    17. import org.apache.http.util.EntityUtils;
    18. import org.junit.jupiter.api.Test;
    19. import org.springframework.boot.test.context.SpringBootTest;
    20. import java.io.FileOutputStream;
    21. import java.io.IOException;
    22. import java.io.OutputStream;
    23. import java.nio.charset.CodingErrorAction;
    24. import java.util.Arrays;
    25. import java.util.concurrent.ExecutorService;
    26. import java.util.concurrent.Executors;
    27. @SpringBootTest
    28. class JsoupApplicationTests {
    29. @Test
    30. void contextLoads() throws Exception {
    31. // 添加连接参数
    32. ConnectionConfig connectionConfig = ConnectionConfig.custom()
    33. .setMalformedInputAction(CodingErrorAction.IGNORE)
    34. .setUnmappableInputAction(CodingErrorAction.IGNORE)
    35. .setCharset(Consts.UTF_8)
    36. .build();
    37. //添加socket参数
    38. SocketConfig socketConfig = SocketConfig.custom()
    39. .setTcpNoDelay(true)
    40. .build();
    41. //配置连接池管理器
    42. PoolingHttpClientConnectionManager pcm =
    43. new PoolingHttpClientConnectionManager();
    44. //设置最大连接数
    45. pcm.setMaxTotal(100);
    46. //设置连接信息
    47. pcm.setDefaultMaxPerRoute(10);
    48. //设置socket信息
    49. pcm.setDefaultSocketConfig(socketConfig);
    50. //设置全局请求配置 包括cookie规范、http认证 超时时间
    51. RequestConfig defaultConfig = RequestConfig.custom()
    52. .setCookieSpec(CookieSpecs.STANDARD_STRICT)
    53. .setExpectContinueEnabled(true)
    54. .setTargetPreferredAuthSchemes(
    55. Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
    56. .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
    57. .setConnectionRequestTimeout(30 * 1000)
    58. .setConnectTimeout(30 * 1000)
    59. .setSocketTimeout(30 * 1000)
    60. .build();
    61. CloseableHttpClient httpClient = HttpClients.custom()
    62. .setConnectionManager(pcm)
    63. .setDefaultRequestConfig(defaultConfig)
    64. .build();
    65. //请求URL
    66. String[] urlArr = {
    67. "https://www.xxx.com",
    68. "https://www.xxj.com"
    69. };
    70. //创建固定大小的线程池
    71. ExecutorService exec = Executors.newFixedThreadPool(3);
    72. for (int i = 0; i < urlArr.length; i++) {
    73. //HTML需要输出的文件名
    74. String filename = urlArr[i].split("html/")[1];
    75. //创建HTML文件输出目录
    76. FileOutputStream out = new FileOutputStream("file/" + filename);
    77. HttpGet httpget = new HttpGet(urlArr[i]);
    78. //启动线程执行请求
    79. exec.execute(new DownHtmlFileThread(httpClient, httpget, out));
    80. //关闭线程
    81. exec.shutdown();
    82. }
    83. }
    84. static class DownHtmlFileThread extends Thread {
    85. private final CloseableHttpClient httpClient;
    86. private final HttpClientContext context;
    87. private final HttpGet httpget;
    88. private final OutputStream out;
    89. public DownHtmlFileThread(CloseableHttpClient httpClient, HttpGet httpget, OutputStream out) {
    90. this.httpClient = httpClient;
    91. this.context = HttpClientContext.create();
    92. this.httpget = httpget;
    93. this.out = out;
    94. }
    95. @SneakyThrows
    96. @Override
    97. public void run() {
    98. System.out.println(Thread.currentThread().getName() + "线程请求的URL为:" + httpget.getURI());
    99. try {
    100. CloseableHttpResponse response = httpClient.execute(httpget, context); //执行请求
    101. //将HTML文档写入文件
    102. try {
    103. out.write(EntityUtils.toString(response.getEntity(), "gbk")
    104. .getBytes());
    105. out.close();
    106. //消耗实体
    107. EntityUtils.consume(response.getEntity());
    108. } finally {
    109. response.close();
    110. }
    111. } catch (IOException e) {
    112. e.printStackTrace();
    113. } catch (ParseException e) {
    114. e.printStackTrace();
    115. }
    116. }
    117. }
    118. }

     

  • 相关阅读:
    ebay运营思路|学会这些技巧,新店铺销量翻倍
    关于分布式锁你需要知道的事
    生态系统服务——水源涵养水源涵养分布
    Java常量池理解
    【DesignMode】设计模式简介
    如何封装安全的go
    面试阿里技术专家岗,对答如流,这些面试题你能答出多少
    netcore项目中的GC模式
    html table 如何导出为excel表格案例分享
    免费,开源,可批量的离线图片文字提取软件OCR
  • 原文地址:https://blog.csdn.net/qq_42847719/article/details/128106182