httpclient
http://www.blogjava.net/Alpha/archive/2007/01/22/95216.html
很多公司提供的页面往往并不是可以通过一个简单的URL就可以访问的,而必须经过注册然后登录后方可
使用提供服务的页面,这个时候就涉及到COOKIE问题的处理。我们知道目前流行的***页技术例如ASP、
JSP无不是通过COOKIE来处理会话信息的。为了使我们的程序能使用别人所提供的服务页面,就要求程序
首先登录后再访问服务页面,这过程就需要自行处理cookie,想想当你用 java.net.HttpURLConnection
来完成这些功能时是多么恐怖的事情啊!况且这仅仅是我们所说的顽固的WEB服务器中的一个很常见的 “
顽固”!
我们不可能列举所有可能的顽固,我们会针对几种最常见的问题进行处理。当然了,正如前面说到的,如
果我们自己使用 java.net.HttpURLConnection来搞定这些问题是很恐怖的事情,因此在开始之前我们先
要介绍一下一个开放源码的项目,这个项目就是 Apache开源组织中的httpclient,它隶属于Jakarta的
commons项目,目前的版本是2.0RC2。commons下本来已经有一个net的子项目,但是又把httpclient单独
提出来,可见http服务器的访问绝非易事。
Commons-httpclient项目就是专门设计来简化HTTP客户端与服务器进行各种通讯编程。通过它可以让原来
很头疼的事情现在轻松的解决,例如你不再管是HTTP或者HTTPS的通讯方式,告诉它你想使用HTTPS方式,
剩下的事情交给httpclient替你完成。本文会针对我们在编写HTTP客户端程序时经常碰到的几个问题进行
分别介绍如何使用httpclient来解决它们,为了让读者更快的熟悉这个项目我们最开始先给出一个简单的
例子来读取一个网页的内容,然后循序渐进解决掉问题。
1. 读取网页(HTTP/HTTPS)内容
2. 以GET或者POST方式向网页提交参数
3. 处理页面重定向
在JSP/Servlet编程中response.sendRedirect方法就是使用 HTTP协议中的重定向机制。它与JSP中的
<jsp:forward …>的区别在于后者是在服务器中实现页面的跳转,也就是说应用容器加载了所要跳转的页
面的内容并返回给客户端;而前者是返回一个状态码,这些状态码的可能值见下表,然后客户端读取需要
跳转到的页面的URL并重新加载新的页面。就是这样一个过程,所以我们编程的时候就要通过
HttpMethod.getStatusCode()方法判断返回值是否为下表中的某个值来判断是否需要跳转。如果已经确认
需要进行页面跳转了,那么可以通过读取HTTP头中的location属性来获取新的地址。
注释:
Web Server中引入了session的概念,用来保存客户端的状态信息。 这里用一个形象的比喻来解释
session的工作方式。假设Web Server是一个商场的存包处,HTTP Request是一个顾客,第一次来到存包
处,管理员把顾客的物品存放在某一个柜子里面(这个柜子就相当于Session),然后把一个号码牌交给
这个顾客,作为取包凭证(这个号码牌就是Session ID)。顾客(HTTP Request)下一次来的时候,就要
把号码牌(Session ID)交给存包处(Web Server)的管理员。管理员根据号码牌(Session ID)找到相
应的柜子(Session),根据顾客(HTTP Request)的请求,Web Server可以取出、更换、添加柜子
(Session)中的物品,Web Server也可以让顾客(HTTP Request)的号码牌和号码牌对应的柜子
(Session)失效。顾客(HTTP Request)的忘性很大,管理员在顾客回去的时候(HTTP Response)都要
重新提醒顾客记住自己的号码牌(Session ID)。这样,顾客(HTTP Request)下次来的时候,就又带着
号码牌回来了。 我们可以看到,Session ID实际上是在客户端和服务端之间通过HTTP Request和HTTP
Response传来传去的。
在Java Web Server(即Servlet/JSP Server)中,Session ID用jsessionid表示(请参见Servlet规范)
。 HTTP Request一般由3部分组成: (1)Request Line 这一行由HTTP Method(如GET或POST)、URL、
和HTTP版本号组成。 例如,GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1 GET
http://www.google.com/search?q=Tomcat HTTP/1.1 POST http://www.google.com/search HTTP/1.1
GET http://www.somsite.com/menu.do;jsessionid=1001 HTTP/1.1
(2)Request Headers 这部分定义了一些重要的头部信息,如,浏览器的种类,语言,类型。Request
Headers中还可以包括Cookie的定义。例如: User-Agent: Mozilla/4.0 (compatible; MSIE 5.5;
Windows NT 5.0) Accept-Language: en-us Cookie: jsessionid=1001
(3)Message Body 如果HTTP Method是GET,那么Message Body为空。 如果HTTP Method是POST,说明这
个HTTP Request是submit一个HTML Form的结果, 那么Message Body为HTML Form里面定义的Input属性。
例如, user=guest password=guest jsessionid=1001 注意,如果把HTML Form元素的Method属性改为
GET。那么,Message Body为空,所有的Input属性都会加在URL的后面。你在浏览器的URL地址栏中会看到
这些属性,类似于 http://www.somesite/login.do?user=guest&password=guest&jsessionid=1001
从理论上来说,这3个部分(Request URL,Cookie Header, Message Body)都可以用来存放Session ID
。由于Message Body方法必须需要一个包含Session ID的HTML Form,所以这种方法不通用。一般用来实
现Session的方法有两种: (1)URL重写。 Web Server在返回Response的时候,检查页面中所有的URL,
包括所有的连接,和HTML Form的Action属性,在这些URL后面加上“;jsessionid=XXX”。下一次,用户
访问这个页面中的URL。jsessionid就会传回到Web Server。 (2)Cookie。如果客户端支持Cookie,Web
Server在返回Response的时候,在Response的Header部分,加入一个“set-cookie: jsessionid=XXXX”
header属性,把jsessionid放在Cookie里传到客户端。客户端会把Cookie存放在本地文件里,下一次访问
Web Server的时候,再把Cookie的信息放到HTTP Request的“Cookie”header属性里面,这样jsessionid
就随着HTTP Request返回给Web Server。
Session的典型应用是存放用户的Login信息,如用户名,密码,权限角色等信息,应用程序(如Email服
务、网上银行等系统)根据这些信息进行身份验证和权限验证
4. 模拟输入用户名和口令进行登录
这样一来,对于HTTP的客户端来讲,如果要访问一个受保护的页面时就必须模拟浏览器所做的工作,首先
就是请求登录页面,然后读取Cookie值;再次请求登录页面并加入登录页所需的每个参数;最后就是请求
最终所需的页面。当然在除第一次请求外其他的请求都需要附带上Cookie信息以便服务器能判断当前请求
是否已经通过验证。说了这么多,可是如果你使用httpclient的话,你甚至连一行代码都无需增加,你只
需要先传递登录信息执行登录过程,然后直接访问想要的页面,跟访问一个普通的页面没有任何区别,因
为类HttpClient已经帮你做了所有该做的事情了,太棒了!下面的例子实现了这样一个访问的过程。
5. 提交XML格式参数
6. 通过HTTP上传文件
7. 访问启用认证的页面
我们经常会碰到这样的页面,当访问它的时候会弹出一个浏览器的对话框要求输入用户名和密码后方可,
这种用户认证的方式不同于我们在前面介绍的基于表单的用户身份验证。这是HTTP的认证策略,
httpclient支持三种认证方式包括:基本、摘要以及NTLM认证。其中基本认证最简单、通用但也最不安全
;摘要认证是在HTTP 1.1中加入的认证方式,而NTLM则是微软公司定义的而不是通用的规范,最新版本的
NTLM是比摘要认证还要安全的一种方式。
8. 多线程模式下使用httpclient
8. 多线程模式下使用httpclient
多线程同时访问httpclient,例如同时从一个站点上下载多个文件。对于同一个HttpConnection 同一个
时间只能有一个线程访问,为了保证多线程工作环境下不产生冲突,httpclient使用了一个多线程连接管
理器的类:MultiThreadedHttpConnectionManager,要使用这个类很简单,只需要在构造HttpClient实例
的时候传入即可,代码如下:
MultiThreadedHttpConnectionManager connectionManager =
new MultiThreadedHttpConnectionManager();
HttpClient client = new HttpClient(connectionManager);
以后尽管访问client实例即可。
参考资料:
httpclient首页: http://jakarta.apache.org/commons/httpclient/
关于NTLM是如何工作: http://davenport.sourceforge.net/ntlm.html
http://www.blogjava.net/Alpha/archive/2007/01/22/95216.html
很多公司提供的页面往往并不是可以通过一个简单的URL就可以访问的,而必须经过注册然后登录后方可
使用提供服务的页面,这个时候就涉及到COOKIE问题的处理。我们知道目前流行的***页技术例如ASP、
JSP无不是通过COOKIE来处理会话信息的。为了使我们的程序能使用别人所提供的服务页面,就要求程序
首先登录后再访问服务页面,这过程就需要自行处理cookie,想想当你用 java.net.HttpURLConnection
来完成这些功能时是多么恐怖的事情啊!况且这仅仅是我们所说的顽固的WEB服务器中的一个很常见的 “
顽固”!
我们不可能列举所有可能的顽固,我们会针对几种最常见的问题进行处理。当然了,正如前面说到的,如
果我们自己使用 java.net.HttpURLConnection来搞定这些问题是很恐怖的事情,因此在开始之前我们先
要介绍一下一个开放源码的项目,这个项目就是 Apache开源组织中的httpclient,它隶属于Jakarta的
commons项目,目前的版本是2.0RC2。commons下本来已经有一个net的子项目,但是又把httpclient单独
提出来,可见http服务器的访问绝非易事。
Commons-httpclient项目就是专门设计来简化HTTP客户端与服务器进行各种通讯编程。通过它可以让原来
很头疼的事情现在轻松的解决,例如你不再管是HTTP或者HTTPS的通讯方式,告诉它你想使用HTTPS方式,
剩下的事情交给httpclient替你完成。本文会针对我们在编写HTTP客户端程序时经常碰到的几个问题进行
分别介绍如何使用httpclient来解决它们,为了让读者更快的熟悉这个项目我们最开始先给出一个简单的
例子来读取一个网页的内容,然后循序渐进解决掉问题。
1. 读取网页(HTTP/HTTPS)内容
2. 以GET或者POST方式向网页提交参数
3. 处理页面重定向
在JSP/Servlet编程中response.sendRedirect方法就是使用 HTTP协议中的重定向机制。它与JSP中的
<jsp:forward …>的区别在于后者是在服务器中实现页面的跳转,也就是说应用容器加载了所要跳转的页
面的内容并返回给客户端;而前者是返回一个状态码,这些状态码的可能值见下表,然后客户端读取需要
跳转到的页面的URL并重新加载新的页面。就是这样一个过程,所以我们编程的时候就要通过
HttpMethod.getStatusCode()方法判断返回值是否为下表中的某个值来判断是否需要跳转。如果已经确认
需要进行页面跳转了,那么可以通过读取HTTP头中的location属性来获取新的地址。
注释:
Web Server中引入了session的概念,用来保存客户端的状态信息。 这里用一个形象的比喻来解释
session的工作方式。假设Web Server是一个商场的存包处,HTTP Request是一个顾客,第一次来到存包
处,管理员把顾客的物品存放在某一个柜子里面(这个柜子就相当于Session),然后把一个号码牌交给
这个顾客,作为取包凭证(这个号码牌就是Session ID)。顾客(HTTP Request)下一次来的时候,就要
把号码牌(Session ID)交给存包处(Web Server)的管理员。管理员根据号码牌(Session ID)找到相
应的柜子(Session),根据顾客(HTTP Request)的请求,Web Server可以取出、更换、添加柜子
(Session)中的物品,Web Server也可以让顾客(HTTP Request)的号码牌和号码牌对应的柜子
(Session)失效。顾客(HTTP Request)的忘性很大,管理员在顾客回去的时候(HTTP Response)都要
重新提醒顾客记住自己的号码牌(Session ID)。这样,顾客(HTTP Request)下次来的时候,就又带着
号码牌回来了。 我们可以看到,Session ID实际上是在客户端和服务端之间通过HTTP Request和HTTP
Response传来传去的。
在Java Web Server(即Servlet/JSP Server)中,Session ID用jsessionid表示(请参见Servlet规范)
。 HTTP Request一般由3部分组成: (1)Request Line 这一行由HTTP Method(如GET或POST)、URL、
和HTTP版本号组成。 例如,GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1 GET
http://www.google.com/search?q=Tomcat HTTP/1.1 POST http://www.google.com/search HTTP/1.1
GET http://www.somsite.com/menu.do;jsessionid=1001 HTTP/1.1
(2)Request Headers 这部分定义了一些重要的头部信息,如,浏览器的种类,语言,类型。Request
Headers中还可以包括Cookie的定义。例如: User-Agent: Mozilla/4.0 (compatible; MSIE 5.5;
Windows NT 5.0) Accept-Language: en-us Cookie: jsessionid=1001
(3)Message Body 如果HTTP Method是GET,那么Message Body为空。 如果HTTP Method是POST,说明这
个HTTP Request是submit一个HTML Form的结果, 那么Message Body为HTML Form里面定义的Input属性。
例如, user=guest password=guest jsessionid=1001 注意,如果把HTML Form元素的Method属性改为
GET。那么,Message Body为空,所有的Input属性都会加在URL的后面。你在浏览器的URL地址栏中会看到
这些属性,类似于 http://www.somesite/login.do?user=guest&password=guest&jsessionid=1001
从理论上来说,这3个部分(Request URL,Cookie Header, Message Body)都可以用来存放Session ID
。由于Message Body方法必须需要一个包含Session ID的HTML Form,所以这种方法不通用。一般用来实
现Session的方法有两种: (1)URL重写。 Web Server在返回Response的时候,检查页面中所有的URL,
包括所有的连接,和HTML Form的Action属性,在这些URL后面加上“;jsessionid=XXX”。下一次,用户
访问这个页面中的URL。jsessionid就会传回到Web Server。 (2)Cookie。如果客户端支持Cookie,Web
Server在返回Response的时候,在Response的Header部分,加入一个“set-cookie: jsessionid=XXXX”
header属性,把jsessionid放在Cookie里传到客户端。客户端会把Cookie存放在本地文件里,下一次访问
Web Server的时候,再把Cookie的信息放到HTTP Request的“Cookie”header属性里面,这样jsessionid
就随着HTTP Request返回给Web Server。
Session的典型应用是存放用户的Login信息,如用户名,密码,权限角色等信息,应用程序(如Email服
务、网上银行等系统)根据这些信息进行身份验证和权限验证
4. 模拟输入用户名和口令进行登录
这样一来,对于HTTP的客户端来讲,如果要访问一个受保护的页面时就必须模拟浏览器所做的工作,首先
就是请求登录页面,然后读取Cookie值;再次请求登录页面并加入登录页所需的每个参数;最后就是请求
最终所需的页面。当然在除第一次请求外其他的请求都需要附带上Cookie信息以便服务器能判断当前请求
是否已经通过验证。说了这么多,可是如果你使用httpclient的话,你甚至连一行代码都无需增加,你只
需要先传递登录信息执行登录过程,然后直接访问想要的页面,跟访问一个普通的页面没有任何区别,因
为类HttpClient已经帮你做了所有该做的事情了,太棒了!下面的例子实现了这样一个访问的过程。
5. 提交XML格式参数
6. 通过HTTP上传文件
7. 访问启用认证的页面
我们经常会碰到这样的页面,当访问它的时候会弹出一个浏览器的对话框要求输入用户名和密码后方可,
这种用户认证的方式不同于我们在前面介绍的基于表单的用户身份验证。这是HTTP的认证策略,
httpclient支持三种认证方式包括:基本、摘要以及NTLM认证。其中基本认证最简单、通用但也最不安全
;摘要认证是在HTTP 1.1中加入的认证方式,而NTLM则是微软公司定义的而不是通用的规范,最新版本的
NTLM是比摘要认证还要安全的一种方式。
8. 多线程模式下使用httpclient
8. 多线程模式下使用httpclient
多线程同时访问httpclient,例如同时从一个站点上下载多个文件。对于同一个HttpConnection 同一个
时间只能有一个线程访问,为了保证多线程工作环境下不产生冲突,httpclient使用了一个多线程连接管
理器的类:MultiThreadedHttpConnectionManager,要使用这个类很简单,只需要在构造HttpClient实例
的时候传入即可,代码如下:
MultiThreadedHttpConnectionManager connectionManager =
new MultiThreadedHttpConnectionManager();
HttpClient client = new HttpClient(connectionManager);
以后尽管访问client实例即可。
参考资料:
httpclient首页: http://jakarta.apache.org/commons/httpclient/
关于NTLM是如何工作: http://davenport.sourceforge.net/ntlm.html