HttpClient之使用方法
现在的网络协议有很多种,httpclient可以提供高效的,最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且支持HTTP协议最新的版本和建议(百度百科)。想要了解HTTP三次握手,四次挥手的过程可以查看:这里。
相关的知识点也会一并写出来,帮助提供清晰的认识。接下来我将根据代码实例进行讲解。
一、设置连接池:
1 private static PoolingHttpClientConnectionManager clientConnectionManager; 2 3 private static RequestConfig requestConfig; 4 5 private static final int MAX_TIMEOUT = 7000; 6 7 private static final int VALIDATE_CONNECTION = 1000; 8 9 static { 10 // 设置连接池 11 clientConnectionManager = new PoolingHttpClientConnectionManager(); 12 // 设置连接池大小 13 clientConnectionManager.setMaxTotal(MAX_TIMEOUT); 14 clientConnectionManager.setDefaultMaxPerRoute(clientConnectionManager.getMaxTotal()); 15 16 RequestConfig.Builder configBuilder = RequestConfig.custom(); 17 // 设置连接超时 18 configBuilder.setConnectTimeout(MAX_TIMEOUT); 19 // 设置读取超时 20 configBuilder.setSocketTimeout(MAX_TIMEOUT); 21 // 设置从连接池获取连接实例的超时 22 configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT); 23 // 在提交请求之前,测试连接是否可用,在一秒不活动之后验证连接 24 clientConnectionManager.setValidateAfterInactivity(VALIDATE_CONNECTION); 25 requestConfig = configBuilder.build(); 26 27 }
在单线程的使用中,每个线程都是执行一段很短的时间就结束了,这样会经历HTTP三次握手和四次挥手,而在多线程并发开发中,如果每次都需要经历这个过程,那么将会消耗大量的时间在创建和销毁中。java使用线程池的方式来使一个线程在执行完之后可以接着执行其他的任务,而不是直接销毁。具体的设置:连接池原理,连接池使用
二、get请求:
1 /** 2 * 3 * Title: doGet Description:发送get请求,不带参数。 4 * 5 * @param url 6 * @return 7 * @throws IOException 8 * @throws ClientProtocolException 9 */ 10 public static String doGet(String url) throws ClientProtocolException, IOException { 11 return doGet(url, new HashMap<String, String>()); 12 } 13 14 /** 15 * 16 * Title: doGet Description: 发送get请求,k-v模式 17 * 18 * @param url 19 * @param params 20 * @return 21 * @throws ClientProtocolException 22 * @throws IOException 23 */ 24 public static String doGet(String url, Map<String, String> params) throws ClientProtocolException, IOException { 25 logger.info("---------------------------------------------------------"); 26 logger.info("get:" + url); 27 logger.info("param" + params); 28 Long l1 = System.currentTimeMillis(); 29 String apiUrl = url; 30 StringBuffer param = new StringBuffer(); 31 Set<Map.Entry<String, String>> entrySet = params.entrySet(); /Map对象中keySet和entrySet的区别 32 Iterator<Map.Entry<String, String>> iterator = entrySet.iterator(); 33 int i = 0; 34 while (iterator.hasNext()) { 35 Map.Entry<String, String> mEntry = iterator.next(); 36 if (i == 0) { 37 param.append("?"); 38 } else { 39 param.append("&"); 40 } 41 param.append(mEntry.getKey()).append("=").append(mEntry.getValue()); 42 } 43 apiUrl += param; 44 String result = null; 45 CloseableHttpClient httpClient = HttpClients.createDefault(); //创建httpclient对象 46 CloseableHttpResponse response = null; 47 try { 48 HttpGet httpGet = new HttpGet(apiUrl); 49 response = httpClient.execute(httpGet); 50 logger.info("get resp" + response); 51 if (response != null) { 52 int statusCode = response.getStatusLine().getStatusCode(); 53 if (statusCode == HttpStatus.SC_OK) { 54 HttpEntity entity = response.getEntity(); 55 if (entity != null) { 56 InputStream inputStream = entity.getContent(); 57 try { 58 result = IOUtils.toString(inputStream, "UTF-8"); 59 } catch (IOException e) { 60 logger.info("IOUtils调用出错"); 61 e.printStackTrace(); 62 } finally { 63 inputStream.close(); 64 } 65 } 66 } 67 } 68 } catch (IOException e) { 69 logger.info("访问task服务接口失败 404"); 70 e.printStackTrace(); 71 } finally { 72 if (response != null) { 73 response.close(); 74 } 75 Long l2 = System.currentTimeMillis(); 76 logger.info("get takes:" + (l2 - l1) + "ms"); 77 } 78 return result; 79 }
get请求的步骤为:
1、创建HttpClient的实例:
1 CloseableHttpClient httpclient = HttpClients.createDefault();
2、创建发送get对象的实例:
1 HttpGet httpGet = new HttpClient(url);
3、创建response的实例:
1 CloseableHttpClientResponse response = httpClient.execute(httpGet);
4、获取结果的流:
1 HttpEntity httpEntity = response.getEntity();
5、使用InputStream方式输出结果:
1 InputStream inputStream = httpEntity.getContent(); 2 result = IOUtils.toString(inputStream,"utf-8");
6、关闭InputStream,response,httpClient:
1 inputStream.close(): 2 response.close(): 3 httpClient.close();
三、发送post请求的方式:
1 /** 2 * 3 * Title: doPost Description: 发送post请求,不带输入数据 4 * 5 * @param url 6 * @return 7 */ 8 public static String doPost(String url) { 9 return doPost(url, new HashMap<String, String>()); 10 } 11 12 /** 13 * 14 * Title: doPost Description: 发送post请求,k-v形式 15 * 16 * @param url 17 * @param params 18 * @return 19 */ 20 public static String doPost(String url, Map<String, String> params) { 21 logger.info("---------------------------------------------------------"); 22 logger.info("get:" + url); 23 logger.info("param" + params); 24 Long l1 = System.currentTimeMillis(); 25 CloseableHttpClient httpClient = HttpClients.createDefault(); //创建httpclient对象 26 String result = null; 27 HttpPost httpPost = new HttpPost(url); 28 CloseableHttpResponse response = null; 29 30 try { 31 httpPost.setConfig(requestConfig); 32 List<NameValuePair> pairsList = new ArrayList<>(); //NameValuePair的用法 33 for (Map.Entry<String, String> entry : params.entrySet()) { //Map对象中keySet和entrySet的区别 34 NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue().toString()); 35 pairsList.add(pair); 36 } 37 httpPost.setEntity(new UrlEncodedFormEntity(pairsList, Charset.forName("UTF-8"))); 38 response = httpClient.execute(httpPost); 39 logger.info("get resp" + response); 40 if (response != null) { 41 HttpEntity entity = response.getEntity(); 42 result = EntityUtils.toString(entity); 43 } 44 } catch (IOException e) { 45 logger.info("访问task服务接口失败 404"); 46 e.printStackTrace(); 47 } finally { 48 try { 49 EntityUtils.consume(response.getEntity()); //EntityUtils和InputStream的区别 50 } catch (IOException e) { 51 logger.info("关闭InputStream失败"); 52 e.printStackTrace(); 53 } 54 Long l2 = System.currentTimeMillis(); 55 logger.info("get takes:" + (l2 - l1) + "ms"); 56 } 57 return result; 58 } 59 60 /** 61 * 62 * Title: doPost Description: 发送post请求,json形式 63 * 64 * @param url 65 * @param json 66 * @return 67 */ 68 public static String doPost(String url, Object json) { 69 logger.info("---------------------------------------------------------"); 70 logger.info("get:" + url); 71 logger.info("param" + json); 72 Long l1 = System.currentTimeMillis(); 73 CloseableHttpClient httpClient = HttpClients.createDefault(); 74 CloseableHttpResponse response = null; 75 String result = null; 76 HttpPost httpPost = new HttpPost(url); 77 78 try { 79 httpPost.setConfig(requestConfig); 80 StringEntity stringEntity = new StringEntity(json.toString(), "UTF-8"); 81 stringEntity.setContentEncoding("UTF-8"); 82 stringEntity.setContentType("application/json"); 83 httpPost.setEntity(stringEntity); 84 response = httpClient.execute(httpPost); 85 logger.info("get resp" + response); 86 if (response != null) { 87 HttpEntity entity = response.getEntity(); 88 result = EntityUtils.toString(entity); 89 } 90 } catch (IOException e) { 91 logger.info("访问task服务接口失败 404"); 92 e.printStackTrace(); 93 } finally { 94 try { 95 EntityUtils.consume(response.getEntity()); 96 } catch (IOException e) { 97 logger.info("关闭InputStream失败"); 98 e.printStackTrace(); 99 } 100 Long l2 = System.currentTimeMillis(); 101 logger.info("get takes:" + (l2 - l1) + "ms"); 102 } 103 return result; 104 105 }
post请求的步骤为:
1、创建HttpClient的实例:
1 CloseableHttpClient httpclient = HttpClients.createDefault();
2、创建发送post对象的实例:
1 HttpPost httpPost = new HttpClient(url);
3、创建response的实例:
1 CloseableHttpClientResponse response = httpClient.execute(httpGet);
4、获取结果的流:
1 HttpEntity httpEntity = response.getEntity();
5、使用InputStream方式输出结果:(EntityUtils也可以)
1 InputStream inputStream = httpEntity.getContent();
2 result = IOUtils.toString(inputStream,"utf-8");
6、关闭InputStream,response,httpClient:
1 inputStream.close():
2 response.close():
3 httpClient.close();
四、Map对象中的keySet和entrySet的区别:转载
Set<K> keySet() //返回值是个只存放key值的Set集合(集合中无序存放的)
Set<Map.Entr<K,V>> entrySet() //返回映射所包含的映射关系的Set集合(一个关系就是一个键值对),就是把(key-value)作为一个整体一对一地存放到Set集合中。
1、keySet()方式:
1 Map<String, String> map = new HashMap<String, String>(); 2 map.put("01", "zhangsan"); 3 map.put("02", "lisi"); 4 map.put("03", "wangwu"); 5 //先获取map集合的所有键的Set集合 6 Set<String> keySet = map.keySet(); 7 //有了Set集合,就可以获取其迭代器。 8 Iterator<String> it = keySet.iterator(); 9 while (it.hasNext()) { 10 String key = it.next(); 11 //有了键可以通过map集合的get方法获取其对应的值。 12 String value = map.get(key); 13 //获得key和value值 14 System.out.println("key: " + key + "-->value: " + value); 15 }
2、entrySet()方式:
1 Map<String, String> map = new HashMap<String, String>(); 2 3 map.put("01", "zhangsan"); 4 map.put("02", "lisi"); 5 map.put("03", "wangwu"); 6 7 //通过entrySet()方法将map集合中的映射关系取出(这个关系就是Map.Entry类型) 8 Set<Map.Entry<String, String>> entrySet = map.entrySet(); 9 //将关系集合entrySet进行迭代,存放到迭代器中 10 Iterator<Map.Entry<String, String>> it2 = entrySet.iterator(); 11 while (it2.hasNext()) { 12 //获取Map.Entry关系对象me 13 Map.Entry<String, String> me = it2.next(); 14 //通过关系对象获取key 15 String key2 = me.getKey(); 16 //通过关系对象获取value 17 String value2 = me.getValue(); 18 System.out.println("key: " + key2 + "-->value: " + value2); 19 }
虽然使用keyset及entryset来进行遍历能取得相同的结果,但两者的遍历速度是有差别的。
keySet():迭代后只能通过get()取key
entrySet():迭代后可以e.getKey(),e.getValue()取key和value。返回的是Entry接口
说明:keySet()的速度比entrySet()慢了很多,也就是keySet方式遍历Map的性能不如entrySet性能好
为了提高性能,以后多考虑用entrySet()方式来进行遍历。
五、EntityUtils类和InputStream类:转载
EntityUtils对象是org.apache.http.util下的一个工具类,用官方的解释是为HttpEntity对象提供的静态帮助类,其常用的几个方法如下:
consume()方法; consumeQuietly(HttpEntity)方法 toByteArray(final HttpEntity entity)方法
最主要的就是consume()这个方法,其功能就是关闭HttpEntity是的流,如果手动关闭了InputStream instream = entity.getContent();这个流,也可以不调用这个方法。看看了其源码就知道了,其实也是inputStream.close();
六、NameValuePair的用法:转载
定义了一个list,该list的数据类型是NameValuePair(简单名称值对节点类型),这个代码多处用于Java像url发送Post请求。在发送post请求时用该list来存放参数。
发送请求的大致过程如下:
String url="http://www.baidu.com"; HttpPost httppost=new HttpPost(url); //建立HttpPost对象 List<NameValuePair> params=new ArrayList<NameValuePair>(); //建立一个NameValuePair数组,用于存储欲传送的参数 params.add(new BasicNameValuePair("pwd","2544"));//添加参数 httppost.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8)); //设置编码 HttpResponse response=new DefaultHttpClient().execute(httppost); //发送Post,并返回一个HttpResponse对象
参考:
https://blog.csdn.net/qq_33417547/article/details/69055518
https://blog.csdn.net/qq_26360877/article/details/70665820
https://blog.csdn.net/lykangjia/article/details/70159619?utm_source=itdadao&utm_medium=referral
https://blog.csdn.net/wxy1234556/article/details/79022402
https://blog.csdn.net/weixin_40144050/article/details/78964741

浙公网安备 33010602011771号