移动API设计的一些心得
最近做一个项目涉及到移动部分,这里我把研究的结果给大家分享一下。由于时间仓促,水平有限,如果大家看后有任何不适请自行吃药:)
RESTFul还是JSON-RPC?
移动API设计大概就分两种RESTFul和JSON-RPC。RESTFul更多适用于对资源类的请求,JSON-RPC适用于功能性的请求。这里我主要说一下我们采用的JSON-RPC(http://www.jsonrpc.org/specification)。
JSON-RPC是一个很简单的协议,网上有很多实现,自己实现也不难。使用JSON-RPC的好处是可以统一API的接口,也就是说所有的API请求接口是一样的。
例如:
curl-XPOST-H"Content-Type:application/json"--data'{"method":"getFoo","params":{"fooId":888}}'http://localhost/jsonrpc
curl-XPOST-H"Content-Type:application/json"--data'{"method":"createFoo","params":{"fooId":888}}'http://localhost/jsonrpc
下面是干货
如何取得HTTPPOST里的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
拿到jsondata检查是否符合JSON-RPC2.0的规范。然后拿到method和params去调用相应的server端service
如何认证
认证有有两种方式:tokenbase,每次请求都把username和password放到httpheader中。sessionbase,先走一个login接口,server端返回sessionid给client,client每次请求都带着这个sessionid。下面是tokenbase的实例代码
curl-XPOST-H"Content-Type:application/json"-H"Authorization:Basicemhhbmd3OmNoYW5nZW1l"--data'{"method":"rhhGetFoo","params":{"fooId":888}}'http://localhost/jsonrpc
这里的"emhhbmd3OmNoYW5nZW1l"是把"zhangw:changeme"进行了Base64encoded
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由于升级被修改了,导致就得clienAPP不能用咋办?扩展JSON-RPC,举例:
requestjson:{"method":"getFoo","params":{"fooId":888},"id":"123","client":{"version":"v1","platform":"android/1"}}
resonpsejson:{"result":[],"server":{"version":"v1","identifier":"12afd=3uy8"}}