最近做一个项目涉及到移动部分,这里我把研究的结果给大家分享一下。由于时间仓促,水平有限,如果大家看后有任何不适请自行吃药:)
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"}}