Android HTTP通訊封裝(包括WebService的呼叫)
阿新 • • 發佈:2018-11-08
第一個物件:
該物件是呼叫WebService用的一個物件基類。
package Entity; import com.google.gson.Gson; import org.json.JSONObject; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * Created by 王彥鵬 on 2017-09-01. */ public class BaseEnity { public String toString() { Gson gson=new Gson(); return gson.toJson(this); } public void LoadJson(String jsonStr) { try { JSONObject json = new JSONObject(jsonStr); Field[] field = this.getClass().getDeclaredFields(); // 獲取實體類的所有屬性,返回Field陣列 for (int j = 0; j < field.length; j++) { // 遍歷所有屬性 String name = field[j].getName(); // 獲取屬性的名字 name = name.substring(0, 1).toUpperCase() + name.substring(1); // 將屬性的首字元大寫,方便構造get,set方法 // // 獲取屬性的型別 try { if (!name.equals("$change") && !name.equals("SerialVersionUID")){ Method m = this.getClass().getMethod("set" + name, field[j].getType()); String type = field[j].getType().getName();// getGenericType().toString(); switch (type) { case "byte": { m.invoke(this, (byte)json.getInt(field[j].getName())); break; } case "int": { m.invoke(this, json.getInt(field[j].getName())); break; } case "char": { m.invoke(this, json.getString(field[j].getName()).charAt(0)); break; } case "String": { m.invoke(this, json.getString(field[j].getName())); break; } case "boolean": { m.invoke(this, json.getBoolean(field[j].getName())); break; } case "double": { m.invoke(this, json.getDouble(field[j].getName())); break; } case "long": { m.invoke(this, json.getLong(field[j].getName())); break; } default: { m.invoke(this, json.get(field[j].getName())); break; } } } } catch (Exception e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } } public Object getPropertyValue(String PName) throws Exception { Field[] fields = this.getClass().getDeclaredFields(); // 獲取實體類的所有屬性,返回Field陣列 for (Field field : fields) { if (field.getName().equalsIgnoreCase(PName)) { String name = field.getName(); // 獲取屬性的名字 name = name.substring(0, 1).toUpperCase() + name.substring(1); // 將屬性的首字元大寫,方便構造get,set方法 Method m = this.getClass().getMethod("get" + name); return m.invoke(this); } } return null; } }
第二個物件:
該物件是Http通訊物件的介面封裝。
package Interface; import org.json.JSONObject; import Entity.BaseEnity; /** * Created by 王彥鵬 on 2017/9/28. */ public interface IHttp extends IInterface { String Get(String url) throws Exception; String Post(String url, String postData) throws Exception; void Post(String url, String postData,IAsynCallBackListener callback) throws Exception; String Post(String url, String postData,IAsynCallBackListener callback,String contentType) throws Exception; JSONObject CallWebService(String url, String IName, BaseEnity... entity) throws Exception; String Get(String url,IAsynCallBackListener callback) throws Exception; void CallWebService(String url, String IName,IAsynCallBackListener callback, BaseEnity... entity) throws Exception; }
第三個物件是IHttp介面的實現,是Http通訊的核心部分:
package Helper; import android.accounts.NetworkErrorException; import android.support.annotation.NonNull; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import Annotation.*; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.HttpURLConnection; import java.net.SocketTimeoutException; import java.net.URL; import java.util.List; import java.util.concurrent.TimeoutException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; //import Const.PublicDefine; import Entity.BaseEnity; import Interface.IAsynCallBackListener; import Interface.IHttp; import Helper.Log; /** * Created by 王彥鵬 on 2017-09-02. */ class HttpAsynResponseData { private String response=""; private Throwable exception; public String getResponse() { return response; } public void setResponse(String response) { this.response = response; } public Throwable getException() { return exception; } public void setException(Throwable exception) { this.exception = exception; } } public class Http implements IHttp { /** * 用Get方式請求伺服器 * * @param url url 地址 * @param contentType 請求資料型別 * @return 伺服器返回的資料 */ @NonNull private String httpMethod(String url, String contentType, String method, String postData) throws Exception { HttpURLConnection conn = null; try { long t1,t2=0; t1=System.currentTimeMillis(); URL murl = new URL(url); //1.得到HttpURLConnection例項化物件 conn = (HttpURLConnection) murl.openConnection(); //2.設定請求資訊(請求方式... ...) //設定請求方式和響應時間 conn.setRequestMethod(method); conn.setRequestProperty("Content-Type", contentType); conn.setRequestProperty("Content-Length", String.valueOf(postData.getBytes().length)); conn.setRequestProperty("encoding", "UTF-8"); //可以指定編碼 conn.setConnectTimeout(5000); conn.setReadTimeout(5000); //不使用快取 conn.setUseCaches(false); // 設定可取 conn.setDoInput(true); // 設定可讀 conn.setDoOutput(true); if (method.toUpperCase() == "POST") { //4.向伺服器寫入資料 conn.getOutputStream().write(postData.getBytes()); } //3.讀取響應 if (conn.getResponseCode() == 200) { InputStream in = conn.getInputStream(); // 建立高效流物件 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); // 建立StringBuilder物件儲存資料 StringBuilder response = new StringBuilder(); String line;// 一次讀取一行 while ((line = reader.readLine()) != null) { response.append(line);// 得到的資料存入StringBuilder } t2= System.currentTimeMillis(); Log.write("Http",String.format("%s 請求(%s)\r\nUrl:%s\r\n請求資料:%s\r\n返回資料:%s\r\n請求用時:%3f", method,contentType,url,postData, response.toString(),(t2-t1)/Double.valueOf(1000))); return response.toString(); } else { Log.write("Http",String.format("%s 請求(%s):%s\r\n請求失敗。",method,contentType,url)); throw new Exception("請求失敗"); } } catch (TimeoutException e) { Log.write("Http",String.format("%s 請求(%s):%s\r\n連線超時。",method,contentType,url)); throw new Exception("請求超時或網路已斷開。"); }catch (SocketTimeoutException e) { throw new Exception("請求超時或網路已斷開。"); } catch (NetworkErrorException e) { throw new Exception("網路斷開"); } catch (Exception e) { Log.write("Http",String.format("%s 請求(%s):%s\r\n請求異常:%s",method,contentType,url,e.getMessage())); e.printStackTrace(); if(e.getMessage().indexOf("Network is unreachable")>=0) { throw new Exception("網路斷開"); } else { throw e; } } finally { //4.釋放資源 if (conn != null) { //關閉連線 即設定 http.keepAlive = false; conn.disconnect(); } } } /** * 用Get方式請求伺服器 * * @param url url 地址 * @param callback 非同步回撥地址,當不為null時為非同步呼叫 * @param contentType 請求資料型別 * @return 伺服器返回的資料 */ public String Get(final String url, final String contentType, final IAsynCallBackListener callback) throws Exception { if (callback == null) { return httpMethod(url, contentType, "GET", ""); } else { new Thread(new Runnable() { @Override public void run() { try { String httpResponse = httpMethod(url, contentType, "GET", ""); // 回撥onFinish()方法 callback.onFinish("",httpResponse); } catch (Exception e) { // 回撥onError()方法 callback.onError(this,e); } } }).start(); return ""; } } /** * 用Get方式請求伺服器 * * @param url 網路地址 * @return */ public String Get(final String url) throws Exception { final Object synObj = new Object(); final HttpAsynResponseData res = new HttpAsynResponseData(); Thread getthread = new Thread(new Runnable() { @Override public void run() { synchronized (synObj) { try { res.setResponse(Get(url, "application/x-www-form-urlencoded", null)); res.setException(null); } catch (Exception e) { e.printStackTrace(); res.setException(e); } synObj.notify(); } } }); getthread.start(); try { //Thread.sleep(1); synchronized (synObj) { synObj.wait(); if (res.getException()==null) { return res.getResponse(); } else { throw new Exception(res.getException()); } } //return res[0]; } catch (Exception e) { throw new Exception(e); } } /** * 用 Post 方式請求伺服器 * * @param url 網路地址 * @param postData 提交資料 * @param callback 回撥地址 * @param contentType 請求資料型別 * @return 伺服器返回資料 */ public String Post(final String url, final String postData, final IAsynCallBackListener callback, final String contentType) throws Exception { if (callback == null) { return httpMethod(url, contentType, "POST", postData); } else { new Thread(new Runnable() { @Override public void run() { try { String httpResponse = httpMethod(url, contentType, "POST", postData); // 回撥onFinish()方法 callback.onFinish("",httpResponse); } catch (Exception e) { // 回撥onError()方法 callback.onError(this,e); } } }).start(); return ""; } } /** * 用 Post 方式請求伺服器 * * @param url 網路地址 * @param postData 提交資料 * @return */ public String Post(final String url, final String postData) throws Exception { final Object synObj = new Object(); final String[] res = {""}; Thread getthread = new Thread(new Runnable() { @Override public void run() { synchronized (synObj) { try { res[0] = Post(url, postData,null,"application/x-www-form-urlencoded"); } catch (Exception e) { e.printStackTrace(); res[0]=e.getMessage(); } synObj.notify(); } } }); getthread.start(); try { //Thread.sleep(1); synchronized (synObj) { synObj.wait(); return res[0]; } //return res[0]; } catch (Exception e) { throw new Exception(res[0]); } } @Override public void Post(String url, String postData, IAsynCallBackListener callback) throws Exception { Post(url, postData,callback,"application/x-www-form-urlencoded"); } /** * 用 Post 方式請求伺服器 * * @param url 網路地址 * @param postData 提交資料 * @return */ public String Post(final String url, final String postData, final String contentType) throws Exception { if (!PublicDefine.NetworkConnState) { throw new Exception("網路連線已斷開,請先檢查網路。"); } final Object synObj = new Object(); final String[] res = {""}; Thread getthread = new Thread(new Runnable() { @Override public void run() { synchronized (synObj) { try { res[0] = Post(url, postData,null,contentType); } catch (Exception e) { e.printStackTrace(); res[0]=e.getMessage(); } synObj.notify(); } } }); getthread.start(); try { //Thread.sleep(1); synchronized (synObj) { synObj.wait(); return res[0]; } //return res[0]; } catch (Exception e) { return res[0]; } } private static JSONObject LoadNodeChild(Node node) throws JSONException { JSONObject json = new JSONObject(); for (int i = 0; i < node.getChildNodes().getLength(); i++) { Node subnode=node.getChildNodes().item(i); String key =subnode.getNodeName(); Object value = null; if (subnode.hasChildNodes()&& (!subnode.getChildNodes().item(0).getNodeName().equals("#text"))) { value = LoadNodeChild(subnode); } else { value = subnode.getTextContent(); } if (json.has(key)){ Object oldJson = json.get(key); if (oldJson instanceof JSONObject){ JSONArray jsonArray = new JSONArray(); jsonArray.put(oldJson); jsonArray.put(value); json.remove(key); json.put(key, jsonArray); }else{ ((JSONArray)oldJson).put(value); json.put(key,oldJson); } }else{ json.put(key, value); } } return json; } private static String GetPropertyName(Field f) { PropertyName pname = f.getAnnotation(PropertyName.class); if (pname==null) { return f.getName(); } else { return pname.value(); } } private static String GetKeyValue(BaseEnity enity) throws Exception { String values = ""; Field[] field = enity.getClass().getDeclaredFields(); // 獲取實體類的所有屬性,返回Field陣列 for (int j = 0; j < field.length; j++) { // 遍歷所有屬性 String name = field[j].getName(); // 獲取屬性的名字 name = name.substring(0, 1).toUpperCase() + name.substring(1); // 將屬性的首字元大寫,方便構造get,set方法 try { Method m = enity.getClass().getMethod("get" + name); Object instance = m.invoke(enity); if (instance.getClass().getSimpleName().equals("ArrayList")){ for (int i = 0; i < ((List)instance).size(); i++) { if (((List) instance).get(i).getClass().getSuperclass().getSimpleName().equals("BaseEnity")) { values += "<" + GetPropertyName(field[j]) + ">" + GetKeyValue((BaseEnity) ((List) instance).get(i)) + "</" + GetPropertyName(field[j]) + ">\n"; } else { values += "<" + GetPropertyName(field[j]) + ">" + ((List) instance).get(i).toString() + "</" + GetPropertyName(field[j]) + ">\n"; } } }else if (instance.getClass().getSuperclass().getSimpleName().equals("BaseEnity")) { values += "<" + GetPropertyName(field[j]) + ">" + GetKeyValue((BaseEnity) instance) + "</" + GetPropertyName(field[j]) + ">\n"; } else { values += "<" + GetPropertyName(field[j]) + ">" + instance.toString() + "</" + GetPropertyName(field[j]) + ">\n"; } } catch (Exception e) { } } return values; } /** * 呼叫WebService介面 * * @param IName * @param args * @return */ public JSONObject CallWebService(String url, String IName, BaseEnity... args) throws Exception { String pdata = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" + /*"<soap:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""+*/ " <soap:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" >\n" + "<%s xmlns=\"http://tempuri.org/\">\n"; if (args!=null) { for (BaseEnity entity:args ) { pdata+=GetKeyValue(entity); } } pdata += "</%s>\n" + " </soap:Body>\n" + "</soap:Envelope>"; pdata = String.format(pdata, IName, IName); String resxml = Post(url, pdata,"text/xml"); DocumentBuilderFactory xml = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = xml.newDocumentBuilder(); Document dom = builder.parse(new InputSource(new ByteArrayInputStream(resxml.getBytes("utf-8")))); Element root = dom.getDocumentElement(); NodeList items = root.getElementsByTagName(IName + "Response");//查詢所有person節點 Node response = items.item(0); JSONObject resJson = LoadNodeChild(response); return resJson; } @Override public String Get(String url, IAsynCallBackListener callback) throws Exception { return Get(url,"application/x-www-form-urlencoded",callback); } @Override public void CallWebService(String url, final String IName, final IAsynCallBackListener callback, BaseEnity... args) throws Exception { String pdata = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" + /*"<soap:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""+*/ " <soap:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" >\n" + "<%s xmlns=\"http://tempuri.org/\">\n"; if (args!=null) { for (BaseEnity entity:args ) { pdata+=GetKeyValue(entity); } } pdata += "</%s>\n" + " </soap:Body>\n" + "</soap:Envelope>"; pdata = String.format(pdata, IName, IName); Post(url, pdata, new IAsynCallBackListener() { @Override public void onFinish(Object sender,Object data) { try { String resxml = data.toString(); DocumentBuilderFactory xml = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = xml.newDocumentBuilder(); Document dom = builder.parse(new InputSource(new ByteArrayInputStream(resxml.getBytes("utf-8")))); Element root = dom.getDocumentElement(); NodeList items = root.getElementsByTagName(IName + "Response");//查詢所有person節點 Node response = items.item(0); JSONObject resJson = LoadNodeChild(response); callback.onFinish("",resJson); } catch (Exception e) { } } @Override public void onError(Object sender, Exception e) { callback.onError(this,e); } }, "text/xml"); } }