注:http://my.oschina.net/xiahuawuyu/blog/82580 为此篇文章的链接。
设置post方法的header,增加红色字体部分的配置:
HttpClient client = new HttpClient();client.getParams().setBooleanParameter(
"http.protocol.expect-continue", false);
PostMethod method = new PostMethod(url);
method.addRequestHeader("Connection", "close");
一。 http 工作 大至 原理
HTTP工作原理
1.客户端和服务器。
2.建立连接,客户端向服务器发送一个请求。
3.服务器接受到请求后,向客户端发出响应信息。
4.客户端与服务器断开链接。
请求报文与响应报文。
请求报文格式:
请求行-->通用信息头-->请求头-->实体头-->报文主体
响应报文格式:
状态行-->通用信息头-->相应头-->实体头-->报文主体
android 集成了org.apache.http.client.HttpClient; 可以直接实现简单的htttp Get 和 Post 操作 但是不支持 多部post 操作 。 要实现 多部分post 操作还需要导 额外 jar包 这里就不介绍了。
实现一个 http 操作
1 。需要生成一个Http Client 客户端对象 。
2。 生成响应的请求对象 。
3。接受发回的信息 。
4.。解析返回的信息。
直接看 get 请求操作 。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public
String httpGet(String url, String params)
throws
Exception{
String result=
""
;
//返回信息
if
(
null
!=params&&!params.equals(
""
))
{
url +=
"?"
+ params;
}
//创建一个httpGet请求
HttpGet request=
new
HttpGet(url);
//创建一个htt客户端
HttpClient httpClient=
new
DefaultHttpClient();
//接受客户端发回的响应
HttpResponse httpResponse=httpClient.execute(request);
int
statusCode=httpResponse.getStatusLine().getStatusCode();
if
(statusCode==HttpStatus.SC_OK){
//得到客户段响应的实体内容
HttpEntity responseHttpEntity=httpResponse.getEntity();
//得到输入流
InputStream in=responseHttpEntity.getContent();
//得到输入流的内容
result=getData(in);
}
Log.d(TAG, statusCode+
""
);
return
result;
}
|
post 操作
Method Request-URI HTTP-Version CRLF
例如 : GET /test.html HTTP/1.1 (CRLF)
HTTP请求方法 : GET POST HEAD DELETE PUT
POST方法用于向服务器发送请求,要求服务器接受附在请求后面的数据.POST方法在表单提交的时候用的最多 .
例如:
POST /login.jsp HTTP/1.1 (CRLF)
Accept:image/gif (CRLF) (...)
........
Host:www.sample.com (CRLF)
(CRLF)
username=hell@password=123456 两个(CRLF)之后加上参数
HEAD方法只是请求消息报头,而不是完整的内容. 通常用于测试超链接的有效性.
HTTP响应
HTTP-Version Status-Code Reason-Phrase CRLF
例如 : HTTP/1.1 200 OK (CRLF)
状态分类
1xx 提示信息
2xx 请求成功
3xx 重定向
4xx 客户端错误
5xx 服务器错误
HTTP消息有客户端到服务器的请求和服务器到客户端的响应组成.
消息都是由开始行,消息报头(可选),空行(只有CRLF的行),消息正文(可选)组成.
对于请求消息,开始行就是请求行,对于响应消息,开始行就是状态行.
Apache HttpClient是很方便的 Java 开源的访问 HTTP 资源的组件。网站上的资源不总是能匿名访问的,很多都需要登陆后才能操作,且不说论坛里登陆后才能发言,就是某些稍显敏感的 XML 等信息也是登陆后才能获取到的。
没问题,HttpClient 能让你做到,它提供了 Basic 和 Form-Based 两种验证方式。登陆后获得服务器端发来的 Cookie 作为下一次访问的凭证, 让服务端认为你还是个合法用户。服务端不是用 Session 来维护会话的吗?是的,Session 也要有个载体,Cookie 了。或有时 Java Web 会用 jsessionid 参数在服务端与客户端来回关联 Session 信息,也没问题,HttpClient 同样能胜任。
下面主要说明 Form-Based 的验证方式,Basic 的验证简单列了几行代码,还未实践,具体可参考文后的链接。
看 Form-Based 方式的演示代码,如果登陆时需要一个验证码的话,那只有自己想办法怎么得到这个码了,登陆时谁都想无码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
package
cc.unmi.httpclient;
import
org.apache.commons.httpclient.Cookie;
import
org.apache.commons.httpclient.HttpClient;
import
org.apache.commons.httpclient.NameValuePair;
import
org.apache.commons.httpclient.cookie.CookiePolicy;
import
org.apache.commons.httpclient.methods.GetMethod;
import
org.apache.commons.httpclient.methods.PostMethod;
import
org.junit.Test;
public
class
HttpClientLogin {
public
static
void
main(String[] args){
//登陆 Url
String loginUrl =
"http://localhost/unmi/login.html"
;
//需登陆后访问的 Url
String dataUrl =
"http://localhost/unmi/user_info.html?userid=123456"
;
HttpClient httpClient =
new
HttpClient();
//模拟登陆,按实际服务器端要求选用 Post 或 Get 请求方式
PostMethod postMethod =
new
PostMethod(loginUrl);
//设置登陆时要求的信息,一般就用户名和密码,验证码自己处理了
NameValuePair[] data = {
new
NameValuePair(
"username"
,
"Unmi"
),
new
NameValuePair(
"password"
,
"123456"
),
new
NameValuePair(
"code"
,
"anyany"
)
};
postMethod.setRequestBody(data);
try
{
//设置 HttpClient 接收 Cookie,用与浏览器一样的策略
httpClient.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
httpClient.executeMethod(postMethod);
//获得登陆后的 Cookie
Cookie[] cookies=httpClient.getState().getCookies();
String tmpcookies=
""
;
for
(Cookie c:cookies){
tmpcookies += c.toString()+
";"
;
}
//进行登陆后的操作
GetMethod getMethod =
new
GetMethod(dataUrl);
//每次访问需授权的网址时需带上前面的 cookie 作为通行证
getMethod.setRequestHeader(
"cookie"
,tmpcookies);
//你还可以通过 PostMethod/GetMethod 设置更多的请求后数据
//例如,referer 从哪里来的,UA 像搜索引擎都会表名自己是谁,无良搜索引擎除外
postMethod.setRequestHeader(
"Referer"
,
"http://unmi.cc"
);
postMethod.setRequestHeader(
"User-Agent"
,
"Unmi Spot"
);
httpClient.executeMethod(getMethod);
//打印出返回数据,检验一下是否成功
String text = getMethod.getResponseBodyAsString();
System.out.println(text);
}
catch
(Exception e) {
e.printStackTrace();
}
}
}
Basic 验证的简单代码导引,还未亲试:
HttpClient client =
new
HttpClient();
// 1
client.getState().setCredentials(
new
AuthScope(
"unmi.cc"
,
80
, AuthScope.ANY_REALM),
new
UsernamePasswordCredentials(
"username"
,
"password"
)
);
// 2
client.getParams().setAuthenticationPreemptive(
true
);
// 3
GetMethod getMothod =
new
GetMethod(
"http://unmi.cc/twitter"
);
// 4
getMothod.setDoAuthentication(
true
);
// 5
int
status = client.executeMethod( getMothod );
|
http://unmi.cc/httpclient-login-session
999999999999999999999999
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
post步骤 解析json数据(向服务器传递,接受服务器传递))
www.MyException.Cn 发布于:
2012
-
08
-
11
20
:
50
:
31
浏览:
13
次
httpClient post方法 解析json数据(向服务器传递,接受服务器传递))
public
class
json
extends
Activity {
public
Context context;
private
TextView textView1;
public
static
String URL =
"http://webservice.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl"
;
private
DefaultHttpClient httpClient;
StringBuilder result =
new
StringBuilder();
private
static
final
int
TIMEOUT =
60
;
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
HttpParams paramsw = createHttpParams();
httpClient =
new
DefaultHttpClient(paramsw);
HttpPost post =
new
HttpPost(
"http://webservice.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl"
);
List<NameValuePair> params =
new
ArrayList<NameValuePair>();
params.add(
new
BasicNameValuePair(
"name"
,
"this is post"
));
try
{
//向服务器写json
JSONObject json =
new
JSONObject();
Object email =
null
;
json.put(
"email"
, email);
Object pwd =
null
;
json.put(
"password"
, pwd);
StringEntity se =
new
StringEntity(
"JSON: "
+ json.toString());
se.setContentEncoding(
new
BasicHeader(HTTP.CONTENT_TYPE,
"application/json"
));
post.setEntity(se);
post.setEntity(
new
UrlEncodedFormEntity(params, HTTP.UTF_8));
HttpResponse httpResponse = httpClient.execute(post);
int
httpCode = httpResponse.getStatusLine().getStatusCode();
if
(httpCode == HttpURLConnection.HTTP_OK&&httpResponse!=
null
) {
Header[] headers = httpResponse.getAllHeaders();
HttpEntity entity = httpResponse.getEntity();
Header header = httpResponse.getFirstHeader(
"content-type"
);
//读取服务器返回的json数据(接受json服务器数据)
InputStream inputStream = entity.getContent();
InputStreamReader inputStreamReader =
new
InputStreamReader(inputStream);
BufferedReader reader =
new
BufferedReader(inputStreamReader);
// 读字符串用的。
String s;
while
(((s = reader.readLine()) !=
null
)) {
result.append(s);
}
reader.close();
// 关闭输入流
//在这里把result这个字符串个给JSONObject。解读里面的内容。
JSONObject jsonObject =
new
JSONObject(result.toString());
String re_username = jsonObject.getString(
"username"
);
String re_password = jsonObject.getString(
"password"
);
int
re_user_id = jsonObject.getInt(
"user_id"
);
setTitle(
"用户id_"
+re_user_id);
Log.v(
"url response"
,
"true="
+re_username);
Log.v(
"url response"
,
"true="
+re_password);
}
else
{
textView1.setText(
"Error Response"
+ httpResponse.getStatusLine().toString());
}
}
catch
(UnsupportedEncodingException e) {
}
catch
(ClientProtocolException e) {
}
catch
(IOException e) {
}
catch
(JSONException e) {
e.printStackTrace();
}
finally
{
if
(httpClient !=
null
) {
httpClient.getConnectionManager().shutdown();
// 最后关掉链接。
httpClient =
null
;
}
}
}
public
static
final
HttpParams createHttpParams() {
final
HttpParams params =
new
BasicHttpParams();
HttpConnectionParams.setStaleCheckingEnabled(params,
false
);
HttpConnectionParams.setConnectionTimeout(params, TIMEOUT *
1000
);
HttpConnectionParams.setSoTimeout(params, TIMEOUT *
1000
);
HttpConnectionParams.setSocketBufferSize(params,
8192
*
5
);
return
params;
}
}
|
348888888888888888
HttpClient程序包是一个实现了 HTTP 协议的客户端编程工具包,要想熟练的掌握它,必须熟悉 HTTP协议。一个最简单的调用如下:
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
package
test;
import
java.util.ArrayList;
import
java.util.List;
import
org.apache.http.Header;
import
org.apache.http.HttpEntity;
import
org.apache.http.HttpResponse;
import
org.apache.http.NameValuePair;
import
org.apache.http.client.entity.UrlEncodedFormEntity;
import
org.apache.http.client.methods.HttpPost;
import
org.apache.http.client.params.CookiePolicy;
import
org.apache.http.client.params.ClientPNames;
import
org.apache.http.impl.client.DefaultHttpClient;
import
org.apache.http.message.BasicNameValuePair;
import
org.apache.http.protocol.HTTP;
import
org.apache.http.util.EntityUtils;
public
class
Test2 {
public
static
void
main(String[] args)
throws
Exception {
DefaultHttpClient httpclient =
new
DefaultHttpClient();
//实例化一个HttpClient
HttpResponse response =
null
;
HttpEntity entity =
null
;
httpclient.getParams().setParameter(
ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);
//设置cookie的兼容性
HttpPost httpost =
new
HttpPost(
"http://127.0.0.1:8080/pub/jsp/getInfo"
); //引号中的参数是:servlet的地址
List <NameValuePair> nvps =
new
ArrayList <NameValuePair>();
nvps.add(
new
BasicNameValuePair(
"jqm"
,
"fb1f7cbdaf2bf0a9cb5d43736492640e0c4c0cd0232da9de"
));
// BasicNameValuePair("name", "value"), name是post方法里的属性, value是传入的参数值
nvps.add(
new
BasicNameValuePair(
"sqm"
,
"1bb5b5b45915c8"
));
httpost.setEntity(
new
UrlEncodedFormEntity(nvps, HTTP.UTF_8));
//将参数传入post方法中
response = httpclient.execute(httpost);
//执行
entity = response.getEntity();
//返回服务器响应
try
{
System.out.println(
"----------------------------------------"
);
System.out.println(response.getStatusLine());
//服务器返回状态
Header[] headers = response.getAllHeaders();
//返回的HTTP头信息
for
(
int
i=
0
; i<headers.length; i++) {
System.out.println(headers[i]);
}
System.out.println(
"----------------------------------------"
);
String responseString =
null
;
if
(response.getEntity() !=
null
) {
responseString = EntityUtils.toString(response.getEntity()); / /返回服务器响应的HTML代码
System.out.println(responseString);
//打印出服务器响应的HTML代码
}
}
finally
{
if
(entity !=
null
)
entity.consumeContent();
// release connection gracefully
}
System.out.println(
"Login form get: "
+ response.getStatusLine());
if
(entity !=
null
) {
entity.consumeContent();
}
}
}
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
// HttpClientTest.java
package
com.baihuo.crawler.test;
import
java.util.regex.Matcher;
import
java.util.regex.Pattern;
import
org.apache.http.Header;
import
org.apache.http.HttpEntity;
import
org.apache.http.HttpHost;
import
org.apache.http.HttpResponse;
import
org.apache.http.client.HttpClient;
import
org.apache.http.client.methods.HttpGet;
import
org.apache.http.impl.client.DefaultHttpClient;
import
org.apache.http.util.EntityUtils;
class
HttpClientTest {
public
final
static
void
main(String[] args)
throws
Exception {
// 初始化,此处构造函数就与3.1中不同
HttpClient httpclient =
new
DefaultHttpClient();
HttpHost targetHost =
new
HttpHost(
"www.google.cn"
);
//HttpGet httpget = new HttpGet("http://www.apache.org/");
HttpGet httpget =
new
HttpGet(
"/"
);
// 查看默认request头部信息
System.out.println(
"Accept-Charset:"
+ httpget.getFirstHeader(
"Accept-Charset"
));
// 以下这条如果不加会发现无论你设置Accept-Charset为gbk还是utf-8,他都会默认返回gb2312(本例针对google.cn来说)
httpget.setHeader(
"User-Agent"
,
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.2)"
);
// 用逗号分隔显示可以同时接受多种编码
httpget.setHeader(
"Accept-Language"
,
"zh-cn,zh;q=0.5"
);
httpget.setHeader(
"Accept-Charset"
,
"GB2312,utf-8;q=0.7,*;q=0.7"
);
// 验证头部信息设置生效
System.out.println(
"Accept-Charset:"
+ httpget.getFirstHeader(
"Accept-Charset"
).getValue());
// Execute HTTP request
System.out.println(
"executing request "
+ httpget.getURI());
HttpResponse response = httpclient.execute(targetHost, httpget);
//HttpResponse response = httpclient.execute(httpget);
System.out.println(
"----------------------------------------"
);
System.out.println(
"Location: "
+ response.getLastHeader(
"Location"
));
System.out.println(response.getStatusLine().getStatusCode());
System.out.println(response.getLastHeader(
"Content-Type"
));
System.out.println(response.getLastHeader(
"Content-Length"
));
System.out.println(
"----------------------------------------"
);
// 判断页面返回状态判断是否进行转向抓取新链接
int
statusCode = response.getStatusLine().getStatusCode();
if
((statusCode == HttpStatus.SC_MOVED_PERMANENTLY) ||
(statusCode == HttpStatus.SC_MOVED_TEMPORARILY) ||
(statusCode == HttpStatus.SC_SEE_OTHER) ||
(statusCode == HttpStatus.SC_TEMPORARY_REDIRECT)) {
// 此处重定向处理 此处还未验证
String newUri = response.getLastHeader(
"Location"
).getValue();
httpclient =
new
DefaultHttpClient();
httpget =
new
HttpGet(newUri);
response = httpclient.execute(httpget);
}
// Get hold of the response entity
HttpEntity entity = response.getEntity();
// 查看所有返回头部信息
Header headers[] = response.getAllHeaders();
int
ii =
0
;
while
(ii < headers.length) {
System.out.println(headers[ii].getName() +
": "
+ headers[ii].getValue());
++ii;
}
// If the response does not enclose an entity, there is no need
// to bother about connection release
if
(entity !=
null
) {
// 将源码流保存在一个byte数组当中,因为可能需要两次用到该流,
byte
[] bytes = EntityUtils.toByteArray(entity);
String charSet =
""
;
// 如果头部Content-Type中包含了编码信息,那么我们可以直接在此处获取
charSet = EntityUtils.getContentCharSet(entity);
System.out.println(
"In header: "
+ charSet);
// 如果头部中没有,那么我们需要 查看页面源码,这个方法虽然不能说完全正确,因为有些粗糙的网页编码者没有在页面中写头部编码信息
if
(charSet ==
""
) {
regEx=
"(?=<meta).*?(?<=charset=[\\'|\\\"]?)([[a-z]|[A-Z]|[0-9]|-]*)"
;
p=Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
m=p.matcher(
new
String(bytes));
// 默认编码转成字符串,因为我们的匹配中无中文,所以串中可能的乱码对我们没有影响
result=m.find();
if
(m.groupCount() ==
1
) {
charSet = m.group(
1
);
}
else
{
charSet =
""
;
}
}
System.out.println(
"Last get: "
+ charSet);
// 至此,我们可以将原byte数组按照正常编码专成字符串输出(如果找到了编码的话)
System.out.println(
"Encoding string is: "
+
new
String(bytes, charSet));
}
httpclient.getConnectionManager().shutdown();
}
}
|

被折叠的 条评论
为什么被折叠?



