HttpClient详细解释

HttpClient详细解释Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会更加深入。

org.apache.commons.httpclient.HttpClient与org.apache.http.client.HttpClient的区别

[java] 
view plain 
copy

  1. Commons的HttpClient项目现在是生命的尽头,不再被开发,  
  2. 已被Apache HttpComponents项目HttpClient和的HttpCore  
  3. 模组取代,提供更好的性能和更大的灵活性。  

一、简介

HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。

下载地址: Apache HttpComponents – HttpComponents Downloads

二、特性

1. 基于标准、纯净的java语言。实现了Http1.0和Http1.1

2. 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。

3. 支持HTTPS协议。

4. 通过Http代理建立透明的连接。

5. 利用CONNECT方法通过Http代理建立隧道的https连接。

6. Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。

7. 插件式的自定义认证方案。

8. 便携可靠的套接字工厂使它更容易的使用第三方解决方案。

9. 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。

10. 自动处理Set-Cookie中的Cookie。

11. 插件式的自定义Cookie策略。

12. Request的输出流可以避免流中内容直接缓冲到socket服务器。

13. Response的输入流可以有效的从socket服务器直接读取相应内容。

14. 在http1.0和http1.1中利用KeepAlive保持持久连接。

15. 直接获取服务器发送的response code和 headers。

16. 设置连接超时的能力。

17. 实验性的支持http1.1 response caching。

18. 源代码基于Apache License 可免费获取。

三、使用方法

使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。

1. 创建HttpClient对象。

2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。

3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。

4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。

5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。

6. 释放连接。无论执行方法是否成功,都必须释放连接

相关jar包

[java] 
view plain 
copy

  1. commons-cli-1.2.jar  
  2. commons-codec-1.9.jar  
  3. commons-logging-1.2.jar  
  4. fluent-hc-4.5.1.jar  
  5. httpclient-4.5.1.jar  
  6. httpclient-cache-4.5.1.jar  
  7. httpclient-win-4.5.1.jar  
  8. httpcore-4.4.3.jar  
  9. httpcore-ab-4.4.3.jar  
  10. httpcore-nio-4.4.3.jar  
  11. httpmime-4.5.1.jar  
  12. jna-4.1.0.jar  
  13. jna-platform-4.1.0.jar  

最简单post请求, 源自 http://my.oschina.net/xinxingegeya/blog/282683

