Apache HttpClient 详解

1、简介

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

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

2、引入依赖

HttpClient 是三方工具,首先需要引入依赖。如下:

<!-- 此处使用的是 5.x 版本,可以根据自身情况引入版本 -->
<dependency><groupId>org.apache.httpcomponents.client5</groupId><artifactId>httpclient5</artifactId><version>5.1.1</version>
</dependency>

3、获取客户端

在使用时,首先需要 获取 HttpClient 对象,有如下几种获取方式

  1. 默认创建方式

// 获取默认配置的 HttpClient 
CloseableHttpClient httpClient = HttpClients.createDefault();

2.根据系统配置创建

// 此种方式是通过 根据 系统配置创建 HttpClient
CloseableHttpClient httpClient = HttpClients.createSystem();

在项目启动时可以通过设置如下JVM启动参数:

  • http.agent 配置 userAgent
  • http.keepAlive 配置 keepAlive 数据

3.自定义创建

// 此种方式可以在创建时 设置一些默认值
CloseableHttpClient  httpClient = HttpClients.custom().setDefaultHeaders(Collections.emptyList())   // 设置默认请求头.setDefaultRequestConfig(RequestConfig.DEFAULT)  // 设置默认配置.build();

4、配置参数

HttpClient 可以通过在创建 HttpClient 对象时就设置全局配置,也可以为单个请求设置请求配置。

  1. 创建配置对象

  //  创建请求配置信息
RequestConfig  requestConfig = RequestConfig.custom()// 设置连接超时时间.setConnectTimeout(Timeout.of(3000, TimeUnit.MILLISECONDS))// 设置响应超时时间.setResponseTimeout(3000, TimeUnit.MILLISECONDS) // 设置从连接池获取链接的超时时间.setConnectionRequestTimeout(3000, TimeUnit.MILLISECONDS).build();

2.设置全局配置

// 此种方式可以在创建时 设置一些默认值
CloseableHttpClient  httpClient = HttpClients.custom().setDefaultHeaders(Collections.emptyList())   // 设置默认请求头.setDefaultRequestConfig(requestConfig)  // 设置默认配置.build();

3.单个请求设置配置

// 创建 GET 请求对象
HttpGet httpGet = new HttpGet(uri);// 设置请求参数
httpGet.setConfig(requestConfig);

5、设置请求头信息

在请求时,经常会遇到设置自定义请求头,或者更改 Conent-Type 的值,可以通过如下两种方式设置:

  1. 设置公共请求头

List<Header> headers = new ArrayList<>();
headers.add(new BasicHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON));
headers.add(new BasicHeader(HttpHeaders.ACCEPT_ENCODING, "gzip, x-gzip, deflate"));
headers.add(new BasicHeader(HttpHeaders.CONNECTION, "keep-alive"));// 创建 一个默认的 httpClient
CloseableHttpClient  httpClient = HttpClients.custom().setDefaultHeaders(headers)   // 设置默认请求头.build()

2.单个请求设置请求头

// 创建 POST 请求
HttpPost httpPost = new HttpPost(uri);
// 添加 Content-Type 请求头
httpPost.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED);
// 添加 accept 请求头
httpPost.addHeader(new BasicHeader(HttpHeaders.ACCEPT, "*/*"));

6、发送请求

GET 请求

GET请求的所有参数是直接拼接在 URL 后面的,在 HttpClient 中 有两种方式可以实现,如下所示:

  1. 请求参数直接拼接在请求路径后面

String name = URLEncoder.encode("张三", "utf-8");
// 请求路径及参数
String url = "http://localhost:10010/user/params?age=20&name=" + name;// 创建 GET 请求对象
HttpGet httpGet = new HttpGet(url);
// 调用 HttpClient 的 execute 方法执行请求
CloseableHttpResponse response = httpClient.execute(httpGet);
// 获取请求状态
int code = response.getCode();
// 如果请求成功
if(code == HttpStatus.SC_OK){LOGGER.info("响应结果为:{}", EntityUtils.toString(response.getEntity()));
}

