HttpClient别说话,用心看
文档D:\httpclient-demo
官网:Apache HttpComponents – Apache HttpComponents
常见使用场景:1.爬虫(python相对做爬虫专业,但是java也可以做) 2.与其他应用进行交互时候
注意下,不同的HttpClient的jar包版本,API和包路径有明显不同
先使用JDK原生API请求网页
将控制台的复制保存为html文件
双击打开
request:请求行,请求头,请求体
可以设置请求方式,请求头,等
依赖
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>
演示使用HttpClient发送get请求,无参
@Testpublic void test1(){//可关闭的httpclient客户端,相当于打开一个浏览器CloseableHttpClient closeableHttpClient=HttpClients.createDefault();String str="https://www.baidu.com";//构造HttpGet请求对象HttpGet httpGet=new HttpGet(str);//声明可关闭响应对象CloseableHttpResponse response = null;try {//可关闭的httpclient客户端对象执行httpGet请求response=closeableHttpClient.execute(httpGet);//获取响应结果 注意HttpEntity有很多实现类,不仅仅可以作为响应结果,还可以作为请求的参数实体//作为响应结果的实现类是DecompressingEntityHttpEntity httpEntity=response.getEntity();//对HttpEntity操作的工具类String toStringResult=EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);System.out.println(toStringResult);//确保流关闭EntityUtils.consume(httpEntity);} catch (Exception e) {e.printStackTrace();}finally {if(response!=null){try {response.close();} catch (IOException e) {e.printStackTrace();}if(closeableHttpClient!=null){try {closeableHttpClient.close();} catch (IOException e) {e.printStackTrace();}}}}}
控制台打印结果和原先一样
关于user-agent和referer:
user-agent意思是用户代理:客户端用的什么浏览器
假如一直用Httpclient连接某些网页,如果对方知道你是机器所为
比如下面这样
可以在请求头里设置user-agent
比如在请求对象里设置:
//构造HttpGet请求对象 HttpGet httpGet=new HttpGet(str); httpGet.addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36");
这样一般可以解决httpClient被认为不是真人行为
另外网站为了保护自己,比如爬对方图片,进行防盗链设置
而Referer是用来,解决网站防盗链
每个请求头,都有对应的作用,自己可查看资料
下面演示,一个网站通过浏览器访问后端,后端获取所有请求头,和通过HttpClien发送请求,所得到的请求头有哪些不一样。
该demo一会上传百度云盘
前端就几个表单,做为参数通过get,post,还有文件上传的演示
后端接收,并打印所有由浏览器发起请求的所有请求头
随便用户名,密码,这里输入aaa,密码 bbb 后端得到的所有请求头
且账号密码 都是Okde
然后再实验 账户aaa,密码aaa+bbb
再来看看用HttpClien发送该请求,后端的结果
也用 aaa bbb
HttpClient代码 主要注意一点,就是表单提交时候 比如用户名是aaa+bbb的时候,会自动帮我们编码
而如果用HttpClient直接将用户名aaa+bbb 密码xxx这样进行提交的话,后台收到的+号会变空格,甚至说比如空格等特殊符号,直接给你报错了,就是说不让你用HttpClient提交该请求
比如String str=http://localhost:8899/httpclient-demo/test1?userName=aaa 空格 Bbbb&password=bbb
就直接给你报错
/*** 使用httpclient发送get请求*/@Testpublic void test1(){//可关闭的httpclient客户端,相当于打开一个浏览器CloseableHttpClient closeableHttpClient=HttpClients.createDefault();//String str="http://localhost:8899/httpclient-demo/test1?userName=aaa%2Bbbb&password=bbb";String str="http://localhost:8899/httpclient-demo/test1?userName="+"aaa+bbb"+"&password=bbb";//构造HttpGet请求对象HttpGet httpGet=new HttpGet(str);httpGet.addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36");//httpGet.addHeader("Referer","http://localhost:8899/httpclient-demo/test1?userName=aaa%2Bbbb&password=bbb");//声明可关闭响应对象CloseableHttpResponse response = null;try {//可关闭的httpclient客户端对象执行httpGet请求response=closeableHttpClient.execute(httpGet);//获取响应结果 注意HttpEntity有很多实现类,不仅仅可以作为响应结果,还可以作为请求的参数实体//作为响应结果的实现类是DecompressingEntityHttpEntity httpEntity=response.getEntity();//对HttpEntity操作的工具类String toStringResult=EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);System.out.println(toStringResult);//确保流关闭EntityUtils.consume(httpEntity);} catch (Exception e) {e.printStackTrace();}finally {if(response!=null){try {response.close();} catch (IOException e) {e.printStackTrace();}if(closeableHttpClient!=null){try {closeableHttpClient.close();} catch (IOException e) {e.printStackTrace();}}}}}
报错的演示
想说明的一点是,用浏览器提交表单请求时候,浏览器会帮我们自动对中文和特殊符号进行编码,后端会自行解码,但是当使用HttpClient的时候用注意中文和特殊符号
那么就要将到URLEncode 它可以对RUL上的特殊字符进行编码
用浏览器,提交时候会自动完成URLEncode 而当使用HttpClient时候,中文与特殊符号就需要我们自己使用URLEncode进行编码
丫的CSDN不能上传图片了
就是用URLEncode对get请求进行编码即可
String str="http://localhost:8899/httpclient-demo/test1?userName= "+"aaa+bbb"+"&password=bbb"; try {str=URLEncoder.encode(str, StandardCharsets.UTF_8.name()); } catch (UnsupportedEncodingException e) {e.printStackTrace(); }
这里注意一点,上面这么做是错的
由于一时没法发图片,这么做的话,会将整个url全部编码,也就是说:// & ?等等全部进行了编码
而我们只需要对我们上传的参数进行编码,因此正确做法是
lic void test1(){//可关闭的httpclient客户端,相当于打开一个浏览器CloseableHttpClient closeableHttpClient=HttpClients.createDefault();//String str="http://localhost:8899/httpclient-demo/test1?userName=aaa%2Bbbb&password=bbb";String userName="aaa 哈哈";String password="你妹";try {//对自定义上传的进行编码userName=URLEncoder.encode(userName, StandardCharsets.UTF_8.name());password=URLEncoder.encode(password, StandardCharsets.UTF_8.name());} catch (Exception e) {e.printStackTrace();}String str="http://localhost:8899/httpclient-demo/test1?+userName="+userName+"&password="+password;
对HttpClient做了些改动,没法发图说明,全复制了一遍
/*** 使用httpclient发送get请求*/@Testpublic void test1(){//可关闭的httpclient客户端,相当于打开一个浏览器CloseableHttpClient closeableHttpClient=HttpClients.createDefault();String userName="收到 你没";String password="阿斯顿)(";try {userName= URLEncoder.encode(userName, StandardCharsets.UTF_8.name());password=URLEncoder.encode(password, StandardCharsets.UTF_8.name());} catch (Exception e) {e.printStackTrace();}String str="http://localhost:8899/httpclient-demo/test1?userName="+userName+"&password="+password;//构造HttpGet请求对象HttpGet httpGet=new HttpGet(str);httpGet.addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36");//httpGet.addHeader("Referer","https://www.amamaw.com");//声明可关闭响应对象CloseableHttpResponse response = null;try {//可关闭的httpclient客户端对象执行httpGet请求response=closeableHttpClient.execute(httpGet);//代表本次请求成功或者失败的状态StatusLine statusLine=response.getStatusLine();if(HttpStatus.SC_OK==statusLine.getStatusCode()){//HttpStatus里有所有状态码 200 404 302等等System.out.println("响应成功");//获取所有响应头Header[] allHeader=response.getAllHeaders();for(Header header:allHeader){System.out.println("响应头:"+header.getName()+":"+header.getValue());}//成功了再获取响应结果//获取响应结果 注意HttpEntity有很多实现类,不仅仅可以作为响应结果,还可以作为请求的参数实体//作为响应结果的实现类是DecompressingEntityHttpEntity httpEntity=response.getEntity();System.out.println("ContentType:"+httpEntity.getContentType());//对HttpEntity操作的工具类String toStringResult=EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);System.out.println(toStringResult);//确保流关闭EntityUtils.consume(httpEntity);}else{System.out.println("响应失败,响应码是:"+statusLine.getStatusCode());}} catch (Exception e) {e.printStackTrace();}finally {if(response!=null){try {response.close();} catch (IOException e) {e.printStackTrace();}if(closeableHttpClient!=null){try {closeableHttpClient.close();} catch (IOException e) {e.printStackTrace();}}}}}
关于保存网络图片到本地:粗暴点讲就是爬取图片,再写个demo
@Testpublic void test3(){//可关闭的httpclient客户端,相当于打开一个浏览器CloseableHttpClient closeableHttpClient=HttpClients.createDefault();String userName="收到 你没";String password="阿斯顿)(";try {userName= URLEncoder.encode(userName, StandardCharsets.UTF_8.name());password=URLEncoder.encode(password, StandardCharsets.UTF_8.name());} catch (Exception e) {e.printStackTrace();}String str="https://img-blog.csdnimg.cn/c2c20ed7275749bba0e43cdf9d66a9d7.png";//String str="http://localhost:8899/httpclient-demo/test1?userName="+userName+"&password="+password;//构造HttpGet请求对象HttpGet httpGet=new HttpGet(str);httpGet.addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36");//httpGet.addHeader("Referer","https://www.amamaw.com");//声明可关闭响应对象CloseableHttpResponse response = null;try {//可关闭的httpclient客户端对象执行httpGet请求response=closeableHttpClient.execute(httpGet);//代表本次请求成功或者失败的状态StatusLine statusLine=response.getStatusLine();if(HttpStatus.SC_OK==statusLine.getStatusCode()){//HttpStatus里有所有状态码 200 404 302等等System.out.println("响应成功");//获取所有响应头Header[] allHeader=response.getAllHeaders();for(Header header:allHeader){System.out.println("响应头:"+header.getName()+":"+header.getValue());}//成功了再获取响应结果//获取响应结果 注意HttpEntity有很多实现类,不仅仅可以作为响应结果,还可以作为请求的参数实体//作为响应结果的实现类是DecompressingEntityHttpEntity httpEntity=response.getEntity();//获取图片,一般图片都有后缀,如何保存为原有的后缀 image/jpg image/png image/jpeg image/图片后缀String contenType= httpEntity.getContentType().getValue();String suffix=".jpg";if(contenType.contains("jpg")||contenType.contains("jpeg")){suffix=".jpg";}else if(contenType.contains("bmp")||contenType.contains("bitmap")){suffix=".bmp";}else if(contenType.contains("png")){suffix=".png";}else if(contenType.contains("gif")){suffix=".gif";}//图片是二进制,toByteArray()可以以流的形式获取任何 文本也可以 图片 视频都行byte[] bytes=EntityUtils.toByteArray(httpEntity); // String str1=new String(bytes); // System.out.println("str1="+str1);//定义个本地保存图片的路径String localAbsPath="D:\\pachongimage\\"+new SimpleDateFormat("yyyyHHmmhhmmss").format(new Date())+suffix;//写入文件FileOutputStream fos=new FileOutputStream(localAbsPath);fos.write(bytes);fos.close();System.out.println("ContentType:"+httpEntity.getContentType());//对HttpEntity操作的工具类 注意图片是二进制文件,不能再toString()了 只有文本可以//String toStringResult=EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);//System.out.println(toStringResult);//确保流关闭EntityUtils.consume(httpEntity);}else{System.out.println("响应失败,响应码是:"+statusLine.getStatusCode());}} catch (Exception e) {e.printStackTrace();}finally {if(response!=null){try {response.close();} catch (IOException e) {e.printStackTrace();}if(closeableHttpClient!=null){try {closeableHttpClient.close();} catch (IOException e) {e.printStackTrace();}}}}}
这样该目录里就有该图片了
设置访问代理,设置访问代理原因,爬虫写多了,高频率访问网站,对方安全性做的比较好的话,会将你IP封掉.那么做爬虫的应对方式就是设置访问代理,用不同IP去访问,请求,避免被封,让它搞不清楚
设置访问代理,有免费的,但是不太稳定,要稳定加钱......
另外再写个Demo
无论HttpGet或者HttpPost都可以配置 这里用HttpGet演示 代理的IP和端口网上找的
//创建一个代理 String ip="120.26.123.95"; int port=8010; //构造HttpGet请求对象 HttpGet httpGet=new HttpGet(str); HttpHost proxy=new HttpHost(ip,port); //对每一个请求进行配置,会覆盖全局的默认请求配置 RequestConfig requestConfig= RequestConfig.custom().setProxy(proxy).build(); httpGet.setConfig(requestConfig);
/*** 演示设置访问代理*/@Testpublic void test4(){//可关闭的httpclient客户端,相当于打开一个浏览器CloseableHttpClient closeableHttpClient=HttpClients.createDefault();String str="http://www.baidu.com";//创建一个代理String ip="120.26.123.95";int port=8010;//构造HttpGet请求对象HttpGet httpGet=new HttpGet(str);HttpHost proxy=new HttpHost(ip,port);//对每一个请求进行配置,会覆盖全局的默认请求配置RequestConfig requestConfig= RequestConfig.custom().setProxy(proxy).build();httpGet.setConfig(requestConfig);//声明可关闭响应对象CloseableHttpResponse response = null;try {//可关闭的httpclient客户端对象执行httpGet请求response=closeableHttpClient.execute(httpGet);//代表本次请求成功或者失败的状态StatusLine statusLine=response.getStatusLine();if(HttpStatus.SC_OK==statusLine.getStatusCode()){//HttpStatus里有所有状态码 200 404 302等等System.out.println("响应成功");//获取所有响应头Header[] allHeader=response.getAllHeaders();for(Header header:allHeader){System.out.println("响应头:"+header.getName()+":"+header.getValue());}//成功了再获取响应结果//获取响应结果 注意HttpEntity有很多实现类,不仅仅可以作为响应结果,还可以作为请求的参数实体//作为响应结果的实现类是DecompressingEntityHttpEntity httpEntity=response.getEntity();System.out.println("ContentType:"+httpEntity.getContentType());//对HttpEntity操作的工具类 注意图片是二进制文件,不能再toString()了 只有文本可以String toStringResult=EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);System.out.println(toStringResult);//确保流关闭EntityUtils.consume(httpEntity);}else{System.out.println("响应失败,响应码是:"+statusLine.getStatusCode());}} catch (Exception e) {e.printStackTrace();}finally {if(response!=null){try {response.close();} catch (IOException e) {e.printStackTrace();}if(closeableHttpClient!=null){try {closeableHttpClient.close();} catch (IOException e) {e.printStackTrace();}}}}
关于连接超时,和读取超时的设置与具体含义
关于连接超时,也是通过RequestConfig来进行设置的,这里先把代理去掉
就是设置HTTP三次握手的时间上限,连接超时就报ConnectTimeoutException
//对每一个请求进行配置,会覆盖全局的默认请求配置 RequestConfig requestConfig= RequestConfig.custom().setConnectTimeout(5000).build();
//对每一个请求进行配置,会覆盖全局的默认请求配置 RequestConfig requestConfig= RequestConfig.custom()//设置CTP三次握手的时间上线.setConnectTimeout(55555)//设置从请求的网址获取响应数据的时间渐渐.setSocketTimeout(50000)//指从连接池获取connection的超时时间.setConnectionRequestTimeout(5000).build(); httpGet.setConfig(requestConfig);
接着演示,用HttpClient发送
Content-Type分别为:
1.application/x-www-form-urlencoded
2.application/json
3multipart/form-data(文件上传时的Content-Type类型)
的Post请求
1.用HttpClient发送content-type为application/x-www-form-urlencoded的post请求
demo送上 注意:content-type为application/x-www-form-urlencoded
他的参数格式是在body体中:KEY1=VALUE1&KEY2=VALUE2的格式
其实下面传送过去的也就是userName=java&password=xxxx的格式
NameValuePair是个接口,BasicNameValuePair是他的一个实现类
/*** - 发送application/x-www-form-urlencoded类型的post请求** @throws Exception*/@Testpublic void testPost1() throws Exception {CloseableHttpClient closeableHttpClient = HttpClients.createDefault();String urlStr = "http://localhost:8899/httpclient-demo/test2";// 创建httppost对象HttpPost httpPost = new HttpPost(urlStr);// 设置请求头httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");// 给post对象设置参数/*NameValuePair: <input id="user-name-label" type="text" name="userName"/>的name(userName)和input标签里面输入的值就构成了一个NameValuePair对象*/List<NameValuePair> list = new ArrayList<>();list.add(new BasicNameValuePair("userName", "java"));list.add(new BasicNameValuePair("password", "xxxxx"));// 把参数集合设置到formEntityUrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(list, Consts.UTF_8);httpPost.setEntity(formEntity);CloseableHttpResponse response = null;try {response = closeableHttpClient.execute(httpPost);HttpEntity entity = response.getEntity();String toStringResult = EntityUtils.toString(entity, StandardCharsets.UTF_8);System.out.println(toStringResult);EntityUtils.consume(entity);} catch (Exception e) {e.printStackTrace();} finally {if (closeableHttpClient != null) {try {closeableHttpClient.close();} catch (IOException e) {e.printStackTrace();}}if (response != null) {try {response.close();} catch (IOException e) {e.printStackTrace();}}}}
2.用HttpClient发送content-type为application/json的post请求
在body体中的格式就是JSON
{
"userName":"java",
"password":"xxxx",
"age":18
}
Demo送上
/*** - 发送application/json类型的post请求*/@Testpublic void testPost2() throws Exception {CloseableHttpClient closeableHttpClient = HttpClients.createDefault();String urlStr = "http://localhost:8899/httpclient-demo/testJson";// 创建httppost对象HttpPost httpPost = new HttpPost(urlStr);// string:是一个json字符串JSONObject jsonObj = new JSONObject();jsonObj.put("userName", "java");jsonObj.put("password", "不知道写什么");StringEntity jsonEntity = new StringEntity(jsonObj.toString(), Consts.UTF_8);// 也需要给entity设置一下内容类型
// jsonEntity.setContentType(new BasicHeader("Content-Type","application/json; charset=utf-8"));jsonEntity.setContentType("application/json; charset=utf-8");// 设置entity的编码jsonEntity.setContentEncoding(Consts.UTF_8.name());httpPost.setEntity(jsonEntity);CloseableHttpResponse response = null;try {response = closeableHttpClient.execute(httpPost);HttpEntity entity = response.getEntity();String toStringResult = EntityUtils.toString(entity, StandardCharsets.UTF_8);System.out.println(toStringResult);EntityUtils.consume(entity);} catch (Exception e) {e.printStackTrace();} finally {if (closeableHttpClient != null) {try {closeableHttpClient.close();} catch (IOException e) {e.printStackTrace();}}if (response != null) {try {response.close();} catch (IOException e) {e.printStackTrace();}}}}
HttpClient别说话,用心看相关推荐
- 提升演讲与说话能力看什么书?这本《演讲与口才必读12篇》不容错过哦
提升演讲与说话能力看什么书?演讲类书籍前前后后也看了一些,个人感觉最值得推荐的还是12Reads的<演讲与口才必读12篇>这本. (注意该书只能从其官网购买,传统电商平台无售.) 这本书最 ...
- 怎么用计算机弹心如水止,心静如水, 怎样用心看自己
作者:糖糖 整理人:曹小涵 人们忙于到处奔波,为生活.为工作.为人生,很难有时间静下心思考一下,自己应该怎样看待自己?习惯了看待别人,或指指点点,或嗤之以鼻,或推崇倍至,或违心应答,但无非是给自己找一 ...
- 用数据说话,看Google 怎样被陷害(转自sina)
转自新浪blog: http://blog.sina.com.cn/s/blog_60676a3f0100e0xk.html 近日,央视爆出谷歌搜索出现大量黄色词条的信息.一个引起舆论强烈反响的例子是 ...
- Dubbo详解,用心看这一篇文章就够了【重点】
1.1 Dubbo概述 Dubbo是阿里巴巴开源的基于 Java 的高性能RPC(一种远程调用) 分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案. 每天为2千 ...
- Linux账号及权限管理!!!用心看!!简单易懂!!
目录 1.用户账号 (1)超级用户 (2)普通用户 (3)程序用户 2.组账号 (1)基本组(私有组) (2)附加组(公共组) 3.标识号 (1)UID((User IDentity ,用户标识号) ...
- Springboot 整合RabbitMq ,用心看完这一篇就够了
该篇文章内容较多,包括有rabbitMq相关的一些简单理论介绍,provider消息推送实例,consumer消息消费实例,Direct.Topic.Fanout的使用,消息回调.手动确认等. (但是 ...
- PXE高效批量网络装机比较乱,用心看
1.部署 PXE 远程安装服务 在大规模的 Linux 应用环境中,如 Web 群集.分布式计算等,服务器往往并不配备光驱设备,在这种情况下,如何为数十乃至上百台服务器裸机快速安装系统呢?传统的 US ...
- MongoDB详解,用心看这篇就够了【重点】
1.1 MongoDB概述 MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间 ...
- RabbitMQ详解,用心看完这一篇就够了【重点】
1.1 消息中间件 消息中间件是基于队列与消息传递技术,在网络环境中为应用系统提供同步或异步.可靠的消息传输的支撑性软件系统--百度百科 1.1.1 应用场景 1.1.1.1 异步处理 场景说明: 用 ...
最新文章
- 中科院刘焕勇老师知识图谱关于schema博客
- 短短30分钟!计算机轻松判断J. K. 罗琳隐姓埋名写新作
- mysql my.cnf key_buffer_size_mysql5.6之key_buffer_size优化设置-阿里云开发者社区
- ELDataQuery 基于.NET 2.0的数据查询框架 雏型
- java 加密服务器_Javascript端加密java服务端解密
- 数据结构选择题(c语言)
- 二级VB培训笔记05:文件操作
- Android系统性能优化(73)---总结
- java大文件读,java 读大文件报错
- Centos7安装完毕后无法联网的解决方法
- 8.1 模型压缩的方法
- 周志华机器学习西瓜书速记第一章绪论
- 部分IT公司面试流程小结
- 学习人工智能导论(1)
- 敌退我进 锂电产业链中日韩三国演义
- java web景点规划导航
- python处理wrf气象数据_气象编程 | Python3之WRF的投影转换
- 3类、5类、超5类线有什么不同
- 互联网的行业都有哪些岗位?
- 【总结】最好的CV学习小组,超200个课时+10个方向+30个项目,从理论到实践全部系统掌握...
热门文章
- 喜讯+1!袋鼠云数栈技术团队获“2022年度优秀开源技术团队”
- 专业演讲技巧学习笔记
- All in 凉凉!德州赔率怎么算?我用Python来搞定!
- 基于dlib进行人脸检测
- C语言:return 0 , return 1 和 return -1 以及 return ,break 的区别
- python列表去除none_从Python列表中删除None
- 股票量化投资目前主要有哪些主流交易方法?
- 叫树兄的上海行849
- 怎么在eclipse里复制项目
- 数字化转型导师坚鹏:数字化转型背景下的保险公司人力资源管理