[java] 
view plain 
copy

  1. package a;  
  2.    
  3. import java.io.FileInputStream;  
  4. import java.io.IOException;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7. import java.util.Properties;  
  8.    
  9. import org.apache.http.HttpEntity;  
  10. import org.apache.http.HttpResponse;  
  11. import org.apache.http.NameValuePair;  
  12. import org.apache.http.client.HttpClient;  
  13. import org.apache.http.client.config.RequestConfig;  
  14. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  15. import org.apache.http.client.methods.HttpPost;  
  16. import org.apache.http.impl.client.DefaultHttpClient;  
  17. import org.apache.http.message.BasicNameValuePair;  
  18. import org.apache.http.util.EntityUtils;  
  19.    
  20. public class First {  
  21.     public static void main(String[] args) throws Exception{  
  22.         List<NameValuePair> formparams = new ArrayList<NameValuePair>();  
  23.         formparams.add(new BasicNameValuePair(“account”“”));  
  24.         formparams.add(new BasicNameValuePair(“password”“”));  
  25.         HttpEntity reqEntity = new UrlEncodedFormEntity(formparams, “utf-8”);  
  26.     
  27.         RequestConfig requestConfig = RequestConfig.custom()  
  28.         .setConnectTimeout(5000)//一、连接超时:connectionTimeout–>指的是连接一个url的连接等待时间  
  29.                 .setSocketTimeout(5000)// 二、读取数据超时:SocketTimeout–>指的是连接上一个url,获取response的返回等待时间  
  30.                 .setConnectionRequestTimeout(5000)  
  31.                 .build();  
  32.     
  33.         HttpClient client = new DefaultHttpClient();  
  34.         HttpPost post = new HttpPost(“http://cnivi.com.cn/login”);  
  35.         post.setEntity(reqEntity);  
  36.         post.setConfig(requestConfig);  
  37.         HttpResponse response = client.execute(post);  
  38.     
  39.         if (response.getStatusLine().getStatusCode() == 200) {  
  40.             HttpEntity resEntity = response.getEntity();  
  41.             String message = EntityUtils.toString(resEntity, “utf-8”);  
  42.             System.out.println(message);  
  43.         } else {  
  44.             System.out.println(“请求失败”);  
  45.         }  
  46.     }  
  47.    
  48. }  

四、实例

主文件

[java] 
view plain 
copy

  1. package com.test;  
  2.       
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.IOException;  
  6. import java.io.UnsupportedEncodingException;  
  7. import java.security.KeyManagementException;  
  8. import java.security.KeyStore;  
  9. import java.security.KeyStoreException;  
  10. import java.security.NoSuchAlgorithmException;  
  11. import java.security.cert.CertificateException;  
  12. import java.util.ArrayList;  
  13. import java.util.List;  
  14. import javax.net.ssl.SSLContext;  
  15. import org.apache.http.HttpEntity;  
  16. import org.apache.http.NameValuePair;  
  17. import org.apache.http.ParseException;  
  18. import org.apache.http.client.ClientProtocolException;  
  19. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  20. import org.apache.http.client.methods.CloseableHttpResponse;  
  21. import org.apache.http.client.methods.HttpGet;  
  22. import org.apache.http.client.methods.HttpPost;  
  23. import org.apache.http.conn.ssl.SSLConnectionSocketFactory;  
  24. import org.apache.http.conn.ssl.SSLContexts;  
  25. import org.apache.http.conn.ssl.TrustSelfSignedStrategy;  
  26. import org.apache.http.entity.ContentType;  
  27. import org.apache.http.entity.mime.MultipartEntityBuilder;  
  28. import org.apache.http.entity.mime.content.FileBody;  
  29. import org.apache.http.entity.mime.content.StringBody;  
  30. import org.apache.http.impl.client.CloseableHttpClient;  
  31. import org.apache.http.impl.client.HttpClients;  
  32. import org.apache.http.message.BasicNameValuePair;  
  33. import org.apache.http.util.EntityUtils;  
  34. import org.apache.http.client.config.RequestConfig;  
  35. import org.junit.Test;  
  36. public class HttpClientTest {  
  37.   //方法见下……..  
  38. }  

HttpClientUtils工具类

[java] 
view plain 
copy

  1. package com.bobo.code.web.controller.technology.httpcomponents;  
  2.    
  3.    
  4. import org.apache.http.HttpEntity;  
  5. import org.apache.http.HttpHost;  
  6. import org.apache.http.HttpResponse;  
  7. import org.apache.http.NameValuePair;  
  8. import org.apache.http.client.HttpClient;  
  9. import org.apache.http.client.config.RequestConfig;  
  10. import org.apache.http.client.methods.HttpUriRequest;  
  11. import org.apache.http.client.methods.RequestBuilder;  
  12. import org.apache.http.conn.routing.HttpRoute;  
  13. import org.apache.http.impl.client.CloseableHttpClient;  
  14. import org.apache.http.impl.client.HttpClientBuilder;  
  15. import org.apache.http.impl.client.HttpClients;  
  16. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;  
  17. import org.apache.http.message.BasicNameValuePair;  
  18. import org.apache.http.util.EntityUtils;  
  19.     
  20. import java.io.IOException;  
  21. import java.util.*;  
  22.     
  23. public class HttpClientUtils {  
  24.     
  25.     private static PoolingHttpClientConnectionManager connectionManager = null;  
  26.     private static HttpClientBuilder httpBuilder = null;  
  27.     private static RequestConfig requestConfig = null;  
  28.     
  29.     private static int MAXCONNECTION = 10;  
  30.     
  31.     private static int DEFAULTMAXCONNECTION = 5;  
  32.     
  33.     private static String IP = “cnivi.com.cn”;  
  34.     private static int PORT = 80;  
  35.     
  36.     static {  
  37.         //设置http的状态参数  
  38.         requestConfig = RequestConfig.custom()  
  39.                 .setSocketTimeout(5000)  
  40.                 .setConnectTimeout(5000)  
  41.                 .setConnectionRequestTimeout(5000)  
  42.                 .build();  
  43.     
  44.         HttpHost target = new HttpHost(IP, PORT);  
  45.         connectionManager = new PoolingHttpClientConnectionManager();  
  46.         connectionManager.setMaxTotal(MAXCONNECTION);//客户端总并行链接最大数  
  47.         connectionManager.setDefaultMaxPerRoute(DEFAULTMAXCONNECTION);//每个主机的最大并行链接数  
  48.         connectionManager.setMaxPerRoute(new HttpRoute(target), 20);  
  49.         httpBuilder = HttpClients.custom();  
  50.         httpBuilder.setConnectionManager(connectionManager);  
  51.     }  
  52.     
  53.     public static CloseableHttpClient getConnection() {  
  54.         CloseableHttpClient httpClient = httpBuilder.build();  
  55.         return httpClient;  
  56.     }  
  57.     
  58.     
  59.     public static HttpUriRequest getRequestMethod(Map<String, String> map, String url, String method) {  
  60.         List<NameValuePair> params = new ArrayList<NameValuePair>();  
  61.         Set<Map.Entry<String, String>> entrySet = map.entrySet();  
  62.         for (Map.Entry<String, String> e : entrySet) {  
  63.             String name = e.getKey();  
  64.             String value = e.getValue();  
  65.             NameValuePair pair = new BasicNameValuePair(name, value);  
  66.             params.add(pair);  
  67.         }  
  68.         HttpUriRequest reqMethod = null;  
  69.         if (“post”.equals(method)) {  
  70.             reqMethod = RequestBuilder.post().setUri(url)  
  71.                     .addParameters(params.toArray(new BasicNameValuePair[params.size()]))  
  72.                     .setConfig(requestConfig).build();  
  73.         } else if (“get”.equals(method)) {  
  74.             reqMethod = RequestBuilder.get().setUri(url)  
  75.                     .addParameters(params.toArray(new BasicNameValuePair[params.size()]))  
  76.                     .setConfig(requestConfig).build();  
  77.         }  
  78.         return reqMethod;  
  79.     }  
  80.     
  81.     public static void main(String args[]) throws IOException {  
  82.         Map<String, String> map = new HashMap<String, String>();  
  83.         map.put(“account”“”);  
  84.         map.put(“password”“”);  
  85.     
  86.         HttpClient client = getConnection();  
  87.         HttpUriRequest post = getRequestMethod(map, “http://cnivi.com.cn/login”“post”);  
  88.         HttpResponse response = client.execute(post);  
  89.     
  90.         if (response.getStatusLine().getStatusCode() == 200) {  
  91.             HttpEntity entity = response.getEntity();  
  92.             String message = EntityUtils.toString(entity, “utf-8”);  
  93.             System.out.println(message);  
  94.         } else {  
  95.             System.out.println(“请求失败”);  
  96.         }  
  97.     }  
  98. }  

get方式

[java] 
view plain 
copy

  1. /** 
  2.      * 发送 get请求 
  3.      */   
  4.     public void get() {   
  5.         CloseableHttpClient httpclient = HttpClients.createDefault();   
  6.         try {   
  7.             // 创建httpget.     
  8.             HttpGet httpget = new HttpGet(“http://www.baidu.com/”);   
  9.             System.out.println(“executing request “ + httpget.getURI());   
  10.             // 执行get请求.     
  11.             CloseableHttpResponse response = httpclient.execute(httpget);   
  12.             try {   
  13.                 // 获取响应实体     
  14.                 HttpEntity entity = response.getEntity();   
  15.                 System.out.println(“————————————–“);   
  16.                 // 打印响应状态     
  17.                 System.out.println(response.getStatusLine());   
  18.                 if (entity != null) {   
  19.                     // 打印响应内容长度     
  20.                     System.out.println(“Response content length: “ + entity.getContentLength());   
  21.                     // 打印响应内容     
  22.                     System.out.println(“Response content: “ + EntityUtils.toString(entity));   
  23.                 }   
  24.                 System.out.println(“————————————“);   
  25.             } finally {   
  26.                 response.close();   
  27.             }   
  28.         } catch (ClientProtocolException e) {   
  29.             e.printStackTrace();   
  30.         } catch (ParseException e) {   
  31.             e.printStackTrace();   
  32.         } catch (IOException e) {   
  33.             e.printStackTrace();   
  34.         } finally {   
  35.             // 关闭连接,释放资源     
  36.             try {   
  37.                 httpclient.close();   
  38.             } catch (IOException e) {   
  39.                 e.printStackTrace();   
  40.             }   
  41.         }   
  42.     }   

post方式

[java] 
view plain 
copy

  1. /** 
  2.      * 发送 post请求访问本地应用并根据传递参数不同返回不同结果 
  3.      */   
  4.     public void post() {   
  5.         // 创建默认的httpClient实例.     
  6.         CloseableHttpClient httpclient = HttpClients.createDefault();   
  7.         // 创建httppost     
  8.         HttpPost httppost = new HttpPost(“http://localhost:8080/myDemo/Ajax/serivceJ.action”);   
  9.         // 创建参数队列     
  10.         List<NameValuePair> formparams = new ArrayList<NameValuePair>();   
  11.         formparams.add(new BasicNameValuePair(“type”“house”));   
  12.         UrlEncodedFormEntity uefEntity;   
  13.         try {   
  14.             uefEntity = new UrlEncodedFormEntity(formparams, “UTF-8”);   
  15.             httppost.setEntity(uefEntity);   
  16.             System.out.println(“executing request “ + httppost.getURI());   
  17.             CloseableHttpResponse response = httpclient.execute(httppost);   
  18.             try {   
  19.                 HttpEntity entity = response.getEntity();   
  20.                 if (entity != null) {   
  21.                     System.out.println(“————————————–“);   
  22.                     System.out.println(“Response content: “ + EntityUtils.toString(entity, “UTF-8”));   
  23.                     System.out.println(“————————————–“);   
  24.                 }   
  25.             } finally {   
  26.                 response.close();   
  27.             }   
  28.         } catch (ClientProtocolException e) {   
  29.             e.printStackTrace();   
  30.         } catch (UnsupportedEncodingException e1) {   
  31.             e1.printStackTrace();   
  32.         } catch (IOException e) {   
  33.             e.printStackTrace();   
  34.         } finally {   
  35.             // 关闭连接,释放资源     
  36.             try {   
  37.                 httpclient.close();   
  38.             } catch (IOException e) {   
  39.                 e.printStackTrace();   
  40.             }   
  41.         }   
  42.     }   

post方式乱码补充 

如果有乱码,可以偿试使用 StringEntity 来替换HttpEntity:

[java] 
view plain 
copy

  1. StringEntity content =new StringEntity(soapRequestData.toString(), Charset.forName(“UTF-8”));// 第二个参数,设置后才会对,内容进行编码  
  2.         content.setContentType(“application/soap+xml; charset=UTF-8”);  
  3.         content.setContentEncoding(“UTF-8”);  
  4.         httppost.setEntity(content);  

具体SOAP协议代码如下:

[java] 
view plain 
copy

  1. package com.isoftstone.core.service.impl;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.File;  
  5. import java.io.FileInputStream;  
  6. import java.io.FileReader;  
  7. import java.io.IOException;  
  8. import java.io.InputStreamReader;  
  9. import java.nio.charset.Charset;  
  10. import java.util.Scanner;  
  11.   
  12. import org.apache.http.HttpEntity;  
  13. import org.apache.http.HttpResponse;  
  14. import org.apache.http.client.ClientProtocolException;  
  15. import org.apache.http.client.HttpClient;  
  16. import org.apache.http.client.entity.EntityBuilder;  
  17. import org.apache.http.client.methods.HttpPost;  
  18. import org.apache.http.entity.ContentType;  
  19. import org.apache.http.entity.StringEntity;  
  20. import org.apache.http.impl.client.HttpClients;  
  21. import org.apache.http.util.EntityUtils;  
  22. import org.apache.log4j.Logger;  
  23. import org.jdom.Document;  
  24. import org.jdom.Element;  
  25.   
  26. import com.isoftstone.core.common.constant.RequestConstants;  
  27. import com.isoftstone.core.common.tools.XmlTool;  
  28. import com.isoftstone.core.service.intf.ServiceOfStringPara;  
  29. /** 
  30.  * 德勤定价系统,由核心主动调用 
  31.  * @author King 
  32.  * 
  33.  */  
  34. public class DeloittePricingSingleCarImpl implements ServiceOfStringPara {  
  35.     private  String serviceUrl = “http://10.30.0.35:7001/ZSInsUW/Auto/PricingService”;  
  36.   
  37.     private static Logger log = Logger.getLogger(DeloittePricingSingleCarImpl.class.getName());  
  38.   
  39.     public String invoke(String sRequest) {  
  40.           
  41.         StringBuffer soapRequestData = new StringBuffer();  
  42.         soapRequestData.append(“<soapenv:Envelope”);  
  43.         soapRequestData.append(”  xmlns:soapenv=\”http://schemas.xmlsoap.org/soap/envelope/\” “);  
  44.         soapRequestData.append(”  xmlns:prov=\”http://provider.webservice.zsins.dtt.com/\”>”);  
  45.         soapRequestData.append(” <soapenv:Header/> “);  
  46.         soapRequestData.append(“<soapenv:Body>”);  
  47.         soapRequestData.append(“<prov:executePrvPricing>”);  
  48.         soapRequestData.append(“<arg0>”);  
  49.         soapRequestData.append(“<![CDATA[“ + sRequest + “]]>”);  
  50.         soapRequestData.append(“</arg0>”);  
  51.         soapRequestData.append(“</prov:executePrvPricing>”);  
  52.         soapRequestData.append(” </soapenv:Body>”);  
  53.         soapRequestData.append(“</soapenv:Envelope>”);  
  54.   
  55.         HttpClient httpclient = HttpClients.createDefault();  
  56.         HttpPost httppost = new HttpPost(serviceUrl);  
  57.   
  58.         StringEntity content =new StringEntity(soapRequestData.toString(), Charset.forName(“UTF-8”));// 第二个参数,设置后才会对,内容进行编码  
  59.         content.setContentType(“application/soap+xml; charset=UTF-8”);  
  60.         content.setContentEncoding(“UTF-8”);  
  61.         httppost.setEntity(content);  
  62.           
  63.         //用下面的服务器端以UTF-8接收到的报文会乱码,原因未知  
  64. //        HttpEntity reqEntity = EntityBuilder.create().setContentType(  
  65. //                ContentType.TEXT_PLAIN) // .TEXT_PLAIN  
  66. //                .setText(soapRequestData.toString()).build();  
  67. //        httppost.setEntity(reqEntity);  
  68. //        httppost.addHeader(“Content-Type”,  
  69. //                “application/soap+xml; charset=utf-8”);  
  70.         HttpResponse response = null;  
  71.         Document doc = null;  
  72.         String returnXml = null;  
  73.         String sentity = null;  
  74.         try {  
  75.             response = httpclient.execute(httppost);  
  76.             HttpEntity resEntity = response.getEntity();  
  77.             if (resEntity != null) {  
  78.                 sentity = EntityUtils.toString(resEntity, “UTF-8”);  
  79.                 doc = XmlTool.getDocument(sentity, RequestConstants.ENCODE);  
  80.                 System.out.println(doc.toString());  
  81.                 Element eRoot = doc.getRootElement();  
  82.                 Element body = eRoot.getChild(“Body”, eRoot.getNamespace());  
  83.                 Element resp = (Element) body.getChildren().get(0);  
  84.                 Element returnele = resp.getChild(“return”);  
  85.                 returnXml = returnele.getText().toString();  
  86.             }  
  87.         } catch (ClientProtocolException e) {  
  88.             e.printStackTrace();  
  89.         } catch (IOException e) {  
  90.             e.printStackTrace();  
  91.         } catch (Exception e) {  
  92.             e.printStackTrace();  
  93.         } finally {  
  94.             log.info(“发送给德勤定价系统的请求报文:\n” + soapRequestData.toString());  
  95.             log.info(“德勤定价系统返回的响应报文:\n” + sentity);  
  96.             log.info(“返回给核心的的报文:\n” + returnXml);  
  97.         }  
  98.         return returnXml;  
  99.     }  
  100.       
  101.       
  102.     public String getServiceUrl() {  
  103.         return serviceUrl;  
  104.     }  
  105.   
  106.   
  107.     public void setServiceUrl(String serviceUrl) {  
  108.         this.serviceUrl = serviceUrl;  
  109.     }  
  110.   
  111.   
  112.     public static void main(String[] args) throws Exception{  
  113.         File file = new File(“D:/浙商项目资料/z浙江资料/t唐建华/德勤定价调试报文.txt”);  
  114.         System.out.println(file.exists());  
  115.           
  116.         String temp2 = null;  
  117.         StringBuilder sb2 = new StringBuilder();  
  118.         InputStreamReader isr = new InputStreamReader(new FileInputStream(file),“GBK”);  
  119.         BufferedReader br = new BufferedReader(isr);  
  120.         temp2 = br.readLine();  
  121.           
  122.         while( temp2 != null ){  
  123.             sb2.append(temp2);  
  124.             temp2 = br.readLine();  
  125.         }  
  126.         String sss = sb2.toString();  
  127. //        System.out.println(sss.toString());  
  128.         new DeloittePricingSingleCarImpl().invoke(sss);  
  129.     }  
  130. }  

post提交表单

[java] 
view plain 
copy

  1. /** 
  2.      * post方式提交表单(模拟用户登录请求) 
  3.      */   
  4.     public void postForm() {   
  5.         // 创建默认的httpClient实例.     
  6.         CloseableHttpClient httpclient = HttpClients.createDefault();   
  7.         // 创建httppost     
  8.         HttpPost httppost = new HttpPost(“http://localhost:8080/myDemo/Ajax/serivceJ.action”);   
  9.         // 创建参数队列     
  10.         List<NameValuePair> formparams = new ArrayList<NameValuePair>();   
  11.         formparams.add(new BasicNameValuePair(“username”“admin”));   
  12.         formparams.add(new BasicNameValuePair(“password”“123456”));   
  13.         UrlEncodedFormEntity uefEntity;   
  14.         try {   
  15.             uefEntity = new UrlEncodedFormEntity(formparams, “UTF-8”);   
  16.             httppost.setEntity(uefEntity);   
  17.             System.out.println(“executing request “ + httppost.getURI());   
  18.             CloseableHttpResponse response = httpclient.execute(httppost);   
  19.             try {   
  20.                 HttpEntity entity = response.getEntity();   
  21.                 if (entity != null) {   
  22.                     System.out.println(“————————————–“);   
  23.                     System.out.println(“Response content: “ + EntityUtils.toString(entity, “UTF-8”));   
  24.                     System.out.println(“————————————–“);   
  25.                 }   
  26.             } finally {   
  27.                 response.close();   
  28.             }   
  29.         } catch (ClientProtocolException e) {   
  30.             e.printStackTrace();   
  31.         } catch (UnsupportedEncodingException e1) {   
  32.             e1.printStackTrace();   
  33.         } catch (IOException e) {   
  34.             e.printStackTrace();   
  35.         } finally {   
  36.             // 关闭连接,释放资源     
  37.             try {   
  38.                 httpclient.close();   
  39.             } catch (IOException e) {   
  40.                 e.printStackTrace();   
  41.             }   
  42.         }   
  43.     }   

文件上传

[java] 
view plain 
copy

  1. /** 
  2.      * 上传文件 
  3.      */   
  4.     public void upload() {   
  5.         CloseableHttpClient httpclient = HttpClients.createDefault();   
  6.         try {   
  7.             HttpPost httppost = new HttpPost(“http://localhost:8080/myDemo/Ajax/serivceFile.action”);   
  8.      
  9.             FileBody bin = new FileBody(new File(“F:\\image\\sendpix0.jpg”));   
  10.             StringBody comment = new StringBody(“A binary file of some kind”, ContentType.TEXT_PLAIN);   
  11.      
  12.             HttpEntity reqEntity = MultipartEntityBuilder.create().addPart(“bin”, bin).addPart(“comment”, comment).build();   
  13.      
  14.             httppost.setEntity(reqEntity);   
  15.      
  16.             System.out.println(“executing request “ + httppost.getRequestLine());   
  17.             CloseableHttpResponse response = httpclient.execute(httppost);   
  18.             try {   
  19.                 System.out.println(“—————————————-“);   
  20.                 System.out.println(response.getStatusLine());   
  21.                 HttpEntity resEntity = response.getEntity();   
  22.                 if (resEntity != null) {   
  23.                     System.out.println(“Response content length: “ + resEntity.getContentLength());   
  24.                 }   
  25.                 EntityUtils.consume(resEntity);   
  26.             } finally {   
  27.                 response.close();   
  28.             }   
  29.         } catch (ClientProtocolException e) {   
  30.             e.printStackTrace();   
  31.         } catch (IOException e) {   
  32.             e.printStackTrace();   
  33.         } finally {   
  34.             try {   
  35.                 httpclient.close();   
  36.             } catch (IOException e) {   
  37.                 e.printStackTrace();   
  38.             }   
  39.         }   
  40.     }   

ssl连接

[java] 
view plain 
copy

  1. /** 
  2.      * HttpClient连接SSL 
  3.      */   
  4.     public void ssl() {   
  5.         CloseableHttpClient httpclient = null;   
  6.         try {   
  7.             KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());   
  8.             FileInputStream instream = new FileInputStream(new File(“d:\\tomcat.keystore”));   
  9.             try {   
  10.                 // 加载keyStore d:\\tomcat.keystore     
  11.                 trustStore.load(instream, “123456”.toCharArray());   
  12.             } catch (CertificateException e) {   
  13.                 e.printStackTrace();   
  14.             } finally {   
  15.                 try {   
  16.                     instream.close();   
  17.                 } catch (Exception ignore) {   
  18.                 }   
  19.             }   
  20.             // 相信自己的CA和所有自签名的证书   
  21.             SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();   
  22.             // 只允许使用TLSv1协议   
  23.             SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { “TLSv1” }, null,   
  24.                     SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);   
  25.             httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();   
  26.             // 创建http请求(get方式)   
  27.             HttpGet httpget = new HttpGet(“https://localhost:8443/myDemo/Ajax/serivceJ.action”);   
  28.             System.out.println(“executing request” + httpget.getRequestLine());   
  29.             CloseableHttpResponse response = httpclient.execute(httpget);   
  30.             try {   
  31.                 HttpEntity entity = response.getEntity();   
  32.                 System.out.println(“—————————————-“);   
  33.                 System.out.println(response.getStatusLine());   
  34.                 if (entity != null) {   
  35.                     System.out.println(“Response content length: “ + entity.getContentLength());   
  36.                     System.out.println(EntityUtils.toString(entity));   
  37.                     EntityUtils.consume(entity);   
  38.                 }   
  39.             } finally {   
  40.                 response.close();   
  41.             }   
  42.         } catch (ParseException e) {   
  43.             e.printStackTrace();   
  44.         } catch (IOException e) {   
  45.             e.printStackTrace();   
  46.         } catch (KeyManagementException e) {   
  47.             e.printStackTrace();   
  48.         } catch (NoSuchAlgorithmException e) {   
  49.             e.printStackTrace();   
  50.         } catch (KeyStoreException e) {   
  51.             e.printStackTrace();   
  52.         } finally {   
  53.             if (httpclient != null) {   
  54.                 try {   
  55.                     httpclient.close();   
  56.                 } catch (IOException e) {   
  57.                     e.printStackTrace();   
  58.                 }   
  59.             }   
  60.         }   
  61.     }   

关于RequestConfig的配置:  

源自:  

CloseableHttpClient设置Timeout – SegmentFault 思否

HttpClient 4.* connectionRequestTimeout, connectionTimeOut, socketTimeOut_walkerJong的博客-CSDN博客

[java] 
view plain 
copy

  1. public void requestConfig(){  
  2. //      新建一个RequestConfig:  
  3.         RequestConfig defaultRequestConfig = RequestConfig.custom()  
  4.             //一、连接目标服务器超时时间:ConnectionTimeout–>指的是连接一个url的连接等待时间  
  5.             .setConnectTimeout(5000)  
  6.             //二、读取目标服务器数据超时时间:SocketTimeout–>指的是连接上一个url,获取response的返回等待时间  
  7.             .setSocketTimeout(5000)  
  8.             //三、从连接池获取连接的超时时间:ConnectionRequestTimeout  
  9.             .setConnectionRequestTimeout(5000)  
  10.             .build();  
  11.            
  12. //      这个超时可以设置为客户端级别,作为所有请求的默认值:  
  13.         CloseableHttpClient httpclient = HttpClients.custom()  
  14.             .setDefaultRequestConfig(defaultRequestConfig)  
  15.             .build();  
  16. //       httpclient.execute(httppost);的时候可以让httppost直接享受到httpclient中的默认配置.  
  17.            
  18. //      Request不会继承客户端级别的请求配置,所以在自定义Request的时候,需要将客户端的默认配置拷贝过去:  
  19.         HttpGet httpget = new HttpGet(“http://www.apache.org/”);  
  20.         RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig)  
  21.             .setProxy(new HttpHost(“myotherproxy”8080))  
  22.             .build();  
  23.         httpget.setConfig(requestConfig);  
  24. //      httpget可以单独地使用新copy的requestConfig请求配置,不会对别的request请求产生影响  
  25.     }  

httpGet或httpPost 的abort()和releaseConnection()差异

[java] 
view plain 
copy

  1. //httpPost.abort();//中断请求,接下来可以开始另一段请求,所以个人理应,用这个应该可以在session中虚拟登录  
  2.  //httpPost.releaseConnection();//释放请求.如果释放了相当于要清空session  

根所以上差异,可知模拟登录可以如下:  源自 httpclient4.0的简单使用(1)马上去偷网页吧~-CSDN论坛

[java] 
view plain 
copy

  1. package com.bms.core;  
  2.      
  3. import java.io.IOException;  
  4. import java.util.ArrayList;  
  5. import java.util.List;  
  6.      
  7. import org.apache.http.Consts;  
  8. import org.apache.http.HttpEntity;  
  9. import org.apache.http.HttpResponse;  
  10. import org.apache.http.NameValuePair;  
  11. import org.apache.http.client.ClientProtocolException;  
  12. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  13. import org.apache.http.client.methods.HttpGet;  
  14. import org.apache.http.client.methods.HttpPost;  
  15. import org.apache.http.impl.client.DefaultHttpClient;  
  16. import org.apache.http.message.BasicNameValuePair;  
  17. import org.apache.http.util.EntityUtils;  
  18.      
  19. import com.bms.util.CommonUtil;  
  20.      
  21. public class Test2 {  
  22.      
  23.     /** 
  24.      * @param args 
  25.      * @throws IOException 
  26.      * @throws ClientProtocolException 
  27.      */  
  28.     public static void main(String[] args) throws ClientProtocolException, IOException {  
  29.         DefaultHttpClient httpclient = new DefaultHttpClient();  
  30.      
  31.          HttpGet httpGet = new HttpGet(“http://www.baidu.com”);  
  32.          String body = “”;  
  33.          HttpResponse response;  
  34.          HttpEntity entity;  
  35.          response = httpclient.execute(httpGet);  
  36.          entity = response.getEntity();  
  37.          body = EntityUtils.toString(entity);//这个就是页面源码了  
  38.          httpGet.abort();//中断请求,接下来可以开始另一段请求  
  39.          System.out.println(body);  
  40.          //httpGet.releaseConnection();//释放请求.如果释放了相当于要清空session  
  41.          //以下是post方法  
  42.          HttpPost httpPost = new HttpPost(“http://www.baidu.com”);//一定要改成可以提交的地址,这里用百度代替  
  43.          List <NameValuePair> nvps = new ArrayList <NameValuePair>();  
  44.          nvps.add(new BasicNameValuePair(“name”“1”));//名值对  
  45.          nvps.add(new BasicNameValuePair(“account”“xxxx”));  
  46.          httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));  
  47.          response = httpclient.execute(httpPost);  
  48.          entity = response.getEntity();  
  49.          body = EntityUtils.toString(entity);  
  50.          System.out.println(“Login form get: “ + response.getStatusLine());//这个可以打印状态  
  51.          httpPost.abort();  
  52.          System.out.println(body);  
  53.          httpPost.releaseConnection();  
  54.     }  
  55.      
  56. }  

源自  HttpClient使用详解_wangpeng047的博客-CSDN博客_httpclient使用

其它相关资料: 非CloseableHttpClient  HTTPClient模块的HttpGet和HttpPost

HttpClient 4.3教程

我的源码

httpclient异常情况分析

我项目中用到的HttpClientUtil (2016/12/17)

[java] 
view plain 
copy

  1. package com.isoftstone.pcis.isc.util;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InterruptedIOException;  
  5. import java.net.UnknownHostException;  
  6.   
  7. import javax.net.ssl.SSLException;  
  8. import javax.net.ssl.SSLHandshakeException;  
  9.   
  10. import org.apache.http.HttpEntityEnclosingRequest;  
  11. import org.apache.http.HttpRequest;  
  12. import org.apache.http.NoHttpResponseException;  
  13. import org.apache.http.client.HttpRequestRetryHandler;  
  14. import org.apache.http.client.protocol.HttpClientContext;  
  15. import org.apache.http.config.Registry;  
  16. import org.apache.http.config.RegistryBuilder;  
  17. import org.apache.http.conn.ConnectTimeoutException;  
  18. import org.apache.http.conn.socket.ConnectionSocketFactory;  
  19. import org.apache.http.conn.socket.LayeredConnectionSocketFactory;  
  20. import org.apache.http.conn.socket.PlainConnectionSocketFactory;  
  21. import org.apache.http.conn.ssl.SSLConnectionSocketFactory;  
  22. import org.apache.http.impl.client.CloseableHttpClient;  
  23. import org.apache.http.impl.client.HttpClients;  
  24. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;  
  25. import org.apache.http.protocol.HttpContext;  
  26. import com.isoftstone.pcis.isc.util.ProperUtil;  
  27.   
  28. public class HttpClientUtil {  
  29.       
  30.     private static CloseableHttpClient httpclient = null;   
  31.       
  32.     static final int maxTotal=Integer.valueOf(ProperUtil.get(“maxTotal”)).intValue();//总最大连接数  
  33.     static final int defaultMaxPerRoute=Integer.valueOf(ProperUtil.get(“corePoolSize”)).intValue();//每条线路最大连接数 = 本系统核心线程数 , 这样永远不会超过最大连接  
  34.       
  35.      public static CloseableHttpClient getHttpClient() {  
  36.               
  37.             if (null == httpclient) {  
  38.                 synchronized (HttpClientUtil.class) {  
  39.                     if (null == httpclient) {  
  40.                         httpclient = getNewHttpClient();  
  41.                     }  
  42.                 }  
  43.             }  
  44.               
  45.             return httpclient;  
  46.         }  
  47.        
  48.        private static CloseableHttpClient getNewHttpClient() {  
  49.   
  50.             
  51.             // 设置连接池  
  52.             ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();  
  53.             LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();  
  54.             Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create().register(“http”, plainsf).register(“https”, sslsf).build();  
  55.             PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);  
  56.             // 配置最大连接数  
  57.             cm.setMaxTotal(maxTotal);  
  58.             // 配置每条线路的最大连接数  
  59.             cm.setDefaultMaxPerRoute(defaultMaxPerRoute);  
  60.               
  61.             // 请求重试处理  
  62.             HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {  
  63.                 @Override  
  64.                 public boolean retryRequest(IOException exception,  
  65.                         int executionCount, HttpContext context) {  
  66.                     if (executionCount >= 2) {
    // 如果已经重试了2次,就放弃  
  67.                         return false;  
  68.                     }  
  69.                     if (exception instanceof NoHttpResponseException) {
    // 如果服务器丢掉了连接,那么就重试  
  70.                         return true;  
  71.                     }  
  72.                     if (exception instanceof SSLHandshakeException) {
    // 不要重试SSL握手异常  
  73.                         return false;  
  74.                     }  
  75.                     if (exception instanceof InterruptedIOException) {
    // 超时  
  76.                         return false;  
  77.                     }  
  78.                     if (exception instanceof UnknownHostException) {
    // 目标服务器不可达  
  79.                         return false;  
  80.                     }  
  81.                     if (exception instanceof ConnectTimeoutException) {
    // 连接被拒绝  
  82.                         return false;  
  83.                     }  
  84.                     if (exception instanceof SSLException) {
    // SSL握手异常  
  85.                         return false;  
  86.                     }  
  87.   
  88.                     HttpClientContext clientContext = HttpClientContext.adapt(context);  
  89.                     HttpRequest request = clientContext.getRequest();  
  90.                       
  91.                     if (!(request instanceof HttpEntityEnclosingRequest)) {  
  92.                         return true;  
  93.                     }  
  94.                     return false;  
  95.                 }  
  96.   
  97.             };  
  98.               
  99.             CloseableHttpClient newHttpclient=null;  
  100.           
  101.                 newHttpclient = HttpClients.custom()  
  102.                                            .setConnectionManager(cm)  
  103. //                                           .setDefaultRequestConfig(requestConfig)  
  104.                                            .setRetryHandler(httpRequestRetryHandler)  
  105.                                            .build();  
  106.                   
  107.              return newHttpclient;  
  108.        }  
  109. }  

我自己整理的HttpClientTool (2017/06/01)

[java] 
view plain 
copy

  1. package com.isoftstone.core.util;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InterruptedIOException;  
  5. import java.net.UnknownHostException;  
  6.   
  7. import javax.net.ssl.SSLException;  
  8. import javax.net.ssl.SSLHandshakeException;  
  9.   
  10. import org.apache.http.HttpEntityEnclosingRequest;  
  11. import org.apache.http.HttpHost;  
  12. import org.apache.http.HttpRequest;  
  13. import org.apache.http.NoHttpResponseException;  
  14. import org.apache.http.client.HttpRequestRetryHandler;  
  15. import org.apache.http.client.config.RequestConfig;  
  16. import org.apache.http.client.protocol.HttpClientContext;  
  17. import org.apache.http.config.Registry;  
  18. import org.apache.http.config.RegistryBuilder;  
  19. import org.apache.http.conn.ConnectTimeoutException;  
  20. import org.apache.http.conn.routing.HttpRoute;  
  21. import org.apache.http.conn.socket.ConnectionSocketFactory;  
  22. import org.apache.http.conn.socket.LayeredConnectionSocketFactory;  
  23. import org.apache.http.conn.socket.PlainConnectionSocketFactory;  
  24. import org.apache.http.conn.ssl.SSLConnectionSocketFactory;  
  25. import org.apache.http.impl.client.CloseableHttpClient;  
  26. import org.apache.http.impl.client.HttpClients;  
  27. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;  
  28. import org.apache.http.protocol.HttpContext;  
  29.   
  30. /** 
  31.  * org.apache.http.impl.client.CloseableHttpClient链接池生成工具 
  32.  * @reference http://www.cnblogs.com/whatlonelytear/articles/4835538.html 
  33.  * @author King 
  34.  * @date 20170601 
  35.  */  
  36. public class HttpClientTool {  
  37.   
  38.     // org.apache.http.impl.client.CloseableHttpClient  
  39.     private static CloseableHttpClient httpclient = null;  
  40.   
  41.     // 这里就直接默认固定了,因为以下三个参数在新建的method中仍然可以重新配置并被覆盖.  
  42.     static final int connectionRequestTimeout = 5000;// ms毫秒,从池中获取链接超时时间  
  43.     static final int connectTimeout = 5000;// ms毫秒,建立链接超时时间  
  44.     static final int socketTimeout = 30000;// ms毫秒,读取超时时间  
  45.   
  46.     // 总配置,主要涉及是以下两个参数,如果要作调整没有用到properties会比较后麻烦,但鉴于一经粘贴,随处可用的特点,就不再做依赖性配置化处理了.  
  47.     // 而且这个参数同一家公司基本不会变动.  
  48.     static final int maxTotal = 500;// 最大总并发,很重要的参数  
  49.     static final int maxPerRoute = 100;// 每路并发,很重要的参数  
  50.   
  51.     // 正常情况这里应该配成MAP或LIST  
  52.     // 细化配置参数,用来对每路参数做精细化处理,可以管控各ip的流量,比如默认配置请求baidu:80端口最大100个并发链接,  
  53.     static final String detailHostName = “http://www.baidu.com”;// 每个细化配置之ip(不重要,在特殊场景很有用)  
  54.     static final int detailPort = 80;// 每个细化配置之port(不重要,在特殊场景很有用)  
  55.     static final int detailMaxPerRoute = 100;// 每个细化配置之最大并发数(不重要,在特殊场景很有用)  
  56.   
  57.     public static CloseableHttpClient getHttpClient() {  
  58.         if (null == httpclient) {  
  59.             synchronized (HttpClientTool.class) {  
  60.                 if (null == httpclient) {  
  61.                     httpclient = init();  
  62.                 }  
  63.             }  
  64.         }  
  65.         return httpclient;  
  66.     }  
  67.   
  68.     /** 
  69.      * 链接池初始化 这里最重要的一点理解就是. 让CloseableHttpClient 一直活在池的世界里, 但是HttpPost却一直用完就消掉. 
  70.      * 这样可以让链接一直保持着. 
  71.      *  
  72.      * @return 
  73.      */  
  74.     private static CloseableHttpClient init() {  
  75.         CloseableHttpClient newHttpclient = null;  
  76.   
  77.         // 设置连接池  
  78.         ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();  
  79.         LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();  
  80.         Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create().register(“http”, plainsf).register(“https”, sslsf).build();  
  81.         PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);  
  82.         // 将最大连接数增加  
  83.         cm.setMaxTotal(maxTotal);  
  84.         // 将每个路由基础的连接增加  
  85.         cm.setDefaultMaxPerRoute(maxPerRoute);  
  86.   
  87.         // 细化配置开始,其实这里用Map或List的for循环来配置每个链接,在特殊场景很有用.  
  88.         // 将每个路由基础的连接做特殊化配置,一般用不着  
  89.         HttpHost httpHost = new HttpHost(detailHostName, detailPort);  
  90.         // 将目标主机的最大连接数增加  
  91.         cm.setMaxPerRoute(new HttpRoute(httpHost), detailMaxPerRoute);  
  92.         // cm.setMaxPerRoute(new HttpRoute(httpHost2),  
  93.         // detailMaxPerRoute2);//可以有细化配置2  
  94.         // cm.setMaxPerRoute(new HttpRoute(httpHost3),  
  95.         // detailMaxPerRoute3);//可以有细化配置3  
  96.         // 细化配置结束  
  97.   
  98.         // 请求重试处理  
  99.         HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {  
  100.             @Override  
  101.             public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {  
  102.                 if (executionCount >= 2) {
    // 如果已经重试了2次,就放弃  
  103.                     return false;  
  104.                 }  
  105.                 if (exception instanceof NoHttpResponseException) {
    // 如果服务器丢掉了连接,那么就重试  
  106.                     return true;  
  107.                 }  
  108.                 if (exception instanceof SSLHandshakeException) {
    // 不要重试SSL握手异常  
  109.                     return false;  
  110.                 }  
  111.                 if (exception instanceof InterruptedIOException) {
    // 超时  
  112.                     return false;  
  113.                 }  
  114.                 if (exception instanceof UnknownHostException) {
    // 目标服务器不可达  
  115.                     return false;  
  116.                 }  
  117.                 if (exception instanceof ConnectTimeoutException) {
    // 连接被拒绝  
  118.                     return false;  
  119.                 }  
  120.                 if (exception instanceof SSLException) {
    // SSL握手异常  
  121.                     return false;  
  122.                 }  
  123.   
  124.                 HttpClientContext clientContext = HttpClientContext.adapt(context);  
  125.                 HttpRequest request = clientContext.getRequest();  
  126.                 // 如果请求是幂等的,就再次尝试  
  127.                 if (!(request instanceof HttpEntityEnclosingRequest)) {  
  128.                     return true;  
  129.                 }  
  130.                 return false;  
  131.             }  
  132.         };  
  133.   
  134.         // 配置请求的超时设置  
  135.         RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(connectionRequestTimeout).setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout).build();  
  136.         newHttpclient = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(requestConfig).setRetryHandler(httpRequestRetryHandler).build();  
  137.         return newHttpclient;  
  138.     }  

个人公众号:java技术干货,微服务,分布式,各种中间件,数据库,JVM,容器化技术,bigdata等相关知识;以及好用的工具

HttpClient详细解释

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/234532.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号