2.通过 URIBuilder 构建请求路径

// 构建请求路径,及参数
URL url = new URL("http://localhost:10010/user/params");
URI uri = new URIBuilder().setScheme(url.getProtocol()).setHost(url.getHost()).setPort(url.getPort()).setPath(url.getPath())// 构建参数.setParameters(new BasicNameValuePair("name", "张三"),new BasicNameValuePair("age", "20")).build();// 创建 GET 请求对象
HttpGet httpGet = new HttpGet(uri);
// 调用 HttpClient 的 execute 方法执行请求
CloseableHttpResponse response = httpClient.execute(httpGet);
// 获取请求状态
int code = response.getCode();
// 如果请求成功
if(code == HttpStatus.SC_OK){LOGGER.info("响应结果为:{}", EntityUtils.toString(response.getEntity()));
}

POST 请求

众所周知,HTTP 中的 POST 请求的数据是包含在请求体中的。在 HttpClient 中 POST 请求发送数据是通过,调用 HttpPost 类的 setEntity(HttpEntity entity) 方法设置消息内容的。

  1. 发送 JSON 数据

    HttpClient 中发送 JSON 数据可以使用 StringHttpEntity 类实现,如下所示:

// 请求参数
String url = "http://localhost:10010/user/body";
// 创建 GET 请求对象
HttpPost httpPost = new HttpPost(url);
// 构建对象
User user = new User();
user.setName("张三").setAge(20).setAddress(new Address().setCounty("中国").setCity("北京")).setAihao(Arrays.asList("跑步", "爬山", "看书"));// 创建 字符串实体对象
HttpEntity httpEntity = new StringEntity(JSON.toJSONString(user));
httpPost.setEntity(httpEntity);// 发送 POST 请求
httpClient.execute(httpPost);

2.模拟form表单数据

在实际使用时,可以存在 需要模拟 form 表单的情况进行请求数据,在 HttpClent 中也可以很方便的实现 form 的提交功能。操作步骤如下:

  • 修改 contentType

// 创建 ContentType 对象为 form 表单模式 
ContentType contentType = ContentType.create("application/x-www-form-urlencoded", StandardCharsets.UTF_8);
// 添加到 HttpPost 头中
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, contentType);

创建请求数据 HttpEntity

// 方式一、自己拼接请求数据,并且创建 StringEntity 对象
String query = "name="+ URLEncoder.encode("张三", "utf-8") +"&age=20";
HttpEntity httpEntity = new StringEntity(query);// 方式二、通过UrlEncodedFormEntity 创建 HttpEntity
HttpEntity httpEntity = new UrlEncodedFormEntity(Arrays.asList(new BasicNameValuePair("name", "张三"),new BasicNameValuePair("age", "20")),StandardCharsets.UTF_8
);// 把 HttpEntity 设置到 HttpPost 中
httpPost.setEntity(httpEntity);

完整代码如下所示:

// 创建 POST 请求对象
HttpPost httpPost = new HttpPost("http://localhost:10010/user/map");
/*String query = "name="+ URLEncoder.encode("张三", "utf-8") +"&age=20";HttpEntity httpEntity = new StringEntity(query);*/HttpEntity httpEntity = new UrlEncodedFormEntity(Arrays.asList(new BasicNameValuePair("name", "张三"),new BasicNameValuePair("age", "20")),StandardCharsets.UTF_8
);// 设置请求数据
httpPost.setEntity(httpEntity);
// 设置请求头
ContentType contentType = ContentType.APPLICATION_FORM_URLENCODED.withCharset(StandardCharsets.UTF_8);
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
// 调用 HttpClient 的 execute 方法执行请求
CloseableHttpResponse response = httpClient.execute(httpPost);
// 获取请求状态
int code = response.getCode();
// 如果请求成功
if(code == HttpStatus.SC_OK){LOGGER.info("响应结果为:{}", EntityUtils.toString(response.getEntity()));
}

7、上传下载

