Apache HttpClient 使用教程 以及 Spring 的 RestTemplate
本文源代码已经收录在我的码云上面的HttpClientDemo 的模块,大家可以参考 ,地址https://gitee.com/njitzyd/JavaDemoCollection
HttpClient简介
HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本。我们可以通过HttpClient发送各种HTTP方法。
主要特性
- 基于标准、纯净的Java语言,实现了HTTP1.0和HTTP1.1。
- 以可扩展的面向对象的结构实现了HTTP全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。
- 支持加密的HTTPS协议(HTTP通过SSL协议)。
- 通过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来保持持久连接。
- 可以直接获取服务器发送的响应码和响应头部。
- 具备设置连接超时的能力。
- 支持HTTP/1.1 响应缓存。
- 源代码基于Apache License 可免费获取。
一般使用步骤
使用HttpClient发送请求、接收响应,一般需要以下步骤。
HttpGet请求响应的一般步骤:
1). 创建HttpClient
对象,可以使用HttpClients.createDefault()
;
2). 如果是无参数的GET请求,则直接使用构造方法HttpGet(String url)
创建HttpGet
对象即可;
如果是带参数GET请求,则可以先使用URIBuilder(String url)
创建对象,再调用addParameter(String param, String value)
,或setParameter(String param, String value)
来设置请求参数,并调用build()方法构建一个URI对象。只有构造方法HttpGet(URI uri)
来创建HttpGet对象。
3). 创建HttpResponse
,调用HttpClient
对象的execute(HttpUriRequest request)
发送请求,该方法返回一个HttpResponse
。调用HttpResponse
的getAllHeaders()、getHeaders(String name)
等方法可获取服务器的响应头;调用HttpResponse
的getEntity()
方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。通过调用getStatusLine().getStatusCode()
可以获取响应状态码。
4). 释放连接。
HttpPost请求响应的一般步骤:
1). 创建HttpClient
对象,可以使用HttpClients.createDefault()
;
2). 如果是无参数的GET请求,则直接使用构造方法HttpPost(String url)
创建HttpPost
对象即可;
如果是带参数POST请求,先构建HttpEntity对象并设置请求参数,然后调用setEntity(HttpEntity entity)创建HttpPost对象。
3). 创建HttpResponse
,调用HttpClient
对象的execute(HttpUriRequest request)
发送请求,该方法返回一个HttpResponse
。调用HttpResponse
的getAllHeaders()、getHeaders(String name)
等方法可获取服务器的响应头;调用HttpResponse
的getEntity()
方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。通过调用getStatusLine().getStatusCode()
可以获取响应状态码。
4). 释放连接。
使用教程(基于Maven)
- 引入依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.12</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
具体代码实现
public class HttpClientTest { /** *普通的GET请求 */ public static void main(String[] args) throws Exception { HttpClientTest clientTest = new HttpClientTest(); // clientTest.doGet(); // clientTest.doGETParam(); clientTest.doPOST(); // clientTest.doPOSTParam(); } /** * * @description: 执行普通的GET请求, * 打开一个url,抓取响应结果输出成html文件 * @param: [] * @return: void * @date: 2020/8/1 */ public void doGet() throws Exception{ // 创建Httpclient对象 CloseableHttpClient httpclient = HttpClients.createDefault(); // 创建http GET请求 HttpGet httpGet = new HttpGet("http://www.baidu.com"); CloseableHttpResponse response = null; try { // 执行请求 response = httpclient.execute(httpGet); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { //请求体内容 String content = EntityUtils.toString(response.getEntity(), "UTF-8"); //内容写入文件 FileUtils.writeStringToFile(new File("D:\\baidu.html"), content, "UTF-8"); System.out.println("内容长度:"+content.length()); } } finally { if (response != null) { response.close(); } //相当于关闭浏览器 httpclient.close(); } } /** * * @description: 执行带参数的GET请求 * 模拟使用百度搜索关键字"njitzyd",并保存搜索结果为html文件 * @param: [] * @return: void * @date: 2020/8/1 */ public void doGETParam() throws Exception{ // 创建Httpclient对象 CloseableHttpClient httpclient = HttpClients.createDefault(); // 定义请求的参数 URI uri = new URIBuilder("http://www.baidu.com/s").setParameter("wd", "njitzyd").build(); // 创建http GET请求 HttpGet httpGet = new HttpGet(uri); //response 对象 CloseableHttpResponse response = null; try { // 执行http get请求 response = httpclient.execute(httpGet); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { String content = EntityUtils.toString(response.getEntity(), "UTF-8"); //内容写入文件 FileUtils.writeStringToFile(new File("D:\\baidu-param.html"), content, "UTF-8"); System.out.println("内容长度:"+content.length()); } } finally { if (response != null) { response.close(); } httpclient.close(); } } /** * * @description:执行无参数的POST请求,并设置Header来伪装浏览器请求 * @param: [] * @return: void * @date: 2020/8/1 */ public void doPOST() throws Exception{ // 创建Httpclient对象 CloseableHttpClient httpclient = HttpClients.createDefault(); // 创建http POST请求 HttpPost httpPost = new HttpPost("https://www.oschina.net/"); //伪装浏览器请求 httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"); CloseableHttpResponse response = null; try { // 执行请求 response = httpclient.execute(httpPost); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { String content = EntityUtils.toString(response.getEntity(), "UTF-8"); //内容写入文件 FileUtils.writeStringToFile(new File("D:\\oschina.html"), content, "UTF-8"); System.out.println("内容长度:"+content.length()); } } finally { if (response != null) { response.close(); } httpclient.close(); } } /** * * @description: 执行带参数的POST请求 * 模拟开源中国检索java,并伪装浏览器请求,输出响应结果为html文件 * @param: [] * @return: void * @date: 2020/8/1 */ public void doPOSTParam() throws Exception { // 创建Httpclient对象 CloseableHttpClient httpclient = HttpClients.createDefault(); // 创建http POST请求 HttpPost httpPost = new HttpPost("https://www.oschina.net/search"); // 设置2个post参数,一个是scope、一个是q List<NameValuePair> parameters = new ArrayList<NameValuePair>(0); parameters.add(new BasicNameValuePair("scope", "project")); parameters.add(new BasicNameValuePair("q", "java")); // 构造一个form表单式的实体 UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters); // 将请求实体设置到httpPost对象中 httpPost.setEntity(formEntity); //伪装浏览器 httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"); CloseableHttpResponse response = null; try { // 执行请求 response = httpclient.execute(httpPost); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { String content = EntityUtils.toString(response.getEntity(), "UTF-8"); //内容写入文件 FileUtils.writeStringToFile(new File("D:\\oschina-param.html"), content, "UTF-8"); System.out.println("内容长度:"+content.length()); } } finally { if (response != null) { response.close(); } httpclient.close(); } } }
- 检测结果
执行第一个可以看到在D盘下有个新的文件 baidu.html
执行第二个可以生成baidu-param.html
其他两个类似,测试成功!!!
RestTemplate 简介
Spring 提供了一个RestTemplate模板工具类,对基于Http的客户端进行了封装,并且实现了对象与json的序列化与反序列化,非常方便(上面的HttpClient返回的相应是json格式的)。RestTemplate 并没有限定Http客户端类型,而是进行了抽象,目前常用的三种都支持:
- HttpClient
- OKHttp
- JDK原生的URLConnection(默认的)
具体使用
如果是基于SpringBoot 项目就引入那个web启动器然后通过@bean
注入一个restTemplate实例就好,这里我以普通的maven项目为例讲解。
- 引入依赖
<!--restTemplate 的支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
- 编写测试
public class RestTemplateTest {
public static void main(String[] args) {
new RestTemplateTest().testRestTemplate();
}
/**
* 测试默认的实现
*/
public void testRestTemplate(){
ResponseEntity<String> forEntity = getRestTemplate().getForEntity("http://www.baidu.com", String.class);
System.out.println(forEntity.toString());
// 还可以有很多方法
}
public static RestTemplate getRestTemplate(){
RestTemplate restTemplate = new RestTemplate();
// 如果想要修改默认的实现方案,可以在new 的时候给他一个初始化的对象
// 或者设置setRequestFactory方法来改变
// RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
// restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
return restTemplate;
}
}
- 可以看到控制台打印出百度的页面,测试成功!!!
总结
一般的项目使用HttpClient 就可以满足需求,当然在spring 尤其是在 SpringBoot 项目中 使用 RestTemplate 会更加方便!!
如果对你有所帮助,希望点赞!!!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。