移动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 -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"}}

猜你喜欢

转载自tzngvi.iteye.com/blog/2093183