上传

在 HttpClient 中实现上传功能是非常方便的,可以通过 MultipartEntityBuilder直接构建 HttpEntity 即可。

//要上传的文件
File file = new File("F:/20150703212056_Yxi4L.jpeg");// 创建对象
MultipartEntityBuilder builder = MultipartEntityBuilder.create();// 添加二进制消息体
builder.addBinaryBody("file", file);// 也可以添加文本消息
ContentType contentType = ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8);
builder.addTextBody("name", "张三", contentType);// 通过 MultipartEntityBuilder 构建消息体
HttpEntity httpEntity = builder.build();
HttpPost httpPost = new HttpPost("http://localhost:10010/user/upload");
httpPost.setEntity(httpEntity);
CloseableHttpResponse response = httpClient.execute(httpPost);
// 获取请求状态
int code = response.getCode();
// 如果请求成功
if(code == HttpStatus.SC_OK){LOGGER.info("响应结果为:{}", EntityUtils.toString(response.getEntity()));
}

下载

HttpClient 中的下载也相当简单,只需要发送请求,判断请求成功后,读取输入流,然后保存到响应的路径下即可,如下:

// 请求下载路径
HttpGet httpGet = new HttpGet("http://localhost:10010/user/downLoad");
CloseableHttpResponse response = httpClient.execute(httpGet);// 如果请求成功
if (response.getCode() == HttpStatus.SC_OK){// 获取下载文件的文件名,此处的 File-Name 头信息,需要在服务端进行自定义Header header = response.getFirstHeader("File-Name");String value = header.getValue();// 读取数据byte[] bytes = EntityUtils.toByteArray(response.getEntity());try (OutputStream outputStream = new FileOutputStream("F:/" + value);){outputStream.write(bytes);outputStream.flush();}
}

8、响应处理

在 HttpClient 中把响应封装成了 CloseableHttpResponse 对象,在此对象中可以获取如下数据:

  1. getCode() 获取响应状态
  2. getEntity() 获取响应数据
 // 如果请求成功
if(code == HttpStatus.SC_OK){LOGGER.info("响应结果为:{}", EntityUtils.toString(response.getEntity()));
}

HttpClient 提供了 EntityUtils工具类,可以很好的把 响应的 HttpEntity 转换为 字节数组或者字符串

// 转换为字符串
EntityUtils.toString(response.getEntity());// 转换为字节数组
EntityUtils.toByteArray(response.getEntity());

除了上述外,还可以在 调用 HttpClient 的 execute()方法时 传入,响应处理器,返回自定义的数据类型。如下所示,是返回一个 自定义的 Response 对象

// 自定义响应对象
@Data
@Accessors(chain = true)
class  Response {// 响应状态private int code;// 响应描述private String msg;// 响应体private String body;
}// 调用  execute 时自定义 响应处理类Response execute = httpClient.execute(httpGet, response -> {return new Response().setCode(response.getCode()).setMsg(response.getReasonPhrase()).setBody(EntityUtils.toString(response.getEntity(),                 StandardCharsets.UTF_8));});

9、会话保持

在实际项目中,经常会遇到需要先登录然后才能进行访问其他接口,那么, 在 HttpClient 中提供了 HttpClientContext 类,可以很好的实现,会话保持功能。

  • 创建HttpClientContext
  • 在 execute() 方法中传入 第一步创建的对象

如下所示:

// 创建 HttpClientContext对象
HttpContext httpContext = new BasicHttpContext();
httpContext.setAttribute("name", "zhangsan");
HttpClientContext httpClientContext = HttpClientContext.adapt(httpContext);// 登录
httpClient.execute(new HttpPost(""), httpClientContext);// 获取数据
httpClient.execute(new HttpGet(""), httpClientContext);

10、总结

这里只是 HttpClient 的使用做了简单的介绍,起到抛砖引玉的作用,其实,HttpClient 提供的功能非常强大的,在接下来会对 HttpClient 层层剖析,慢慢揭开 其神秘面纱。


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/495659.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

