首先简单描述一下Google的Android开发团队在2013年推出的一个网络通信框架Volley.它的设计目标是进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如下载文件等,Volley的表现就不尽如人意。
在app开发中,我们最常见的就是从app客户端向服务端发一个http请求.对于两种基本的web请求方式get和post来说,get请求方式相对比较简单,在此略过不表.本文重点描述一下通过volley进行几种post提交的方式.
1.客户端以普通的post方式进行提交,服务端返回字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
StringRequest stringRequest =
new
StringRequest(Request.Method.POST,httpurl,
new
Response.Listener<String>() {
@Override
public
void
onResponse(String response) {
Log.d(TAG,
"response -> "
+ response);
}
},
new
Response.ErrorListener() {
@Override
public
void
onErrorResponse(VolleyError error) {
Log.e(TAG, error.getMessage(), error);
}
}) {
@Override
protected
Map<String, String> getParams() {
//在这里设置需要post的参数
Map<String, String> map =
new
HashMap<String, String>();
map.put(
"name1"
,
"value1"
);
map.put(
"name2"
,
"value2"
);
return
params;
}
};
requestQueue.add(stringRequest);
|
2.客户端以json串的post请求方式进行提交,服务端返回json串
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
|
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
Map<String, String> map =
new
HashMap<String, String>();
map.put(
"name1"
,
"value1"
);
map.put(
"name2"
,
"value2"
);
JSONObject jsonObject =
new
JSONObject(params);
JsonRequest<JSONObject> jsonRequest =
new
JsonObjectRequest(Method.POST,httpurl, jsonObject,
new
Response.Listener<JSONObject>() {
@Override
public
void
onResponse(JSONObject response) {
Log.d(TAG,
"response -> "
+ response.toString());
}
},
new
Response.ErrorListener() {
@Override
public
void
onErrorResponse(VolleyError error) {
Log.e(TAG, error.getMessage(), error);
}
})
{
//注意此处override的getParams()方法,在此处设置post需要提交的参数根本不起作用
//必须象上面那样,构成JSONObject当做实参传入JsonObjectRequest对象里
//所以这个方法在此处是不需要的
// @Override
// protected Map<String, String> getParams() {
// Map<String, String> map = new HashMap<String, String>();
// map.put("name1", "value1");
// map.put("name2", "value2");
// return params;
// }
@Override
public
Map<String, String> getHeaders() {
HashMap<String, String> headers =
new
HashMap<String, String>();
headers.put(
"Accept"
,
"application/json"
);
headers.put(
"Content-Type"
,
"application/json; charset=UTF-8"
);
return
headers;
}
};
requestQueue.add(jsonRequest);
|
新版本写法如下,和以上有所不同
@Override
public RequestInfo Create(String url , final RequestMethod method , final Map<String, Object> params , final IRequestCallBack<JSONObject> callBack)
{
if (TextUtils.isEmpty(url) || method == null)
{
return null;
}
final boolean isIcsonRequest = NetRequestUtils.isIcsonRequest(url);
// JSONObject jsonParams = new JSONObject(params);
JSONObject jsonObject = new JSONObject(params);
mRequestInfo = new RequestInfo();
JsonRequest<JSONObject> request = new JsonRequest(method.getValue(), url,jsonObject.toString(),new Response.Listener<JSONObject>()
{
@Override
public void onResponse(JSONObject result)
{
if (result != null)
{
callBack.onResponse(mRequestInfo.getRequestToken(), result);
}
else
{
callBack.onError(mRequestInfo.getRequestToken(), ErrorMsgUtil.getCommNetDataErrorMsg());
}
}
}, new Response.ErrorListener()
{
@Override
public void onErrorResponse(VolleyError arg0)
{
ErrorMsg msg = new ErrorMsg();
if (arg0 != null && arg0.networkResponse != null)
{
ErrorDetail errorDetal = new ErrorDetail();
errorDetal.data = arg0.networkResponse.data;
errorDetal.headers = arg0.networkResponse.headers;
errorDetal.networkTimeMs = arg0.networkResponse.networkTimeMs;
errorDetal.notModified = arg0.networkResponse.notModified;
errorDetal.statusCode = arg0.networkResponse.statusCode;
msg.setErrorObject(errorDetal);
}
//TODO:设置通用的异常code msg.setErrorCode(errorCode);
callBack.onError(mRequestInfo.getRequestToken(), msg);
}
})
{
@Override
protected String getParamsEncoding()
{
return mRequestInfo.getRequestCharset();
}
@Override
protected String getPostParamsEncoding()
{
return super.getPostParamsEncoding();
}
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response)
{
String parsedStr;
try
{
byte[] ret = response.data;
if (response.headers.containsKey("Content-Encoding") && response.headers.get("Content-Encoding").equals("gzip"))
{
ByteArrayInputStream input = new ByteArrayInputStream(response.data);
ByteArrayOutputStream tmpOutput = new ByteArrayOutputStream(BUFFERSIZE);
GZIPInputStream gin = new GZIPInputStream(input);
int count;
byte data[] = new byte[BUFFERSIZE];
while ((count = gin.read(data, 0, BUFFERSIZE)) != -1)
{
tmpOutput.write(data, 0, count);
}
gin.close();
ret = tmpOutput.toByteArray();
}
if (TextUtils.isEmpty(mRequestInfo.getResponseCharset()))
{
String chartSet = HttpHeaderParser.parseCharset(response.headers);
parsedStr = new String(ret, chartSet);
}
else
{
parsedStr = new String(response.data, mRequestInfo.getResponseCharset());
}
}
catch (UnsupportedEncodingException e)
{
parsedStr = new String(response.data);
}
catch (IOException e)
{
e.printStackTrace();
parsedStr = new String(response.data);
}
try {
return Response.success(new JSONObject(parsedStr), HttpHeaderParser.parseCacheHeaders(response));
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError
{
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Accept", "application/json");
headers.put("Content-Type", "application/json; charset=UTF-8");
return headers;
}
};
看了上面这段代码,会觉得volley这个框架实在是还不够完善,使用JsonObjectRequest对象提交一个post请求,如果有参数需要提交,就必须以JSONObject的json串方式提交.
如果服务端并不支持这种方式呢?比如常见的spring mvc服务端,就很难支持json的请求方式.
那么我们想实现这个目标,就需要使用下面给出的办法.
3.客户端以普通的post方式进行提交,服务端返回json串
首先在Activity类里,继承Request实现一个NormalPostRequest类
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
|
private
class
NormalPostRequest
extends
Request<JSONObject> {
private
Map<String, String> mMap;
private
Listener<JSONObject> mListener;
public
NormalPostRequest(String url, Listener<JSONObject> listener,ErrorListener errorListener, Map<String, String> map) {
super
(Request.Method.POST, url, errorListener);
mListener = listener;
mMap = map;
}
//mMap是已经按照前面的方式,设置了参数的实例
@Override
protected
Map<String, String> getParams()
throws
AuthFailureError {
return
mMap;
}
//此处因为response返回值需要json数据,和JsonObjectRequest类一样即可
@Override
protected
Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try
{
String jsonString =
new
String(response.data,HttpHeaderParser.parseCharset(response.headers));
return
Response.success(
new
JSONObject(jsonString),HttpHeaderParser.parseCacheHeaders(response));
}
catch
(UnsupportedEncodingException e) {
return
Response.error(
new
ParseError(e));
}
catch
(JSONException je) {
return
Response.error(
new
ParseError(je));
}
}
@Override
protected
void
deliverResponse(JSONObject response) {
mListener.onResponse(response);
}
}
|
接下来的调用方式和前面差不多,生成一个Request实例,加入队列中即可.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
Request<JSONObject> request =
new
NormalPostRequest(httpurl,
new
Response.Listener<JSONObject>() {
@Override
public
void
onResponse(JSONObject response) {
Log.d(TAG,
"response -> "
+ response.toString());
}
},
new
Response.ErrorListener() {
@Override
public
void
onErrorResponse(VolleyError error) {
Log.e(TAG, error.getMessage(), error);
}
}, params);
requestQueue.add(request);
|
以上代码在android 4.3环境下测试通过.
2、请求报头
请求报头允许客户端向服务器端传递请求的附加信息以及客户端自身的信息。
常用的请求报头
Accept
Accept请求报头域用于指定客户端接受哪些类型的信息。eg:Accept:image/gif,表明客户端希望接受GIF图象格式的资源;Accept:text/html,表明客户端希望接受html文本。http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html
分类: Linux
这个话题源于一次客户端与服务器交互的联调。下面以java为例来说明。
首先要分清的是,在客户端发起请求到服务器端收到请求处理完毕返回信息再到客户端收到反馈,这中间经历了哪些环节:
- 首先,客户端构造了一个HttpRequest,里面包含了需要提交到服务器端的数据,客户端提交该HtteRequest(比如通过HttpClient对象提交)。
- 接着,服务器端收到此请求,在服务器端对应的对象为HttpServletRequest
- 然后,服务器端根据请求处理后,生成了一个HttpServletResponse,返回给客户端
- 客户端展现服务器端返回的数据
清楚了这几个环节,自然也就可以得知,我们熟悉的HttpServletRequest和HttpServletResponse是服务器端的对象,而HttpRequest是客户端的对象,切不可搞混。他们的Content-Type都遵循RFC2616中定义的规范,但对于不同的对象,他们的Content-Type是不同的,例如,对于HttpRequest/HttpServletRequest对象,在最常见的表单提交中,Content-Type通常是application/x-www-form-urlencoded或multipart/form-data,前者通常用于没有附件上传的表单,后者通常用于需要上传附件的表单,详阅RFC1867;而HttpServletResponse的Content-Type通常是text/html、application/json等。
ok,理解清楚了数据交互的过程,也就不难理解他们的Content-Type为何不同了。
提交参数和返回都有相应的内容类型
java发送http的get、post请求, 通过阅读发现,POST的提交本质就是把参数写到BODY之中
譬如:要提交JSON参数,应该写入的参数是JSON字符串,content-type应该是json
地址:http://www.cnblogs.com/zhuawang/archive/2012/12/08/2809380.html
以上内容来源:http://www.open-open.com/lib/view/open1407727047207.html
http://blog.itpub.net/29867/viewspace-692485/