1. put、get、post和delete
他们是与服务器交互的方法。post、delete、put、get分别对应HTTP协议中的增删改查四种操作行为。
1.1 get和post的区别
这两者都是发送数据并返回数据。只是get是发送索引去获取服务器内容,而post是发送内容获取服务器的反馈。Rest模式get,put,post,delete含义与区别(转)这篇Blog着重分析了get和post的区别。
2. 错误返回码
网络请求发生错误就会返回一个错误码,如我们常见的404.下面就是HTTP中的一些错误返回码,红色标注的是我在工作中遇到的错误码。
400 - 错误的请求。
·401 - 访问被拒绝。IIS定义了许多不同的 401 错误,它们指明更为具体的错误原因。这些具体的错误代码在浏览器中显示,但不在IIS日志中显示: ·401.1 - 登录失败。
·401.2 - 服务器配置导致登录失败。
·401.3 - 由于ACL对资源的限制而未获得授权。
·401.4 - 筛选器授权失败。
·401.5 - ISAPI/CGI应用程序授权失败。
·401.7 – 访问被 Web 服务器上的URL授权策略拒绝。这个错误代码为IIS 6.0 所专用。
·403 - 禁止访问:IIS 定义了许多不同的 403 错误,它们指明更为具体的错误原因: ·403.1 - 执行访问被禁止。
·403.2 - 读访问被禁止。
·403.3 - 写访问被禁止。
·403.4 - 要求 SSL。
·403.5 - 要求 SSL 128。
·403.6 - IP地址被拒绝。
·403.7 - 要求客户端证书。
·403.8 - 站点访问被拒绝。
·403.9 - 用户数过多。
·403.10 - 配置无效。
·403.11 - 密码更改。
·403.12 - 拒绝访问映射表。
·403.13 - 客户端证书被吊销。
·403.14 - 拒绝目录列表。
·403.15 - 超出客户端访问许可。
·403.16 - 客户端证书不受信任或无效。
·403.17 - 客户端证书已过期或尚未生效。
·403.18 - 在当前的应用程序池中不能执行所请求的URL。这个错误代码为 IIS 6.0 所专用。
·403.19 - 不能为这个应用程序池中的客户端执行CGI。这个错误代码为 IIS 6.0 所专用。
·403.20 - Passport 登录失败。这个错误代码为 IIS 6.0 所专用。
·404 - 未找到。 ·404.0 -(无) – 没有找到文件或目录。
·404.1 - 无法在所请求的端口上访问 Web 站点。
·404.2 - Web 服务扩展锁定策略阻止本请求。
·404.3 - MIME 映射策略阻止本请求。
·405 - 用来访问本页面的 HTTP 谓词不被允许(方法不被允许)
·406 - 客户端浏览器不接受所请求页面的 MIME 类型。
·407 - 要求进行代理身份验证。
·412 - 前提条件失败。
·413 – 请求实体太大。
·414 - 请求 URI 太长。
·415 – 不支持的媒体类型。
·416 – 所请求的范围无法满足。
·417 – 执行失败。
·423 – 锁定的错误。
3. volley的get方法的简单使用
get方法是最简单的请求方法,只要有url,在url后面拼接请求的字符,使用volley直接请求即可获取数据。
String url = "";
RequestQueue requestQueue = Volley.newRequestQueue(this);
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
//成功返回数据
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//返回错误信息
}
});
requestQueue.add(stringRequest);
在浏览器上输入的url都是以get方法来获取的数据。
get字段的拼接:域名?key=value&key=value&key=value
4. volley的post方法的学习研究
当我们需要往服务器中发送内容时,我们使用post或put方法
这里有两种post传递json格式数据到服务器的方法
4.1 在JsonObjectRequest中传入定义好的JsonObject
String url = "";
JSONObject requestBody = new JSONObject();
try {
requestBody.put("key","value");
} catch (JSONException e) {
e.printStackTrace();
}
RequestQueue requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, requestBody, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(jsonObjectRequest);
4.2 重写getParams方法
String url = "";
RequestQueue requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
}){
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> map = new HashMap<>();
map.put("key", "value");
return map;
}
};
requestQueue.add(jsonObjectRequest);
4.3 对比结果:两个方法是一样的这两种方法看着不同,其实是一个东东。看了volley源码发现这两个值最后都会到getBody方法中
@Override public byte[] getBody() { try { return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET); } catch (UnsupportedEncodingException uee) { VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", mRequestBody, PROTOCOL_CHARSET); return null; } }这里的mRequestBody就是我们传入的jsonObject。而在另一边:
public byte[] getBody() throws AuthFailureError { Map<String, String> params = getParams(); if (params != null && params.size() > 0) { return encodeParameters(params, getParamsEncoding()); } return null; }也就是说,两者都会被getBody方法使用,而优先级是传入JsonObject要比重写getParams方法高。
另外看到网上有说重写getBody、getPostBody方法传参,其实执行的都是获取body行为。
5. 使用volley实现以put方法推送消息到服务器
研究两天成功将数据以put方法推送的服务器,代码如下:
RequestQueue requestQueue = Volley.newRequestQueue(context);
String url = "";
StringRequest stringRequest = new StringRequest(Request.Method.PUT, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
LogUtil.e("获取成功=" + response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
LogUtil.e("获取失败=" + error);
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> map = new HashMap<>();
map.put("key", "value");
return map;
}
};
requestQueue.add(stringRequest);
使用方法实测和post的用法是一样的,只是想method改成了put。
6. Volley单例工具类
为了防止请求队列RequestQueue对象被多次重复创建,不必要的耗费手机资源。Google建议使用Volley单例工具类。
工具类代码(参考 Android Volley框架使用详解):
/** * Volley单例工具 */ public class VolleySingleton { private static VolleySingleton volleySingleton; private RequestQueue mRequestQueue; private ImageLoader mImageLoader; private Context mContext; public VolleySingleton(Context context) { this.mContext = context; mRequestQueue = getRequestQueue(); mImageLoader = new ImageLoader(mRequestQueue, new ImageLoader.ImageCache(){ private final LruCache<String,Bitmap> cache = new LruCache<String ,Bitmap>(20); @Override public Bitmap getBitmap(String url){ return cache.get(url); } @Override public void putBitmap(String url,Bitmap bitmap){ cache.put(url,bitmap); } }); } public static synchronized VolleySingleton getVolleySingleton(Context context){ if(volleySingleton == null){ volleySingleton = new VolleySingleton(context); } return volleySingleton; } public RequestQueue getRequestQueue(){ if(mRequestQueue == null){ mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext()); } return mRequestQueue; } /** * 添加到请求队列 * @param req * @param <T> */ public <T> void addToRequestQueue(Request<T> req){ getRequestQueue().add(req); } public ImageLoader getImageLoader() { return mImageLoader; } }
7. 对Volley的封装
在工作中发现对于自己的业务逻辑,可以对代码进行封装。
public class VolleyModel { private static final String TAG = "Volley Model"; public static Gson gson = new Gson(); public static void volleyGet(String url, final Context context, final VolleyResult volleyResult) { StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { String result = response.replace("\\", "").substring(1, response.replace("\\", "").length() - 1); LogUtil.e(TAG + " 获取成功=" + result); if (result.contains("ERROR")) { Error error = gson.fromJson(result, Error.class); ToastUtil.showToast(context, error.getMsg()); } else { volleyResult.onSuccess(result, gson); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { LogUtil.e(TAG + " 获取失败=" + error); volleyResult.onFail(error); } }); VolleySingletonUtil.getVolleySingleton(context.getApplicationContext()).addToRequestQueue(stringRequest); } public static void volleyUpload(String url, int type, final Context context, final Map<String, String> map, final VolleyResult volleyResult){ StringRequest stringRequest = new StringRequest(type, url, new Response.Listener<String>() { @Override public void onResponse(String response) { String result = response.replace("\\", "").substring(1, response.replace("\\", "").length() - 1); LogUtil.e(" 获取成功=" + result); if (result.contains("ERROR")) { Error error = gson.fromJson(result, Error.class); ToastUtil.showToast(context, error.getMsg()); } else { volleyResult.onSuccess(result, gson); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { LogUtil.e(" 获取失败=" + error); ToastUtil.showToast(context, R.string.toast_connect_fail); volleyResult.onFail(error); } }) { @Override protected Map<String, String> getParams() throws AuthFailureError { return map; } }; VolleySingletonUtil.getVolleySingleton(context.getApplicationContext()).addToRequestQueue(stringRequest); } }在服务器返回结果中存在ERROR的时候gson解析为错误对象、否则解析为正确的数据对象。
8. 一些心得
Volley可以胜任大多数的网络通信行为,少数无法实现的网络行为,可以通过重写volley来实现(当然,这个还没深究过);
在浏览器中的输入的url都是get方式获取的数据;
get、post、put都是发送数据并返回数据,只是用途不同;
在url地址后面加上各个字段可以是用get直接拼接实现,也可以将后面的拼接字段放在post里面去发送,当然,使用get才是正解,post大多时候还是用来像服务器推送数据而非发送索引字段的。
volley中可以用到匿名方法getParams,getBody,getHeader这些方法来实现一些特殊需求。
当出现404、405、400等错误时,说明服务端有问题,多与服务器后端开发人员扯皮。
PS:服务器和HTTP的知识还需要多了解才是。