寒武纪创始人兼CEO陈天石博士的公开信

来源&#xff1a;来源&#xff1a;寒武纪科技摘要&#xff1a;2018年5月3日&#xff0c;寒武纪已在中国上海发布了首款云端智能芯片MLU100及相应的板卡产品。作为寒武纪的创始人和CEO&#xff0c;我非常自豪地与大家分享一个消息&#xff1a;2018年5月3日&#xff0c;寒武纪已在…

压栈, 跳转,执行,返回:从汇编看函数调用

From&#xff1a;https://www.jianshu.com/p/594357dff57e C函数调用过程原理及函数栈帧分析&#xff1a;https://blog.csdn.net/zsy2020314/article/details/9429707 从本篇开始&#xff0c;我们讨论一些高级语言中的基础设施&#xff1a;堆栈&#xff0c;函数调用&#xff0…

IBM AIX 5.3 系统管理 -- 系统启动过程详解

一. 启动过程 启动过程包含下面的一些步骤&#xff1a; 1.1启动一个系统的初始步骤是上电自检&#xff08;Power On Self Test&#xff0c;POST&#xff09;。其目的是验证基本硬件是否处于正常的工作状态。同时初始化内存、键盘、通信&#xff0c;以及音频设备。您可以看到在屏…

Collectors.toMap应用

Collectors.toMap介绍 在真实的业务场景中有很多集合转map的操作&#xff0c;例如 Data public class House {private Integer id; //idprivate Integer ownerid; //家主编号private String housename; //家庭名称private String address; //家庭地址}模拟数据 …

作弊阴影罩棋盘,人工智能咋避嫌?

来源&#xff1a;奇怪的科学家为什么要写这样一句话&#xff0c;就是为了避免剧情和现实生活中发生的事情万一差不多&#xff0c;会侵犯到别人的隐私&#xff0c;发生侵权&#xff0c;给双方带来不必要的麻烦。这位名为刘超的棋手把手机插在上衣兜里&#xff0c;摄像头正对棋盘…

小甲鱼视频教程系列

在学习 Ollydbg 时&#xff0c;发现小甲鱼讲的 Ollydbg 教程还可以&#xff0c;就把小甲鱼的视频整理了下。 小甲鱼主页&#xff1a;https://ilovefishc.com 小甲鱼论坛&#xff1a;https://fishc.com.cn 《零基础入门C语言》&#xff1a;https://www.bilibili.com/video/av277…

ubuntu server版本安装指南(1)

ubuntu是基于GNU/Linux 的操作系统&#xff0c;本身是在同样GNU/Linux 架构下的Debian的基础上的一个版本。由于它在桌面环境上的易用性和精细度是许多人认识了他。ubuntu的强大在一定程度上体现在apt包管理系 统。安装软件不必像以前那样幸苦找到下载地址。编译安装。还要非常…

深入理解Nginx~Nginx的命令行控制

默认情况下&#xff0c;Nginx被安装在目录usrlocal/nginx/中&#xff0c;其二进制文件路径为usrlocal/nginc/sbin/nginx&#xff0c;配置文件路径为usrlocal/nginx/conf/nginx.conf。 &#xff08;1&#xff09;默认方式启动 usrlocal/nginx/sbin/nginx 这时&#xff0c;会读…

Arm中国合资公司具体布局浮出水面

来源&#xff1a;经济观察报摘要&#xff1a;作为全球最具影响力的芯片技术供应商之一&#xff0c;Arm在中国正迎来新的时代。对于Arm与中国合资公司事宜&#xff0c;5月4日下午&#xff0c;Arm授权的代表邮件回复《经济观察报》称&#xff1a;“合资公司目前刚开始运营”&…

汇编逆向基础

汇编逆向基础&#xff1a;https://www.xmind.net/m/kvJK/

转:教你如何备考PMP

