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

相关推荐