1 简介
超文本传输协议(http)是目前互联网上极其普遍的传输协议,它为构建功能丰富,绚丽多彩的网页提供了强大的支持。构建一个网站,通常无需直接操作http协议,目前流行的WEB框架已经透明的将这些底层功能封装的很好了,如常见的J2EE, .NET, php等框架或语言。
除了作为网站系统的底层支撑,http同样可以在其它的一些场景中使用,如游戏服务器和客户端的传输协议、web service、 网络爬虫、HTTP代理、网站后台数据接口等。
Http Components 对HTTP底层协议进行了很好的封装,如果你是一个J2EE、.net或php程序员,对下面涉及的概念可能不会陌生。
2 httpComponents组件结构
HttpComponents Core
简称HttpCore, 是一组底层Http传输协议组件,支持两种I/O模型,阻塞I/O模型和和非阻塞I/O模型。上层组件(HttpComponents Client, HttpComponents AsyncClient)依赖此组件实现数据传输。
阻塞I/O模型基于基本的JAVA I/O实现,非阻塞模型基于JAVA NIO实现。
HttpComponents Client
建立在HttpCore之上的Http客户端管理组件。底层基于HttpCore 阻塞I/O。从Commons HttpClient 3.x 继承而来,Commons HttpClient原来是apache commons组建的一部分,现在被HttpComponents Client所替代了。
原始的Commons HttpClient 3.x可以在http://hc.apache.org/httpclient-legacy/index.html找到。
HttpComponents AsyncClient
建立在HttpCore NIO模型之上的Http客户端,与基于阻塞I/O的HttpComponents Client形成互补,由于底层使用的NIO非阻塞模型,所以适用于高性能的应用场景。
开始使用HttpComponents组件
首先打开http://hc.apache.org/,点击左侧的Download链接,进入下载页面,下载最新版本的HttpComponents。在编写本文时最新版本是4.1.2。解压缩下载到的压缩包,lib目录下是HttpComponents和它依赖的类库,将它们放到你的工程classpath中,如果依赖文件已经存在了,不要放置多份,以免类库之间的冲突。
然后需要检查一下工程的classpath中是否存在commons http包。Commons http与HttpComponents是完全两个东西,HttpComponents中的Client是从Commons http继承而来的,所以很多类名是相同的。为了避免出现莫名奇妙的问题,应将Commons http从工程中删除(当然,如果你认为自己足够聪明,也可以在引用java包时小心区分)。
Commons http类库的包是org.apache.commons.httpclient
HttpComonents类库的包是org.apache.http
3 Get请求
Get、Post是最常见的获取网页内容的请求形式,当然,返回内容并非必须是html代码,任何的xml、json或文字字符串都可以作为返回内容。
下面是用Get请求获取一个html网页内容的代码
- // (1) 创建HttpGet实例
- HttpGet get = new HttpGet("http://www.126.com");
- // (2) 使用HttpClient发送get请求,获得返回结果HttpResponse
- HttpClient http = new DefaultHttpClient();
- HttpResponse response = http.execute(get);
- // (3) 读取返回结果
- if (response.getStatusLine().getStatusCode() == 200) {
- HttpEntity entity = response.getEntity();
- InputStream in = entity.getContent();
- readResponse(in);
- }
(1)HttpGet的实例就是一个get请求,构造函数只有一个字符串参数,即要获取的网页地址。另外一种构造形式是使用URI实例作为HttpGet的参数。HttpComponents提供了URIUtils类,它的createURI()返回一个URI实例,将请求地址拆分构造不失为一种更加清晰的方式。
URI uri = URIUtils.createURI("http", "www.126.com", 80, "/", "", null);
HttpGet get = new HttpGet(uri);
(2)请求最后被HttpClient发送出去,new DefaultHttpClient()创建一个基本的HttpClient实例。由于底层是基于阻塞的JAVA I/O模型,执行execute()的时间与具体请求的远程服务器和网络速度有关,在实际运行场景中应特别注意此问题。如果是在tomcat等环境中执行可能会造成线程等待,浪费服务器资源,或拒绝其它的连接。
(3)请求返回后就可以读取返回内容了,但有一个前提是此次请求是否真的成功了?服务器地址错误,或请求的页面不存在等问题都会让请求失败。为了确保得到了正确的响应首先应判断返回码是否正确。调用response.getStatusLine()返回一个StatusLine的实例,此实例描述了一次请求的响应信息。一个成功响应的StatusLine实例本身包含如下信息:
HTTP/1.0 200 OK
HTTP/1.0:是请求协议和版本号
200:是响应码
StatusLine的下面2个方法分别用于获取响应信息的各部分内容
getProtocolVersion(): 得到请求协议和协议版本号,如HTTP/1.0
getStatusCode():得到响应码,如200
HttpEntity entity = response.getEntity()返回一个HttpEntity实例,进而调用getContent()就得到了一个输入流。后面的事情应该很明确了。readResponse()是一个自己写的读取输入流中字符串的方法,代码如下:
- public static void readResponse(InputStream in) throws Exception{
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- String line = null;
- while ((line = reader.readLine()) != null) {
- System.out.println(line);
- }
- }
4 Post请求
Post请求在代码上与Get请求的主要区别是将HttpGet换成了HttpPost,其余部分代码基本一致。请看代码:
- // (1) 创建HttpGet实例
- <span style="color: #ff0000;">HttpPost post = new HttpPost("http://www.126.com");</span>
- // (2) 使用HttpClient发送get请求,获得返回结果HttpResponse
- HttpClient http = new DefaultHttpClient();
- HttpResponse response = http.execute(<span style="color: #ff0000;">post</span>);
- // (3) 读取返回结果
- if (response.getStatusLine().getStatusCode() == 200) {
- HttpEntity entity = response.getEntity();
- InputStream in = entity.getContent();
- readResponse(in);
- }
与Get请求不同的代码被标注为红色。可见Post请求与Get请求在代码上的区别并不大,互相切换也是比较容易的。在下面可以看到的令一个不同之处是传递的查询字符串,即请求参数。
5 参数传递
Get与Post在传递参数时有一些区别,Get请求的参数作为查询字符串出传递,而Post请求的参数则作为实体传递。在开发WEB项目时经常遇到乱码的问题,使用HttpComponents也会涉及到这个问题,所以在使用时应特别注意。服务器端的处理方法与WEB项目相同, HttpComponents只要注意字符编码就可以了。
Get请求传递参数方法一:将查询字符串作为请求地址的一部分
这是一种最简单的传参方式,将查询参数用(&)连接,然后放在请求地址?的后面,如下面这个请求地址
http://localhost:8080/servlet1?name=ahopedog&work=programer
请看代码:
- // (1) 创建HttpGet实例
- HttpGet get = new HttpGet("http://localhost:8080/jsx/servlet?id=007");
这里只对请求地址稍作了些修改,请求地址是http://localhost:8080/jsx/servlet
查询参数是id=007
请求地址与查询参数之间用?连接
Get请求传递参数方法二:使用URI携带查询字符串
还记得上面提到的HttpGet有一种用URI构造的方法吗?这第二种传递的方式就是借助了这个机制,只是HttpComponents提供了一种创建查询参数比较清晰的方式NameValuePair
- // (1)创建查询参数
- List<NameValuePair> params = new ArrayList<NameValuePair>();
- params.add(new BasicNameValuePair("name", "ahopedog"));
- params.add(new BasicNameValuePair("work", "程序员"));
- String queryString = URLEncodedUtils.format(params, "utf-8");
- // (2) 创建Get实例
- URI uri = URIUtils.createURI("http", "localhost", 8080, "/jsx/servlet", queryString, null);
- HttpGet get = new HttpGet(uri);
(1)NameValuePair用一对键、值表示一个查询参数,将多个NameValuePair放在一个List中,就形成了一组查询参数。但是List<NameValuePair>并不能直接被HttpGet使用,所以需要用URLEncodedUtils.format()方法将其编码成字符串。URLEncodedUtils是HttpComponents提供的一个编译查询字符串的工具类。
(2)使用编译好的查询字符串构造URI对象,这样查询参数就一起被发送到了服务器上。
其实,这里的查询字符串完全可以手工的方式拼凑出来,只是,从代码的清晰性和维护性方面考虑,NameValuePair和URLEncodedUtils的方式更加可取。值得一提的是,在开发J2EE项目时,经常遇到一些查询条件或请求条件众多的情况,有的是将多个值放在一个Map中管理,有的则创建一个固定结构的Java Bean类。在这方面不同人可能会有不同的看法。Map方式固然省事,而且也很灵活,但是如果缺少了文档和注释时,会很难知道这个Map中放的到底是什么。而创建成Java Bean的话,代码本身就是一个很好的说明,让人一目了然,缺点是导致Java Bean的急剧增加,以致混乱和难以管理。
本人想不到什么很完美的解决办法,但是,任何极端的方式都是不可取,我想在这时折中或许稍好些,什么方法由场景决定。
Post请求传递参数:
- // (1) Post请求
- HttpPost post = new HttpPost("http://localhost:8080/jsx/servlet");
- //添加参数
- List<NameValuePair> params = new ArrayList<NameValuePair>();
- params.add(new BasicNameValuePair("name", "ahopedog"));
- params.add(new BasicNameValuePair("work", "程序员"));
- post.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
- // (3) 发送请求
- HttpClient http = new DefaultHttpClient();
- HttpResponse response = http.execute(post);
也是用到了List<NameValuePair>组织参数,这样就不用费更多心思研究新的方式了。将请求参数加入查询是上面代码中红色文字的一行。很简单,只要别把你的字符编码搞错就行了。
6 响应
直接操作响应中的输入流是最直接也是最有效的方式,不过需要注意的一点是,输入流读取完以后一定要将其关闭。
其实在前面的代码中已经涉及过了对响应的处理,这里再加详细的给予说明:
- // (1) Post请求
- HttpPost post = new HttpPost("http://www.126.com");
- // (2) 发送请求
- HttpClient http = new DefaultHttpClient();
- HttpResponse response = http.execute(post);
- // (3) 处理响应结果
- if (response.getStatusLine().getStatusCode() == 200) {
- HttpEntity entity = response.getEntity();
- // (4) 从输入流读取网页字符串内容
- System.out.println(entity.getContentType());
- System.out.println(entity.getContentEncoding());
- System.out.println(entity.getContentLength());
- InputStream in = null;
- try{
- in = entity.getContent();
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- String line = null;
- while ((line = reader.readLine()) != null) {
- System.out.println(line);
- }
- }finally{
- //记得关闭输入流
- if(in != null)
- in.close();
- }
在本例中只需关心标记为红色的代码,其它行的代码上面已经介绍过了。
HttpEntity有3个获取返回数据的描述信息(或叫做元数据)
getContentType():获取响应体的类型
getContentEncoding():获取响应体的字符编码
getContentLength():获取响应体的字节长度
元数据的内容由远程服务器返回,实际上这些信息是包含在响应的头部信息中的,HTTP请求的响应头中还包含了其它有用的信息,HttpComponents将返回头中的关键元数据封装到了HttpEntity中,已便于使用。
entity.getContent()可以得到响应体的InputStream,有了这个流对象,基本上就可以"为所欲为"了。因为InputStream是Java I/O中底层的基础类,结合相对上层的输入流对象或者对字节进行编码等方法就可以获得不同类型和形式的响应数据了。在本例中用BufferedReader将响应体以字符串形式读取(返回的内容确实也是字符串的内容)。
7 headers
头部信息在客户端与服务器的HTTP传输过程中提供元数据,如服务器类型、处理时间、内容长度、内容类型等。
7.1 请求头部信息
下图是用Firefox访问Google时获取到的请求头信息,在我们使用浏览器访问一个网址时,浏览器都会默默的将一些与请求和客户端相关的信息发送给服务器,让服务器能更好的处理特定的客户端请求。这里面也包括了Cookie。
从上图中可以看到,在发送给服务器的头信息里,Host是我们访问的远程服务器主机地址。User-Agent是浏览器标识,服务器程序可以通过这个字符串得知客户端浏览器的类型和操作系统等信息。Accept-Charset则是客户端可以接受的字符编码类型。
其它各参数的含义在这里就不再一一说明了,感兴趣的读者可以参考相关文章或在Google上搜索相关的资料。
我们是使用HttpComponents代替浏览器访问服务器,默认情况并不包含浏览器所传递的头信息。即使不传递这些信息,通常服务器也会正常返回你所要的网页HTML内容的。但如果你真的很无聊,或者有一些特殊的操作,则完全可以模拟浏览给远程服务器发送这些头信息。
- // (1) Post请求
- HttpPost post = new HttpPost("http://www.126.com");
- // (2) 添加请求头信息
- post.setHeader("User-Agent", "Ahopedog/5.0 (Linux NT 5.1; rv:5.0) Gecko/20100101 FireDog/5.0");
- post.setHeader("Accept-Charset", "GB2312,utf-8;q=0.7,*;q=0.7");
- // (3) 发送请求
- HttpClient http = new DefaultHttpClient();
- http.execute(post);
上面两行红色代码向HttpPost中添加了User-Agent, Accept-Charset两个头信息(内容可以随意设置),头信息会随着HttpClient的execute一起发送出去。
7.2 响应头部信息
还是先在浏览器中都会得到什么样的响应头
上图内容是从FireBug返回头的截图,返回头包含了服务器时间,缓存控制,返回内容编码,服务器等信息。这里很有意思的一处是Google的服务器是gws,而百度的服务器则是BWS/1.0,从没见过的服务器,看来是自主研发的,不过名字也用不着太相近吧。
接下来,看看HttpComponents是如何解析这些信息的
- // (1) Post请求
- HttpPost post = new HttpPost("http://www.126.com");
- // (2) 发送请求
- HttpClient http = new DefaultHttpClient();
- HttpResponse response = http.execute(post);
- // (3) 遍历返回头
- Header[] headers = response.getAllHeaders();
- for(Header h : headers){
- System.out.println(h.getName() + " : " + h.getValue());
- }
- System.out.println("======================================");
- // (4) 获取Server头信息,头名字不区分大小写
- Header serverHeader = response.getFirstHeader("server");
- System.out.println(serverHeader.getName() + " : " + serverHeader.getValue());
(3)response.getAllHeaders()得到响应头数组,一个响应头封装成一个Header实例。Header的两个关键方法是getName()和getValue(),得到头名字和值。
(4)response.getFirstHeader()可以指定获取一个特定的头,需要指定头的名字。多个头名字是可以重名的,而getFirstHeader是得到同名头中的第一个。
相关推荐
li_3ck_02a_1118
基于MATLAB的牛顿迭代法实现
mellitz_3ck_01_0319
内容概要:文章阐述了银行采用人工智能(AI)技术替代传统系统的紧迫性和收益,讨论了通过构建现代化的数据和技术平台实现效率提升的方法,同时强调实施过程中确保数据质量和建立信任的重要性。文中提及,在金融行业中,若想优化业绩则必须拥抱AI带来的机遇,并为此进行经营模式的革新。根据Workday主办的研讨会内容,PwC金融服务风险与监管领导和Workday金融服务高层指出了大部分银行对AI认知不足的问题,强调AI在金融、人力资源以及IT等领域的广泛应用潜力及具体应用场景,如欺诈检测、技能映射和财务管理方面的作用。并且提到了AI部署过程中可能出现的技术与非技术难题及相应解决办法,鼓励金融机构及时投资建设新型基础设施,以保持竞争力。 适用人群:银行及其他金融机构管理人员;金融科技领域的专业研究人员;对企业数字化和智能化转型感兴趣的商业分析师、投资者;从事信息技术咨询工作的顾问。 使用场景及目标:本文可以帮助金融机构制定合理的技术发展战略规划,评估是否有必要推进AI技术转型,同时也为希望涉足银行科技项目的开发者提供了宝贵的市场洞察,帮助理解行业内普遍存在的困难与潜在的市场需求。此外,对于想要了解银行
matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
chromedriver-linux64-136.0.7058.0.zip
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
内容概要:本文档介绍了背压热电联产(CHP)发电厂的详细设计步骤,涵盖确定各状态点的压力、温度、比焓以及质量流率的具体方法。主要内容围绕计算净电功率、燃料消耗及其效率展开,并提供了T-s图绘制的指南。针对每个组件(如蒸汽轮机、冷凝器、除氧器等),都列出了详细的效率假设和压力损失表,为实际工程应用提供了宝贵的参考资料和操作指导。同时,该作业任务要求学生从给定初始值中选择合适的操作条件进行系统模拟,并利用课程讲义和Moodle平台资料完成计算流程。 适用人群:对能源转换和动力设备设计感兴趣的学生或者初涉该领域的工程师。 使用场景及目标:旨在帮助学员深入了解并掌握背压热电联产装置的工作原理和技术指标计算的方法论,通过实践练习提高他们的问题解决能力。 其他说明:文档强调了稳态运行假设的重要性,即物质平衡等于能量输入等于输出的原则,并鼓励参与者借助附录提供的典型操作参数图表来寻找解决问题的方向。此外,它还特别指出对于一些变量值求解可能需要迭代法来进行调整,直至获得稳定结果。提交的报告必须含有一份详细的T-s图和其他必要附件。
机器学习_市财政收入分析(含数据集)
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
tracy_3cd_01_0318
lusted_3cd_01_0918
题目:基于51的自动分拣系统设计 主控:AT89C52 测距模块:超声波测距模块 甲醛传感器(ADC0832+滑动变阻器模拟) 粉尘传感器(PCF8591+滑动变阻器模拟) 净化模块(继电器驱动蓝灯) 排风模块(继电器驱动绿灯) 电源电路(5V降压为3.3V供电) 显示模块(LCD1602) 声光报警 按键(3个,切换阈值选择,阈值加减) 检测物体:开关模拟 电机驱动模块(继电器驱动直流电机转动) 功能: 1.显示屏显示甲醛,粉尘浓度可以切换设置阈值。 2.通过甲醛传感器检测车间环境,大于阈值时声光报警并启动净化模块。 3.通过粉尘传感器检测车间环境,大于阈值时声光报警并启动排风模块。 4.采用超声波传感器进行物体超高监测异常(大于XX距离)时触发声光报警 5.检测到物体(开关闭合)直流电机转动(模拟传送带)
network_server
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
sun_01_0308