随着PMP在国内报考人数、培训机构、培训讲师数量的增多&#xff0c;PMP已经没那么神秘&#xff0c;PMP证书的含金量已经不向有些人宣传的那样眩目&#xff0c;但参加PMP的学习与认证还是会对我们的知识积累及经验总结有一个不错的提高。PMP认证考试的组织者(PMI)规定&#xff0…

深入理解Nginx~运行中的Nginx进程间的关系

在正式提供服务的产品环境下&#xff0c;部署Nginx时都是使用一个master进程来管理多个worker 进程&#xff0c;一般情况下&#xff0c;worker进程的数量与服务器上的CPU核心数相等。每一个worker进程都 是繁忙的&#xff0c;它们在真正地提供互联网服务&#xff0c;master进程…

哥伦比亚大学AI实验室主任Hod Lipson:阻碍无人驾驶技术发展的7个误区

来源&#xff1a;智车科技摘要&#xff1a;我们发现有些针对无人驾驶的误解还在广泛肆意传播&#xff0c;并且这些信息会被反对者拿来和对抗无人驾驶的推广政策。每年&#xff0c;全世界都有将近120万人死于车祸&#xff0c;这个死亡率相当于每年释放10个广岛级别的原子弹爆炸。…

PE文件结构详解 --(完整版)

From&#xff1a;https://blog.csdn.net/adam001521/article/details/84658708 PE结构详解&#xff1a;https://www.cnblogs.com/zheh/p/4008268.html PE格式解析-区段表及导入表结构详解&#xff1a;https://blog.csdn.net/qq_30145355/article/details/78859214 PE文件基本…

Silverlight MMORPG网页游戏开发课程(Game Lesson):目录

[感谢 银光中国 提供本课程所有源码资源分流]一次全新的开始&#xff0c;一次全新的构建与诠释。渴望在时空长廊中寻觅传说中光的起源&#xff0c;我决定用这部课程编写一首血脉喷张之进行曲。一年前&#xff0c;我一个人在战斗&#xff0c;前行&#xff0c;引导我绝不放弃的是…

人工智能下一个热点探讨,为什么要提出互联网大脑模型 ?

作者&#xff1a;刘锋 计算机博士 《互联网进化论作者》前言从2008年发表论文第一次提出互联网大脑模型&#xff0c;时间已经过去十年。撰写这篇文章&#xff0c;主要是详细介绍我们在十年前提出互联网大脑模型的原因&#xff1b;十年来在计算机和智能领域产生了哪些进展&…

深入理解Nginx~Nginx配置的通用语法

Nginx的配置文件其实是一个普通的文本文件。 user nobody; worker_processes 8; error_log varlog/nginx/error.log error; #pid logs/nginx.pid; events {use epoll;worker_connections 50000; } http {include mime.types;default_type application/octet-stream;log_forma…

学会了这些技术,你离BAT大厂不远了

每一个程序员都有一个梦想&#xff0c;梦想着能够进入阿里、腾讯、字节跳动、百度等一线互联网公司&#xff0c;由于身边的环境等原因&#xff0c;不知道 BAT 等一线互联网公司使用哪些技术&#xff1f;或者该如何去学习这些技术&#xff1f;或者我该去哪些获取这些技术资料&am…

LPC2000 UART串口使用心得

针对zgpswh在串口使用上的一些难题&#xff0c;总结个人在前一阶段的理解&#xff0c;比较片面&#xff0c;不对的地方请高手指正。 1、LPC2000 系列芯片的串口的接收模块包括接收缓冲寄存器和移位寄存器。接收的数据进入移位寄存器后经移位处理并行传入缓冲寄存器&#xff0c;…

张钹院士:可解释、可理解是人工智能研究的主攻方向 | CCF-GAIR 2018

作者&#xff1a;刘鹏摘要&#xff1a;张钹院士历经了中国人工智能的从无到有&#xff0c;从弱到强&#xff0c;因而他也最能清楚地针对中国人工智能近年来的不同发展状态&#xff0c;发表适合的看法和提出正确的建议。2017 年末清华大学举办的「从阿尔法 Go 到通用人工智能&am…