目的:一份代碼運行三處, ios , android ,web 。通訊底層也共用。react-web使用的http請求是 JSONP,他的特點是: 只能發 get 請求,並且服務端要配合將請求回來的 callback 欄位帶回來。
用戶端實現方案:
將 post 請求內容 base64 放到 url 裡面
var fetch = Platform.OS === 'web'? require('ReactJsonp'): require('ReactFetch');post(url, body) { let fetchOptions = { method: 'POST', deadline: kDeadline, timeout: kDeadline, headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'uutype': AppGlobal.uutype, 'latitude': AppGlobal.latitude, 'longitude': AppGlobal.longitude, 'token': AppGlobal.userToken, }, body: JSON.stringify(body) } console.log('請求包頭是=='+JSON.stringify(fetchOptions)); if (Platform.OS === 'web') { // Check if the user set their own params, and if not add a ? to start a list of params url += url.indexOf('?') === -1 ? '?' : '&'; //把參數放置到 url 裡面 var optString = JSON.stringify(fetchOptions); var options = new Buffer(optString).toString("base64"); url += 'options='+options; } return fetch(url, fetchOptions) .then(res=>{ try { console.log('post method res = ' + JSON.stringify(res)); return res.json(); } catch (e) { return parseError; } }, (res)=> { console.log(`request rejected ${res}`); throw res; }) }
服務端方案:
1.支援JSONP
public static void renderJsonporJson(HttpServletResponse response,final String callbackName, final Object object, final String... headers){if (callbackName!=null&&!callbackName.equals("")){renderJsonp(response, callbackName, object, headers);}else {renderJson(response, object, headers);}}
2.支援POST內容放到URL裡面的解碼
流程是:修改 DispatchController 為自訂,然後在自訂類裡面改寫 httpservletrequest ,解碼 url 裡面的 post 內容,然後把內容填寫到新的 request 的 head 和 body 裡面去。
public class CustomDispatch extends DispatcherServlet {@Autowiredprotected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {System.out.println("CustomDispatch --------- doDispatch ");String option = request.getParameter("options");if(option != null){//為JSONP請求特殊處理,修改 request 的內容(因為 jsonp 只能 get請求)//System.out.println("CustomDispatch --------- doDispatch options options");HashMap m=new HashMap(request.getParameterMap());//取出參數 base64解碼byte[] b = Encodes.decodeBase64(option);String jsonOption = new String(b); //替換 requestHttpServletRequest req = (HttpServletRequest) request; HttpRequestChangeable wrapRequest=new HttpRequestChangeable(req,m,jsonOption); request=wrapRequest; //這是rquest就和本身的request一樣了 }else{ }super.doDispatch(request, response);}}
package com.defa.tcm.common.customDispatch;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import javax.servlet.ServletRequest; public class HttpHelper { /** * 擷取請求Body * * @param request * @return */ public static String getBodyString(ServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = request.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } }
@SuppressWarnings("unchecked") public class HttpRequestChangeable extends HttpServletRequestWrapper { private Map params; private final byte[] body; private final HashMap headersHash;private final List headKey; public HttpRequestChangeable(HttpServletRequest request, Map newParams,String postContent) { super(request); this.params = newParams; JSONObject jsonObj = JSONObject.fromObject(postContent); String bodyStr = jsonObj.getString("body");String headers = jsonObj.getString("headers");JSONObject jsonHead = JSONObject.fromObject(headers);headersHash = new HashMap();parserToMap(headers,headersHash ); //列印 head// Enumeration e = request.getHeaderNames() ; // while(e.hasMoreElements()){ // String name = (String) e.nextElement(); // String value = request.getHeader(name); // System.out.println(name+" = "+value); // // } //設定 head key headKey = new ArrayList(); Iterator keys=jsonHead.keys(); while(keys.hasNext()){ String key=(String) keys.next(); if(key != "body"){ headKey.add(key); } } //設定 head 和 body body = bodyStr.getBytes(Charset.forName("UTF-8")); // body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8")); } public Map getParameterMap() { return params; } public Enumeration getParameterNames() { Vector l = new Vector(params.keySet()); return l.elements(); } public String[] getParameterValues(String name) { Object v = params.get(name); if (v == null) { return null; } else if (v instanceof String[]) { return (String[]) v; } else if (v instanceof String) { return new String[] { (String) v }; } else { return new String[] { v.toString() }; } } public String getParameter(String name) { Object v = params.get(name); if (v == null) { return null; } else if (v instanceof String[]) { String[] strArr = (String[]) v; if (strArr.length > 0) { return strArr[0]; } else { return null; } } else if (v instanceof String) { return (String) v; } else { return v.toString(); } } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public int read() throws IOException { return bais.read(); }@Overridepublic boolean isFinished() {if(bais.available() == 0){return true;}return false;}@Overridepublic boolean isReady() {if(bais.available() > 0){return true;}return false;}@Overridepublic void setReadListener(ReadListener readListener) {// TODO Auto-generated method stub} }; } @Override public String getHeader(String name) { return (String) headersHash.get(name);// return super.getHeader(name); } @Override public Enumeration<String> getHeaderNames() { return new Enumeration(){ int count = headKey.size(); int curIndex = 0;@Overridepublic boolean hasMoreElements() {if(curIndex < count){return true;}return false;}@Overridepublic Object nextElement() {if(curIndex < count){Object res = headKey.get(curIndex++);return res;}return null;} };// return super.getHeaderNames(); } @Override public Enumeration<String> getHeaders(final String name) { return new Enumeration(){ int count = 1; int curIndex = 0;@Overridepublic boolean hasMoreElements() {if(curIndex < count){return true;}return false;}@Overridepublic Object nextElement() {if(curIndex < count){curIndex++;return headersHash.get(name);}return null;} };// return super.getHeaders(name); } //public static Map parserToMap(String s,Map initMap){ Map map= initMap; if(map == null){ map = new HashMap(); } JSONObject json=JSONObject.fromObject(s); Iterator keys=json.keys(); while(keys.hasNext()){ String key=(String) keys.next(); String value=json.get(key).toString(); if(value.startsWith("{")&&value.endsWith("}")){ map.put(key, parserToMap(value,null)); }else{ map.put(key, value); } } return map; } public static final byte[] readBytes(InputStream is, int contentLen) {if (contentLen > 0) {int readLen = 0;int readLengthThisTime = 0;byte[] message = new byte[contentLen];try {while (readLen != contentLen) {readLengthThisTime = is.read(message, readLen, contentLen - readLen);if (readLengthThisTime == -1) {// Should not happen.break;}readLen += readLengthThisTime;}return message;} catch (IOException e) {// Ignore// e.printStackTrace();}}return new byte[] {};} }