赞
踩
现在开源的http请求库有很多,但是呢,有时候总有些不合适的地方,然后呢我就自己摸索的一套异步http请求处理机制;
1:get/post 请求
2:多种方式携带token,并有token过期、失效等处理机制;
3:使用简单,几行代码搞定一个请求,只需专注业务实现;
话不多说,直接上代码
1:首先是创建几个实体类,用于接收请求的结果以及内容
Result.calss :请求的结果的实体类
/** * isSuccess;//返回结果,基于本地的判断 * resultDes;//返回结果描述(错误描述),基于本地的判断 * * @param <T>服务器返回的内容 */ public class Result<T> implements java.io.Serializable { public Boolean isSuccess; public T result; public String resultDes; public Boolean getSuccess() { return isSuccess; } public void setSuccess(Boolean success) { isSuccess = success; } public T getResult() { return result; } public void setResult(T 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;//查询结果状态码,例如200:成功 201:失败 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(); } }
对了如果是带页码的数据
还需要做增加一个
ResultPage.calss
public class ResultPage<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; } }
URL及配置等实体类
UrlDetails.calss
public class UrlDetails { String URL = ""; String ContentType = null; 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
public class HttpClient { // http连接对象 private HttpURLConnection urlConn; Result mResultInfo; String TAG = "HttpClient"; UrlDetails mUrlInfo; Type mType; public HttpClient(UrlDetails urlInfo) { mUrlInfo = urlInfo; LogOut.i(TAG, urlInfo.getURL() + (urlInfo.getParams() != null && !urlInfo.getParams().equals("") ? "?" + urlInfo.getParams() : "")); } public HttpClient(UrlDetails urlInfo, Type type) { mUrlInfo = urlInfo; LogOut.i(TAG, urlInfo.getURL() + (urlInfo.getParams() != null && !urlInfo.getParams().equals("") ? "?" + urlInfo.getParams() : "")); mType = type; if (mType != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { LogOut.i(TAG, mType.getTypeName()); } } public Result Get() { mResultInfo = new Result(); BufferedReader reader = null; InputStream in = null; try { URL url = new URL(mUrlInfo.URL + "?" + mUrlInfo.params); urlConn = (HttpURLConnection) url.openConnection(); urlConn.setRequestMethod("GET"); urlConn.setReadTimeout(httpConfig.ReadTimeout); urlConn.setConnectTimeout(httpConfig.ConnectTimeout); if (!httpConfig.SESSION.equals("")) { urlConn.setRequestProperty("Cookie", httpConfig.SESSION); } if (mUrlInfo.ContentType != null && !mUrlInfo.ContentType.equals("")) urlConn.setRequestProperty("Content-Type", mUrlInfo.ContentType); 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()) { httpConfig.SESSION = cookies.get(0).split(";")[0]; if (cookies.get(1).split(";")[0].contains("SESSION")) httpConfig.SESSION = httpConfig.SESSION + ";" + cookies.get(1).split(";")[0]; //LogOut.i(TAG, "SESSION:" + httpConfig.SESSION); } // 得到读取的内容 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) { if (mType == null) { mResultInfo.setResultDes(bSt.substring(1)); } else { try { Gson gson = new Gson(); mResultInfo.setResult(gson.fromJson(bSt.substring(1), mType)); mResultInfo.setSuccess(true); } catch (JsonSyntaxException tx) { mResultInfo.setResult(null); mResultInfo.setSuccess(false); mResultInfo.setResultDes("数据解析错误"); } } } else { mResultInfo.setSuccess(false); mResultInfo.setResultDes("服务器返回为空"); } } else { mResultInfo.setSuccess(false); mResultInfo.setResultDes("服务器无返回"); } } else { mResultInfo.setSuccess(false); mResultInfo.setResultDes("服务器返回:" + urlConn.getResponseCode()); } } catch (SocketTimeoutException tx) { mResultInfo.setSuccess(false); mResultInfo.setResultDes("网络连接超时"); } catch (Exception ex) { mResultInfo.setSuccess(false); mResultInfo.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(); } } if (urlConn != null) LogOut.i(TAG, urlConn.getURL().toString() + "\n" + mResultInfo.getResultDes()); return mResultInfo; } /** * http请求 <功能详细描述> * * @throws Exception */ public Result Post() { mResultInfo = new Result(); BufferedReader reader = null; InputStream in = null; try { URL url = new URL(mUrlInfo.URL); urlConn = (HttpURLConnection) url.openConnection(); //允许读入 urlConn.setDoInput(true); urlConn.setRequestMethod("POST"); urlConn.setReadTimeout(httpConfig.ReadTimeout); urlConn.setConnectTimeout(httpConfig.ConnectTimeout); if (!httpConfig.SESSION.equals("")) { urlConn.setRequestProperty("Cookie", httpConfig.SESSION); } if (mUrlInfo.ContentType != null && !mUrlInfo.ContentType.equals("")) urlConn.setRequestProperty("Content-Type", mUrlInfo.ContentType); // 设置提交内容 if (mUrlInfo.params != null && mUrlInfo.params.length() != 0) { //方法一 // byte[] bypes = mUrlInfo.params.toString().getBytes("UTF-8"); // urlConn.getOutputStream().write(bypes);// 输入参数 //方法二 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()) { httpConfig.SESSION = cookies.get(0).split(";")[0]; LogOut.i(TAG, "SESSION:" + httpConfig.SESSION); } // 得到读取的内容 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) { if (mType != null) try { Gson gson = new Gson(); mResultInfo.setResult(gson.fromJson(bSt.substring(1), mType)); mResultInfo.setSuccess(true); } catch (JsonSyntaxException tx) { mResultInfo.setResult(null); mResultInfo.setSuccess(false); mResultInfo.setResultDes("数据解析错误"); LogOut.i(TAG, "数据解析错误"); } else { mResultInfo.setResultDes(bSt.toString().substring(1)); } } else { mResultInfo.setSuccess(false); mResultInfo.setResultDes("服务器返回为空"); } } else { mResultInfo.setSuccess(false); mResultInfo.setResultDes("服务器无响应"); } } else { mResultInfo.setSuccess(false); mResultInfo.setResultDes("服务器返回:" + urlConn.getResponseCode()); } } catch (SocketTimeoutException tx) { mResultInfo.setSuccess(false); mResultInfo.setResultDes("网络连接超时"); } catch (Exception ex) { mResultInfo.setSuccess(false); mResultInfo.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(); } } if (urlConn != null) LogOut.i(TAG, urlConn.getURL().toString() + "\n" + mUrlInfo.getParams() + "\n" + mResultInfo.getResultDes()); return mResultInfo; } /** * 1:使用前需要申请权限 * 2:使用前请声明文件操作路径 * * @return */ public Result Download() { String fileName = mUrlInfo.URL.substring(mUrlInfo.URL.lastIndexOf("/") + 1); mResultInfo = new Result(); InputStream input = null; OutputStream out = null; File file; try { URL url = new URL(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(); mResultInfo.setSuccess(true); mResultInfo.setResultDes("下载成功,文件路径:" + file.getAbsolutePath()); } catch (Exception e) { e.printStackTrace(); mResultInfo.setSuccess(false); mResultInfo.setResultDes("下载失败"); return mResultInfo; } finally { try { if (input != null) { input.close(); } if (out != null) { out.close(); } } catch (IOException e) { e.printStackTrace(); } } return mResultInfo; } /** * 下载指定路径下的文件 * * @param context * @param path * @param filename * @return */ 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(); } /** * 文件上传 * * @param urlStr 接口路径 * @param filePath 本地图片路径 * @return */ public static String Upload(String urlStr, String filePath) { String rsp = ""; HttpURLConnection conn = null; String BOUNDARY = "|"; // request头和上传文件内容分隔符 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("Cookie", httpConfig.JSESSIONID // + (httpConfig.account != null ? "; userNo=" + httpConfig.account // : "") + "; password="); 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; } // 获取app下载路径 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; } }
接下来就是通过异步请求数据,并将内容返回给业务层;
HttpAsyncTask.class
public class HttpsAsyncTask { UrlDetails mUrlInfo; public static final int HTTP_TYPE_POST = 0; public static final int HTTP_TYPE_GET = 1; /** * 此方法返回的数据类型为String * * @param HTTP_TYPE * @param mUrlInfo * @param onResult */ public HttpsAsyncTask(int HTTP_TYPE, UrlDetails mUrlInfo, onResult onResult) { this.onResult = onResult; this.mUrlInfo = mUrlInfo; if (HTTP_TYPE == HTTP_TYPE_GET) { new getResultAsyncTask().execute(); } else { new postResultAsyncTask().execute(); } } /** * 此方法返回的数据类型可指定 * * @param HTTP_TYPE * @param mUrlInfo * @param onResult:返回数据实体类1:判断网络返回 2:返回数据 * @param type:指定返回数据类型 */ public HttpsAsyncTask(int HTTP_TYPE, UrlDetails 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); } } class getResultAsyncTask extends AsyncTask<Type, Integer, Result> { @Override protected Result doInBackground(Type... types) { Result result; if (types != null && types.length > 0) result = new HttpClient(mUrlInfo, types[0]).Get(); else result = new HttpClient(mUrlInfo).Get(); return result; } protected void onPostExecute(Result result) { if (result.isSuccess) {//本地请求是否成功; if (result.getResult() != null) {//服务器查询返回是否是规范化的内容,是则优先判断返回内容规范正确性 onResult.onSuccess(result.getResult()); } else {//未指定返回类型则将返回的内容以String方式返回交由Presenter处理 onResult.onSuccess(result.getResultDes()); } } else { onResult.onFail(result.getResultDes()); } } } class postResultAsyncTask extends AsyncTask<Type, Integer, Result> { @Override protected Result doInBackground(Type... types) { Result result; if (types != null && types.length > 0) result = new HttpClient(mUrlInfo, types[0]).Post(); else result = new HttpClient(mUrlInfo).Post(); return result; } protected void onPostExecute(Result result) { if (result.isSuccess) {//本地请求是否成功; if (result.getResult() != null) {//服务器查询返回是否是规范化的内容,是则优先判断返回内容规范正确性 onResult.onSuccess(result.getResult()); } else {//未指定返回类型则将返回的内容以String方式返回交由Presenter处理 onResult.onSuccess(result.getResultDes()); } } else { onResult.onFail(result.getResultDes()); } } } public onResult onResult; public interface onResult<T> { void onSuccess(T result); void onFail(String ResultDes); } }
接下来就是使用啦
UrlDetails mUrlInfo = new UrlDetails(); mUrlInfo.setURL(appApi.queryInfuxdb()); //添加参数方式一 mUrlInfo.addParams("参数一", ""); mUrlInfo.addParams("参数二", ""); //添加参数方式二 //mUrlInfo.setParams("参数=参数内容&参数=参数内容"); Type type = new TypeToken<Result<DataEntity>>() { }.getType(); new HttpsAsyncTask(HttpAsyncTask.HTTP_TYPE_GET, mUrlInfo, new HttpsAsyncTask.onResult<Result<DataEntity>>() { @Override public void onSuccess(Result<DataEntity> result) {//处理返回的内容 } } @Override public void onFail(String ResultDes) {//处理请求报错 } }, type);
好了,代码至此就完了,需要说明的是,代码在拷贝过来的过程中,我有删掉一些自定义的内容,原因是懒得一起贴上来,如果拷贝使用过程中有什么报错的,哈哈哈哈,自己排查一下,应该都是容易解决的。逻辑流程还是比较简单的,分享给大家,也是自己记录一下,当然啦,有不足的地方/更好的方式/需要优化的地方也欢迎大家一起探讨一下;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。