现在开源的http请求库有很多,但是呢,有时候总有些不合适的地方,然后呢我就自己摸索的一套异步http请求处理机制; 1:get/post 请求 2:多种方式携带token,并有token过期、失效等处理机制; 3:使用简单,几行代码搞定一个请求,只需专注业务实现; 话不多说,直接上代码
1:首先是创建几个实体类,用于接收请求的结果以及内容 Result.calss :请求的结果的实体类
public class Result {
public Boolean isSuccess;
public ResultInfo result;
public String resultDes;
public Boolean isSuccess() {
return isSuccess;
}
public void setSuccess(Boolean success) {
isSuccess = success;
}
public ResultInfo getResult() {
return result;
}
public void setResult(ResultInfo result) {
this.result = result;
}
public String getResultDes() {
return resultDes;
}
public void setResultDes(String resultDes) {
this.resultDes = resultDes;
}
@Override
public String toString() {
StringBuffer SB = new StringBuffer();
SB.append("------------------------------");
SB.append(isSuccess);
SB.append("------------------------------");
SB.append("\n");
SB.append("------------------------------");
SB.append(resultDes);
SB.append("------------------------------");
SB.append("\n");
SB.append(result.toString());
return SB.toString();
}
}
ResultInfo.calss:返回内容的实体类
public class ResultInfo<T> implements java.io.Serializable {
public int code;
public String message;
public T data;
public ResultPage page;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public ResultPage getPage() {
return page;
}
public void setPage(ResultPage page) {
this.page = page;
}
@Override
public String toString() {
StringBuffer SB = new StringBuffer();
SB.append("code=" + code);
SB.append("\n");
SB.append("message=" + message);
if(data!=null){
SB.append("\n");
SB.append("data=" + data.toString());
}
if(page!=null){
SB.append("\n");
SB.append("page=" + page.toString());
}
return SB.toString();
}
}
URL及配置等实体类 UrlInfo.calss
public class UrlInfo {
String URL = "";
String ContentType = null;
String token = "";
public String getContentType() {
return ContentType;
}
public void setContentType(String contentType) {
ContentType = contentType;
}
@Override
public String toString() {
return "UrlInfo{" +
"URL='" + URL + '\'' +
", params='" + params + '\'' +
'}';
}
public void setURL(String URL) {
this.URL = URL;
}
public String getURL() {
return URL;
}
String params = "";
public void setParams(String params) {
this.params = params;
}
public String getParams() {
return params;
}
public void addParams(String key, Object value) {
StringBuffer pa = new StringBuffer();
if (!params.equals("")) {
pa.append(params);
pa.append("&");
}
pa.append(key);
pa.append("=");
pa.append(value.toString());
params = pa.toString();
}
}
接下来就是正式开始请求数据了,我只是实现了常用的POST和GET请求,其他的各位可以按需自己实现步骤是一样的; 首先是创建实际请求的方法类 注意:我这里这里用到了JSON解析库,用于将返回的内容序列化;
implementation 'com.google.code.gson:gson:2.8.6'
HttpClient.class
import android.content.Context;
import android.os.Environment;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.List;
import java.util.Map;
public class HttpClient<T> {
private HttpURLConnection urlConn;
Result mResult;
String TAG = "HttpClient";
UrlInfo mUrlInfo;
public HttpClient(UrlInfo urlInfo) {
mUrlInfo = urlInfo;
}
public Result Get(Type mType) {
mResult = new Result();
BufferedReader reader = null;
InputStream in = null;
try {
if (!mUrlInfo.token.equals(""))
mUrlInfo.addParams("token", mUrlInfo.token.replace("token=", ""));
URL url = new URL("http://" + mUrlInfo.URL + "?" + mUrlInfo.params);
Log.i(TAG, "http://" + mUrlInfo.URL + "?" + mUrlInfo.params);
urlConn = (HttpURLConnection) url.openConnection();
urlConn.setRequestMethod("GET");
urlConn.setReadTimeout(30 * 1000);
urlConn.setConnectTimeout(30 * 1000);
if (!mUrlInfo.token.equals("")) {
urlConn.setRequestProperty("Cookie", mUrlInfo.token);
}
if (!mUrlInfo.token.equals("")) {
urlConn.setRequestProperty("Authorization", "Bearer " + mUrlInfo.token);
}
if (mUrlInfo.getContentType() != null)
urlConn.setRequestProperty("Content-Type", mUrlInfo.getContentType());
urlConn.connect();
if (urlConn.getResponseCode() == 200) {
Map<String, List<String>> cookie_map = urlConn.getHeaderFields();
List<String> cookies = cookie_map.get("Set-Cookie");
if (null != cookies && 0 < cookies.size()) {
mUrlInfo.token = cookies.get(0).split(";")[0];
if (cookies.get(1).split(";")[0].contains("SESSION"))
mUrlInfo.token = mUrlInfo.token + ";" + cookies.get(1).split(";")[0];
}
in = urlConn.getInputStream();
if (null != in) {
StringBuffer bSt = new StringBuffer();
reader = new BufferedReader(new InputStreamReader(in,
"UTF-8"));
String line = "";
while ((line = reader.readLine()) != null) {
bSt.append("\n" + line);
}
if (bSt.length() != 0) {
mResult.setSuccess(true);
mResult.setResultDes(bSt.substring(1));
if (mType != null)
try {
Gson gson = new Gson();
ResultInfo<T> resultData = gson.fromJson(bSt.substring(1), mType);
mResult.setResult(resultData);
} catch (JsonSyntaxException tx) {
mResult.setSuccess(false);
mResult.setResult(null);
mResult.setResultDes("接口返回有误");
LogOut.i(TAG,"服务器返回数据格式错误");
LogOut.i(TAG, tx.toString());
}
} else {
mResult.setSuccess(false);
mResult.setResultDes("服务器返回为空");
}
} else {
mResult.setSuccess(false);
mResult.setResultDes("服务器无返回");
}
} else if (urlConn.getResponseCode() == 401 || urlConn.getResponseCode() == 404) {
mResult.setSuccess(false);
mResult.setResultDes("登录失效,请重新登录!");
} else {
mResult.setSuccess(false);
mResult.setResultDes("服务器接口有误");
LogOut.i(TAG, urlConn.getURL().toString() + "\n" + mUrlInfo.getParams()
+ "\n" + "服务器返回" + urlConn.getResponseCode());
}
} catch (SocketTimeoutException tx) {
mResult.setSuccess(false);
mResult.setResultDes("网络连接超时");
} catch (Exception ex) {
mResult.setSuccess(false);
mResult.setResultDes("网络连接错误");
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (urlConn != null) {
urlConn.disconnect();
}
}
Log.i(TAG, urlConn.getURL().toString() + "\n" + mUrlInfo.getParams());
Log.i(TAG, mResult.toString());
return mResult;
}
public Result Post(Type mType) {
mResult = new Result();
BufferedReader reader = null;
InputStream in = null;
try {
String urlStr = "http://" + mUrlInfo.URL;
if (!mUrlInfo.token.isEmpty()) {
urlStr = "http://" + mUrlInfo.URL + "?" + mUrlInfo.token;
}
URL url = new URL(urlStr);
Log.i(TAG, urlStr);
Log.i(TAG, mUrlInfo.params.toString());
urlConn = (HttpURLConnection) url.openConnection();
urlConn.setDoInput(true);
urlConn.setRequestMethod("POST");
urlConn.setReadTimeout(30 * 1000);
urlConn.setConnectTimeout(30 * 1000);
if (!mUrlInfo.token.equals("")) {
urlConn.setRequestProperty("Cookie", mUrlInfo.token);
}
if (!mUrlInfo.token.equals("")) {
urlConn.setRequestProperty("Authorization", "Bearer " + mUrlInfo.token);
}
if (mUrlInfo.getContentType() != null)
urlConn.setRequestProperty("Content-Type", mUrlInfo.getContentType());
if (mUrlInfo.params != null && mUrlInfo.params.length() != 0) {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(urlConn.getOutputStream(), "UTF-8"));
writer.write(mUrlInfo.params);
writer.close();
}
urlConn.connect();
if (urlConn.getResponseCode() == 200) {
Map<String, List<String>> cookie_map = urlConn
.getHeaderFields();
List<String> cookies = cookie_map.get("Set-Cookie");
if (null != cookies && 0 < cookies.size()) {
mUrlInfo.SESSION = cookies.get(0).split(";")[0];
if (cookies.get(1).split(";")[0].contains("SESSION"))
mUrlInfo.SESSION = mUrlInfo.SESSION + ";" + cookies.get(1).split(";")[0];
}
in = urlConn.getInputStream();
if (null != in) {
StringBuffer bSt = new StringBuffer();
reader = new BufferedReader(new InputStreamReader(in,
"UTF-8"));
String line = "";
while ((line = reader.readLine()) != null) {
bSt.append("\n" + line);
}
if (bSt.length() != 0) {
mResult.setSuccess(true);
mResult.setResultDes(bSt.toString());
if (mType != null)
try {
Gson gson = new Gson();
ResultInfo<T> resultData = gson.fromJson(bSt.substring(1), mType);
mResult.setResult(resultData);
} catch (JsonSyntaxException tx) {
tx.printStackTrace();
mResult.setSuccess(false);
mResult.setResult(null);
mResult.setResultDes("接口返回有误");
LogOut.i(TAG,"服务器返回数据格式错误");
LogOut.i(TAG, tx.toString());
}
} else {
mResult.setSuccess(false);
mResult.setResultDes("服务器返回为空");
}
} else {
mResult.setSuccess(false);
mResult.setResultDes("服务器无响应");
}
} else if (urlConn.getResponseCode() == 401 || urlConn.getResponseCode() == 404) {
mResult.setSuccess(false);
mResult.setResultDes("登录失效,请重新登录!");
}else {
mResult.setSuccess(false);
mResult.setResultDes("服务器接口有误");
LogOut.i(TAG, urlConn.getURL().toString() + "\n" + mUrlInfo.getParams()
+ "\n" + "服务器返回" + urlConn.getResponseCode());
}
} catch (SocketTimeoutException tx) {
mResult.setSuccess(false);
mResult.setResultDes("网络连接超时");
} catch (Exception ex) {
Log.e(TAG, ex.toString());
mResult.setSuccess(false);
mResult.setResultDes("网络连接错误");
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (urlConn != null) {
urlConn.disconnect();
}
}
LogOut.i(TAG, urlConn.getURL().toString() + "\n" + mUrlInfo.getParams());
LogOut.i(TAG, mResult.toString());
return mResult;
}
public Result Download() {
String fileName = mUrlInfo.URL.substring(mUrlInfo.URL.lastIndexOf("/") + 1);
mResult = new Result();
InputStream input = null;
OutputStream out = null;
File file;
try {
URL url = new URL("http://" + mUrlInfo.URL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
input = conn.getInputStream();
byte[] b = new byte[1024];
int n = -1;
file = new File(getPath(fileName));
out = new FileOutputStream(file);
while ((n = input.read(b)) != -1) {
out.write(b, 0, n);
}
out.flush();
mResult.setSuccess(true);
mResult.setResultDes("下载成功,文件路径:" + file.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
mResult.setSuccess(false);
mResult.setResultDes("下载失败");
return mResult;
} finally {
try {
if (input != null) {
input.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return mResult;
}
public static synchronized String Download(Context context, String path, String filename, String folder) {
InputStream input = null;
OutputStream out = null;
File file = null;
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
input = conn.getInputStream();
byte[] b = new byte[1024];
int n = -1;
file = Environment.getExternalStorageDirectory();
file = new File(file.getAbsolutePath() + "/kbd/" + folder);
if (!file.exists()) {
file.mkdirs();
}
file = new File(file, filename);
if (file.exists()) {
file.delete();
}
out = new FileOutputStream(file);
while ((n = input.read(b)) != -1) {
out.write(b, 0, n);
}
out.flush();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
if (input != null) {
input.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return file.getAbsolutePath();
}
public static String Upload(String urlStr, String filePath) {
String rsp = "";
HttpURLConnection conn = null;
String BOUNDARY = "|";
try {
URL url = new URL(urlStr);
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(50000);
conn.setReadTimeout(50000);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("User-Agent",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
conn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + BOUNDARY);
OutputStream out = new DataOutputStream(conn.getOutputStream());
File file = new File(filePath);
String filename = file.getName();
String contentType = "";
if (filename.endsWith(".png")) {
contentType = "image/png";
}
if (filename.endsWith(".jpg")) {
contentType = "image/jpg";
}
if (filename.endsWith(".gif")) {
contentType = "image/gif";
}
if (filename.endsWith(".bmp")) {
contentType = "image/bmp";
}
if (contentType == null || contentType.equals("")) {
contentType = "application/octet-stream";
}
StringBuffer strBuf = new StringBuffer();
strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
strBuf.append("Content-Disposition: form-data; name=\"" + filePath
+ "\"; filename=\"" + filename + "\"\r\n");
strBuf.append("Content-Type:" + contentType + "\r\n\r\n");
out.write(strBuf.toString().getBytes());
DataInputStream in = new DataInputStream(new FileInputStream(file));
int bytes = 0;
byte[] bufferOut = new byte[1024];
while ((bytes = in.read(bufferOut)) != -1) {
out.write(bufferOut, 0, bytes);
}
in.close();
byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
out.write(endData);
out.flush();
out.close();
StringBuffer buffer = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(
conn.getInputStream(), "utf-8"));
String line = null;
while ((line = reader.readLine()) != null) {
buffer.append(line).append("\n");
}
rsp = buffer.toString();
reader.close();
reader = null;
} catch (Exception e) {
e.printStackTrace();
rsp = "safkhash";
} finally {
if (conn != null) {
conn.disconnect();
conn = null;
}
}
return rsp;
}
public InputStream getImageData() {
ResultInfo<T> resultData;
InputStream inputStream;
URL url = null;
try {
url = new URL("http://" + mUrlInfo.URL);
if (url != null) {
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(3000);
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setDoInput(true);
int responseCode = httpURLConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
inputStream = httpURLConnection.getInputStream();
} else
inputStream = null;
} else
inputStream = null;
} catch (MalformedURLException e) {
e.printStackTrace();
inputStream = null;
} catch (ProtocolException e) {
e.printStackTrace();
inputStream = null;
} catch (IOException e) {
e.printStackTrace();
inputStream = null;
}
return inputStream;
}
public static String getPath(String fileName) {
File filedir = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/pue/Download/");
if (!filedir.isDirectory())
filedir.mkdirs();
String path = filedir.getPath() + "/" + fileName;
File file = new File(path);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
return path;
}
}
!!!注意:代码中上传下载的写的时间已经比较久远,当时都是可用的,但考虑到Android 在储存这块的限制增加,不敢保证慎用!
接下来就是通过异步将内容返回给视图层; HttpAsyncTask.class
import android.os.AsyncTask;
import java.lang.reflect.Type;
public class HttpAsyncTask<T> {
UrlInfo mUrlInfo;
public static final int HTTP_TYPE_POST = 0;
public static final int HTTP_TYPE_GET = 1;
public HttpAsyncTask(int HTTP_TYPE, UrlInfo mUrlInfo, onResult onResult) {
this.onResult = onResult;
this.mUrlInfo = mUrlInfo;
if (HTTP_TYPE == HTTP_TYPE_GET) {
new getResultAsyncTask().execute();
} else {
new postResultAsyncTask().execute();
}
}
public HttpAsyncTask(int HTTP_TYPE, UrlInfo mUrlInfo, onResult onResult, Type type) {
this.onResult = onResult;
this.mUrlInfo = mUrlInfo;
if (HTTP_TYPE == HTTP_TYPE_GET) {
new getResultAsyncTask().execute(type);
} else {
new postResultAsyncTask().execute(type);
}
}
public HttpAsyncTask(UrlInfo mUrlInfo, onResult onResult) {
this.onResult = onResult;
this.mUrlInfo = mUrlInfo;
}
class getResultAsyncTask extends AsyncTask<Type, Integer, Result> {
@Override
protected Result doInBackground(Type... types) {
HttpClient mHttpClient = new HttpClient<T>(mUrlInfo);
Result result;
if (types != null && types.length > 0)
result = mHttpClient.Get(types[0]);
else
result = mHttpClient.Get(null);
return result;
}
protected void onPostExecute(Result result) {
OnPostExecute(result);
}
}
class postResultAsyncTask extends AsyncTask<Type, Integer, Result> {
@Override
protected Result doInBackground(Type... types) {
HttpClient<T> mHttpClient = new HttpClient(mUrlInfo);
Result result;
if (types != null && types.length > 0)
result = mHttpClient.Post(types[0]);
else
result = mHttpClient.Post(null);
return result;
}
protected void onPostExecute(Result result) {
OnPostExecute(result);
}
}
void OnPostExecute(Result result) {
if (result.isSuccess) {
if (result.getResult() != null) {
if (result.getResult().code == 200 || result.getResult().code == 0) {
onResult.onSuccess(result.getResult().getData());
} else {
onResult.onFail(result.getResultDes());
if (result.getResult().code == 99)
onResult.onTokenError("退出登录");
}
} else {
onResult.onSuccess(result.getResultDes(), null);
}
} else {
onResult.onFail(result.getResultDes());
if (result.getResultDes().contains("登录失效"))
onResult.onTokenError(result.getResultDes());
}
}
public onResult onResult;
public interface onResult<T> {
void onSuccess(T result);
void onFail(String ResultDes);
void onTokenError(String tip);
}
}
好了,接下来就是使用啦 哈哈哈哈哈哈哈,也算一行代码搞定了
UrlInfo mUrlInfo = new UrlInfo();
mUrlInfo.setURL("接口URL");
mUrlInfo.addParams("xxx","xxx");
mUrlInfo.setContentType("application/json;charset=UTF-8");
mUrlInfo.setToken("");
Type type = new TypeToken<Result<ArrayList<taskInfo>>() {
}.getType();
new HttpAsyncTask(HttpAsyncTask.HTTP_TYPE_POST, mUrlInfo, new HttpAsyncTask.onResult<ArrayList<taskInfo>>() {
@Override
public void onSuccess(ArrayList<taskInfo> result) {
}
@Override
public void onFail(String ResultDes) {
}
@Override
public void onTokenError(String tip) {
}
}, type);
对了如果是带页码的数据 还需要做增加一个 Rows.calss
public class Rows<T> {
T data;
int pageNo = 0;
int pageSize = 0;
int records = 0;
int total = 0;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getRecords() {
return records;
}
public void setRecords(int records) {
this.records = records;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
}
好了,代码至此就完了,需要说明的是,代码在拷贝过来的过程中,我有删掉一些自定义的内容,原因是懒得一起贴上来,如果拷贝使用过程中有什么报错的,哈哈哈哈,自己排查一下,应该都是容易解决的。逻辑流程还是比较简单的,分享给大家,也是自己记录一下,当然啦,有不足的地方/更好的方式/需要优化的地方也欢迎大家一起探讨一下;
|