httpclient 订阅
HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。 展开全文
HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
信息
所属项目
Apache Jakarta Common
支持版本
HTTP 协议最新的版本和建议
外文名
httpclient
中文名
httpclient
性    质
客户端编程工具包
httpclient简介
HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。现在HttpClient最新版本为 HttpClient 4.5 .6(2015-09-11)
收起全文
精华内容
下载资源
问答
  • HttpClient详细使用示例

    万次阅读 多人点赞 2018-07-14 12:11:04
    HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中...HttpClient 是 Apache Jakarta Common 下的子项目,用...

            HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。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的主要功能:

    • 实现了所有 HTTP 的方法(GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS 等)
    • 支持 HTTPS 协议
    • 支持代理服务器(Nginx等)等
    • 支持自动(跳转)转向
    • ……

    进入正题


    环境说明:JDK1.8、SpringBoot

    准备环节

    第一步:在pom.xml中引入HttpClient的依赖

    第二步:引入fastjson依赖

    注:本人引入此依赖的目的是,在后续示例中,会用到“将对象转化为json字符串的功能”,也可以引其他有此功能的依赖。 

    注:SpringBoot的基本依赖配置,这里就不再多说了。


    详细使用示例

    声明:此示例中,以JAVA发送HttpClient(在test里面单元测试发送的);也是以JAVA接收的(在controller里面接收的)。

    声明:下面的代码,本人亲测有效。

    GET无参

    HttpClient发送示例:

        /**
    	 * GET---无参测试
    	 *
    	 * @date 2018年7月13日 下午4:18:50
    	 */
    	@Test
    	public void doGetTestOne() {
    		// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
    		CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    		// 创建Get请求
    		HttpGet httpGet = new HttpGet("http://localhost:12345/doGetControllerOne");
    
    		// 响应模型
    		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();
    			}
    		}
    	}

    对应接收示例:

    GET有参(方式一:直接拼接URL)

    HttpClient发送示例:

        /**
    	 * GET---有参测试 (方式一:手动在url后面加上参数)
    	 *
    	 * @date 2018年7月13日 下午4:19:23
    	 */
    	@Test
    	public void doGetTestWayOne() {
    		// 获得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:12345/doGetControllerTwo" + "?" + 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();
    			}
    		}
    	}

    对应接收示例:

    GET有参(方式二:使用URI获得HttpGet)

    HttpClient发送示例:

        /**
    	 * GET---有参测试 (方式二:将参数放入键值对类中,再放入URI中,从而通过URI得到HttpGet实例)
    	 *
    	 * @date 2018年7月13日 下午4:19:23
    	 */
    	@Test
    	public void doGetTestWayTwo() {
    		// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
    		CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    
    		// 参数
    		URI uri = null;
    		try {
    			// 将参数放入键值对类NameValuePair中,再放入集合中
    			List<NameValuePair> 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(12345).setPath("/doGetControllerTwo")
    					              .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无参

    HttpClient发送示例:

        /**
    	 * POST---无参测试
    	 *
    	 * @date 2018年7月13日 下午4:18:50
    	 */
    	@Test
    	public void doPostTestOne() {
    
    		// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
    		CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    
    		// 创建Post请求
    		HttpPost httpPost = new HttpPost("http://localhost:12345/doPostControllerOne");
    		// 响应模型
    		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();
    			}
    		}
    	}

    对应接收示例:

    POST有参(普通参数)

    注:POST传递普通参数时,方式与GET一样即可,这里以直接在url后缀上参数的方式示例。

    HttpClient发送示例:

        /**
    	 * POST---有参测试(普通参数)
    	 *
    	 * @date 2018年7月13日 下午4:18:50
    	 */
    	@Test
    	public void doPostTestFour() {
    
    		// 获得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();
    		}
    
    		// 创建Post请求
    		HttpPost httpPost = new HttpPost("http://localhost:12345/doPostControllerFour" + "?" + params);
    
    		// 设置ContentType(注:如果只是传普通参数的话,ContentType不一定非要用application/json)
    		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();
    			}
    		}
    	}

    对应接收示例:

    POST有参(对象参数)

    先给出User类

    HttpClient发送示例:

    	/**
    	 * POST---有参测试(对象参数)
    	 *
    	 * @date 2018年7月13日 下午4:18:50
    	 */
    	@Test
    	public void doPostTestTwo() {
    
    		// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
    		CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    
    		// 创建Post请求
    		HttpPost httpPost = new HttpPost("http://localhost:12345/doPostControllerTwo");
    		User user = new User();
    		user.setName("潘晓婷");
    		user.setAge(18);
    		user.setGender("女");
    		user.setMotto("姿势要优雅~");
    		// 我这里利用阿里的fastjson,将Object转换为json字符串;
    		// (需要导入com.alibaba.fastjson.JSON包)
    		String jsonString = JSON.toJSONString(user);
    
    		StringEntity entity = new StringEntity(jsonString, "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();
    			}
    		}
    	}

    对应接收示例:

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

    注:POST传递普通参数时,方式与GET一样即可,这里以通过URI获得HttpPost的方式为例。

    先给出User类:

    HttpClient发送示例:

    	/**
    	 * POST---有参测试(普通参数 + 对象参数)
    	 *
    	 * @date 2018年7月13日 下午4:18:50
    	 */
    	@Test
    	public void doPostTestThree() {
    
    		// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
    		CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    
    		// 创建Post请求
    		// 参数
    		URI uri = null;
    		try {
    			// 将参数放入键值对类NameValuePair中,再放入集合中
    			List<NameValuePair> params = new ArrayList<>();
    			params.add(new BasicNameValuePair("flag", "4"));
    			params.add(new BasicNameValuePair("meaning", "这是什么鬼?"));
    			// 设置uri信息,并将参数集合放入uri;
    			// 注:这里也支持一个键值对一个键值对地往里面放setParameter(String key, String value)
    			uri = new URIBuilder().setScheme("http").setHost("localhost").setPort(12345)
    					.setPath("/doPostControllerThree").setParameters(params).build();
    		} catch (URISyntaxException e1) {
    			e1.printStackTrace();
    		}
    
    		HttpPost httpPost = new HttpPost(uri);
    		// HttpPost httpPost = new
    		// HttpPost("http://localhost:12345/doPostControllerThree1");
    
    		// 创建user参数
    		User user = new User();
    		user.setName("潘晓婷");
    		user.setAge(18);
    		user.setGender("女");
    		user.setMotto("姿势要优雅~");
    
    		// 将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();
    			}
    		}
    	}

    对应接收示例:


    对评论区关注度较高的问题进行相关补充

    提示:如果想要知道完整的具体的代码及测试细节,可去下面给的项目代码托管链接,将项目clone下来
               进行观察。如果需要运行测试,可以先启动该SpringBoot项目,然后再运行相关test方法,进行
               测试。

    解决响应乱码问题(示例)

    进行HTTPS请求并进行(或不进行)证书校验(示例)

    使用示例:

    相关方法详情(非完美封装):

    /**
     * 根据是否是https请求,获取HttpClient客户端
     *
     * TODO 本人这里没有进行完美封装。对于 校不校验校验证书的选择,本人这里是写死
     *      在代码里面的,你们在使用时,可以灵活二次封装。
     *
     * 提示: 此工具类的封装、相关客户端、服务端证书的生成,可参考我的这篇博客:
     *      <linked>https://blog.csdn.net/justry_deng/article/details/91569132</linked>
     *
     *
     * @param isHttps 是否是HTTPS请求
     *
     * @return  HttpClient实例
     * @date 2019/9/18 17:57
     */
    private CloseableHttpClient getHttpClient(boolean isHttps) {
       CloseableHttpClient httpClient;
       if (isHttps) {
          SSLConnectionSocketFactory sslSocketFactory;
          try {
             /// 如果不作证书校验的话
             sslSocketFactory = getSocketFactory(false, null, null);
    
             /// 如果需要证书检验的话
             // 证书
             //InputStream ca = this.getClass().getClassLoader().getResourceAsStream("client/ds.crt");
             // 证书的别名,即:key。 注:cAalias只需要保证唯一即可,不过推荐使用生成keystore时使用的别名。
             // String cAalias = System.currentTimeMillis() + "" + new SecureRandom().nextInt(1000);
             //sslSocketFactory = getSocketFactory(true, ca, cAalias);
          } catch (Exception e) {
             throw new RuntimeException(e);
          }
          httpClient = HttpClientBuilder.create().setSSLSocketFactory(sslSocketFactory).build();
          return httpClient;
       }
       httpClient = HttpClientBuilder.create().build();
       return httpClient;
    }
    
    /**
     * HTTPS辅助方法, 为HTTPS请求 创建SSLSocketFactory实例、TrustManager实例
     *
     * @param needVerifyCa
     *         是否需要检验CA证书(即:是否需要检验服务器的身份)
     * @param caInputStream
     *         CA证书。(若不需要检验证书,那么此处传null即可)
     * @param cAalias
     *         别名。(若不需要检验证书,那么此处传null即可)
     *         注意:别名应该是唯一的, 别名不要和其他的别名一样,否者会覆盖之前的相同别名的证书信息。别名即key-value中的key。
     *
     * @return SSLConnectionSocketFactory实例
     * @throws NoSuchAlgorithmException
     *         异常信息
     * @throws CertificateException
     *         异常信息
     * @throws KeyStoreException
     *         异常信息
     * @throws IOException
     *         异常信息
     * @throws KeyManagementException
     *         异常信息
     * @date 2019/6/11 19:52
     */
    private static SSLConnectionSocketFactory getSocketFactory(boolean needVerifyCa, InputStream caInputStream, String cAalias)
          throws CertificateException, NoSuchAlgorithmException, KeyStoreException,
          IOException, KeyManagementException {
       X509TrustManager x509TrustManager;
       // https请求,需要校验证书
       if (needVerifyCa) {
          KeyStore keyStore = getKeyStore(caInputStream, cAalias);
          TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
          trustManagerFactory.init(keyStore);
          TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
          if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
             throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
          }
          x509TrustManager = (X509TrustManager) trustManagers[0];
          // 这里传TLS或SSL其实都可以的
          SSLContext sslContext = SSLContext.getInstance("TLS");
          sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom());
          return new SSLConnectionSocketFactory(sslContext);
       }
       // https请求,不作证书校验
       x509TrustManager = new X509TrustManager() {
          @Override
          public void checkClientTrusted(X509Certificate[] arg0, String arg1) {
          }
    
          @Override
          public void checkServerTrusted(X509Certificate[] arg0, String arg1) {
             // 不验证
          }
    
          @Override
          public X509Certificate[] getAcceptedIssuers() {
             return new X509Certificate[0];
          }
       };
       SSLContext sslContext = SSLContext.getInstance("TLS");
       sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom());
       return new SSLConnectionSocketFactory(sslContext);
    }
    
    /**
     * 获取(密钥及证书)仓库
     * 注:该仓库用于存放 密钥以及证书
     *
     * @param caInputStream
     *         CA证书(此证书应由要访问的服务端提供)
     * @param cAalias
     *         别名
     *         注意:别名应该是唯一的, 别名不要和其他的别名一样,否者会覆盖之前的相同别名的证书信息。别名即key-value中的key。
     * @return 密钥、证书 仓库
     * @throws KeyStoreException 异常信息
     * @throws CertificateException 异常信息
     * @throws IOException 异常信息
     * @throws NoSuchAlgorithmException 异常信息
     * @date 2019/6/11 18:48
     */
    private static KeyStore getKeyStore(InputStream caInputStream, String cAalias)
          throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException {
       // 证书工厂
       CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
       // 秘钥仓库
       KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
       keyStore.load(null);
       keyStore.setCertificateEntry(cAalias, certificateFactory.generateCertificate(caInputStream));
       return keyStore;
    }

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

    发送文件(示例)

    准备工作:

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

    在pom.xml中额外引入:

    <!--
         如果需要灵活的传输文件,引入此依赖后会更加方便
    -->
    <dependency>
    	<groupId>org.apache.httpcomponents</groupId>
    	<artifactId>httpmime</artifactId>
    	<version>4.5.5</version>
    </dependency>

    发送端是这样的:

    /**
     *
     * 发送文件
     *
     * multipart/form-data传递文件(及相关信息)
     *
     * 注:如果想要灵活方便的传输文件的话,
     *    除了引入org.apache.httpcomponents基本的httpclient依赖外
     *    再额外引入org.apache.httpcomponents的httpmime依赖。
     *    追注:即便不引入httpmime依赖,也是能传输文件的,不过功能不够强大。
     *
     */
    @Test
    public void test4() {
       CloseableHttpClient httpClient = HttpClientBuilder.create().build();
       HttpPost httpPost = new HttpPost("http://localhost:12345/file");
       CloseableHttpResponse response = null;
       try {
          MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
          // 第一个文件
          String filesKey = "files";
          File file1 = new File("C:\\Users\\JustryDeng\\Desktop\\back.jpg");
          multipartEntityBuilder.addBinaryBody(filesKey, file1);
          // 第二个文件(多个文件的话,使用同一个key就行,后端用数组或集合进行接收即可)
          File file2 = new File("C:\\Users\\JustryDeng\\Desktop\\头像.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();
          }
       }
    }

    接收端是这样的:

    发送流(示例)

    发送端是这样的:

    /**
     *
     * 发送流
     *
     */
    @Test
    public void test5() {
       CloseableHttpClient httpClient = HttpClientBuilder.create().build();
       HttpPost httpPost = new HttpPost("http://localhost:12345/is?name=邓沙利文");
       CloseableHttpResponse response = null;
       try {
          InputStream is = new ByteArrayInputStream("流啊流~".getBytes());
          InputStreamEntity ise = new InputStreamEntity(is);
          httpPost.setEntity(ise);
    
          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();
          }
       }
    }

    接收端是这样的:

     


    再次提示:如果想要自己进行测试,可去下面给的项目代码托管链接,将项目clone下来,然后先启动该
                      SpringBoot项目,然后再运行相关test方法,进行测试。

    工具类提示:使用HttpClient时,可以视情况将其写为工具类。如:Github上Star非常多的一个HttpClient
                          的工具类是httpclientutil。本人在这里也推荐使用该工具类,因为该工具类的编写者封装了
                          很多功能在里面,如果不是有什么特殊的需求的话,完全可以不用造轮子,可以直接使用
                          该工具类。使用方式很简单,可详见https://github.com/Arronlong/httpclientutil


     

    ^_^ 如有不当之处,欢迎指正

    ^_^ 代码托管链接
               
       https://github.com/JustryDeng/P.../Abc_HttpClientDemo

    ^_^ 本文已经被收录进《程序员成长笔记(五)》,作者JustryDeng

    展开全文
  • HttpClient

    万次阅读 2019-03-30 23:25:46
    HttpClient 入门

    HttpClient主页: http://hc.apache.org/

    HttpClient下载:http://hc.apache.org/downloads.cgi

    主页:http://hc.apache.org/httpcomponents-client-4.5.x/index.html


    HttpClient简介

    超文本传输协议(HTTP)也许是现在 Internet 上使用得最多、最重要的协议了。Web服务,有网络功能的设备和网络计算的发展,都持续扩展了HTTP协议的角色,超越了用户使用的Web浏览器范畴,同时,也增加了需要HTTP协议支持的应用程序的数量。越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。

    尽管java.net包提供了基本通过HTTP访问资源的功能,但它没有提供全面的灵活性和其他应用程序需要的功能。HttpClient就是需求弥补这项空白的组件,通过提供一个有效的,保持更新的,功能丰富的软件包来实现客户端最新的HTTP标准和建议。

    HttpClient 为扩展而设计,同时为基本的HTTP协议提供强大的支持,HttpClient组件也许就是构建Http客户端应用程序,比如web浏览器,web服务器,利用或扩展Http协议进行分布式通信的系统的开发人员的关注点。

    我们搞爬虫的,主要是用HttpClient模拟浏览器请求第三方站点url,然后响应,获取网页数据,然后用Jsoup来提取我们需要的信息。

    Maven 地址:

    import org.apache.http.HttpEntity;
    import org.apache.http.HttpHost;
    import org.apache.http.ParseException;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    import org.junit.Test;
    import org.apache.commons.io.FileUtils;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.7</version>
    </dependency>
    

     gradle 地址:

    //添加 httpclient 支持
    // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
    compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.7'
    

    简单演示

    前面我们介绍了HttpClient 这个框架主要用来请求第三方服务器,然后获取到网页,得到我们需要的数据。获取网站首页源码,要获得具体数据的话,要用到Jsoup。

    gradle 配置:

    //添加 httpclient 支持
    // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
    compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.7'
    
    //添加 jsoup 支持
    // https://mvnrepository.com/artifact/org.jsoup/jsoup
    compile group: 'org.jsoup', name: 'jsoup', version: '1.11.3'
    
    //添加 FileUtils 支持
    // https://mvnrepository.com/artifact/commons-io/commons-io
    compile group: 'commons-io', name: 'commons-io', version: '2.6'
    @Test
    public void test() throws IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault(); // 创建httpClient实例
        HttpGet httpGet = new HttpGet("https://blog.csdn.net/"); // 创建httpget实例
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpGet); // 执行http get请求
        } catch (ClientProtocolException e) { // http协议异常
            e.printStackTrace();
        } catch (IOException e) { // io异常
            e.printStackTrace();
        }
        HttpEntity entity = response.getEntity(); // 获取返回实体
        try {
            System.out.println("网页内容:" + EntityUtils.toString(entity, "utf-8")); // 获取网页内容
        } catch (ParseException e) { // 解析异常
            e.printStackTrace();
        } catch (IOException e) { // io异常
            e.printStackTrace();
        }
        try {
            response.close(); // response关闭
        } catch (IOException e) {  // io异常
            e.printStackTrace();
        }
        try {
            httpClient.close(); // httpClient关闭
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    假如你对这些异常都熟悉 我们可以简化下,异常抛出,这样代码可读性好点。

    /**
     * 异常全部抛出
     * 这样请求容易被服务器拒绝,有些服务器做了限制,拒绝服务,只允许游览器(代理工具)代理
     * 比如:推酷 爬取的别人的,但是他不让别爬取它的类容
     */
    @Test
    public void test2() throws IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault(); // 创建httpClient实例
        HttpGet httpGet = new HttpGet("http://www.tuicool.com/"); // 创建httpget实例
    
        CloseableHttpResponse response = httpClient.execute(httpGet); // 执行http get请求
        HttpEntity entity = response.getEntity(); // 获取返回实体
        System.out.println("网页内容:" + EntityUtils.toString(entity, "utf-8")); //获取网页内容( 指定编码打印网页内容) EntityUtils 工具类设置编码<meta charset="utf-8">
        response.close(); // response关闭
        httpClient.close(); // httpClient关闭
    }

    但是实际开发的话,我们对于每一种异常的抛出,catch里都需要做一些业务上的操作,所以以后用的话,还是第一种,假如爬虫任务很简单,容易爬取,并且量小,那就第二种。还是要根据具体情况来。


    HttpClient设置请求头消息User-Agent模拟浏览器

     HttpClient设置请求头消息User-Agent模拟浏览器,比如我们请求 www.tuicool.com 。

    /**
     * 不设置请求
     */
    @Test
    public void test3() throws IOException {
        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例
        HttpGet httpGet=new HttpGet("http://www.tuicool.com/"); // 创建httpget实例
    
        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求
        HttpEntity entity=response.getEntity(); // 获取返回实体
        System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 获取网页内容
        response.close(); // response关闭
        httpClient.close(); // httpClient关闭
    }

     网页内容:<!DOCTYPE html>
    <html>
        <head>
              <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        </head>
        <body>
            <p>系统检测亲不是真人行为,因系统资源限制,我们只能拒绝你的请求。如果你有疑问,可以通过微博 http://weibo.com/tuicool2012/ 联系我们。</p>
        </body>
    </html>

    我们模拟下浏览器 设置下User-Agent头消息:加下 

    httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0"); // 设置请求头消息User-Agent
    /**
     * 模拟游览器
     */
    @Test
    public void test3() throws IOException {
        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例
        HttpGet httpGet=new HttpGet("http://www.tuicool.com/"); // 创建httpget实例
    
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");
    
        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求
        HttpEntity entity=response.getEntity(); // 获取返回实体
        System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 获取网页内容
        response.close(); // response关闭
        httpClient.close(); // httpClient关闭
    }

    当然通过火狐firebug,我们还可以看到其他请求头消息。

     

    都是可以通过setHeader方法 设置key value;来得到模拟浏览器请求。 


    HttpClient获取响应内容类型Content-Type

     响应的网页内容都有类型也就是Content-Type,通过火狐firebug,我们看响应头信息:

     当然我们可以通过HttpClient接口来获取,HttpEntity的getContentType().getValue() 就能获取到响应类型。  

    /**
     * 获取响应类型
     */
    @Test
    public void test4() throws IOException {
        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例
        HttpGet httpGet=new HttpGet("http://central.maven.org/maven2/HTTPClient/HTTPClient/0.3-3/HTTPClient-0.3-3.jar"); // 创建httpget实例
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");
        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求
        HttpEntity entity=response.getEntity(); // 获取返回实体
        System.out.println("Content-Type:"+entity.getContentType().getValue());//entity.getContentType()返回的是 key, .getValue() 用于获取值
        //System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 获取网页内容
        response.close(); // response关闭
        httpClient.close(); // httpClient关闭
    }

     输出:

    Content-Type:application/java-archive

    一般网页是text/html当然有些是带编码的,比如请求www.tuicool.com:输出:

    Content-Type:text/html; charset=utf-8

    假如请求js文件,比如 http://www.open1111.com/static/js/jQuery.js

    运行输出:

    Content-Type:application/javascript

     

    假如请求的是文件,比如 http://central.maven.org/maven2/HTTPClient/HTTPClient/0.3-3/HTTPClient-0.3-3.jar

    运行输出:

    Content-Type:application/java-archive

     

    当然Content-Type还有一堆,那这东西对于我们爬虫有啥用的,我们再爬取网页的时候 ,可以通过Content-Type来提取我们需要爬取的网页或者是爬取的时候,需要过滤掉的一些网页。


    HttpClient获取响应状态Status

     我们HttpClient向服务器请求时,正常情况 执行成功 返回200状态码,不一定每次都会请求成功,比如这个请求地址不存在返回404,服务器内部报错返回500,有些服务器有防采集,假如你频繁的采集数据,则返回403 拒绝你请求。当然 我们是有办法的 后面会讲到用代理IP。

    这个获取状态码,我们可以用 CloseableHttpResponse对象的getStatusLine().getStatusCode()

    200 正常
    403 拒绝
    500 服务器报错
    400 未找到页面
    /**
     * 获取响应状态
     */
    @Test
    public void test5() throws IOException {
        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例
        HttpGet httpGet=new HttpGet("http://www.open1111.com/"); // 创建httpget实例
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");
        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求
    
        System.out.println("Status:"+response.getStatusLine().getStatusCode());//getStatusLine()返回Status:HTTP/1.1 200
        HttpEntity entity=response.getEntity(); // 获取返回实体
        //System.out.println("Content-Type:"+entity.getContentType().getValue());
        //System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 获取网页内容
        response.close(); // response关闭
        httpClient.close(); // httpClient关闭
    }

    假如换个页面 https://blog.csdn.net/qq_40794973/hehe.jsp 因为不存在,所以返回 404。


    抓取图片

    /**
     * 抓取图片
     * commons io  apache io框架
     */
    @Test
    public void test6() throws IOException {
        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例
        HttpGet httpGet=new HttpGet("http://www.java1234.com/gg/dljd4.gif"); // 创建httpget实例
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");
        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求
        HttpEntity entity=response.getEntity(); // 获取返回实体
        if(entity!=null){
            System.out.println("ContentType:"+entity.getContentType().getValue());
            InputStream inputStream=entity.getContent();
            FileUtils.copyToFile(inputStream, new File("F:/Test/download.gif"));
        }
        response.close(); // response关闭
        httpClient.close(); // httpClient关闭
    }

     

     


    HttpClient使用代理IP

    在爬取网页的时候,有的目标站点有反爬虫机制,对于频繁访问站点以及规则性访问站点的行为,会采集屏蔽IP措施。这时候,代理IP就派上用场了。关于代理IP的话也分几种、透明代理、匿名代理、混淆代理、高匿代理。

    1、透明代理(Transparent Proxy)

    REMOTE_ADDR = Proxy IP
    HTTP_VIA = Proxy IP
    HTTP_X_FORWARDED_FOR = Your IP

    透明代理虽然可以直接“隐藏”你的IP地址,但是还是可以从HTTP_X_FORWARDED_FOR来查到你是谁。

     

    2、匿名代理(Anonymous Proxy)

    REMOTE_ADDR = proxy IP
    HTTP_VIA = proxy IP
    HTTP_X_FORWARDED_FOR = proxy IP

    匿名代理比透明代理进步了一点:别人只能知道你用了代理,无法知道你是谁。

     

    3、混淆代理(Distorting Proxies)

    REMOTE_ADDR = Proxy IP
    HTTP_VIA = Proxy IP
    HTTP_X_FORWARDED_FOR = Random IP address

    如上,与匿名代理相同,如果使用了混淆代理,别人还是能知道你在用代理,但是会得到一个假的IP地址,伪装的更逼真。

     

    4、高匿代理(Elite proxy或High Anonymity Proxy)

    REMOTE_ADDR = Proxy IP
    HTTP_VIA = not determined
    HTTP_X_FORWARDED_FOR = not determined

    可以看出来,高匿代理让别人根本无法发现你是在用代理,所以是最好的选择。一般我们搞爬虫 用的都是 高匿的代理IP

     

    那代理IP 从哪里搞呢 很简单  百度一下,你就知道 一大堆代理IP站点。  一般都会给出一些免费的,但是花点钱搞收费接口更加方便。比如 http://www.66ip.cn/   https://www.xicidaili.com/?=144581

    httpClient使用代理IP代码:

    /**
     * 使用代理 ip
     * https://www.xicidaili.com/?=144581
     */
    @Test
    public void test7() throws IOException {
        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例
        HttpGet httpGet=new HttpGet("http://www.tuicool.com/"); // 创建httpget实例
    
        HttpHost proxy=new HttpHost("116.209.54.43", 9999);
        RequestConfig config=RequestConfig.custom().setProxy(proxy).build();
        httpGet.setConfig(config);
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");
        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求
        HttpEntity entity=response.getEntity(); // 获取返回实体
        System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 获取网页内容
        response.close(); // response关闭
        httpClient.close(); // httpClient关闭
    }

    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

    建议大家用国内代理IP 以及主干道网络大城市的代理IP 访问速度快。 


     

    HttpClient连接超时及读取超时

    httpClient在执行具体http请求时候 有一个连接的时间和读取内容的时间。

    HttpClient连接时间

    所谓连接的时候 是HttpClient发送请求的地方开始到连接上目标url主机地址的时间,理论上是距离越短越快,线路越通畅越快,但是由于路由复杂交错,往往连接上的时间都不固定,运气不好连不上,HttpClient的默认连接时间,据我测试,默认是1分钟,假如超过1分钟 过一会继续尝试连接,这样会有一个问题 假如遇到一个url老是连不上,会影响其他线程的线程进去,说难听点,就是蹲着茅坑不拉屎。所以我们有必要进行特殊设置,比如设置10秒钟 假如10秒钟没有连接上 我们就报错,这样我们就可以进行业务上的处理,比如我们业务上控制 过会再连接试试看。并且这个特殊url写到log4j日志里去。方便管理员查看。

    HttpClient读取时间

    所谓读取的时间 是HttpClient已经连接到了目标服务器,然后进行内容数据的获取,一般情况 读取数据都是很快速的,但是假如读取的数据量大,或者是目标服务器本身的问题(比如读取数据库速度慢,并发量大等等..)也会影响读取时间。同上,我们还是需要来特殊设置下,比如设置10秒钟 假如10秒钟还没读取完,就报错,同上,我们可以业务上处理。

    比如我们这里给个地址 http://central.maven.org/maven2/ ,这个是国外地址 连接时间比较长的,而且读取的内容多 很容易出现连接超时和读取超时。

     

    我们如何用代码实现呢?

    HttpClient给我们提供了一个RequestConfig类 专门用于配置参数比如连接时间,读取时间以及前面讲解的代理IP等。

    这里给下示例代码:

    /**
     * 连接超时
     * 读取超时
     */
    @Test
    public void test8() throws IOException {
        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例
        HttpGet httpGet=new HttpGet("http://central.maven.org/maven2/"); // 创建httpget实例
        RequestConfig config=RequestConfig.custom()
                .setConnectTimeout(10000) // 设置连接超时时间 10秒钟
                .setSocketTimeout(20000) // 设置读取超时时间10秒钟
                .build();
        httpGet.setConfig(config);
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");
        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求
        HttpEntity entity=response.getEntity(); // 获取返回实体
        System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 获取网页内容
        response.close(); // response关闭
        httpClient.close(); // httpClient关闭
    }

    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

     

    展开全文
  • httpClient

    万次阅读 2019-05-14 18:28:24
    public static void main(String[] args) throws ... //创建httpClient实例 CloseableHttpClient httpClient = HttpClients.createDefault(); //创建httpGet实例 HttpGet httpGet = new HttpGet("https:/...
    public static void main(String[] args) throws Exception{
    		//创建httpClient实例
    		CloseableHttpClient httpClient = HttpClients.createDefault();	
    		
    		//创建httpGet实例
    		HttpGet httpGet = new HttpGet("https://www.baidu.com/");	
    		
    		//设置请求头信息,这是chrome的请求头信息
    		httpGet.setHeader("User-Agent", "这是请求头信息");		
    
    		//设置代理
    		new().httpProxySet(httpGet);
    		
    		//执行http协议的get请求
    		CloseableHttpResponse response = httpClient.execute(httpGet);	
    		
    		//返回服务器对你的状态,如HTTP/1.1 200 OK,
    		//加.getStusCode后只返回数字(如:200),便于分析
    		System.out.println("status:" + response.getStatusLine().getStatusCode());
    		
    		HttpEntity entity = response.getEntity();	//获得返回实体
    		
    		//下载图片
    		new().downloadPicture(httpEntity);
    
    		//获取响应类型:ContentType,特征识别
    		System.out.println("ContentType:" + entity.getContentType().getValue()); 
    		
    		//查看网页内容
    		System.out.println("网页内容是:" + EntityUtils.toString(entity,"utf-8"));
    		
    		response.close();
    		httpClient.close();
    	}
    
    	//设置代理
    	public void httpProxySet(HttpGet httpGet) {
    		HttpHost proxy = new HttpHost("222.189.190.58", 9999);
    		RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
    		httpGet.setConfig(config);
    	}
    
    	//下载图片
    	public void downloadPicture(HttpEntity entity) throws Exception{
    		/*打开输入流,将图片放在内存中,然后用copyToFile方法将内存中的内容写入到想要的地方,
    		实现一个简单的粘贴复制*/
    		if(entity != null) {
    			System.out.println("COntenType:" + entity.getContentType().getValue());
    			//打开输入流
    			InputStream inputStream = entity.getContent();
    			//将输入流写入到文件中
    			FileUtils.copyToFile(inputStream,new File("D://ZCQ//copy.jpg"));
    		}
    	}
    
    • httpclient请求Get请求带参数
    void method(){
    		CloseableHttpClient httpClient = HttpClients.createDefault();
    
            //设置请求的地址是:https://search.bilibili.com/all?keyword=httpclient
            //创建UriBulider
            URIBuilder uriBuilder = new URIBuilder("https://search.bilibili.com/all");
    
            //设置参数
            uriBuilder.setParameter("keyword","httpclient")
            			.setParameter("param1","value1")
            			.setParameter("param2","value2");
    
            //创建HttpGet对象,设置uri访问地址
            HttpGet httpGet = new HttpGet(uriBuilder.build());
    
    		//再参照httpclient,即可
    		}
    
    展开全文
  • httpclient

    千次阅读 2017-04-16 20:22:49
    之前服务调用一用过直是用的dubbo,没有用过httpclient 这次试用感觉还是很简单的,上手简单,可能深入理解就没有那么简单了,下面简单写下上手使用的小demo // 发送xml数据到服务 HttpClientUtil httpClient...

    之前服务调用一用过直是用的dubbo,没有用过httpclient

    这次试用感觉还是很简单的,上手简单,可能深入理解就没有那么简单了,下面简单写下上手使用的小demo

    // 发送xml数据到服务
    		
    		HttpClientUtil httpClientUtil = new HttpClientUtil();
    		
    		String result = httpClientUtil.sendHttpPost("httpurl", outbound.getXMLString(a, b, c, d, e, f, g));
    		System.out.println(result);
    		String code = result.substring(result.indexOf("<statuscode>")+"<statuscode>".length(),result.indexOf("</statuscode>"));
    		System.out.println(code);
    		return code;

    // 获取xml
    	public String getXMLString(Integer channelid, Integer customerid, long batchid, Integer mediatype, String media,
    			String tels, String auth) {
    //		String XML_HEADER = "<?xml version=\"1.0\"?>";
    		StringBuffer sb = new StringBuffer();
    //		sb.append(XML_HEADER);
    		sb.append("<Request>");
    		sb.append("    <a>" + a+ "</a>");
    		sb.append("    <b>" + b+ "</b>");
    		sb.append("    <c>" + c+ "</c>");
    		sb.append("    <d>" + d+ "</d>");
    		sb.append("    <e>" + e+ "</e>");
    		sb.append("    <f>" + f+ "</f>");
    		sb.append("    <g>" + g+ "</g>");
    		sb.append("</Request>");
    		// 返回String格式
    		return sb.toString();
    
    	}
    工具类

     /**
         * 发送 post请求
         *
         * @param httpUrl 地址
         * @param params  参数(格式:key1=value1&key2=value2)
         */
        public String sendHttpPost(String httpUrl, String params) {
            HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
            try {
                //设置参数
                StringEntity stringEntity = new StringEntity(params, "UTF-8");
                stringEntity.setContentType("application/xml");
                httpPost.setEntity(stringEntity);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return sendHttpPost(httpPost);
        }



    展开全文
  • HttpClient使用详解

    万次阅读 多人点赞 2014-02-28 11:04:29
    Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端...HttpClient是Apache Jakarta Common下的子项目,用来提供高效的
  • HttpClient入门

    2017-05-06 18:57:38
    HttpClient
  • httpclient-4.5所需jar包

    万次下载 热门讨论 2015-07-15 15:43:21
    httpclient-4.5所需jar包,里面包含httpclient-4.5.jar等等10个必须的开发包
  • HttpClient工具类

    万次阅读 多人点赞 2019-09-25 22:23:57
    最近在工作中需要在后台调用短信接口,经过研究决定使用HttpClient,自己封装了一个HttpClient工具类,简单轻松的实现get,post,put和delete请求,希望分享给大家。 1. 什么是HttpClient HTTP 协议可能是现在 ...
  • httpclient和异步httpclient

    万次阅读 2016-08-11 13:35:41
    本文偏重使用,简单讲述httpclient,其实在网络编程中,基于Java的实现几乎都是包装了socket的通信,然后来模拟各种各样的协议;httpclient其实就是模拟浏览器发起想服务器端的请求,而这种更加类似于JS的请求或页面...
  • HttpClient2

    千次阅读 2019-05-16 16:39:25
    HttpClient2
  • HTTPClient和CloseableHttpClient

    万次阅读 多人点赞 2019-05-16 09:14:47
    使用HttpClient发送请求的一般步骤 (1) 创建HttpClient对象。 (2)创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。 (3) 如果需要发送请求参数...
  • 通用HttpClientUtil工具类

    万次阅读 2020-03-02 22:38:58
    依赖 <dependency> <groupId>org.apache.httpcomponents</groupId>...httpclient</artifactId> <version>4.5.11</version> </dependency> package com...
  • httpclient.jar包下载

    千次下载 热门讨论 2012-12-06 12:45:49
    httpclient.jar下载 包括code.jar包
  • HttpClient 教程 HttpClient Tutorial

    千次阅读 2015-05-02 20:28:31
    首先声明教程非我原创,本文仅收集了教程链接。 HttpClient不再介绍。直接上干货。 HttpClient Tutorial 官方英文原版,地址:HttpClient ...HttpClient Tutorial...Apache HttpClient 4.4.1 API,地址:HttpClient
  • HttpClient详解

    2019-06-18 15:07:19
    HttpClient详细使用示例 HttpClient使用详解
  • HttpClient调用接口的实例

    万次阅读 2020-07-20 13:34:50
    public class TestHttpClient { public static void main(String[] args) { // 请求接口地址 String url = ""; // 请求参数 ... HttpClient httpclient = null; PostMethod post = null; try {
  • HttpClient httpClient = new HttpClient();报错

    千次阅读 2018-12-28 18:02:18
    jar包错了 ...commons-httpclient&lt;/groupId&gt; &lt;artifactId&gt;commons-httpclient&lt;/artifactId&gt; &lt;version&gt;3.1&lt;/version&gt; &
  • commons-httpclienthttpclient 区别 项目里的pom中,里面有这么两个包依赖。 <dependency> <groupId>commons-httpclient</groupId> <artifactId>commons-httpclient</...
  • Java工具类--通过HttpClient发送http请求

    万次阅读 多人点赞 2015-11-27 15:17:34
    在写网络程序的时候,经常会有从网址获取数据的需求,上一篇解析JSON就需要从百度...HttpClient的介绍 The most essential function of HttpClient is to execute HTTP methods. Execution of an HTTP method involves
  • HttpClient4.5源码

    热门讨论 2015-07-10 15:27:30
    HttpClient4.5源码,包括fluent-hc,httpclienthttpclient-cache,httpclient-osgi,httpclient-win,httpmime

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 49,242
精华内容 19,696
热门标签
关键字:

httpclient