RESTFul还是JSON-RPC?
移动API设计大概就分两种RESTFul和JSON-RPC。RESTFul更多适用于对资源类的请求,JSON-RPC适用于功能性的请求。这里我主要说一下我们采用的JSON-RPC(http://www.jsonrpc.org/specification)。
JSON-RPC是一个很简单的协议,网上有很多实现,自己实现也不难。使用JSON-RPC的好处是可以统一API的接口,也就是说所有的API请求接口是一样的。
例如:
curl -X POST -H "Content-Type: application/json" --data '{ "method":"getFoo", "params":{"fooId":888}}' http://localhost/jsonrpc
curl -X POST -H "Content-Type: application/json" --data '{ "method":"createFoo", "params":{"fooId":888}}' http://localhost/jsonrpc
下面是干货
如何取得HTTP POST里的payload?
也就是curl里的--data部分的json参数。
public static String getBody(HttpServletRequest request) throws IOException { String body = null; StringBuilder stringBuilder = new StringBuilder(); BufferedReader bufferedReader = null; try { InputStream inputStream = request.getInputStream(); if (inputStream != null) { bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); char[] charBuffer = new char[128]; int bytesRead = -1; while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { stringBuilder.append(charBuffer, 0, bytesRead); } } else { stringBuilder.append(""); } } catch (IOException ex) { throw ex; } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException ex) { throw ex; } } } body = stringBuilder.toString(); return body; }
参见
http://stackoverflow.com/questions/14525982/getting-request-payload-from-post-request-in-java-servlet
拿到json data检查是否符合JSON-RPC 2.0的规范。然后拿到method和params去调用相应的server端service
如何认证
认证有有两种方式:token base,每次请求都把username和password放到http header中。session base,先走一个login接口,server端返回sessionid给client,client每次请求都带着这个sessionid。下面是token base的实例代码
curl -X POST -H "Content-Type: application/json" -H "Authorization: Basic emhhbmd3OmNoYW5nZW1l" --data '{ "method":"rhhGetFoo", "params":{"fooId":888}}' http://localhost/jsonrpc
这里的"emhhbmd3OmNoYW5nZW1l"是把"zhangw:changeme"进行了Base64 encoded
String authzHeader = request.getHeader("Authorization") if (authzHeader && authzHeader.substring(0, 6).equals("Basic ")) { String basicAuthEncoded = authzHeader.substring(6).trim() String basicAuthAsString = new String(basicAuthEncoded.decodeBase64()) if (basicAuthAsString.indexOf(":") > 0) { String username = basicAuthAsString.substring(0, basicAuthAsString.indexOf(":")) String password = basicAuthAsString.substring(basicAuthAsString.indexOf(":") + 1) //TODO do your login here } else { logger.warn("For HTTP Basic Authorization got bad credentials string. Base64 encoded is [${basicAuthEncoded}] and after decoding is [${basicAuthAsString}].") } }
如何做版本管理
移动APP无论是client端还是server端都需要不断升级,可是如果server端的API由于升级被修改了,导致就得clien APP不能用咋办?扩展JSON-RPC,举例:
request json : {"method": "getFoo", "params":{"fooId":888}, "id": "123", "client": {"version": "v1","platform": "android/1"}}
resonpse json:{"result":[],"server":{"version": "v1", "identifier": "12afd=3uy8"}}