大连城乡建设局官网,重庆网站建设seo,合肥高端网站建设cnfg,西安网站建设定制一、简单介绍 1、简介 HttpClient是Apache Jakarta Common下的子项目#xff0c;用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包#xff0c;并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中#xff0c;比如Apache Jakarta上很著…一、简单介绍 1、简介 HttpClient是Apache Jakarta Common下的子项目用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。 HTTP和浏览器有点像但却不是浏览器。很多人觉得既然HttpClient是一个HTTP客户端编程工具很多人把他当做浏览器来理解但是其实HttpClient不是浏览器它是一个HTTP通信库因此它只提供一个通用浏览器应用程序所期望的功能子集最根本的区别是HttpClient中没有用户界面浏览器需要一个渲染引擎来显示页面并解释用户输入例如鼠标点击显示页面上的某处有一个布局引擎计算如何显示HTML页面包括级联样式表和图像。javascript解释器运行嵌入HTML页面或从HTML页面引用的javascript代码。来自用户界面的事件被传递到javascript解释器进行处理。除此之外还有用于插件的接口可以处理Applet嵌入式媒体对象如pdf文件Quicktime电影和Flash动画或ActiveX控件可以执行任何操作。HttpClient只能以编程的方式通过其API用于传输和接受HTTP消息。 2、特性
基于标准、纯净的java语言。实现了Http1.0和Http1.1以可扩展的面向对象的结构实现了Http全部的方法GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE。 支持HTTPS协议。通过Http代理建立透明的连接。利用CONNECT方法通过Http代理建立隧道的https连接。Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。 插件式的自定义认证方案。便携可靠的套接字工厂使它更容易的使用第三方解决方案。连接管理器支持多线程应用。支持设置最大连接数同时支持设置每个主机的最大连接数发现并关闭过期的连接。 自动处理Set-Cookie中的Cookie。插件式的自定义Cookie策略。Request的输出流可以避免流中内容直接缓冲到socket服务器。Response的输入流可以有效的从socket服务器直接读取相应内容。 在http1.0和http1.1中利用KeepAlive保持持久连接。 直接获取服务器发送的response code和 headers。 设置连接超时的能力。实验性的支持http1.1 response caching。源代码基于Apache License 可免费获取。 二、简单使用 1、引入依赖 dependencygroupIdorg.apache.httpcomponents/groupIdartifactIdhttpclient/artifactIdversion4.5.13/version/dependency 2、使用HttpClient发送请求、接收响应很简单一般需要如下几步即可。 //1. 创建HttpClient对象。CloseableHttpClient httpClient HttpClientBuilder.create().build();//2. 创建请求方法的实例并指定请求URL。// 如果需要发送GET请求创建HttpGet对象如果需要发送POST请求创建HttpPost对象。HttpGet httpGet new HttpGet(http://localhost:8090/emp/get);//3. 如果需要发送请求参数可调用HttpGet、HttpPost共同的setParams(HttpParams params)方法来添加请求参数// 对于HttpPost对象而言也可调用setEntity(HttpEntity entity)方法来设置请求参数。// 响应模型CloseableHttpResponse response null;try {// 4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求// 该方法返回一个HttpResponse。response httpClient.execute(httpGet);// 从响应模型中获取响应实体//5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头// 调用HttpResponse的getEntity()方法可获取HttpEntity对象该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。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 {// 6. 释放连接。无论执行方法是否成功都必须释放连接if (httpClient ! null) {httpClient.close();}if (response ! null) {response.close();}} catch (IOException e) {e.printStackTrace();}} 三、各种使用案例 1、GET请求 没有参数 //1、创建HttpClient 客户端CloseableHttpClient httpClient HttpClientBuilder.create().build();//2、 创建请求方法的实例并指定请求URLHttpGet httpGet new HttpGet(http://localhost:8090/user/get);//响应模型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();}} 2、GET 请求 路径上拼接参数 1直接拼接参数
String userId 1;String userName 张三;//1、创建HttpClient 客户端CloseableHttpClient httpClient HttpClientBuilder.create().build();//参数 拼接StringBuffer params new StringBuffer();try {// 字符数据最好encoding一下;这样一来某些特殊字符才能传过去(如:某人的名字就是“”,不encoding的话,传不过去)params.append(userId URLEncoder.encode(userId, utf-8));params.append();params.append(userName URLEncoder.encode(userName, utf-8));} catch (UnsupportedEncodingException e1) {e1.printStackTrace();}//2、 创建请求方法的实例并指定请求URLHttpGet httpGet new HttpGet(http://localhost:8090/user/get ? params);//响应模型CloseableHttpResponse response null;try {//添加配置信息RequestConfig requestConfig RequestConfig.custom()//设置连接超时时间单位毫秒.setConnectTimeout(5000)//设置请求超时时间单位毫秒.setConnectionRequestTimeout(5000)//socket读写超时时间单位毫秒.setSocketTimeout(50000)//设置是否允许重定向默认为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();}}2使用URI获得HttpGet String userId 1;String userName 张三;//1、创建HttpClient 客户端CloseableHttpClient httpClient HttpClientBuilder.create().build();// 使用URI 拼接好请求路径URI uri null;try {// 将参数放入键值对类NameValuePair中,再放入集合中ListNameValuePair params new ArrayList();params.add(new BasicNameValuePair(userId, userId));params.add(new BasicNameValuePair(userName, userName));// 设置uri信息,并将参数集合放入uri;// 注:这里也支持一个键值对一个键值对地往里面放setParameter(String key, String value)uri new URIBuilder().setScheme(http).setHost(localhost).setPort(8090).setPath(/user/get).setParameters(params).build();} catch (URISyntaxException e1) {e1.printStackTrace();}//2、 创建请求方法的实例并指定请求URLHttpGet httpGet new HttpGet(uri);//响应模型CloseableHttpResponse response null;try {//添加配置信息RequestConfig requestConfig RequestConfig.custom()//设置连接超时时间单位毫秒.setConnectTimeout(5000)//设置请求超时时间单位毫秒.setConnectionRequestTimeout(5000)//socket读写超时时间单位毫秒.setSocketTimeout(50000)//设置是否允许重定向默认为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();}}3、POST请求 没有参数 //1、创建HttpClient 客户端CloseableHttpClient httpClient HttpClientBuilder.create().build();//2、 创建请求方法的实例并指定请求URLHttpPost httpPost new HttpPost(http://localhost:8090/user/get);//响应模型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();}} 4、POST请求 有参对象参数 或 路径参数 1路径拼接参数 String userId 1;String userName 张三;//1、创建HttpClient 客户端CloseableHttpClient httpClient HttpClientBuilder.create().build();//参数 拼接StringBuffer params new StringBuffer();try {// 字符数据最好encoding一下;这样一来某些特殊字符才能传过去(如:某人的名字就是“”,不encoding的话,传不过去)params.append(userId URLEncoder.encode(userId, utf-8));params.append();params.append(userName URLEncoder.encode(userName, utf-8));} catch (UnsupportedEncodingException e1) {e1.printStackTrace();}//2、 创建请求方法的实例并指定请求URLHttpPost httpPost new HttpPost(http://localhost:8090/user/get?params);// 设置ContentType(注:一般路径拼接参数请求头都是application/x-www-form-urlencoded)httpPost.setHeader(Content-Type, application/x-www-form-urlencoded);//响应模型CloseableHttpResponse response null;try {//添加配置信息RequestConfig requestConfig RequestConfig.custom()//设置连接超时时间单位毫秒.setConnectTimeout(5000)//设置请求超时时间单位毫秒.setConnectionRequestTimeout(5000)//socket读写超时时间单位毫秒.setSocketTimeout(50000)//设置是否允许重定向默认为true.setRedirectsEnabled(true).build();// 将上面的配置信息添加到Get请求中httpPost.setConfig(requestConfig);// 由客户端执行发送Get请求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();}} 2对象参数
//1、创建HttpClient 客户端CloseableHttpClient httpClient HttpClientBuilder.create().build();//2、 创建请求方法的实例并指定请求URLHttpPost httpPost new HttpPost(http://localhost:8090/user/get);User user new User();user.setId(1L);user.setName(张三);// 我这里利用阿里的fastjson将Object转换为json字符串;// (需要导入com.alibaba.fastjson.JSON包)String jsonString JSON.toJSONString(user);// post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中StringEntity entity new StringEntity(jsonString, UTF-8);httpPost.setEntity(entity);// json参数需要设置请求头为 application/jsonhttpPost.setHeader(Content-Type, application/json;charsetutf8);//响应模型CloseableHttpResponse response null;try {//添加配置信息RequestConfig requestConfig RequestConfig.custom()//设置连接超时时间单位毫秒.setConnectTimeout(5000)//设置请求超时时间单位毫秒.setConnectionRequestTimeout(5000)//socket读写超时时间单位毫秒.setSocketTimeout(50000)//设置是否允许重定向默认为true.setRedirectsEnabled(true).build();// 将上面的配置信息添加到Get请求中httpPost.setConfig(requestConfig);// 由客户端执行发送Get请求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();}}3(普通参数 对象参数)
String userId 1;String userName 张三;//1、创建HttpClient 客户端CloseableHttpClient httpClient HttpClientBuilder.create().build();//参数 拼接StringBuffer params new StringBuffer();try {// 字符数据最好encoding一下;这样一来某些特殊字符才能传过去(如:某人的名字就是“”,不encoding的话,传不过去)params.append(userId URLEncoder.encode(userId, utf-8));params.append();params.append(userName URLEncoder.encode(userName, utf-8));} catch (UnsupportedEncodingException e1) {e1.printStackTrace();}//2、 创建请求方法的实例并指定请求URLHttpPost httpPost new HttpPost(http://localhost:8090/user/get?params);User user new User();user.setId(1L);user.setName(张三);// 我这里利用阿里的fastjson将Object转换为json字符串;// (需要导入com.alibaba.fastjson.JSON包)String jsonString JSON.toJSONString(user);// post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中StringEntity entity new StringEntity(jsonString, UTF-8);httpPost.setEntity(entity);// json参数需要设置请求头为 application/jsonhttpPost.setHeader(Content-Type, application/json;charsetutf8);//响应模型CloseableHttpResponse response null;try {//添加配置信息RequestConfig requestConfig RequestConfig.custom()//设置连接超时时间单位毫秒.setConnectTimeout(5000)//设置请求超时时间单位毫秒.setConnectionRequestTimeout(5000)//socket读写超时时间单位毫秒.setSocketTimeout(50000)//设置是否允许重定向默认为true.setRedirectsEnabled(true).build();// 将上面的配置信息添加到Get请求中httpPost.setConfig(requestConfig);// 由客户端执行发送Get请求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();}}5、使用httpClient下载文件 使用httpclient下载文件其实在调用上跟上面没有区别唯一需要注意的是再获取响应实体时容易出现 Attempted read from closed stream尝试读取关闭的流 异常我们可以用BufferedHttpEntity 的方式获取流
//1、创建HttpClient 客户端CloseableHttpClient httpClient HttpClientBuilder.create().build();//2、 创建请求方法的实例并指定请求URLHttpPost httpPost new HttpPost(http://localhost:8090/user/get);//响应模型CloseableHttpResponse response null;try {//添加配置信息RequestConfig requestConfig RequestConfig.custom()//设置连接超时时间单位毫秒.setConnectTimeout(5000)//设置请求超时时间单位毫秒.setConnectionRequestTimeout(5000)//socket读写超时时间单位毫秒.setSocketTimeout(50000)//设置是否允许重定向默认为true.setRedirectsEnabled(true).build();// 将上面的配置信息添加到Get请求中httpPost.setConfig(requestConfig);// 由客户端执行发送Get请求response httpClient.execute(httpPost);// 从响应模型中获取响应实体HttpEntity responseEntity response.getEntity();//entity实体流保存缓冲区,否则只能操作一次流就会关闭 ,BufferedHttpEntity可以多次读取流responseEntity new BufferedHttpEntity(responseEntity);System.out.println(响应状态为: response.getStatusLine());if (responseEntity ! null) {System.out.println(响应内容长度为: responseEntity.getContentLength());System.out.println(响应内容为: EntityUtils.toString(responseEntity));try(FileOutputStream fileOutputStream new FileOutputStream(C:\\Users\\Administrator\\Desktop\\新建文件夹 (2)\\测试.docx)){responseEntity.writeTo(fileOutputStream);}}} 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();}}6、关于https的调用 目前还没使用到等使用到再补充。 四、HttpClient连接池 事实上对于httpClient 连接池以及相关的配置大有学问针对高并发的场景有很多解决策略这里只先简单介绍一下如何配置连接池以及怎么使用复杂的业务范围可自行查询。 HttpClient连接池是用于优化HTTP请求性能的一个关键机制特别是在处理大量HTTP请求时通过重用现有连接来减少每次新建连接的开销。连接池的主要优势包括减少建立连接的时间、减少资源消耗、提高请求的并发处理能力。 以下是HttpClient连接池的几个核心概念和配置 1. 连接池的作用 每次HTTP请求都需要进行TCP握手特别是对于HTTPS还需要进行TLS握手这个过程非常耗时。连接池通过复用连接连接保持在一个池中避免了为每次请求都新建连接从而大大提高性能。 2、配置HttpClient连接池 在Apache HttpClient中可以通过PoolingHttpClientConnectionManager类来配置连接池。以下是一个基本的配置示例
// 创建连接池管理器
PoolingHttpClientConnectionManager cm new PoolingHttpClientConnectionManager();
// 设置最大连接数
cm.setMaxTotal(100);
// 设置每个路由的最大连接数
cm.setDefaultMaxPerRoute(20);
// 创建HttpClient实例
CloseableHttpClient client HttpClients.custom().setConnectionManager(connectionManager).setConnectionManagerShared(true).evictIdleConnections(30, TimeUnit.SECONDS) // 超过30秒的闲置连接会被清除.build();
最大连接数MaxTotal: 池中允许的最大连接数。默认值较小通常需要根据实际情况调大。
每个路由的最大连接数DefaultMaxPerRoute: 每个目标主机路由允许的最大并发连接数。不同的主机或API服务器通常会有各自的并发限制。
保持连接活动时间ConnectionKeepAlive: 指定一个连接在闲置后可以保持多久。短时间的保活可以避免不必要的重建连接但太长时间可能导致连接闲置过多浪费资源。 注意事项
连接泄漏: 如果不正确管理连接如未关闭可能会导致连接泄漏从而耗尽连接池中的可用连接影响系统的稳定性。线程安全: PoolingHttpClientConnectionManager是线程安全的可以在多个线程中共享同一个HttpClient实例。 高并发场景下的 HttpClient 优化方案QPS 大大提升