diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e3d3337 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# IDEA files +.idea +*.iml +spring-shell.log diff --git a/doc/.DS_Store b/doc/.DS_Store new file mode 100644 index 0000000..6b8bebd Binary files /dev/null and b/doc/.DS_Store differ diff --git a/doc/download.md b/doc/download.md index 901db29..2e02a86 100644 --- a/doc/download.md +++ b/doc/download.md @@ -2,7 +2,6 @@ 文件名|描述|版本|__ --- | ---| --- | --- -JavaBaas|服务端程序及命令行工具|1.0.0|[下载](http://7xr649.dl1.z0.glb.clouddn.com/JavaBaas.zip) -Android_SDK|AndroidSDK|1.0.0|下载 -iOS_SDK|iosSDK(ObjectiveC)|1.0.0|下载 -JS_SDK|jsSDK|1.0.0|下载 \ No newline at end of file +JavaBaasServer|服务端程序|2.0.0|[下载](http://7xr649.dl1.z0.glb.clouddn.com/JavaBaasServer_v2.0.0.zip) +JavaBaasShell [Windows]|命令行工具|2.0.0|[下载](http://7xr649.dl1.z0.glb.clouddn.com/shell-2.0.0.jar) +JavaBaasShell [mac/linux]|命令行工具|2.0.0|[下载](http://7xr649.dl1.z0.glb.clouddn.com/shell-2.0.0.jar) \ No newline at end of file diff --git a/doc/favicon.png b/doc/favicon.png new file mode 100644 index 0000000..7661500 Binary files /dev/null and b/doc/favicon.png differ diff --git a/doc/index.md b/doc/index.md index 3238270..4ac7628 100644 --- a/doc/index.md +++ b/doc/index.md @@ -1,44 +1,70 @@ - # JavaBaas -**JavaBaas** 是基于Java语言开发的后台服务框架,其核心设计目标是实现移动客户端的后台结构化数据存储、物理文件存储、消息推送等功能。极大的降低移动客户端的后台开发难度,实现快速开发。 +**JavaBaas** 是基于Java语言开发的后台服务框架,其核心设计目标是实现移动客户端、网页应用的后台数据存储、物理文件存储、消息推送等功能,极大的降低后台开发难度,实现快速开发。 + +使用 **JavaBaas** 提供的工具进行简单的配置,即可完成后台搭建。后台搭建成功后,即可使用RestAPI、iOS/Android-SDK进行数据的增删改查等操作。 + +项目地址: -项目地址:[GitHub](https://github.com/JavaBaas/JavaBaasServer) +* [码云](https://gitee.com/javabaas/JavaBaas) 技术讨论群:479167886 完整文档参见:[www.javabaas.com](http://www.javabaas.com/) -备注: [JavaBaas稳定版下载地址](http://7xr649.dl1.z0.glb.clouddn.com/JavaBaas.zip) - ## 主要功能 * 结构化数据存储 +* RestAPI接口 +* iOS/Android SDK * 物理文件存储 * ACL权限管理机制 * 用户系统 * 消息推送 -##快速上手 +## 快速上手 + +### 一、安装 +#### 1.Docker方式 + +JavaBaas提供了完整的Docker演示环境(包含数据库等),需安装[Docker](https://www.docker.com)后使用。 + +``` +docker pull javabaas/javabaas-starter +docker run -p 8080:8080 javabaas/javabaas-starter +``` + +执行成功后,即可使用本地8080端口访问JavaBaas环境。 + +以上的执行方式每次会创建全新的执行环境,如需要持久化数据,需使用 DockerVolume。 + +``` +docker run -p 8080:8080 -v /usr/javabaas:/data/db javabaas/javabaas-starter +``` -###相关环境 -####JDK +其中`/usr/javabaas`为本地数据存储目录,请创建该目录或修改为你所需要的目录。 + +#### 2.Jar包方式 +也可以选择使用jar包方式启动JavaBaas,我们需要先配置以下环境。 + +##### JDK JavaBaas基于JDK1.8编写,编译及运行需要安装JDK1.8环境。 提示: 在Oracle官网可以下载最新的[JDK安装包](http://www.oracle.com/technetwork/java/javase/downloads/index.html)。 -####MongoDB +##### MongoDB JavaBaas使用MongoDB作为存储数据库,请先正确安装并启动MongoDB数据库。 -提示: 在MongoDB官网可以下载最新的[MongoDB安装包](www.mongodb.com)。 +提示: 在MongoDB官网可以下载最新的[MongoDB官网](http://www.mongodb.com)。 -####Redis +##### Redis JavaBaas使用Redis作为缓存引擎,请先正确安装并启动Redis数据库。 -提示: 在Redis官网可以下载最新的[Redis安装包](http://redis.io/)。 +提示: 在Redis官网可以下载最新的[Redis官网](http://redis.io/)。 -###启动 -Server目录下的`JavaBaas.jar`为系统启动文件,系统依赖环境配置正确后,使用以下命令启动系统: +##### 启动 +在[下载](/download.md)页面,下载JavaBaasServer服务端程序,解压后`JavaBaas.jar`为系统启动文件,系统依赖环境配置正确后,使用以下命令启动系统。 `java -jar JavaBaas.jar` + 看到以下信息,表明系统启动成功。 ``` @@ -46,19 +72,38 @@ Server目录下的`JavaBaas.jar`为系统启动文件,系统依赖环境配置 [main] c.s.b.c.l.ApplicationEventListener : JavaBaasServer started. [main] c.j.s.c.l.ApplicationEventListener : Key: JavaBaas [main] c.j.s.c.l.ApplicationEventListener : Timeout: 600000 +[main] c.s.b.c.l.ApplicationEventListener : Host:127.0.0.1 +[main] c.j.s.c.l.ApplicationEventListener : JavaBaas status at http://127.0.0.1:8080 +[main] c.j.s.c.l.ApplicationEventListener : Browse REST API at http://127.0.0.1:8080/explorer.html [main] com.staryet.baas.Main : Started Main in 2.653 seconds (JVM running for 3.232) ``` -###命令行工具 +### 二、命令行工具 `JavaBaas`系统成功启动后,默认将在http 8080端口监听所有用户请求。此时首先要使用命令行工具`JBShell`创建应用。 命令行工具`JBShell`是JavaBaas的配套工具,使用`JBShell`可以完成应用的创建删除、类的创建删除、字段的创建删除、对象的增删改查等操作,以及一些便捷的辅助功能。 `JBShell`基于java编写,编译及运行需要安装JDK环境。 -使用以下命令启动命令行工具: +#### Mac&Linux安装 +在命令行中执行 -`java -jar JBShell.jar` +``` +curl -s "http://get.javabaas.com/jbshell.sh" | bash +``` + +安装成功后,打开一个新窗口,输入命令`JB`即可启动命令行工具。 + +#### Windows安装 +在[下载](/download.md)页面,下载JavaBaasShell(windows)命令行工具程序,启动执行即可。 + + +#### 启动 +在命令行中使用以下命令启动`JBShell`工具: + +``` +jb +``` 启动成功后显示以下信息 @@ -69,38 +114,29 @@ Server目录下的`JavaBaas.jar`为系统启动文件,系统依赖环境配置 | | / _` |\ \ / // _` || ___ \ / _` | / _` |/ __| /\__/ /| (_| | \ V /| (_| || |_/ /| (_| || (_| |\__ \ \____/ \__,_| \_/ \__,_|\____/ \__,_| \__,_||___/ -Version:1.0.0 +Version:2.0.0 Host:http://localhost:8080/api/ AdminKey:JavaBaas BAAS> ``` -###配置 -`JBShell.jar `为命令行工具执行文件。同目录下的`config.properties`为配置文件。内容如下: +### 三、构建数据 -``` -host = http://localhost:8080/api/ -key = JavaBaas -``` - -其中`host`为`JavaBaas`服务器所在的地址,本地调用`JBShell`默认使用localhost即可,远程管理需设置正确的远程服务器地址。 - -`key`为`JavaBaas`超级密钥,不设置默认为JavaBaas。 - -###创建应用 -在`JavaBaas`中,最高层的组织结构为应用系统,各应用之间权限、用户、数据相互隔离。为了开始使用`JavaBaas`,我们首先需要创建一个应用。 +#### 创建应用 +在`JavaBaas`中,最高层的组织结构为`应用`,各应用之间权限、用户、数据相互隔离。为了开始使用`JavaBaas`,我们首先需要创建一个应用。 首先启动命令行工具,在命令行工具中,使用命令`app add Blog`,创建一个博客应用。 ```bash BAAS>app add Blog -App added. +应用创建成功 +设置当前应用为 Blog ``` 现在,我们成功创建了一个名为`Blog`的应用。 提示: 一般情况下建议使用大写字母开头做为应用名称 -####查看应用列表 +#### 查看应用列表 在命令行工具中,使用`apps`命令可以查看当前`JavaBaas`中所有的应用。 ``` @@ -109,29 +145,29 @@ Blog ``` 现在我们可以看到,系统中只有我们刚刚创建的,名为`Blog`的一个应用。 -####切换当前应用 +#### 切换当前应用 在命令行工具中,使用`use`命令即可切换当前应用,切换应用后,即可为当前应用创建类来存储数据。 ``` BAAS>use Blog -Set current app to Blog +设置当前应用为 Blog ``` 现在我们的应用即切换为刚刚创建的`Blog`。 -####创建类 -在`JavaBaas`中,数据使用类进行组织。用户可以自由创建类,类名需使用英文字母开头且名称中只能包含数字与英文字母。类创建后,需要在类中创建字段以存储数据。同时、系统初始化后会自动创建用户类、设备类、文件类等系统内建类,内建类名使用下划线`_`开头,系统内建类禁止删除或修改。 +#### 创建类 +在`JavaBaas`中,数据使用`类`进行组织。用户可以自由创建类,类名需使用英文字母开头且名称中只能包含数字与英文字母。类创建后,需要在类中创建字段以存储数据。同时、系统初始化后会自动创建用户类、设备类、文件类等系统内建类,内建类名使用下划线`_`开头,系统内建类禁止删除或修改。 现在我们使用命令`class add Article`创建一个类用于存储博客中的文章信息。 ``` Blog>class add Article -Class added. +类创建成功 ``` 现在我们便在`Blog`应用中创建了名为`Article`的类。 提示: 一般情况下建议使用大写字母开头做为类名称 -####查看类列表 +#### 查看类列表 使用`class`命令,可以查看当前应用下所有的类。 ``` @@ -144,104 +180,198 @@ Article(0) ``` 可以看到,当前应用中存在系统内建的文件类、设备类、推送日志类、用户类,以及我们刚刚创建的用于存储文章的`Article`类。 -####切换当前类 +#### 切换当前类 成功创建`Article`类后,我们需要为类创建用于存储文章标题、作者等信息的字段以存储数据。首先,我们需要将当前类切换至`Article`以便在此类下创建字段。 使用`set Article`命令,将当前类切换至`Article` ``` Blog>set Article -Set current class to Article +设置当前类为 Article Blog Article> ``` 切换完成后,光标变为`Blog Article>`,表示当前应用为`Blog`,当前类为`Article`。 -###创建字段 +#### 创建字段 使用`field add title`命令,在`Article`类中创建一个用于存储文章标题的字符型字段。 ``` Blog Article>field add title -Field added. -Blog Article> -``` -现在我们在类`Article`中创建了名为`title`的字符型字段。 - -使用`field add author`命令,在`Article`类中创建一个用于存储文章作者的字符型字段。 - -``` -Blog Article>field add author -Field added. -Blog Article> -``` -现在我们在类`Article`中创建了名为`author`的字符型字段。 +请选择FieldType 默认为STRING +1 STRING +2 NUMBER +3 BOOLEAN +4 DATE +5 FILE +6 OBJECT +7 ARRAY +8 POINTER +0 取消 +>1 +创建字段成功 +``` +创建字段时,需要选择[数据类型](/overview/object.md#数据类型)。此处我们选择1(字符型)。现在我们就在类`Article`中创建了名为`title`的字符型字段。 + +使用`field add read`命令,在`Article`类中创建一个用于存储文章浏览次数的数值型字段。 + +``` +Blog Article>field add read +请选择FieldType 默认为STRING +1 STRING +2 NUMBER +3 BOOLEAN +4 DATE +5 FILE +6 OBJECT +7 ARRAY +8 POINTER +0 取消 +>2 +创建字段成功 +``` +现在我们在类`Article`中创建了名为`read`的数值型字段。 提示: 一般情况下建议使用小写字母开头做为字段名称 -####查看字段列表 +#### 查看字段列表 使用命令`fields`即可查看当前类中的所有字段列表。 ``` Blog Article>fields - author - title + read + title ``` -可以看到,当前类中存在两个我们刚创建的字符型字段。 +可以看到,当前类中存在我们刚创建的两个字段。 -###存储数据 -成功创建类并添加字段后,我们可以开始存储数据。使用命令行工具即可以进行基本的增删改查操作。 +#### 存储数据 +成功创建类并添加字段后,我们就可以开始存储数据操作了(包括使用`RestAPI`以及`iOS/Android-SDK`)。此处我们先使用命令行工具进行基本的增删改查操作。 -####插入数据 +#### 插入数据 使用命令`add`在`Article`类中插入数据。 ``` -Blog Article>add {"title":"StarWars","author":"Lucas"} -Object added. +Blog Article>add {"title":"StarWars","read":10} +对象创建. ``` 现在我们便在`Article`类中插入了一条数据记录。 提示: 在 JavaBaas 中,所有数据以json形式存储。详情参见[数据存储](/overview/object.md)文档。 -####查询数据 +#### 查询数据 使用命令`list`查询`Article`类中的所有数据。 ``` Blog Article>list -{"_id":"f2e88fd91c3a49c988901f774cc9e879","createdAt":1471335596116,"updatedAt":1471335596116,"createdPlat":"admin","updatedPlat":"admin","acl":{"*":{"read":true,"write":true}},"author":"Lucas","title":"StarWars"} +{"className":"Article", "objectId":"06904d004d2d462b888800abb9d03a8b", "updatedAt":"1509953994688", "createdAt":"1509953994688", "serverData":{"read":10,"title":"StarWars"}} ``` 可以看到,现在`Article`类中只有一条刚刚创建的数据。 -####表格打印 +#### 表格打印 使用命令`table`打印`Article`类中的所有数据。 ``` Blog Article>table ┌──────────────────────────────────┬────────────────────┬────────────────────┐ -│ id │ author │ title │ -│ │ +│ id │ read │ title │ +│ │ ├──────────────────────────────────┼────────────────────┼────────────────────┤ -│ f2e88fd91c3a49c988901f774cc9e879 │ Lucas │ StarWars │ +│ 06904d004d2d462b888800abb9d03a8b │ 10 │ StarWars │ └──────────────────────────────────┴────────────────────┴────────────────────┘ ``` -####删除数据 +#### 删除数据 使用命令`del id`,删除指定数据,其中 `id` 为刚才查询结果中的id。 ``` -Blog Article>del f2e88fd91c3a49c988901f774cc9e879 -Object deleted. +Blog Article>del 06904d004d2d462b888800abb9d03a8b +对象删除. +``` + +### 四、使用RestAPI操作数据 +我们已经成功创建了应用,构建了数据结构,并存储了一些数据。现在我们可以使用`RestAPI`存取数据了。 + +使用`RestAPI`操作数据,我们需要首先在`HTTP Header`指定需要操作的应用,使用JB-AppId指明应用id,使用JB-Key来进行鉴权,使用JB-Plat指明请求来源的平台(可选值为android/ios/cloud/js/admin)。 + +我们可以很方便的使用`JBShell`获取应用的id、key等信息。在shell工具中输入以下命令: + +``` +Blog Article>token +AppId: 5a0021c3ae07be6fd9e58bb5 +Key: 06ee7e28d4e4402a97b8ef05a6690e8f +``` + +此处我们只使用AppId和Key,其他信息详解请查看`JBShell`相关文档。 + +下面我们使用`RestAPI`向`Article`类中添加一条数据。(此处将jb-appid/jb-key替换为刚刚查询的结果) + +``` +curl -X POST \ + -H 'jb-appid: 5a0021c3ae07be6fd9e58bb5' \ + -H 'jb-key: 06ee7e28d4e4402a97b8ef05a6690e8f' \ + -H 'jb-plat: admin' \ + -H "Content-Type: application/json" \ + -d '{"title":"这是一片测试文章"}' \ + http://127.0.0.1:8080/api/object/Article +``` + +请求成功后,我们即向`Article`类中添加了一条新的记录。 + +#### 获取数据 +同时,我们也可以使用`RestAPI`获取数据,如查询`Article`类中的所有数据。 + ``` +curl -X GET \ + -H 'jb-appid: 5a0021c3ae07be6fd9e58bb5' \ + -H 'jb-key: 06ee7e28d4e4402a97b8ef05a6690e8f' \ + -H 'jb-plat: admin' \ + -H "Content-Type: application/json" \ + http://127.0.0.1:8080/api/object/Article +``` + +返回结果为`Article`类中的所有数据。更多关于`RestAPI`的使用方式,请参考[RestAPI](/manual/rest_api.md)相关文档。 + +注意: RestAPI请求必须添加请求头Content-Type:application/json + + +### 五、使用RestAPI测试工具 +为了方便测试API接口,`JavaBaas`内建了`RestAPI测试工具`。启动成功后,使用浏览器访问`http://127.0.0.1:8080/explorer.html`页面即可看到API测试工具。 + + + +在文本框输中输入AdminKey(默认为JavaBaas)并回车,然后在下拉菜单中选择应用,此处我们选择刚刚创建的博客应用Blog。 + + + +此时会显示应用中所有类的列表,此处可以看到我们已经创建的`Article`类,点击后,会展示对应类的数据操作接口(增删改查、计数等)。 + + + +展开GET方法,点击测试按钮,即可请求查询接口。 + + + +测试后,可以看到请求结果,此处看到的数据即为我们刚才使用命令行工具添加的数据。 + + + +提示: API测试工具中会显示完整的请求结构,可以参照此处显示的请求构建http请求。 + +下面我们使用`RestAPI测试工具`向`JavaBaas`中添加一条数据。选择POST方法,并按照Article类的数据格式构建一条新数据,然后点击测试按钮。 + + -###使用客户端SDK -我们已经成功创建了应用,构建了数据结构,并存储了一些数据。现在我们可以使用`客户端SDK`、`REST API`存取数据了。详见`客户端SDK`以及`REST API`相关文档。 +现在我们再调用GET方法,查询表中的数据,可以看到,此时表中已经有了两条记录。 +### 六、使用客户端SDK +`JavaBaas`也提供了方便的`客户端SDK`以存取数据,包括`Java` `iOS` `Android`等SDK。详见`客户端SDK`相关文档。 -##自定义配置 -###配置文件 +## 自定义配置 +### 配置文件 Server目录下的`application.properties`为配置文件。 -###MongoDB配置 +### MongoDB配置 在application.properties中配置MongoDB数据库连接信息。 ``` @@ -252,24 +382,24 @@ spring.data.mongodb.password = baas //密码 不填写为无身份校验 spring.data.mongodb.authentication-database = admin //用于校验身份的数据库 ``` -###Redis配置 +### Redis配置 在application.properties中配置Redis数据库连接信息。 ``` spring.redis.host = 127.0.0.1 //Redis数据库地址 ``` -###监听端口 +### 监听端口 在`application.properties`中配置监听端口,不设置默认为8080。 ``` server.port = 8080 ``` -###超级密钥 -超级密钥用于鉴定管理员的超级权限,系统的核心管理接口需要使用此权限进行调用。超级密钥可以自行设置,建议使用32位随机字符串。如:`c3ca79cca3c24147902c1114640268a5`。 +### 超级密钥 +超级密钥用于鉴定管理员的超级权限,系统的核心管理接口需要使用此权限进行调用(以及`JBShell`工具),默认密钥为`JavaBaas`。超级密钥可以自行设置,建议使用32位随机字符串。如:`c3ca79cca3c24147902c1114640268a5`。 -在`application.properties`中配置超级密钥,不设置默认为JavaBaas。 +在`application.properties`中配置超级密钥,不设置默认为`JavaBaas`。 注意: 为了保障数据安全,强烈建议不要使用默认密钥! @@ -277,24 +407,24 @@ server.port = 8080 baas.auth.key = c3ca79cca3c24147902c1114640268a5 ``` -###服务器地址 +### 服务器地址 JavaBaas需要接收外部系统回调请求,因此需要配置系统部署服务器的ip地址。(本地测试时可使用127.0.0.1代替,生产环境需配置公网ip地址。) 例如,在`application.properties`中配置当前服务器ip信息。 ``` -host = http://58.132.171.126/ +baas.host = http://58.132.171.126/ ``` -###七牛云存储 +### 七牛云存储 为了使用七牛云存储作为物理文件存储引擎,需要配置七牛云存储相关信息。 在`application.properties`中配置以下信息。 ``` -qiniu.ak = 七牛云存储的帐号ak -qiniu.sk = 七牛云存储的帐号sk -qiniu.bucket = bucket名称 -qiniu.file.host = bucket的存储域名 +baas.file.handler.qiniu.ak = 七牛云存储的帐号ak +baas.file.handler.qiniu.sk = 七牛云存储的帐号sk +baas.file.handler.qiniu.bucket = bucket名称 +baas.file.handler.qiniu.url = bucket的存储域名 ``` -##常见问题 \ No newline at end of file +## 常见问题 \ No newline at end of file diff --git a/doc/jbshell b/doc/jbshell new file mode 100644 index 0000000..32ffb3b --- /dev/null +++ b/doc/jbshell @@ -0,0 +1 @@ +2013 \ No newline at end of file diff --git a/doc/jbshell.sh b/doc/jbshell.sh new file mode 100755 index 0000000..a5764bf --- /dev/null +++ b/doc/jbshell.sh @@ -0,0 +1,138 @@ +#!/bin/bash +echo "开始安装" + +JAVABAAS_SERVICE="http://file.kerust.com/jbshell_2013.zip" + +if [ -z "$JAVABAAS_DIR" ]; then + JAVABAAS_DIR="$HOME/.javabaas" +fi + +javabaas_bash_profile="${HOME}/.bash_profile" +javabaas_zhsrc="${HOME}/.zshrc" + +javabaas_init_snippet=$( cat << EOF +JBSHELL_DIR="$JAVABAAS_DIR/jbshell/bin" +export JBSHELL_DIR +export PATH=\$JBSHELL_DIR:\$PATH + +EOF +) + + +echo "检查是否已经安装jbshell..." +if [ -d "$JBSHELL_DIR" ]; then + echo "发现jbshell" + echo "" + echo "======================================================================================================" + echo "你已经安装了jbshell " + echo " 地址为:" + echo "" + echo " ${JBSHELL_DIR}" + echo "" + echo "请检查" + echo " 如果你想更新jbshell 请使用" + echo " $ jb u 或 $ jb update" + echo "" + echo "======================================================================================================" + echo "" + exit 0 +fi + +echo "检查是否安装了unzip..." +if [ -z $(which unzip) ]; then + echo "没有发现unzip." + echo "======================================================================================================" + echo " 请安装unzip." + echo "" + echo " 安装完unzip后请重新安装jbshell." + echo "======================================================================================================" + echo "" + exit 0 +fi + +echo "检查是否安装了curl..." +if [ -z $(which curl) ]; then + echo "没有发现curl." + echo "" + echo "======================================================================================================" + echo " 请安装curl." + echo "" + echo " 安装完curl后请重新安装jbshell." + echo "======================================================================================================" + echo "" + exit 0 +fi + +echo "检查是否安装了java..." +if [ -z $(which java) ]; then + echo "没有发现java." + echo "" + echo "======================================================================================================" + echo " 请安装java(最低版本1.7)." + echo "" + echo " 安装完java后请重新安装jbshell." + echo "======================================================================================================" + echo "" + exit 0 +fi + +jbshell_zip_file="${JAVABAAS_DIR}/javabaasshell.zip" + +echo "创建jbshell目录..." +mkdir -p "$JAVABAAS_DIR" +echo "创建jbshell目录成功..." +curl -L "$JAVABAAS_SERVICE" > "$jbshell_zip_file" +echo "下载jbshell..." +unzip -qo "$jbshell_zip_file" -d "$JAVABAAS_DIR" -x __MACOSX/* +rm -f "$jbshell_zip_file" +echo "解压成功" + +echo "添加bash环境变量..." +if [ ! -f "$javabaas_bash_profile" ]; then + echo "#!/bin/bash" > "$javabaas_bash_profile" + echo "$javabaas_init_snippet" >> "$javabaas_bash_profile" + echo "创建并更新 ${javabaas_bash_profile}" + #source "$javabaas_bash_profile" +else + if [[ -z $(grep 'JBSHELL_DIR' "$javabaas_bash_profile") ]]; then + echo -e "\n$javabaas_init_snippet" >> "$javabaas_bash_profile" + echo "更新 ${javabaas_bash_profile}" + #source "$javabaas_bash_profile" + fi +fi + +echo "添加zsh环境变量..." +if [ ! -f "$javabaas_zhsrc" ]; then + echo "$javabaas_init_snippet" >> "$javabaas_zhsrc" + echo "创建并更新 ${javabaas_zhsrc}" + #source "$javabaas_zhsrc" + #之所以不打开是因为咱们是没有解决zsh报的错误信息,如果有人知道怎么解决帮忙解决一下: + #/Users/test/.oh-my-zsh/oh-my-zsh.sh: line 12: autoload: command not found + #/Users/test/.oh-my-zsh/oh-my-zsh.sh: line 31: syntax error near unexpected token `(' + #/Users/test/.oh-my-zsh/oh-my-zsh.sh: line 31: `for config_file ($ZSH/lib/*.zsh); do' +else + if [[ -z $(grep 'JBSHELL_DIR' "$javabaas_zhsrc") ]]; then + echo -e "\n$javabaas_init_snippet" >> "$javabaas_zhsrc" + echo "更新 ${javabaas_zhsrc}" + #source "$javabaas_zhsrc" + fi +fi + + +echo "成功安装jbshell" +echo "" +echo "请打开一个新的终端,或者在当前终端执行下面命令:" +echo "请打开一个新的终端,或者在当前终端执行下面命令:" +echo "请打开一个新的终端,或者在当前终端执行下面命令:" +echo "" +echo "source \"${JAVABAAS_DIR}/jbshell/export/jbexport\"" +echo "" +echo "" +echo "然后输入下面的命令:" +echo "然后输入下面的命令:" +echo "然后输入下面的命令:" +echo "" +echo "jb" +echo "" +echo "开始造吧..." +echo "如果想获得jbshell的更多命令,请输入jb help" \ No newline at end of file diff --git a/doc/jbshell_update.sh b/doc/jbshell_update.sh new file mode 100755 index 0000000..e2874b7 --- /dev/null +++ b/doc/jbshell_update.sh @@ -0,0 +1,116 @@ +#!/bin/bash +echo "开始安装" + +JAVABAAS_SERVICE="http://file.kerust.com/jbshell_2013.zip" + +if [ -z "$JAVABAAS_DIR" ]; then + JAVABAAS_DIR="$HOME/.javabaas" +fi + +javabaas_bash_profile="${HOME}/.bash_profile" +javabaas_zhsrc="${HOME}/.zshrc" + +javabaas_init_snippet=$( cat << EOF +JBSHELL_DIR="$JAVABAAS_DIR/jbshell/bin" +export JBSHELL_DIR +export PATH=\$JBSHELL_DIR:\$PATH +EOF +) + +echo "检查是否安装了unzip..." +if [ -z $(which unzip) ]; then + echo "没有发现unzip." + echo "======================================================================================================" + echo " 请安装unzip." + echo "" + echo " 安装完unzip后请重新安装jbshell." + echo "======================================================================================================" + echo "" + exit 0 +fi + +echo "检查是否安装了curl..." +if [ -z $(which curl) ]; then + echo "没有发现curl." + echo "" + echo "======================================================================================================" + echo " 请安装curl." + echo "" + echo " 安装完curl后请重新安装jbshell." + echo "======================================================================================================" + echo "" + exit 0 +fi + +echo "检查是否安装了java..." +if [ -z $(which java) ]; then + echo "没有发现java." + echo "" + echo "======================================================================================================" + echo " 请安装java(最低版本1.7)." + echo "" + echo " 安装完java后请重新安装jbshell." + echo "======================================================================================================" + echo "" + exit 0 +fi + +jbshell_zip_file="${JAVABAAS_DIR}/javabaasshell.zip" + + +echo "创建jbshell目录..." +mkdir -p "$JAVABAAS_DIR" +echo "创建jbshell目录成功..." +curl -L "$JAVABAAS_SERVICE" > "$jbshell_zip_file" +echo "下载jbshell..." +jbshell_dir_del="${JAVABAAS_DIR}/jbshell" + +# 判断之前是否有配置文件,如果有拷贝出来 +echo "保留旧的配置文件" +if [ -f "${jbshell_dir_del}/lib/jbshell.properties" ]; then + cp -f "${jbshell_dir_del}/lib/jbshell.properties" "${JAVABAAS_DIR}" +fi +# 删除之前的文件 +rm -f -r "$jbshell_dir_del" +unzip -qo "$jbshell_zip_file" -d "$JAVABAAS_DIR" -x __MACOSX/* +rm -f "$jbshell_zip_file" +echo "解压成功" + +if [ -f "${JAVABAAS_DIR}/jbshell.properties" ]; then + mv -f "${JAVABAAS_DIR}/jbshell.properties" "${jbshell_dir_del}/lib" +fi + +echo "添加bash环境变量..." +if [ ! -f "$javabaas_bash_profile" ]; then + echo "#!/bin/bash" > "$javabaas_bash_profile" + echo "$javabaas_init_snippet" >> "$javabaas_bash_profile" + echo "创建并更新 ${javabaas_bash_profile}" + #source "$javabaas_bash_profile" +else + if [[ -z $(grep 'JBSHELL_DIR' "$javabaas_bash_profile") ]]; then + echo -e "\n$javabaas_init_snippet" >> "$javabaas_bash_profile" + echo "更新 ${javabaas_bash_profile}" + #source "$javabaas_bash_profile" + fi +fi + +echo "添加zsh环境变量..." +if [ ! -f "$javabaas_zhsrc" ]; then + echo "$javabaas_init_snippet" >> "$javabaas_zhsrc" + echo "创建并更新 ${javabaas_zhsrc}" + #source "$javabaas_zhsrc" + #之所以不打开是因为咱们是没有解决zsh报的错误信息,如果有人知道怎么解决帮忙解决一下: + #/Users/test/.oh-my-zsh/oh-my-zsh.sh: line 12: autoload: command not found + #/Users/test/.oh-my-zsh/oh-my-zsh.sh: line 31: syntax error near unexpected token `(' + #/Users/test/.oh-my-zsh/oh-my-zsh.sh: line 31: `for config_file ($ZSH/lib/*.zsh); do' +else + if [[ -z $(grep 'JBSHELL_DIR' "$javabaas_zhsrc") ]]; then + echo -e "\n$javabaas_init_snippet" >> "$javabaas_zhsrc" + echo "更新 ${javabaas_zhsrc}" + #source "$javabaas_zhsrc" + fi +fi + +echo "" +echo "成功更新jbshell" +echo "" diff --git a/doc/manual/android-adk_api.md b/doc/manual/android-adk_api.md deleted file mode 100644 index ce9c419..0000000 --- a/doc/manual/android-adk_api.md +++ /dev/null @@ -1,806 +0,0 @@ -# 目录 -## 一、SDK安装与初始化 -#### SDK 手动安装: - -下载SDK并解压得到如下文件: - -``` -├── JavaBaas-sdk-<版本号>.jar // JavaBaas SDK核心模块 -├── fastjson-<版本号>.jar // JavaBaas SDK序列化模块 -├── okhttp-<版本号>.jar // JavaBaas SDK网络请求模块 -├── okio-<版本号>.jar // 七牛云存储SDK依赖模块 -├── happy-dns-0.2.5.jar // 七牛云存储SDK依赖模块 -└── qiniu-android-sdk-<版本号>.jar // 七牛云存储SDK核心模块 -``` - -将解压出的模块导入到项目中。 - -#### Maven自动导入安装(coming soon) - - - -#### SDK初始化: - -新建一个类 `App`继承自`Application `类: - -```java -public class App extends Application { - - @Override - public void onCreate() { - super.onCreate(); - - // 初始化参数依次为 this, AppKey, AppId, 后台服务器地址, - // 获取InstallationId的回调(用来处理与InstallationId有关的操作,如绑定到用户等) - JBCloud.init(this , "1f7049bfde7d440cb31210aa5e4d44ed" , "5645b2a574242e39eee89829" , "https://api.javabaas.com" , null); - } -} -``` - -然后在`AndroidManifest.xml`中配置SDK所需的一些权限以及声明刚才创建的`App`类 - -```xml - - - - - - - ... - -``` - -SDK配置完成,可以进行一些简单的访问测试: - -```java -public void onSave(View view) { - final JBObject testC = new JBObject("testC"); - testC.put("testA", "测试A"); - testC.put("testB", "测试B"); - testC.saveInBackground(new SaveCallback() { - @Override - public void done(JBObject object) { - Log.d("ObjectTest" ,"保存成功 id=" + testC.getId()); - } - - @Override - public void error(JBException e) { - Log.d("ObjectTest" ,"保存失败 "+e.getResponseErrorMsg); - e.printStackTrace(); - } - }); -} -``` - -## 二、对象 -### 32..1 JBObject -`JBOject`是JavaBaas中的基础对象,也可以理解为`JBOject`对应着数据库表中的一条信息。 - -假如你在云端数据库中使用`FoodLike`表来记录用户最喜欢的食物,那么表中至少会有`foodName`(食品名称),`userName`(用户名称)属性,那么,你应该这样生成`JBOject`: - -```java -JBObject jbObject = new JBObject("FoodLike"); -jbObject.put("foodName","dumpling"); -jbObject.put("userName","ZhangSan"); -``` -有几点需要注意: - -* 每个`JBOject`都必须在云端有对应的数据库表和相应的字段。 -* 每个`JBOject`都有保留字段,分别为`_id``acl``createdPlat``updatedPlat``createdAt``updatedAt`,这些字段由系统自动生成和修改,不需要开发者进行指定。 - -### 2.2 同步与异步 - JavaBaas提供了数据检索,保存,更新,删除,查询的同步与异步的方法。 - - 注: 在Android UI主线程中调用同步的方法,可能会导致UI主线程阻塞。所以,在UI主线程中请使用异步的方式。 - - -### 2.3 检索对象 - 如果你知道了云端中某条数据的`objectId`,那么可以通过以下代码获取此条数据对应的`JBOject`对象: - -```java -1.同步检索: -JBQuery jbQuery = JBQuery.getInstance("FoodLike"); -jbQuery.whereEqualTo("_id", objectID); -JBObject result; -try { - List resultList = jbQuery.find(); - result = resultList.get(0); -} catch (JBException e) { - e.printStackTrace(); -} - -2.异步检索: -JBQuery jbQuery = JBQuery.getInstance("FoodLike"); -jbQuery.whereEqualTo("_id", objectID); -jbQuery.findInBackground(new FindCallback() { - @Override - public void done(List resultList) { - JBObject result = resultList.get(0); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` - -### 2.4 保存对象 -如2.1所示,假如你在本地生成一个`JBObject`之后,那么可以使用以下代码将其保存至云端: - -```java -1.同步保存: -try { - jbObject.save(); - Log.d("ObjectTest" , "保存成功 "+ jbObject.getId()); -} catch (JBException e) { - e.printStackTrace(); -} - -2.异步保存: -jbObject.saveInBackground(new SaveCallback() { - @Override - public void done(JBObject object) { - Log.d("ObjectTest" , "保存成功 "+ object.getId()); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` - - -### 2.5 更新对象 -如果你知道了云端中某条数据的`objectId`,那么可以通过以下代码更新云端对应的数据: - -```java -1.同步更新: -JBObject jbObject = new JBObject("FoodLike"); -jbObject.setId(objectId); -jbObject.put("foodName","hamburger"); -try { - jbObject.save(); - Log.d("ObjectTest", "修改成功了"); -} catch (JBException e) { - e.printStackTrace(); -} - -2.异步更新: -JBObject jbObject = new JBObject("FoodLike"); -jbObject.setId(objectId); -jbObject.put("foodName","hamburger"); -jbObject.saveInBackground(new SaveCallback() { - @Override - public void done(JBObject object) { - Log.d("ObjectTest", "修改成功了"); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` -### 2.6 删除对象 -如果你知道了云端中某条数据的`objectId`,那么可以通过以下代码删除云端对应的数据: - -```java -1.同步删除: -try { - JBObject.deleteById("FoodLike", objectId); - Log.d("ObjectTest", "删除成功了"); -} catch (JBException e) { - e.printStackTrace(); -} - -2.异步删除: -JBObject.deleteByIdInBackground("FoodLike", objectId, new DeleteCallback() { - @Override - public void done() { - Log.d("ObjectTest", "删除成功了"); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` - -### 2.7 关联对象 - -在数据存储中,类之间可能会有直接的关联关系。 - -比如,一个公民拥有一个唯一身份证。那么如果在一个公民对象中想指向一个身份证类的对象,那么可以通过以下代码来实现: - -```java - -JBObject citizenObject = new JBObject("Citizen"); - -//实例化一个'身份证'对象,并将已知的Id赋值进去。 -JBObject identificationCardObject = JBObject.createWithoutDate("IdentificationCard","babc5b153dc0401fb5fcd8ffaae0ddf6"); - -//将'身份证'对象赋值到'公民'对象中。 -citizenObject.put("identificationCard", identificationCardObject); - -//保存 -citizenObject.saveInBackground(new SaveCallback() { - @Override - public void done(JBObject object) { - Log.d("ObjectTest", "保存成功 " + object.getId()); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` - -### 2.8 原子操作 -很多应用都会用到计数器的功能,比如在一个新闻类的应用中,我们需要记录每条新闻的查看次数,可以使用以下代码: - -``` -//第一个参数为新闻对象所在的表名,第二个参数为新闻对象的id -JBObject testObject = JBObject.createWithoutData("News",objectId); -//第一个参数为要增加的字段名称,第二个参数为要增加的个数 -testObject.incrementKeyInBackground("openCount", 1, new RequestCallback() { - @Override - public void done() { - Log.d("ObjectTest", "自增成功"); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); - -``` -针对上面的情况,还可以直接调用`incrementKeyInBackground`方法,来实现参数加1。 - -``` -testObject.incrementKeyInBackground("openCount", new RequestCallback() { - @Override - public void done() { - Log.d("ObjectTest", "自增成功"); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); - -``` - -### 2.9 批量操作 (敬请期待) - -### 2.10 数据类型 - -目前我们支持的数据类型有: - -`String``Int``Float``Boolean`以及`Date``File``Object``Array`类型 - -简单使用用例如下: - -```java -JBObject testObject = new JBObject("Test"); - -//String -testObject.put("testString", "测试"); -//Int -testObject.put("testInt",1); -//Float -testObject.put("testFloat",1.111f); -//boolean -testObject.put("testBoolean", true); -//Date -testObject.put("testDate", new Date()); -//Array -List list = new ArrayList<>(); -list.add("A"); -list.add("B"); -testObject.put("testArray", list); - -testObject.saveInBackground(new SaveCallback() { - @Override - public void done(JBObject object) { - Log.d("ObjectTest", "保存成功 " + object.getId()); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` -## 三、查询 -SDK中提供了`JBQuery`类来满足应用不同条件下的查询需求。 -### 3.1 基本查询 -如果想查询指定表中的所有数据,可以使用以下代码: - -```java -1.同步查询: -JBQuery jbQuery = JBQuery.getInstance("Test"); -List list; -try { - list = jbQuery.find(); - Log.d("ObjectTest", "查询到的所有条数为" + list.size()); -} catch (JBException e) { - e.printStackTrace(); -} - -2.异步查询: -JBQuery jbQuery = JBQuery.getInstance("Test"); -jbQuery.findInBackground(new FindCallback() { - @Override - public void done(List result) { - Log.d("ObjectTest", "查询到的所有条数为" + result.size()); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` -### 3.2 约束查询 -SDK支持多种约束查询条件,举例如下: - -```java -//限制查询条数为10条 -jbQuery.setLimit(10); - -//查询会跳过前两条 -jbQuery.skip(2); - -//查询'age'字段为'18'的 -jbQuery.whereEqualTo("age",18); -``` -### 3.3 数组值查询 -如果想查询数据库中某个字段包含在指定数组中的所有数据,可以添加以下限制条件: - -```java -List list = new ArrayList<>(); -list.add(18); -list.add(19); -list.add(20); - -//查询年龄包含在指定数组中的所有数据 -jbQuery.whereContainedIn("age", list); -``` - -### 3.4 模糊查询 - -JavaBaas支持多种模糊查询条件,举例如下: - -```java -//查询所有name中包含'浩'字的 -jbQuery.whereMatches("name","浩"); - -//查询所有name中以'王'开头的 -jbQuery.whereStartsWith("name","王"); - -//查询所有name中以'超'结尾的 -jbQuery.whereEndsWith("name","超"); -``` - -### 3.5 关系查询 - -因为在数据存储中,类之间可能会有直接的关联关系。比如一个Student对象studentA,它的英语老师会指向一个Teacher的对象teacherA。 - -那么,如果我要查询所有英语老师为teacherA的Student对象,可以使用以下代码: - -``` -JBQuery jbQuery = JBQuery.getInstance("Student"); -//第二个参数为teacherA的id -JBObject teacherA = JBObject.createWithoutData("Teacher","939666c47ded4fafb1a8403b830cdc98"); -jbQuery.whereEqualTo("englishTeacher",teacherA); -jbQuery.findInBackground(new FindCallback() { - @Override - public void done(List result) { - Log.d("ObjectTest", "查询成功,查询到的所有条数为" + result.size()); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); - -``` -当涉及到云端中的三张表的关系查询时,就需要用到`whereMatchesKeyInQuery`方法。 - -假如,在一个图书馆系统中,用户可以关注多个类别,如"经典著作"类别,"历史地理"类别。 - -如果要查询用户关注的类别中的所有书籍,可以使用以下代码: - -``` -JBQuery mainQuery = JBQuery.getInstance("Book"); -JBQuery subQuery = JBQuery.getInstance("SubscriptionCategory"); -subQuery.whereEqualTo("user", JBUser.getCurrentUser()); -mainQuery.whereMatchesKeyInQuery("category", "subscriptionCategory", "Category", subQuery); -mainQuery.findInBackground(new FindCallback() { - @Override - public void done(List result) { - Log.d("ObjectTest", "查询成功,查询到的所有条数为" + result.size()); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` - -当我们需要将JBQuery查询对象融合起来一起查询的时候,可以使用静态方法`or`来实现 - -例如查询Student中年龄大于18或者小于10的对象,可以使用以下代码: - -``` -JBQuery lotsOfQuery = JBQuery.getInstance("Student"); -lotsOfQuery.whereGreaterThan("age", 18); - -JBQuery fewQuery = JBQuery.getInstance("Student"); -fewQuery.whereLessThan("age", 10); - -List> list = new ArrayList<>(); -list.add(lotsOfQuery); -list.add(fewQuery); - -JBQuery mainQuery = JBQuery.or(MainActivity.this,list); -mainQuery.findInBackground(new FindCallback() { - @Override - public void done(List result) { - Log.d("ObjectTest", "查询成功,查询到的所有条数为" + result.size()); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` - - - -### 3.6 缓存查询 -缓存查询是将查询的结果缓存到本地,当程序处于没有网络连接的状态时,就可以通过缓存查询查出上一次相同查询的结果。 -JavaBaas支持的缓存类型有: - -``` -CACHE_ELSE_NETWORK:先从缓存中获取数据,如果本地没有缓存,从网络中获取数据。 -CACHE_ONLY:只从缓存中获取数据, -CACHE_THEN_NETWORK:先从缓存中获取数据,再从网络中获取数据。 -IGNORE_CACHE:不从缓存中获取数据,只从网络中获取数据,并且获取到的数据不存入缓存中。这是JavaBaas默认的查询方式。 -NETWORK_ELSE_CACHE:先从网络中获取数据,再从缓存中获取数据 -NETWORK_ONLY:只从网络中获取数据,从网络中获取的数据会存入缓存中。 -``` - -使用方法如下: - -```java -JBQuery jbQuery = JBQuery.getInstance("Data"); -jbQuery.setCachePolicy(JBQuery.CachePolicy.CACHE_ELSE_NETWORK); -jbQuery.findInBackground(new FindCallback() { - @Override - public void done(List result) { - Log.d("ObjectTest", "查询成功,查询到的所有条数为" + result.size()); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` - -### 3.7 计数查询 - -如果只是想知道数据库中指定条件的数据个数的话,可以使用计数查询,举例如下: - -```java -1.同步查询: -JBQuery jbQuery = JBQuery.getInstance("Test"); -try { - int count = jbQuery.count(); - Log.d("ObjectTest", "查询到的所有条数为" + count); -} catch (JBException e) { - e.printStackTrace(); -} - -2.异步查询: -JBQuery jbQuery = JBQuery.getInstance("Test"); -//查询'age'字段为'18'的 -jbQuery.whereEqualTo("age",18); -jbQuery.countInBackground(new CountCallback() { - @Override - public void done(int count) { - Log.d("ObjectTest", "查询到的所有条数为" + count); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` -## 四、ACL权限控制 - -JavaBaas提供了ACL(访问控制列表)来管理数据的访问权限。 - -在默认情况下,数据是可读可写的,在特殊情况下,我们可以设置数据在特定的用户访问的权限。比如,Data表中存入某条数据,此条数据在用户A下才可写,而其它用户都只是可读权限。可以使用以下代码: - - -```java -JBObject dataObject = new JBObject("Data"); -dataObject.put("secretData", "100"); -JBAcl acl = new JBAcl(); -//此方法为设置数据全部可读 -acl.setPublicReadAccess(true); -//第一个参数为用户A的userId,此方法为设置数据只有用户A可写。 -acl.setWriteAccess(userAId, true); -dataObject.setACL(acl); - -dataObject.saveInBackground(new SaveCallback() { - @Override - public void done(JBObject object) { - Log.d("ObjectTest", "保存成功 "); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` - -## 五、文件JBFile -### 5.1 JBFile -JBFile允许你将文件存储到服务器中,常见的文件类型有: - - * 图片 - * 影像文件 - * 音乐文件 - * 其它二进制数据 - - -### 5.2 文件元数据 -### 5.4 图像与缩略图获取(待定) -### 5.5 进度提示 -在JBFile的上传回调中可以获得上传的进度 - -例如,保存本地的一张图片到云端,并获取上传的进度,可以使用以下代码: - -``` -JBFile jbFile = new JBFile(new File(Environment.getExternalStorageDirectory() , "demo.jpg")); -jbFile.saveInBackground(new FileUploadCallback() { - @Override - public void done(JBFile jbFile) { - Log.d("ObjectTest", "上传成功"); - } - - @Override - public void error(JBException e) { - Log.d("ObjectTest", "上传失败"); - } - - @Override - public void onProgress(double percent) { - Log.d("ObjectTest", "上传进度为" + percent); - } -}); -``` - -## 六、用户JBUser - -### 6.1 JBUser -JavaBaas提供了JBUser类来处理用户相关的功能。 - -需要注意的是,JBUser继承了JBObject,并在JBObject的基础上增加了一些对用户账户操作的功能。 - -### 6.2 特殊属性 -JBUser有几个特定的属性为: - -* username:用户的用户名(必须) -* password:用户的密码(必须) -* email:用户的电子邮箱(可选) -* phone:用户的手机号码(可选) - -设置属性的方法如下: - -``` -JBUser jbUser = new JBUser(); -//设置用户名 -jbUser.setUsername("ZhangSan"); -//设置密码 -jbUser.setPassword("123456"); -//设置手机号 -jbUser.setPhone("110"); -``` - -### 6.3 注册 -用户注册的示例代码如下: - -``` -1.同步注册 -JBUser jbUser = new JBUser(); -jbUser.setUsername("ZhangSan"); -jbUser.setPassword("123456"); -jbUser.setPhone("110"); -try { - jbUser.signUp(); - Log.d("ObjectTest", "注册成功" + jbUser.getId()); -} catch (JBException e) { - e.printStackTrace(); -} - -2.异步注册 -JBUser jbUser = new JBUser(); -jbUser.setUsername("ZhangSan"); -jbUser.setPassword("123456"); -jbUser.setPhone("110"); -jbUser.signUpInBackground(new SignUpCallback() { - @Override - public void done(JBUser jbUser) { - Log.d("ObjectTest", "注册成功" + jbUser.getId()); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` - -### 6.4 登录 -当用户注册成功后,用户可以通过注册的用户名,密码登录到他们的账户。 -用户登陆的示例代码如下: - -``` -//用户名、密码登录 -String username = "ZhangSan"; -String password = "123456"; -JBUser.loginWithUsernameInBackground(username, password, new LoginCallback() { - @Override - public void done(JBUser jbUser) { - Log.d("ObjectTest", "登陆成功" + jbUser.getId()); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); - -//第三方授权登录(目前仅支持需要传入从第三方平台获取到的accessToken和uid, 并传入登录平台(如QQ、微信微博等)的登陆的方法) -//第一个参数为accessToken,第二个参数为登陆的平台,第三个参数为uid -JBUser.JBThirdPartyUserAuth jbThirdPartyUserAuth = new JBUser.JBThirdPartyUserAuth("OezXcEiiBSKSxW0eoylIeKszaZo3pw9ABL2UB", JBUser.JBThirdPartyUserAuth.SNS_QQ,"8343726DA09DB9830CC32486A4856E0A"); -JBUser.loginWithSnsInBackground(jbThirdPartyUserAuth, new LoginCallback() { - @Override - public void done(JBUser jbUser) { - Log.d("ObjectTest", "登陆成功" + jbUser.getId()); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } -}); -``` - -### 6.5 当前用户 -为了避免用户每次打开应用程序的时候都要登陆,可以使用本地缓存的`currentUser`对象 - -当用户注册或者登陆成功后,本地会生成一个`currentUser`对象,你可以使用此对象来进行判断用户是否登陆: - -``` -//使用currentUser对象进行判断 -JBUser jbUser = JBUser.getCurrentUser(); -if (jbUser!=null){ - Log.d("ObjectTest", "currentUser不为空,允许用户使用"); -}else { - Log.d("ObjectTest", "currentUser为空,此时可打开用户注册/登陆的界面"); -} - -``` -清除缓存的`currentUser`对象。 - -``` -JBUser.logout(new LogoutCallback() { - @Override - public void onLogout(boolean isSuccess) { - if (isSuccess){ - Log.d("ObjectTest", "登出成功"); - } - } -}); -``` - - -### 6.6 修改密码 -假如用户登录成功后,想改变自己的用户信息,可以通过以下代码来更新: - -``` -JBUser jbUser = JBUser.getCurrentUser(); -if (jbUser!=null){ - jbUser.updatePassword("123456", "456789", new RequestCallback() { - @Override - public void done() { - Log.d("ObjectTest", "修改成功"); - } - - @Override - public void error(JBException e) { - e.printStackTrace(); - } - }); -} -``` -### 6.7 SessionToken介绍 -`SessionToken`是`JBUser`的一个非常特殊的属性,是 -`JBUser`的内建字段。当用户注册成功后,自动生成且唯一。 - -当用户更改重置密码后,`SessionToken`也会被重置。 - -`SessionToken`的作用主要有两个方面: - -* 服务器用来校验用户登录与否 -* 保证在多设备登录同一账号情况下,用户账号安全 - -## 七、设备与推送 - -`_Installation`是存在于云端的一个用来管理设备信息的默认表。 - -* `deviceToken` : 设备的唯一标示符 -* `deviceType` : 对于Android设备来说,type就是"Android" - - -## 八、调用云方法 - -有些逻辑是无法通过普通的增删改查数据来实现的,比如记录所有用户打开某界面的次数openCount。这时候,服务端通过提供"云端方法"即可解决这些问题。 - -假如为了解决上述问题,服务端提供了一个"addOpenCount"云方法,当客户端调用此方法的时候,服务端则会把openCount数量加1。 - -调用云方法的代码非常简单: - -```java -JBCloud.callFunctionInBackground("addOpenCount", null ,new CloudCallback() { - @Override - public void done(ResponseEntity responseEntity) { - Log.d("ObjectTest", "调用成功 " + responseEntity.getMessage()); - } - - @Override - public void error(JBException e, ResponseEntity responseEntity) { - Log.d("ObjectTest", "调用失败 " + responseEntity.getMessage()); - } -}); -``` - -有的时候调用云方法还需将参数传递上去,比如我们需要实现一个用户给某产品评分的需求,服务端提供一个"addProductScore"云方法,客户端就可以调用此方法并将所评的分数传上去。 - -代码如下: - -``` -HashMap params = new HashMap<>(); -params.put("productScore",100); - -JBCloud.callFunctionInBackground("addProductScore", params, new CloudCallback() { - @Override - public void done(ResponseEntity responseEntity) { - Log.d("ObjectTest", "调用成功 " + responseEntity.getMessage()); - } - - @Override - public void error(JBException e, ResponseEntity responseEntity) { - Log.d("ObjectTest", "调用失败 " + responseEntity.getMessage()); - } -}); -``` diff --git a/doc/manual/android-sdk.md b/doc/manual/android-sdk.md new file mode 100644 index 0000000..bea0b3e --- /dev/null +++ b/doc/manual/android-sdk.md @@ -0,0 +1,382 @@ +# 目录 +## 一、SDK安装与初始化 + +#### Maven自动导入安装 + +``implementation 'com.javabaas:javasdk:+'`` + +#### SDK初始化: + +在系统启动的地方,如自己的Application类中注册SDK: + +```java +public class App extends Application { + + @Override + public void onCreate() { + super.onCreate(); + + // 初始化参数依次为 后台服务器地址,AppId, AppKey + JBConfig.init("http://139.198.5.252:9000/api","59f85aee12a0aa06cb8539a7","4a4b67e87db24adbabfc5c64c1343dd2"); + } +} +``` + +然后在`AndroidManifest.xml`中配置SDK所需的一些权限 + +``` + +``` + +SDK配置完成,可以进行一些简单的访问测试: +确保服务器端已经创建一个表叫`Test` + +```java +public void onSave(View view) { + final JBObject testC = new JBObject("Test"); + testC.put("testA", "测试A"); + testC.put("testB", "测试B"); + testC.saveInBackground(new JBBooleanCallback() { + @Override + public void done(boolean success, JBException e) { + if (success){ + Log.d(TAG,"保存成功"); + }else { + Log.d(TAG,"保存失败"); + } + } + }); +} +``` + +## 二、对象 +### 32..1 JBObject +`JBOject`是JavaBaas中的基础对象,也可以理解为`JBOject`对应着数据库表中的一条信息。 + +假如你在云端数据库中使用`FoodLike`表来记录用户最喜欢的食物,那么表中至少会有`foodName`(食品名称),`userName`(用户名称)属性,那么,你应该这样生成`JBOject`: + +```java +JBObject jbObject = new JBObject("FoodLike"); +jbObject.put("foodName","dumpling"); +jbObject.put("userName","ZhangSan"); +``` +>有几点需要注意: + +* 每个`JBOject`都必须在云端有对应的数据库表和相应的字段。 +* 每个`JBOject`都有保留字段,分别为`_id``acl``createdPlat``updatedPlat``createdAt``updatedAt`等,这些字段由系统自动生成和修改,不需要开发者进行指定。 + +### 2.2 同步与异步 +JavaBaas提供了数据检索,保存,更新,删除,查询的同步与异步的方法。 + +注: 在Android UI主线程中调用同步的方法,可能会导致UI主线程阻塞。所以,在UI主线程中请使用异步的方式。 + + +### 2.3 检索对象 +如果你知道了云端中某条数据的`objectId`,那么可以通过以下代码获取此条数据对应的`JBOject`对象: + +```java +1.同步检索: +JBQuery jbQuery = JBQuery.getInstance("FoodLike"); +jbQuery.whereEqualTo("_id", objectID); +JBObject result; +try { + List resultList = jbQuery.find(); + result = resultList.get(0); +} catch (JBException e) { + e.printStackTrace(); +} + +2.异步检索: +JBQuery jbQuery = JBQuery.getInstance("FoodLike"); +jbQuery.whereEqualTo("_id", objectID); +jbQuery.findInBackground(new JBFindCallBack() { + @Override + public void done(boolean success, List objects, JBException e) { + if (success){ + Log.d(TAG,"查询成功"); + }else { + Log.d(TAG,"查询失败"); + } + } +}); +``` + +### 2.4 保存对象 +如2.1所示,假如你在本地生成一个`JBObject`之后,那么可以使用以下代码将其保存至云端: + +```java +1.同步保存: +try { + jbObject.save(); + Log.d(TAG , "保存成功"); +} catch (JBException e) { + e.printStackTrace(); +} + +2.异步保存: +jbObject.saveInBackground(new JBBooleanCallback() { + @Override + public void done(boolean b, JBException e) { + if (b){ + Log.d(TAG , "保存成功"); + }else { + Log.d(TAG , "保存失败"); + } + } +}); +``` + 如需在保存成功后更新本地对象,可以调用 + + `jbObject.setFetchWhenSave(true);` + +### 2.5 更新对象 +如果你知道了云端中某条数据的`objectId`,那么可以通过以下代码更新云端对应的数据: + +```java +1.同步更新: +JBObject jbObject = new JBObject("FoodLike"); +jbObject.setId(objectId); +jbObject.put("foodName","hamburger"); +try { + jbObject.save(); + Log.d(TAG , "更新成功"); +} catch (JBException e) { + Log.d(TAG , "更新失败"); + e.printStackTrace(); +} + +2.异步更新: +JBObject jbObject = new JBObject("FoodLike"); +jbObject.setId(objectId); +jbObject.put("foodName","hamburger"); +jbObject.saveInBackground(new JBBooleanCallback() { + @Override + public void done(boolean b, JBException e) { + if (b){ + Log.d(TAG , "更新成功"); + }else { + Log.d(TAG , "更新失败"); + } + } +}); +``` +### 2.6 删除对象 +如果你知道了云端中某条数据的`objectId`,那么可以通过以下代码删除云端对应的数据: + +```java +1.同步删除: +JBObject jbObject = new JBObject("FoodLike"); +jbObject.setId(objectId); +try { + jbObject.delete() + Log.d(TAG, "删除成功"); +} catch (JBException e) { + e.printStackTrace(); +} + +2.异步删除: +JBObject jbObject = new JBObject("FoodLike"); +jbObject.setId(objectId); + +jbObject.deleteInBackground(new JBBooleanCallback() { + @Override + public void done(boolean success, JBException e) { + view.setClickable(true); + if (success) { + Log.d(TAG, "删除成功"); + } else { + Log.d(TAG, "删除失败"); + } + } +}); +``` + +## 三、用户JBUser + +### 3.1 JBUser +JavaBaas提供了JBUser类来处理用户相关的功能。 + +需要注意的是,JBUser继承了JBObject,并在JBObject的基础上增加了一些对用户账户操作的功能。 + +### 3.2 特殊属性 +JBUser有几个特定的属性为: + +* username:用户的用户名(必须) +* password:用户的密码(必须) +* email:用户的电子邮箱(可选) +* phone:用户的手机号码(可选) + +设置属性的方法如下: + +``` +JBUser jbUser = new JBUser(); +//设置用户名 +jbUser.setUsername("ZhangSan"); +//设置密码 +jbUser.setPassword("123456"); +//设置手机号 +jbUser.setPhone("110"); +``` + +### 3.3 注册 +用户注册的示例代码如下: + +``` +1.同步注册 +JBUser jbUser = new JBUser(); +jbUser.setUsername("ZhangSan"); +jbUser.setPassword("123456"); +try { + jbUser.signUp(); + Log.d(TAG, "注册成功"); +} catch (JBException e) { + e.printStackTrace(); +} + +2.异步注册 +JBUser jbUser = new JBUser(); +jbUser.setUsername("ZhangSan"); +jbUser.setPassword("123456"); +jbUser.signUpInBackground(new JBBooleanCallback() { + @Override + public void done(boolean success, JBException e) { + if (success) { + Log.d(TAG, "注册成功"); + } else { + Log.d(TAG, "注册失败"); + } + } +}); +``` + +### 3.4 登录 +当用户注册成功后,用户可以通过注册的用户名,密码登录到他们的账户。 +用户登陆的示例代码如下: + +``` +//用户名、密码登录 +String username = "ZhangSan"; +String password = "123456"; +JBUser.loginInBackground(username, password, new JBLoginCallback() { + @Override + public void done(boolean success, JBUser user, JBException e) { + if (success) { + Log.d(TAG, "登录成功"); + } else { + Log.d(TAG, "登录失败"); + } + } +}); + +``` +第三方授权登录,参考[这里](https://github.com/JavaBaas/JavaBaasDoc/blob/master/doc/manual/java-sdk.md#%E7%AC%AC%E4%B8%89%E6%96%B9%E7%A4%BE%E4%BA%A4%E5%B9%B3%E5%8F%B0%E6%B3%A8%E5%86%8C) +### 3.5 当前用户 + +当用户登陆成功后,本地会生成一个`currentUser`对象,你可以使用此对象来进行判断用户是否登陆: + +``` +//使用currentUser对象进行判断 +JBUser jbUser = JBUser.getCurrentUser(); +if (jbUser!=null){ + Log.d(TAG, "currentUser不为空,允许用户使用"); +}else { + Log.d(TAG, "currentUser为空,此时可打开用户注册/登陆的界面"); +} + +``` +清除缓存的`currentUser`对象,即退出登录。 + +``` +JBUser.updateCurrentUser(null); +``` + + +### 3.6 修改密码 +假如用户登录成功后,想改变自己的用户信息,可以通过以下代码来更新: + +``` +JBUser jbUser = JBUser.getCurrentUser(); +if (jbUser!=null){ + jbUser.updatePassword("123456", "456789", new JBUpdatePasswordCallback() { + @Override + public void done(boolean success, String sessionToken, JBException e) { + if (success) { + Log.d(TAG, "修改成功"); + } else { + Log.d(TAG, "修改失败"); + } + } + }); +} +``` +### 3.7 SessionToken介绍 +`SessionToken`是`JBUser`的一个非常特殊的属性,是 +`JBUser`的内建字段。当用户注册成功后,自动生成且唯一。 + +当用户更改重置密码后,`SessionToken`也会被重置。 + +`SessionToken`的作用主要有两个方面: + +* 服务器用来校验用户登录与否 +* 保证在多设备登录同一账号情况下,用户账号安全 + +## 四、设备与推送 + +`_Installation`是存在于云端的一个用来管理设备信息的默认表。 + +* `deviceToken` : 设备的唯一标示符 +* `deviceType` : 对于Android设备来说,type就是"Android" + +```java +JBInstallation.registerDeviceInBackground(deviceType, deviceToken, new JBInstallationCallback() { + @Override + public void done(boolean success, String installationId, JBException e) { + if (success) { + Log.d(TAG, "成功"); + } else { + Log.d(TAG, "失败"); + } + } +}); +``` + +## 五、调用云方法 + +有些逻辑是无法通过普通的增删改查数据来实现的,比如记录所有用户打开某界面的次数openCount。这时候,服务端通过提供"云端方法"即可解决这些问题。 + +假如为了解决上述问题,服务端提供了一个"addOpenCount"云方法,当客户端调用此方法的时候,服务端则会把openCount数量加1。 + +调用云方法的代码非常简单: + +```java +JBCloud.cloudInBackground("addOpenCount", null, new JBCloudCallback() { + @Override + public void done(boolean success, Map data, JBException e) { + if (success) { + Log.d(TAG, "成功"); + } else { + Log.d(TAG, "失败"); + } + } +}); +``` + +有的时候调用云方法还需将参数传递上去,比如我们需要实现一个用户给某产品评分的需求,服务端提供一个"addProductScore"云方法,客户端就可以调用此方法并将所评的分数传上去。 + +代码如下: + +``` +HashMap params = new HashMap<>(); +params.put("productScore",100); + +JBCloud.cloudInBackground("addProductScore", params, new JBCloudCallback() { + @Override + public void done(boolean success, Map data, JBException e) { + if (success) { + Log.d(TAG, "成功"); + } else { + Log.d(TAG, "失败"); + } + } +}); +``` diff --git a/doc/manual/command_line.md b/doc/manual/command_line.md index 4a3272a..227b937 100644 --- a/doc/manual/command_line.md +++ b/doc/manual/command_line.md @@ -1,13 +1,36 @@ -#命令行工具 -命令行工具`JBShell`是JavaBaas的配套工具,使用`JBShell`可以完成应用的创建删除、类的创建删除、字段的创建删除、对象的增删改查等操作,以及一些便捷的辅助功能。 +# 命令行工具 +命令行工具`JBShell`是JavaBaas的配套工具,可以使用JBShell对JavaBaas进行管理维护操作。包括应用的创建删除、类的创建删除、字段的创建删除、对象的增删改查等操作,以及一些便捷的辅助功能。 +## 主要功能 + +* 应用管理(创建、删除、导入导出) +* 类管理(创建、删除、权限管理) +* 字段管理(创建、删除、权限管理) +* 数据操作(增删改查) +* 生成鉴权信息 +* 获取数据源URL + +## 安装 `JBShell`基于java编写,编译及运行需要安装JDK环境。 -##运行 -使用以下命令启动命令行工具 +### Mac&Linux安装 +在命令行中执行 + +``` +curl -s "http://get.javabaas.com/jbshell.sh" | bash +``` + +安装成功后,打开一个新窗口,输入命令`JB`即可启动命令行工具。 + +### Windows安装 +在[下载](/download.md)页面,下载JavaBaasShell(windows)命令行工具程序,启动执行即可。 + + +## 启动 +在命令行中使用以下命令启动`JBShell`工具: ``` -java -jar JBShell.jar +jb ``` 启动成功后显示以下信息 @@ -19,48 +42,39 @@ java -jar JBShell.jar | | / _` |\ \ / // _` || ___ \ / _` | / _` |/ __| /\__/ /| (_| | \ V /| (_| || |_/ /| (_| || (_| |\__ \ \____/ \__,_| \_/ \__,_|\____/ \__,_| \__,_||___/ -Version:1.0.0 +Version:2.0.0 Host:http://localhost:8080/api/ -AdminKey:V1hwT1UyRkhUblZpUjNoclVWTlZlbEpEVlhwU1FTVXpSQ1V6UkElM0QlM0Qc3Rhc +AdminKey:JavaBaas BAAS> ``` -###配置文件 -`JBShell.jar `为程序执行文件。同目录下的`config.properties`为配置文件。内容如下: - -``` -host = http://localhost:8080/api/ -key = JavaBaas -``` +## 命令 +`JBShell`使命命令行交互方式进行操作。 -其中`host`为`JavaBaas`服务器所在的地址,本地调用`JBShell`默认使用localhost即可,远程管理需设置正确的地址。 - -`key`为`JavaBaas`超级密钥,不设置默认为JavaBaas。 - -##命令 -###内建命令 -####帮助信息 help +### 内建命令 +#### 帮助信息 help 查看帮助信息。 -####版本号 version +#### 版本号 version 查看`JBShell`版本号。 -####清屏 cls +#### 清屏 cls 清空当前终端信息。 -####退出 exit +#### 退出 exit 退出`JBShell`命令行。 -###应用相关命令 -####创建应用 app add {appName} +### 应用相关命令 +#### 创建应用 app add {appName} 创建应用。 ```bash BAAS>app add Comic -App added. +应用创建成功 +设置当前应用为 Comic ``` -####显示应用列表 app +#### 显示应用列表 app 查询系统中所有的应用。如: ```bash @@ -68,147 +82,258 @@ BAAS>apps Comic ``` -####删除应用 app del {appName} +#### 设置当前应用 use {appName} +设置当前正在操作的应用 `appName`参数为应用名。设置成功后光标将变为 当前应用名。 + +```bash +BAAS>use Comic +设置当前应用为 Comic +Comic> +``` +设置当前应用为Comic。 + +#### 删除应用 app del {appName} 删除应用,`appName `参数为应用名。如: ```bash BAAS>app del Comic -App deleted. +确认要删除应用? +(y/n)>y +删除成功 ``` -####设置当前应用 use {appName} -设置当前正在操作的应用 `appName`参数为应用名。设置成功后光标将变为 当前应用名。 +提示:删除应用时需要进行二次确认(输入y) + +#### 显示鉴权信息 token +显示当前正在操作应用的鉴权信息。包括AppId、Key等信息。 -```bash -BAAS>use Comic -Set current app to Comic -Comic> ``` -设置当前应用为Comic。 +Comic>token +Timestamp: 1510217270432 +Nonce: 83ee9b42aba0455882f383fd03c3f860 +AdminSign: d0bdd0cb587f5b544a470f53491d5356 +AppId: 5a040a88ae07be6f1fcfb98a +Key: 01bca9e5148e43458335e288468dff54 +MasterKey: 433f4abc5b18470282daaac8e8bd272a +Sign: d0bdd0cb587f5b544a470f53491d5356 +MasterSign: cd917d5a4729f24e0403646857d665a2 +``` -###类相关命令 +### 类相关命令 由于所有类操作都是针对某一个应用中的类进行的,因此类相关操作需先**设置当前应用**。 -####添加类 class add {className} +#### 添加类 class add {className} 为当前应用添加类,`className`参数为类名。 此方法必须在已经设置了当前应用时调用。 如: ```bash Comic>class add Book -Class added. +类创建成功 ``` 添加名称为Book的类 -####显示类列表 class +#### 显示类列表 class 查询当前应用中的所有类。此方法必须在已经设置了当前应用时调用。如: ```bash -Comic>classes -_User -_Installation -_File -Book -Page -Category +Comic>class +_File(0) +_Installation(0) +_PushLog(0) +_SmsLog(0) +_User(0) +Book(0) +``` +表示当前应用中有六个类,分别为内建类`_User` `_Installation` `_File` `_PushLog ` `_SmsLog `以及用户自建的`Book`。 + +#### 设置当前类 set {className} +设置当前正在操作的类`className`参数为类名。设置成功后光标将变为 当前应用名_当前类名。 + +```bash +BAAS>set Book +Set current class to Book +Comic Book> ``` -表示当前应用中有六个类,分别为内建类`_User` `_Installation` `_File`以及用户自建的`Book` `Page` `Category`。 +设置当前类为Book。 -####删除类 class del {className} +#### 删除类 class del {className} 在当前应用中,删除类`className`参数为类名。此方法必须在已经设置了当前应用时调用。如: ```bash BAAS>class del Book -Class deleted. +是否确认删除类? +(y/n)>y +删除成功 ``` 删除名称为Book的类 -####设置当前类 set {className} -设置当前正在操作的类`className`参数为类名。设置成功后光标将变为 当前应用名_当前类名。 +提示:删除类时需要进行二次确认(输入y) + +### 字段相关命令 +由于所有字段操作都是针对某一个类进行的,因此字段操作需先**设置当前类**。 + +#### 添加字段 field add {fieldName} +在当前类中添加一个字段。其中`fieldName`为字段名,添加后,需要选择字段类型,参见[数据类型](/overview/object.md#数据类型)。如: ```bash BAAS>set Book Set current class to Book -Comic Book> +Comic Book>field add name +请选择FieldType 默认为STRING +1 STRING +2 NUMBER +3 BOOLEAN +4 DATE +5 FILE +6 OBJECT +7 ARRAY +8 POINTER +0 取消 +>1 +创建字段成功 ``` -设置当前类为Book。 -###字段相关命令 -由于所有字段操作都是针对某一个类进行的,因此字段操作需先**设置当前类**。 +``` +Comic Book>field add price +请选择FieldType 默认为STRING +1 STRING +2 NUMBER +3 BOOLEAN +4 DATE +5 FILE +6 OBJECT +7 ARRAY +8 POINTER +0 取消 +>2 +创建字段成功 +``` -####显示字段列表 field +在`Book`类中添加字符型字段`name`以及数值型字段`price`。 + +#### 显示字段列表 field 显示当前类的所有字段。如: ```bash -BAAS>set Book -Set current class to Book +Comic>set Book +设置当前类为 Book Comic Book>field name price ``` 表示当前类`Book`中有两个字段、分别为字符型字段`name`以及数值型字段`price`。 -####添加字段 field add {fieldName} [--type {typeId}] -在当前类中添加一个字段。其中`fieldName`为字段名,`typeId`为可选参数,参数值为字段的[数据类型](/overview/object.md#数据类型)。如: - -```bash -BAAS>set Book -Set current class to Book -Comic Book>field add name -Field added. -Comic Book>field add price --type 2 -Field added. -``` -在`Book`类中添加字符型字段`name`以及数值型字段`price`。 - -####删除字段 field del {fieldName} +#### 删除字段 field del {fieldName} 在当前类中删除一个字段。其中`fieldName`为字段名。如: ```bash Comic Book>field del name -Field deleted. +是否确认删除字段? +(y/n)>y +删除成功 ``` 在`Book`类中删除字段`name`。 -####查看所有字段数据类型 field type +提示:删除字段时需要进行二次确认(输入y) + +#### 查看所有字段数据类型 field type 显示当前支持的字段类型及对应的值。参见[数据类型](/overview/object.md#数据类型)。 -###对象相关命令 +### 对象相关命令 在对对象进行操作前,需要先**设置当前类**。 -####查询所有对象 list [{where}] -查询当前类的所有对象。参数`where`是查询条件,条件为空时显示所有对象。 +#### 插入对象 add {body} +向当前类插入对象。如: ```bash -Comic Book>list {price:20} -{"createdAt":1441880564365,"price":20,"name":"b","id":"55f159f477c877a455248a23","acl":{"*":{"read":true,"write":true}},"updatedAt":1441880564365} -{"createdAt":1441880561707,"price":20,"name":"a","id":"55f159f177c877a455248a22","acl":{"*":{"read":true,"write":true}},"updatedAt":1441880561707} +Comic Book>add {"name":"Three body","price":100} +对象创建. +Comic Book>add {"name":"Four body","price":20} +对象创建. ``` -查询`Book`类中所有`price`等于20的对象。请参阅查询条件相关文档。 +在`Book`类中添加一个对象。 -####插入对象 add {body} -向当前类插入对象。如: +#### 查询所有对象 list [{where}] +查询当前类的所有对象。参数`where`是查询条件,条件为空时显示所有对象。 ```bash -Comic Book>add {name:"Three body",price:100} -Object added. +Comic Book>list {"price":20} +{"className":"Book", "objectId":"963bc4856ee743038bf15d022e9b33f2", "updatedAt":"1510758374320", "createdAt":"1510758374320", "serverData":{"price":20,"name":"Four body"}} ``` -在`Book`类中添加一个对象。 +查询`Book`类中所有`price`等于20的对象。请参阅查询条件相关文档。 -####删除对象 del {id} +#### 删除对象 del {id} 删除当前类中指定`id`的对象。如: ```bash Comic Book>del 55f159f777c877a455248a24 -Object deleted. +对象删除. ``` 删除`Book`类中`id`为55f159f777c877a455248a24的对象。 -####查询对象个数 count [{where}] +#### 查询对象个数 count [{where}] 查询当前类中对象的个数。参数`where`是查询条件,条件为空时则显示当前类中所有对象的个数。如: ```bash -Comic Book>count {price:20} -2 +Comic Book>count {"price":20} +1 ``` 查询`Book`类中所有`price`等于20的对象个数。请参阅查询条件相关文档。 + +#### 表格打印 table [{where}] +查询当前类的所有对象,并以表格形式打印,参数`where`是查询条件,条件为空时显示所有对象。 + +``` +Comic Book>table +┌──────────────────────────────────┬────────────────────┬────────────────────┐ +│ id │ name │ price │ +│ │ +├──────────────────────────────────┼────────────────────┼────────────────────┤ +│ e19a578647f24f76b8af4a54c6e2e4ee │ Four body │ 20 │ +├──────────────────────────────────┼────────────────────┼────────────────────┤ +│ 517c34501f8e4188b01223094dd56fa6 │ Three body │ 100 │ +└──────────────────────────────────┴────────────────────┴────────────────────┘ +``` + +### 服务端地址配置 +`JBShell`可以同时配置多个服务器地址并自由切换。程序安装后会自动配置为默认服务器地址(http://localhost:8080/api)。如果需要连接远程服务器需要使用服务器地址配置相关命令。 + +#### 选择服务器地址 server + +``` +BAAS>server +请选择服务器: +1 http://localhost:8080/api +0 取消 +``` + +可以看到,我们当前只存在默认本地服务器,端口号为8080,输入数字即可切换服务器。 + +#### 添加服务器 server add + +``` +BAAS>server add +请输入服务器地址: +>(http://127.0.0.1:8080/api)http://192.168.1.1:8080/api +请输入AdminKey: +>(JavaBaas)JavaBaas +当前服务器地址切换为 http://192.168.1.1:8080/api +服务器添加成功 +``` + +添加服务器,需输入服务器地址(ip地址+端口号+/api作为结尾),AdminKey(在JavaBaasServer的配置文件中配置)。 + +#### 删除服务器 server del + +``` +BAAS>server del +请选择要删除的服务器: +1 http://localhost:8080/api +2 http://192.168.1.1:8080/api +0 取消 +>2 +服务器删除成功 +``` + +删除服务器时,输入要删除的服务器编号。 \ No newline at end of file diff --git a/doc/manual/ios-adk_api.md b/doc/manual/ios-sdk.md similarity index 91% rename from doc/manual/ios-adk_api.md rename to doc/manual/ios-sdk.md index ebc90a3..4347db1 100644 --- a/doc/manual/ios-adk_api.md +++ b/doc/manual/ios-sdk.md @@ -1,8 +1,8 @@ -#目录 -#一、SDK介绍与快速入门 -##SDK介绍 +# 目录 +# 一、SDK介绍与快速入门 +## SDK介绍 -#二、SDK安装 +# 二、SDK安装 CocoaPods 是一个强大的管理第三方库的工具,能最大化的简化安装过程。因此我们推荐您使用这个方法来安装SDK。 首先,安装CocoaPods,安装方法具体参考:[《CocoaPods 安装和使用教程》](http://code4app.com/article/cocoapods-install-usage) @@ -10,12 +10,13 @@ CocoaPods 是一个强大的管理第三方库的工具,能最大化的简化 CocoaPods安装完毕以后,在项目的根目录下创建一个名为`Podfile`的文件(无扩展名),并添加以下内容 ``` -pod 'JavaBaasSDK' +pod 'javabaas' ``` 然后在终端执行`pod install`来安装。安装完毕以后,运行`pod search JavaBaasSDK`以确认SDK安装到本地库。 -#三、对象 -##3.1 JBObject + +# 三、对象 +## 3.1 JBObject `JBObject`是基础对象和数据类型,其本质是一个json字符串。可以像使用`NSDictionary`一样,给`JBObject`赋值取值。 由于与`NSDictionary`的相似性,每个`JBObject`对象都包含若干属性值对,也就是键值对(key-value)。属性值可以直接设定,也可随时添加新属性值。 @@ -27,6 +28,7 @@ singer : "张三"; songName : "张三的歌"; length : 241; ``` + 需要注意的是,以下所列出的为系统保留字段,由系统自动生成或更新,既不可作为属性名使用,也无需开发者进行指定。 ```objectivec @@ -44,7 +46,8 @@ JBObject *single = [JBObject objectWithClassName:@"Single"]; [single setObject:@"张三的单曲" forKey:@"songName"]; [single setObject:@(241) forKey:@"length"]; ``` -##3.2 同步与异步 + +## 3.2 同步与异步 JavaBaas的SDK同时提供了数据查询、保存、更新等的同步和异步方法。 例如,我们要保存上面创建好的"张三的单曲"的单曲对象: @@ -62,9 +65,10 @@ NSError *error = nil; } }]; ``` + 在iOS或OS X中,大部分代码都是在主线程中运行的。但是,当程序在主线程中访问网络时,会经常出现卡顿崩溃,而且在通常情况下,我们需要在一些操作完成后立即运行后面的代码,所以同步方法不放在主线程中运行。 -##3.3 检索对象 +## 3.3 检索对象 如果已知objectId,用JBQuery就可以查询到与之相对应的唯一的JBObject。例如, ```objectivec @@ -83,7 +87,8 @@ JBObject *single = [getObjectOfClass:@"Single" objectId:@"ac31c72291854630824dbe } }]; ``` -##3.4 保存对象 + +## 3.4 保存对象 如果我们需要发布或上传一首单曲(single),那么,需要调用`save`方法,数据才能被真正保存下来。 例如,将创建好的"张三的单曲"保存到服务器: @@ -101,13 +106,15 @@ NSError *error = nil; } }]; ``` + 运行上述示例代码后,想要确认保存是否已经生效,可以到云端的数据管理页面查看数据存储情况。如果已经保存成功,那么在Single的数据表中应该显示出以下纪录: ```objectivec objectId:"ac31c72291854630824dbe94bf269748", singer: "张三", songName:"张三的单曲", length:251, createdAt:"2016-01-03 11:13:39", updatedAt:"2016-01-03 11:13:39" ``` -##3.5 更新对象 + +## 3.5 更新对象 更新对象相对简单,只需要更新属性,再保存即可。例如: ```objectivec @@ -121,9 +128,30 @@ createdAt:"2016-01-03 11:13:39", updatedAt:"2016-01-03 11:13:39" } }]; ``` -需要注意的是,更新对象都是针对单个对象的操作,获得对象的`objectId`才可以去更新对象。服务器判断对象是新增还是更新,是根据有无objectId来决定的。 -##3.6 删除对象 +需要注意的是,更新对象都是针对单个对象的操作,获得对象的`objectId`才可以去更新对象。服务器判断对象是新增还是更新,是根据有无objectId来决定的。
+ +此外,对于一些特殊情况,例如Number类型的字段,我们需要记录某个音频的打开次数(readCount),然而对于一个热门音频,可能会有很多并发打开音频操作,如果每次我们都是通过请求获取改音频目前的readCount,然后加1后再通过请求写到后台,那么这极容易造成数据脏读,引发冲突和覆盖,最终导致结果不准。对于这种场景,在更新对象的操作中,我们提供了一些原子操作: + +```objectivec +[single incrementKey:@"readCount"]; +[single saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) { + // code +}]; +``` + +除了`incrementKey`这个原子操作外,我们还提供了其他几种原子操作: + +方法 | 描述 +--- | --- +removeKey:(NSString *)key | 删除字段 +addArray:(NSArray *)objects forKey:(NSString *)key | NSArray类型字段添加值 +addUniqueArray:(NSArray *)objects forKey:(NSString *)key | NSArray类型字段添加与之前不重复的值 +removeArray:(NSArray *)objects forKey:(NSString *)key | NSArray类型字段删除值 +incrementKey:(NSString *)key byAmount:(NSNumber *)amount; | NSNumber类型字段原子增加或原子减少 +multiply:(NSString *)key byAmount:(NSNumber *)amount | NSNumber类型字段原子倍数增加 + +## 3.6 删除对象 删除一个`JBObject`对象: ```objectivec @@ -131,6 +159,7 @@ createdAt:"2016-01-03 11:13:39", updatedAt:"2016-01-03 11:13:39" NSError *error = nil; [single delete:&error]; ``` + 如果需要在删除后进行操作可以使用`deleteInBackgroundWithBlock:` ```objectivec @@ -143,7 +172,8 @@ NSError *error = nil; } }]; ``` -##3.7 关联对象 + +## 3.7 关联对象 对象可以和其他对象之间相互关联。我们可以把一个JBObject的实例a,当成另一个JBObject的实例b的属性值保存。 例如,一首单曲是隶属一张专辑的,创建一张专辑信息并对应一首单曲,那么,这首单曲就是实例a,而它所属的专辑就是实例b。专辑可以作为单曲的属性保存。因此可以这样写: @@ -174,6 +204,7 @@ NSError *error = nil; } }]; ``` + 默认情况下,在获取到一个JBObject对象实例时,与之相关联的JBObject对象的属性值是获取不到的。这些对象除了objectId之外,其他属性值都是空的。例如我们获取到一个单曲对象,而它关联的专辑对象的属性值,除了objectId,其他的名称、发布时间等都是空的,我们要得到全部这些属性数据,用include来获得关联对象的所有属性: ```objectivec @@ -193,45 +224,13 @@ NSArray *objects = (NSArray *)[query findObjects:&error]; } }]; ``` -##3.8 原子操作 -许多应用都需要实现计数器功能。比如一首单曲,我们需要记录有多少用户下载了它,但可能在同一时间内有多个用户对同一首单曲进行下载操作,如果在每个客户端直接把它们读到的计数值增加之后再写回去,那么极容易引发冲突和付费,导致结果不准,因此,我们使用`incrementKeyInBackground:block:`以原子操作方式来实现计数,这个方法默认计数加1: - -```objectivec -//同步方法-默认计数加1 -NSError *error = nil; -[single incrementKey:@"downloadCount" error:&error]; -//异步方法-默认计数加1 -[singel incrementKeyInBackground:@"downloadCount" block:^(BOOL succeeded, NSError *error) { - if (succeeded) { - //返回成功,计数加1 - } else { - //返回失败 - } -}]; -``` -也可以使用`incrementKeyInBackground:byAmount:block:`来给字段累加一个特定数值,传入的数值只能是整形的: -```objectivec -//同步方法-计数加任意值 -NSError *error = nil; -[single incrementKeyInBackground:@"playCount" byAmount:@(10) error:&error]; - -//异步方法-计数加任意值 -[single incrementKeyInBackground:@"playCount" byAmount:@(10) block:^(BOOL succeeded, NSError *error) { - if (succeeded) { - //返回成功,计数加10 - } else { - //返回失败 - } -}]; -``` -##3.9 批量操作 -正在开发,敬请等待 -##3.10 数据类型 +## 3.8 数据类型 目前,我们使用过的数据类型有`NSString`、`NSDate`、`NSNumber`、`NSArray`、`NSDictionary`和`JBObject`。 -#四、查询 + +# 四、查询 SDK中的`JBQuery`类提供了多种检索方法,以满足诸如单对象查询、多对象查询、缓存查询等多种需求。 -##4.1 基本查询 +## 4.1 基本查询 单对象查询:`getObjectInBackgroundWithId:block:`,只能查询单个对象实例。 多对象查询:`findObjectsInBackgrounWithBlock:`,一般来说,在这之前需要创建一个`JBQuery`对象,并设定相应的查询条件,之后block会返回符合条件的由JBObject组成的NSArray. @@ -256,7 +255,8 @@ NSArray *objects = (NSArray *)[query findObjects:&error]; } }]; ``` -##4.2 约束查询 + +## 4.2 约束查询 给`JBQuery`的查询添加约束条件有多种方法。 `whereKey:equalTo:`、`whereKey:notEqualTo:`用来搭配对应的键和值过滤对象。 @@ -264,6 +264,7 @@ NSArray *objects = (NSArray *)[query findObjects:&error]; //查询歌手不是张三的单曲 [query whereKey:@"singer" notEqualTo:@"张三"]; ``` + 一次查询可以设置多个约束条件,只有满足所有约束条件的对象才会被返回,这相当于使用and类型的查询条件。 ```objectivec @@ -271,11 +272,13 @@ NSArray *objects = (NSArray *)[query findObjects:&error]; [query whereKey:@"singer" notEqualTo:@"张三"]; [query whereKey:@"length" greaterThan:@(180)]; ``` + `limit`:限制返回结果的数量。返回数量默认是100,limit取值范围是1到1000。 ```objectivec query.limit = 20; //最多返回20条结果 ``` + `skip`:跳过初始结果,对于分页很实用。 ```objectivec @@ -290,6 +293,7 @@ query.skip = 20; //跳过前20条查询结果 //按照播放次数降序排列 [query addDescendingOrder:@"playTimes"]; ``` + 查询中“比较”,`whereKey:lessThan:`(小于)、`whereKey:lessThanOrEqualTO:`(小于等于)、`whereKey:greaterThan:`(大于)、`whereKey:greaterThanOrEqualTo:`(大于等于): ```objectivec @@ -302,6 +306,7 @@ query.skip = 20; //跳过前20条查询结果 //下载次数 >= 100 [query whereKey:@"downloadCount" greaterThanOrEqualTo:@(100)]; ``` + 查询中的“存在”,`whereKeyExist:`(存在)、`whereDoesNotExist:`(不存在): ```objectivec @@ -322,7 +327,6 @@ NSArray *objects = (NSArray *)[query findObjects:&error]; } }]; - //检索所有不存在MV的单曲对象 JBQury *query = [JBQuery queryWithClassName:@"Single"]; [query whereKeyDoesNotExist:@"mv"]; @@ -340,21 +344,24 @@ NSArray *objects = (NSArray *)[query findObjects:&error]; } }]; ``` -##4.3 数组值查询 + +## 4.3 数组值查询 当属性值为数组时,可以使用`whereKey:containedIn:` ```objectivec //假定已知歌手名为"张三"的zhangsan(Singer)对象和歌手名为"李四"的lisi(Singer)对象,检索出歌手为张三或李四的单曲对象 [query whereKey:@"singer" containedIn:@[zhangsan, lisi]]; ``` -##4.4 模糊查询 + +## 4.4 模糊查询 ```objectivec //查询所有名字name中包含“张”的歌手 JBQuery *query = [JBQuery queryWithClassName:@"Singer"]; [query whereKey:@"name" containsString:@"张"]; ``` -##4.5 关系查询 + +## 4.5 关系查询 查询关系数据的方法有多种。可以使用`whereKey:equalTo:`,就像使用其他数据类型一样。 例如,每个单曲`Single`的`singer`字段都有一个`Singer`歌手对象,那么找出指定歌手的单曲: @@ -373,6 +380,7 @@ NSArray *objects = (NSArray *)[query findObjects:&error]; // 返回的objects数组就是singer字段为张三所有Single对象 }]; ``` + 如果要做嵌套查询,应使用`whereKey:matchesQuery:`,举例来说,检索专辑销量超过50000的所有单曲对象: ```objectivec @@ -391,6 +399,7 @@ NSArray *objects = (NSArray *)[query findObjects:&error]; //objects包含了所有专辑销量超过50000的单曲对象 }]; ``` + 如果要用一个对象中某一键值,去匹配另一个查询结果对象中一个键值,来得到最终结果,可以使用`whereKey:matchesKey:matchesClass:inQuery:`,例如,检索当前用户所关注歌手的所有单曲对象: ```objectivec @@ -414,6 +423,7 @@ NSArray *objects = (NSArray *)[query findObjects:&error]; } }]; ``` + 而如果是复合查询的话,可以使用`orQueryWithSubqueries:`. 例如,检索出下载次数很多或者下载次数很少的单曲: @@ -437,8 +447,10 @@ NSArray *objects = (NSArray *)[query findObjects:&error]; } }]; ``` + 注意:在复合查询的子查询中,不能使用非过滤性的约束(如limit、skip、includeKey:)等 -##4.6 缓存查询 + +## 4.6 缓存查询 如果设备离线或者失去网络连接时,打开应用,希望数据也能显示出来,所以通常来说,将请求结果缓存到磁盘是最为简单有效的方法。 而默认的查询不会查询缓存数据,需要通过JBQuery的cachePolicy属性来设置。 @@ -475,7 +487,7 @@ NSArray *objects = (NSArray *)[query findObjects:&error]; 只查网络,查询只查网络数据。 -##4.7 计数查询 +## 4.7 计数查询 只需要获取查询结果的数量,而不需要获取具体的对象时,可以使用`countObject`和`countObjectsInBackgroundWithBlock`:方法。 例如,如果我们想知道某张专辑有多少首单曲的时候: @@ -496,8 +508,8 @@ NSInteger count = [query countObjects:&error]; //返回查询结果的数量 } }]; -``` -#五、ACL权限控制 +``` +# 五、ACL权限控制 ACL(Access Control List)是数据安全管理办法,设置了访问修改权限,更好的保证用户数据安全,因此每一个表都有一个ACL列。 拥有读权限的User才能获取一个对象的数据,拥有写权限的User才能更改或删除一个对象。 @@ -509,6 +521,7 @@ ACL(Access Control List)是数据安全管理办法,设置了访问修改权 [acl setPublicReadAccess:YES]; //设置全部用户均可读 [acl setPublicWriteAccess:YES]; //设置全部用户均可写 ``` + 大部分时候,不同用户针对同一对象访问权限是不同的,那么就需要指定用户访问权限: ```objectivec @@ -516,8 +529,9 @@ JBACL *acl = [JBACL ACL]; [acl setPublicReadAccess:YES]; [acl setWriteAccess:YES forUser:[JBUser currentUser]]; ``` -#六、文件JBFile -##6.1 JBFile + +# 六、文件JBFile +## 6.1 JBFile `JBFile`是继承自`JBObject`的子类。是用来处理文件管理所需功能的专门类。 `JBFile` 允许应用将文件存储到服务端,支持图片、视频等常见的文件类型,以及其他任何二进制数据。 @@ -525,18 +539,17 @@ JBACL *acl = [JBACL ACL]; NSData *data = [NSdata dataWithContentsOfURL:http://7xnus0.com2.z0.glb.qiniucdn.com/5645b2a574242e39eee89829/c25b2241637b49c8bc021a60abb5f23e]; JBFile *file = [JBFile fileWithName:@"video.mp4" data:data]; ``` + * 文件名允许重名,因为每一个JBFile对象都有唯一的objectId,所以即使重名也没问题。同样因为有objectId作为标识,文件也可以没有名字。 * 给文件添加拓展名十分必要,服务器通过拓展名判断文件类型,例如PNG图片的拓展名应该是.png,MP4视频文件的拓展名应该是.mp4,不应弄混弄错。 如果需要存储的文件是来自网上,可以使用JBFile提供的方法`fileWithURL:`,所以上面的代码也可以这么写: + ```objectivec JBFile *file = [JBFile fileWithURL:http://7xnus0.com2.z0.glb.qiniucdn.com/5645b2a574242e39eee89829/c25b2241637b49c8bc021a60abb5f23e]; ``` -##6.2 文件元数据 -##6.3 视频类流媒体M3U8处理 -##6.4 图像与缩略图获取(待定) -##6.5 进度提示 +## 6.2 进度提示 使用`saveInBackgroundWithBlock:progressBlock:`可以获取到`JBFile`的上传进度。例如: ```objectivec @@ -546,10 +559,11 @@ JBFile *file = [JBFile fileWithURL:http://7xnus0.com2.z0.glb.qiniucdn.com/5645b2 //更新进度数据 }]; ``` -#七、用户JBUser -##7.1 JBUser + +# 七、用户JBUser +## 7.1 JBUser `JBUser`与`JBFile`一样都是`JBObject`的子类,是用来处理用户账户管理所需工能的专门用户类。它不光继承了`JBObject`所有的方法,具备同`JBObject`相同的功能,还增加扩展了一些特定的与用户账户相关的功能。 -##7.2 特殊属性 +## 7.2 特殊属性 `JBUser`除了继承自`JBObject`的属性外,还有一些特有属性: * `username` : 用户的用户名(必需且唯一) @@ -558,7 +572,7 @@ JBFile *file = [JBFile fileWithURL:http://7xnus0.com2.z0.glb.qiniucdn.com/5645b2 * `email` : 用户用来注册的电子邮件地址(可选) * `auth` : 用户授权第三方登录(可选) -##7.3 注册 +## 7.3 注册 大部分程序都会需要用户注册,例如: ```objectivec @@ -579,6 +593,7 @@ NSError *error = nil; } }]; ``` + ##7.4 登录(修改) 让已经成功注册的用户登录到自己的账户,可以调用`JBUser`类中登录相关的同异步方法,并根据用户选择登录方式的不同调用不同的方法。例如: @@ -610,6 +625,7 @@ NSError *error = nil; } }]; ``` + 目前支持的第三方平台有: * JBPlatformSinaWeibo 使用微博账号登录 @@ -617,7 +633,7 @@ NSError *error = nil; * JBPlatformWeixin 使用微信账号登录 -##7.5 当前用户 +## 7.5 当前用户 用户,是应用程序的核心。如果每次打开应用程序都要登录,会直接影响用户体验。为避免这种情况,可以使用缓存的`currentUser`对象。当用户成功注册或者第一次成功登录后,就将当前用户对象缓存在本地中,既方便下次调用,也给用户以最好的应用体验。 ```objectivec @@ -628,13 +644,15 @@ if (currentUser != nil) { //本地缓存用户对象为空,当前用户未登录 } ``` + 清除缓存的用户对象: ```objectivec [JBUser logout]; //清除本地缓存用户对象 JBUser *currentUser = [JBUser currentUser]; //现在currentUser是nil了 ``` -##7.6 修改/重置密码 + +## 7.6 修改/重置密码 当用户使用非第三方授权登录而是用户名密码或手机密码登录时,就会有更改密码的需求,我们也提供了相应的方法来满足用户的这一需求: ```objectivec @@ -658,7 +676,8 @@ NSError *error = nil; } }]; ``` -##7.7 SessionToken介绍 + +## 7.7 SessionToken介绍 `SessionToken`是`JBUser`的一个非常特殊的属性,是 `JBUser`的内建字段。当用户注册成功后,自动生成且唯一。 @@ -669,14 +688,14 @@ NSError *error = nil; * 服务器用来校验用户登录与否 * 保证在多设备登录同一账号情况下,用户账号安全 -#八、设备与推送 +# 八、设备与推送 `JBInstallation`同样也是一个继承自`JBObject`的一个子类,是用来处理设备管理所需功能的专门类。 * `deviceToken` : 设备的唯一标示符 * `deviceType` : 对于iOS设备来说,type就是"iOS" -#九、调用云代码 +# 九、调用云代码 可以使用JBCloud类的静态方法调用云代码中定义的函数: ```objectivec @@ -684,7 +703,5 @@ NSError *error = nil; //返回结果,业务逻辑 })]; ``` -functionName是云代码中函数的名称, parameters是传入的函数的参数,block对象作为调用结果的回调传入。 -#十、其他 -##10.1 调试模式 \ No newline at end of file +functionName是云代码中函数的名称, parameters是传入的函数的参数,block对象作为调用结果的回调传入。 diff --git a/doc/manual/java-sdk.md b/doc/manual/java-sdk.md new file mode 100644 index 0000000..cbc72f5 --- /dev/null +++ b/doc/manual/java-sdk.md @@ -0,0 +1,1228 @@ +# Java SDK +## SDK安装 +### 获取SDK +获取 `SDK` 有多种方式,较为推荐的方式是通过包依赖管理工具下载最新版本。 +#### 包依赖管理工具安装 +通过 `maven` 配置相关依赖。 + +``` + + + com.javabaas + javasdk + 2.0.1 + + +``` + +或者通过 `gradle` 配置相关依赖。 + +``` +dependencies { + compile("com.javabaas:javasdk:2.0.1") +} +``` + +#### 手动安装 +[Java_SDK 源码(码云gitee)](https://gitee.com/javabaas/JavaBaas_SDK_Java.git)
+[Java_SDK 源码(github)](https://github.com/JavaBaas/JavaBaas_SDK_Java.git) + +## 初始化 +首先使用`JBShell`工具获取我们需要使用的应用AppId、Key等信息。[获取鉴权信息](/manual/command_line.md#显示鉴权信息_token) + +`JavaSDK`提供三种权限的初始化方法,使用者可以根据实际情况使用相应的`JavaSDK`初始化方法: + +### 初始化 应用普通 权限 +在 `main` 函数中间调用 `JBConfig.init` 来设置你的应用普通权限初始化的信息: + +``` java + public static void main(String[] args) { + // 参数依次为 请求地址(例如:http://127.0.0.1:8080/api)、appId("594895b0b55198292ae266f1")、key("a8c18441d7ab4dcd9ed78477015ab8b2") + JBConfig.init("http://127.0.0.1:8080/api", "594895b0b55198292ae266f1","a8c18441d7ab4dcd9ed78477015ab8b2") + } +``` + +提示: 普通权限用于操作数据,一般用户客户端程序。 + +### 初始化 master 权限 +在 `main` 函数中间调用 `JBConfig.initAdmin` 来设置你的 master 管理权限初始化的信息: + +``` java + public static void main(String[] args) { + // 参数依次为 请求地址(例如:http://127.0.0.1:8080/api)、appId("594895b0b55198292ae266f1")、masterKey("cebde78a2d2d48c9870cf4887cbb3eb1") + JBConfig.initMaster("http://127.0.0.1:8080/api", "594895b0b55198292ae266f1","cebde78a2d2d48c9870cf4887cbb3eb1") + } +``` + +提示: Master权限用于无视ACL的操作数据,一般用于后台云代码服务器。 + +### 初始化 admin 权限 +在 `main` 函数中间调用 `JBConfig.initAdmin` 来设置你的 `admin` 超级权限初始化的信息: + +``` java + public static void main(String[] args) { + // 参数依次为 请求地址("例如:"http://127.0.0.1:8080/api")、adminKey("JavaBaas") + JBConfig.initAdmin("http://127.0.0.1:8080/api", "JavaBaas") + } +``` + +提示: Admin权限用于创建和管理应用 + +## 对象列表 +JavaSDK目前提供了包括`JBApp`、`JBClazz`、`JBField`、`JBObject`、`JBUser`、`JBQuery`、`JBFile`等主要对象(除了这些主要的对象外,JavaSDK中还有一些内部类、工具类等,不再详细介绍)。 + +对象|描述 +--- | --- +JBApp | [应用对象](java-sdk.md#JBApp-应用) +JBClazz | [表对象,通常一个JBClazz对应一个mongoDB中的Collection](java-sdk.md#JBClazz-表) +JBField | 字段对象,对应mongoDB中的文档的key +JBObject | 文档对象 +JBUser | 用户 +JBQuery | 查询对象 +JBFile | 文件对象 + +## JBObject 文档 +`JBObject`是对`JavaBaas`对复杂对象的封装,通常一个`JBObject`对应一条文档数据。 + +>`JBObject `的一些主要的属性如下: + +属性名|描述 +--- | --- +objectId | 文档id +className | 文档对应的表名 +createdAt | 文档创建时间 +updatedAt | 文档更新时间 +acl | 文档级acl +serverData | 文档非内建字段数据 +query | JBQuery,查询条件,在findAndModify操作时候会用到 +fetchWhenSave | 保存成功后是否更新数据 +operationQueue | 所有字段待操作队列 + +>`JBObject`提供的一些主要的方法为: + +序号| 方法 | 方法说明 +--- | --- | --- +1 | save() | [创建或者更新文档信息(同步)](java-sdk.md#创建或者更新文档信息) +2 | saveInBackground(JBSaveCallback callback) | [创建或者更新文档信息(异步)](java-sdk.md#创建或者更新文档信息) +3 | delete() | [删除文档信息(同步)](java-sdk.md#删除文档信息) +4 | deleteInBackground(JBDeleteCallback callback) | [删除文档信息(异步)](java-sdk.md#删除文档信息) + +### 构建对象 +你可以通过下面几种方式构建`JBObject`对象: + +```java +JBObject object = new JBObject("Sound"); +object.setObjectId("objectId"); +``` + +```java +JBObject object = JBObject.create("Sound"); +``` + +```java +JBObject object = JBObject.createWithOutData("Sound", "objectId"); +``` +### 支持的数据类型 +`JBObject`支持所有`JBField`字段类型。 + +```java +JBObject object = JBObject.create("Sound"); +// 字符串 String +object.put("name", "soundName"); +// 数字 Number +object.put("size", 998); +// 布尔 Boolean +object.put("publish", true); +// 日期 Date +object.put("publishTime", new Date().getTime()); +// 文件 File +JBFile file = new JBFile(); +file.setObjectId("fileId"); +object.put("soundFile", file); +// 对象 Object +Map m3u8 = new HashMap<>(); +m3u8.put("ts1", "ts1url"); +m3u8.put("ts2", "ts2url"); +object.put("m3u8", m3u8); +// 数组 Array +List tags = new ArrayList<>(); +tags.add("流行"); +tags.add("港台"); +object.addArray("tag", tags); +// 指针 Pointer +JBUser user = JBUser.getCurrentUser(); +object.put("user", user); +``` + +### 创建或者更新文档信息 +使用者使用普通权限,可以创建或更新文档信息。如上面 [支持的数据类型](java-sdk.md#支持的数据类型) 中的例子,可以使用同步或者异步方法进行保存,`JavaSDK`会根据`JBObject`对象中是否存在`objectId`值而选择是创建或者更新操作。 + +```java +// 同步 +try { + object.save(); +} catch (JBException e) { + System.out.println(e.getMessage()); +} + +// 异步 +object.saveInBackground(new JBSaveCallback() { + @Override + public void done(boolean success, JBException e) { + if (!success) { + System.out.println(e.getMessage()); + } + } +}); +``` + +上面的代码执行后保存的数据如下: + +```json +{ + "_id" : "69af618624854cc9b77296b0c4c69524", + "acl" : { + "*" : { + "read" : true, + "write" : true + } + }, + "createdAt" : NumberLong(1510111638356), + "updatedAt" : NumberLong(1510123750716), + "createdPlat" : "cloud", + "updatedPlat" : "cloud", + "m3u8" : { + "ts2" : "ts2url", + "ts1" : "ts1url" + }, + "name" : "soundName", + "publish" : true, + "publishTime" : NumberLong(1510123750685), + "size" : 998, + "user" : { + "__type" : "Pointer", + "className" : "_User", + "_id" : "54710efba85e46a690034ba0df49e69d" + }, + "tag" : [ + "流行", + "港台" + ], + "soundFile" : { + "__type" : "File", + "className" : "_File", + "_id" : "09258ae6cb484b20b3f075e2768cc43f", + "url" : "http://youdomain.com/594895b0b55198292ae266f1/8a11682a0ca14cd1bd313812c0240e41", + "name" : "2017_07_14_17_09" + } +} +``` + +### 原子操作 +原子操作是为解决不同客户端并发读取并修改同一文档的字段信息,因脏读而引发的写入数据错误。`JBObject` 目前支持六种原子操作: + +操作|描述 +--- | --- +removeKey | 删除字段 +addArray | Array类型字段添加值 +addUniqueArray | Array类型字段添加与之前不重复的值 +removeArray | Array类型字段删除值 +increment | Number类型字段原子增加或原子减少 +multiply | Number类型字段原子倍数增加 + +例如,原始数据为: + +```java +{ + "_id":"7e5ddc041a3b4661a0d2fd54ae288378", + "size":998, + "multiplySize":998, + "name":"soundName", + "tag":[ + "流行", + "港台" + ], + "uniqueTag":[ + "流行", + "港台" + ], + "removeTag":[ + "流行", + "港台" + ] +} +``` + +使用原子操作对上面的数据进行处理: + +```java +JBObject object = new JBObject("Sound"); +// objectId为7e5ddc041a3b4661a0d2fd54ae288378的Sound文档 +object.setObjectId("7e5ddc041a3b4661a0d2fd54ae288378"); +// 删除字段的值 +object.removeKey("name"); +List tags = new ArrayList<>(); +tags.add("流行"); +tags.add("内地"); +// 添加数组 +object.addArray("tag", tags); +// 添加unique数组 +object.addUniqueArray("uniqueTag", tags); +// 去掉数组值的部分内容 +object.removeArray("removeTag", tags); +// 原子增size值 +object.increment("size"); +// 原子倍数增multiplySize值 +object.multiply("multiplySize", 10); +object.saveInBackground(new JBSaveCallback() { + @Override + public void done(boolean success, JBException e) { + // code + } +}); +``` + +处理后的数据为: + +```json +{ + "_id":"7e5ddc041a3b4661a0d2fd54ae288378", + "size":999, + "multiplySize":9980, + "tag":[ + "流行", + "港台", + "流行", + "内地" + ], + "uniqueTag":[ + "流行", + "港台", + "内地" + ], + "removeTag":[ + "港台" + ] +} +``` + +### 其他保存选项 +`JBObject`支持在更新文档数据时查询当前文档是否满足一定条件,并且支持在更新后返回服务端的最新值。 + +>使用setFetchWhenSave可以在更新数据后返回服务端的最新值。 + +```java +object.setFetchWhenSave(true); +``` + +>使用query可以在更新时判断当前文档是否满足一定条件。 + +```java +// 判断当前文档中size是否大于0 +JBQuery query = JBQuery.createQuery(object); +query.whereGreaterThan("size", 0); +object.setQuery(query); +``` + +### 删除文档信息 +使用者使用普通权限,可以创建文档信息。 + +```java +JBObject object = new JBObject("Sound"); +object.setObjectId("7e5ddc041a3b4661a0d2fd54ae288378"); +object.deleteInBackground(new JBDeleteCallback() { + @Override + public void done(boolean success, JBException e) { + // code + } +}); +``` + +## JBUser 用户 +`JBUser`是`JBObject`子类,主要处理和用户有关的操作。 + +>`JBUser`的一些主要的属性如下(除了父类`JBObject`属性外): + +属性名|描述 +--- | --- +sessionToken | 用户身份鉴权 +username | 用户名 +email | 邮箱 +password | 密码 +phone | 电话 +auth | 第三方登录信息 + +>`JBUser `提供的一些主要的方法为: + +序号| 方法 | 方法说明 +--- | --- | --- +1 | signUp() | [用户名密码注册(同步)](java-sdk.md#用户名密码注册) +2 | signUpInBackground(JBSignUpCallback callback) | [用户名密码注册(异步)](java-sdk.md#用户名密码注册) +3 | getSmsCode(String phone) | [获取短信验证码(同步)](java-sdk.md#获取短信验证码) +4 | getSmsCodeInBackground(String phone, JBGetSmsCodeCallback callback) | [获取短信验证码(异步)](java-sdk.md#获取短信验证码) +5 | signUpWithSns(JBAuth auth, JBSnsType type) | [第三方社交平台注册(同步)](java-sdk.md#第三方社交平台注册) +6 | signUpWithSnsInBackground(JBAuth auth, JBSnsType type, JBSignUpCallback callback) | [第三方登录注册(异步)](java-sdk.md#第三方社交平台注册) +7 | login(String username, String password) | [用户名密码登录(同步)](java-sdk.md#用户名密码登录) +8 | loginInBackground(String username, String password, JBLoginCallback callback) | [用户名密码登录(异步)](java-sdk.md#用户名密码登录) +9 | loginWithPhone(String phone, String code) | [手机号验证码登录(同步)](java-sdk.md#手机号验证码登录) +10 | loginWithPhoneInBackground(String phone, String code, JBLoginCallback callback) | [手机号验证码登录(异步)](java-sdk.md#手机号验证码登录) +11 | loginWithSns(JBAuth auth, JBSnsType type) | [第三方社交平台登录(同步)](java-sdk.md#第三方社交平台登录) +12 | loginWithSnsInBackground(JBAuth auth, JBSnsType type, JBLoginCallback callback) | [第三方社交平台登录(异步)](java-sdk.md#第三方社交平台登录) +13 | updatePassword(String oldPassword, String newPassword) | [修改登录密码(同步)](java-sdk.md#修改登录密码) +14 | updatePasswordInBackground(String oldPassword, String newPassword, JBUpdatePasswordCallback callback) | [修改登录密码(异步)](java-sdk.md#修改登录密码) +15 | update() | [更新用户信息(同步)](java-sdk.md#更新用户信息) +16 | updateInBackground(JBUpdateCallback callback) | [更新用户信息(异步)](java-sdk.md#更新用户信息) + +### 用户名密码注册 +使用者可以使用普通权限使用用户名密码进行注册: + +```java +JBUser user = new JBUser(); +// 用户名,用户名规则为"^[a-zA-Z0-9_@.]*$" +user.setUsername("woshiwo"); +// 密码 +user.setPassword("aaaaaa"); +user.signUpInBackground(new JBSignUpCallback() { + @Override + public void done(boolean success, JBException e) { + // + } +}); +``` + +### 第三方社交平台注册 +使用者可以使用普通权限可以通过第三方平台注册。 + +```java +try { + JBUser user = new JBUser(); + user.setUsername("woshiwo"); + + JBAuth auth = new JBAuth(); + // 微博、qq、微信需要accessToken + String accessToken = "xxxxxx"; + auth.setAccessToken(accessToken); + // 微博需要uid + String uid = "xxxx"; + auth.setUid(uid); + // 微信、qq、微信小程序需要openId或unionId,当两者都赋值的话优先使用unionId。 + String openId = "xxxxx"; + String unionId = "xxxxx"; + auth.setOpenId(openId); + auth.setUnionId(unionId); + // 微信小程序需要encryptedData、code和iv + String encryptedData = "xxxxx"; + String code = "xxxx"; + String iv = "xxxxx"; + auth.setEncryptedData(encryptedData); + auth.setCode(code); + auth.setIv(iv); + + // 根据实际,选择不同的type + JBSnsType type = JBSnsType.WEBAPP; + + user.signUpWithSns(auth, type); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +### 用户名密码登录 +使用者可以使用普通权限可以通过用户名密码登录,登录成功后,服务端会返回该用户的所有可见信息和用户鉴权用的sessionToken。 + +```java +JBUser.loginInBackground("woshiwo", "aaaaaa", new JBLoginCallback() { + @Override + public void done(boolean success, JBUser user, JBException e) { + // 更新currentUser + JBUser.updateCurrentUser(user); + } +}); +``` + +### 获取短信验证码 +使用者可以使用普通权限使用手机号验证码登录时可以通过下面的方法获取短信验证码: + +```java +try { + JBUser.getSmsCode("18988888888"); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +### 手机号验证码登录 +使用者可以使用普通权限,在获取到手机有效验证码后可以通过手机号验证码方式登录,需要注意的是如果用户之前没有注册,服务端会自动为改手机号注册一个用户,用户名默认为 “phone_” 加手机号。 + +```java +JBUser.loginWithPhoneInBackground("18988888888", "smsCode", new JBLoginCallback() { + @Override + public void done(boolean success, JBUser user, JBException e) { + // code + } +}); +``` + +### 第三方社交平台登录 +使用者可以使用普通权限,并且已经通过第三方平台注册过,可以使用第三方社交平台进行登录: + +```java +// auth和snsType参考第三方社交平台注册 +JBUser.loginWithSnsInBackground(auth, snsType, new JBLoginCallback() { + @Override + public void done(boolean success, JBUser user, JBException e) { + // code + } +}); + +``` + +### 修改登录密码 + +使用者可以使用普通权限,可以在登录成功后修改本人的用户名登录密码: + +```java +// 旧密码为"aaaaaaa", 新密码为"bbbbbb" +user.updatePasswordInBackground("aaaaaaa", "bbbbbb", new JBUpdatePasswordCallback() { + @Override + public void done(boolean success, String sessionToken, JBException e) { + // code + } +}); +``` + +### 更新用户信息 +使用者可以使用普通权限,在成功登录后可以修改本人的一些信息: + +```java +user.put("nickname", "小王"); +user.updateInBackground(new JBUpdateCallback() { + @Override + public void done(boolean success, JBException e) { + //code + } +}); +``` + +## JBQuery 查询 +`JBQuery`主要处理和查询有关的操作。 + +>`JBQuery`的一些主要的属性如下: + +属性名|描述 +--- | --- +className | 类名 +whereSting | 查询语句(json串) +isRunning | 是否正在查询 +conditions | 查询条件 + +>`JBUser `提供的一些主要的方法为: + +序号| 方法 | 方法说明 +--- | --- | --- +1 | get(String objectId) | [根据objectId获取对象(同步)](java-sdk.md#根据objectId获取对象) +2 | getInBackground(String objectId, JBGetCallback callback) | [根据objectId获取对象(异步)](java-sdk.md#根据objectId获取对象) +3 | find() | [数据查询(同步)](java-sdk.md#数据查询) +4 | findInBackground(JBFindCallBack callBack) | [数据查询(异步)](java-sdk.md#数据查询) +5 | count() | [简单统计查询(同步)](java-sdk.md#简单统计查询) +6 | countInBackground(JBCountCallback callback) | [简单统计查询(异步)](java-sdk.md#简单统计查询) +7 | deleteByQuery() | [批量删除(同步)](java-sdk.md#批量删除) +8 | deleteByQueryInBackground(JBDeleteCallback callback) | [批量删除(异步)](java-sdk.md#批量删除) + +### 根据objectId获取对象 +使用者可以通过文档的`objectId`获取有读权限的文档数据: + +```java +JBQuery query = new JBQuery("Sound"); +query.getInBackground("7e5ddc041a3b4661a0d2fd54ae288378", new JBGetCallback() { + @Override + public void done(boolean success, JBObject object, JBException e) { + // code + } +}); +``` + +### 数据查询 +使用者可以通过设置一些查询条件查询有读权限的相关数据,需要注意的是用户不设置查询数量限制的前提下,服务端默认返回符合条件最多100条数据,用户也可以自己设置最大返回数据量,范围为1到1000,超过1000服务端按1000条算,查询的默认排序是根据文档数据的`updatedAt`倒叙排序。 + +```java +// 构建基于Sound表的查询 +JBQuery query = new JBQuery("Sound"); +// 查询name等于soudName的数据 +query.whereEqualTo("name", "soudName"); +// 查询name等于otherName的数据 +query.whereNotEqualTo("name", "otherName"); +// 查询size小于10的数据 +query.whereLessThan("size", 10); +// 查询size大于0的数据 +query.whereGreaterThan("size", 0); +// 查询size小于等于10的数据 +query.whereLessThanOrEqualTo("size", 10); +// 查询size大于等于0的数据 +query.whereGreaterThanOrEqualTo("size", 0); +// 查询name字段不为空的数据 +query.whereExists("name"); +// 查询name字段为空的数据 +query.whereNotExist("name"); +// 查询name字段中包含“sound”字符串的数据 +query.whereContains("name", "sound"); + +List list = new ArrayList<>(); +list.add("港台"); +// 查询tag中含有list中数据的数据 +query.whereContainedIn("tag", list); +// 查询tag中不含有list中数据的数据 +query.whereNotContainedIn("tag", list); +// 查询name字段以“me”字符串结尾的数据 +query.whereEndWith("name", "me"); +// 查询name字段以“sou”字符串开头的数据 +query.whereStartWith("name", "sou"); + +// 查询根据正则表达式查询的数据 +String regex = ".*o.*"; +String options = "i"; +query.whereMatches("name", regex); +query.whereMatches("name", regex, options); + +// 设置查询结果返回数量最大为30 +query.setLimit(30); +// 设置查询跳过符合条件的前60个 +query.setSkip(60); +// 按createdAt的倒叙排序 +query.addDescendingOrder("createdAt"); +// 按size的正序排序 +query.addAscendingOrder("size"); +// 查询user的全部信息,只针对Pointer类型字段 +// 如果查询的字段对应的文档中还有Pointer字段,并且也需要查询出来 +// 则可以使用“album.user”(album是当前表中的Pointer字段,user是Album表中的一个Pointer字段) +query.include("user"); + +query.findInBackground(new JBFindCallBack() { + @Override + public void done(boolean success, List objects, JBException e) { + // code + } +}); +``` + +### 子查询 +子查询是数据查询的一种,用于构建复杂一些的查询。 + +>例如,音频 `Sound` 类中有一个字段作者 `user` 是一个 `Pointer` 字段,它指向 `_User` 类,现在我们要查询用户的昵称 `nickname` 中含有 `ABC` 字符串的用户发布的所有音频。 + +```java +JBQuery query = new JBQuery("Sound"); +JBQuery subQuery = new JBQuery("_User"); +subQuery.whereContains("nickName", "ABC"); +query.whereMatchesQuery("user", subQuery); +query.findInBackground(new JBFindCallBack() { + @Override + public void done(boolean success, List objects, JBException e) { + // code + } +}); +``` + +>还一种情况,例如 音频 `Sound` 类中有一个字段专辑 `album` 是一个 `Pointer` 字段,指向 `Album` 类,专辑订阅信息 `SubscriptionAlbum` 类中有两个 `Pointer` 类型字段订阅者 `user` 和专辑 `subsAlbum` (为了跟 `Sound` 中的 `album` 区分,这个字段名称命名为 `subsAlbum` ) ,分别指向 `_User` 和 `Album` 类,现知道用户 A ,其 `_id` 为 `a6159350c5964cebbe523d679b9889ae` ,要查询用户 A 订阅的专辑的所有音频数据。 + +```java +JBQuery query = new JBQuery("Sound"); +JBQuery subQuery = new JBQuery("SubscriptionAlbum"); +JBUser user = new JBUser(); +user.setObjectId("a6159350c5964cebbe523d679b9889ae"); +subQuery.whereEqualTo("user", user); +query.whereMatchesKeyInQuery("album", "subsAlbum", subQuery, "Album"); +query.findInBackground(new JBFindCallBack() { + @Override + public void done(boolean success, List objects, JBException e) { + // code + } +}); + +``` + +### 简单统计查询 +使用者可以使用普通权限,对某表的数据根据一定条件查询。 + +```java +JBQuery query = new JBQuery("Sound"); +query.whereGreaterThanOrEqualTo("size", 10); +query.countInBackground(new JBCountCallback() { + @Override + public void done(boolean success, int count, JBException e) { + // code + } +}); +``` +### 批量删除 +使用者可以根据查询条件批量删除一些有删除权限的文档。 + +```java +query.deleteByQueryInBackground(new JBDeleteCallback() { + @Override + public void done(boolean success, JBException e) { + // code + } +}); +``` + +## JBFile 文件 +`JBFile`是`JBObject`的子类,主要处理和文件有关的操作。 + +>`JBFile `的一些主要的属性如下: + +属性名|描述 +--- | --- +url | 链接地址 +name | 名称 + +## JBApp 应用 + +`JBApp`主要是处理在 `admin` 超级权限或者当前应用的 `master` 管理权限下对应用的管理。 + +>`JBApp`的一些重要的属性如下: + +属性名|描述 +------------ | ------------ +id | 应用id 既 appId +name | 应用名称 +key | 本应用普通权限的key +masterKey | 本应用的管理权限key +cloudSetting | 本应用相关的云方法和钩子设置 + +>`JBApp`提供的一些主要的方法为: + +序号| 方法 | 方法说明 +--- | --- | --- +1| save() | [创建或更新应用信息(同步)](java-sdk.md#创建或更新应用信息) +2| saveInBackground(JBSaveCallback callback) | [创建或更新应用信息(异步)](java-sdk.md#创建或更新应用信息) +3| delete() | [删除应用(同步)](java-sdk.md#删除应用) +4| deleteInBackground(JBDeleteCallback callback)| [删除应用(异步)](java-sdk.md#删除应用) +5| get(String appId) | [获取应用信息(同步)](java-sdk.md#获取应用信息) +6| getInBackground(String appId, JBGetAppCallback callback) | [获取应用信息(异步)](java-sdk.md#获取应用信息) +7| resetKey(int type) | [更新应用key或masterKey值(同步)](java-sdk.md#更新应用key或masterKey值) +8| resetKeyInBackground(int type, JBUpdateCallback callback) | [更新应用key或masterKey值(异步)](java-sdk.md#更新应用key或masterKey值) +9| list() | [获取应用列表(同步)](java-sdk.md#获取应用列表) +10| listInBackground(JBAppListCallback callback) | [获取应用列表(异步)](java-sdk.md#获取应用列表) +11| export(String appId) | [导出应用信息(同步)](java-sdk.md#导出应用信息) +12| exportInBackground(String appId, JBAppExportCallback callback) | [导出应用信息(异步)](java-sdk.md#导出应用信息) +13| importData(String data) | [导入应用信息(同步)](java-sdk.md#导入应用信息) +14| importDataInBackground(String data, JBImportCallback callback) | [导入应用信息(异步)](java-sdk.md#导入应用信息) +15| getApiStat(JBApiStat apiStat) | [获取应用api调用统计(同步)](java-sdk.md#获取应用api调用统计) +16| getApiStatInBackground(JBApiStat apiStat, JBApiStatListCallback callback) | [获取应用api调用统计(异步)](java-sdk.md#获取应用api调用统计) +17| updateAppConfig(JBAppConfig config) | [更新应用设置(同步)](java-sdk.md#更新应用设置) +18| updateAppConfigInBackground(JBAppConfig config, JBUpdateCallback callback) | [更新应用设置(异步)](java-sdk.md#更新应用设置) +19| getAppConfig(JBAppConfigKey appConfigKey) | [查看应用config信息(同步)](java-sdk.md#) +20| getAppConfigInBackground(JBAppConfigKey appConfigKey, JBGetConfigCallback callback) | [查看应用config信息(异步)](java-sdk.md#) + +### 创建或更新应用信息 +使用者可以在设置了`admin`超级权限后可以通过调用创建或更新应用信息方法创建或者更新应用: + +``` java +try { + JBApp app = new JBApp(); + app.setName("应用名称"); + app.save(); + System.out.println("创建应用成果"); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +### 删除应用 +使用者拥有了`admin`超级权限后可以通过调用删除应用方法删除应用: + +``` java +JBApp app = new JBApp(); +app.setId("appId"); +app.deleteInBackground(new JBDeleteCallback() { + @Override + public void done(boolean success, JBException e) { + if (success) { + System.out.println("应用删除成功"); + } else { + System.out.println(e.getMessage()); + } + } +}); +``` + +### 获取应用信息 +使用者拥有了`admin`超级权限后可以通过调用获取应用信息的方法获取应用信息。 + +``` java +try { + JBApp app = JBApp.get("appId"); + System.out.println(app); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +### 重置应用key或masterKey值 +使用者拥有了`admin`超级权限后可以重置应用`key`或`masterKey`值,需要注意的是,一旦重置了应用`key`或`masterKey`值,之前的`key`或`masterKey`立即不能使用,可能会影响之前已经上线的应用。 + +``` java +app.resetKeyInBackground(1, new JBUpdateCallback() { + @Override + public void done(boolean success, JBException e) { + if (success) { + System.out.println("更改应用key成功"); + } else { + System.out.println(e.getMessage()); + } + } +}); +``` + +### 获取应用列表 +使用者拥有了`admin`超级权限后可以获取应用列表,查看所有应用信息。 + +``` java +try { + List list = JBApp.list(); + list.forEach(app -> System.out.println(app.getId() + " : " + app.getName())); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +结果如下: + +``` +59dc970bce69f81448a2a119 : NewApp +59f0173012a0aa06cb853985 : TestApp +``` + +### 导出应用信息 +使用者拥有了`admin`超级权限后可以使用应用信息导出方法备份应用的结构信息,需要注意的是导出的时候结构信息,不含表中数据。 + +``` java +JBApp app = new JBApp(); +app.setId("59dc970bce69f81448a2a119"); +JBApp.exportInBackground("59dc970bce69f81448a2a119", new JBAppExportCallback() { + @Override + public void done(boolean success, JBApp.JBAppExport appExport, JBException e) { + if (success) { + System.out.println(appExport); + } + } +}); +``` + +结果如下: + +``` +{ + "id":"59dc970bce69f81448a2a119", + "name":"NewApp", + "key":"cde5b8c5e097436aafe6377e33eeb003", + "masterKey":"c57cd396c2034ef6a6ae1c74b7596730", + "clazzs":[ + Object{...}, + Object{...}, + Object{...}, + Object{...}, + Object{...}, + { + "id":"59dc9869ce69f81448a2a13e", + "name":"Test", + "acl":{ + "*":{ + "find":true, + "get":true, + "insert":true, + "update":true, + "delete":true + } + }, + "internal":false, + "fields":[ + { + "id":"59dc9869ce69f81448a2a13f", + "name":"count", + "type":2, + "internal":false, + "security":false, + "required":false + }, + { + "id":"59e970a212a0aa7f91bb0487", + "name":"name", + "type":1, + "internal":false, + "security":false, + "required":false + }, + Object{...} + ] + } + ] +} +``` + +### 导入应用信息 +使用者拥有了`admin`超级权限后可以使用导入应用信息回复应用结构信息, 需要注意的是导入的只是应用结构信息,包括应用信息、表信息、字段信息等,不含表中文档内容。 + +``` java +try { + String data = "{\"id\":\"59dc970bce69f81448a2a119\",\"name\":\"NewApp\",\"key\":\"cde5b8c5e097436aafe6377e33eeb003\",\"masterKey\":\"c57cd396c2034ef6a6ae1c74b7596730\",\"clazzs\":[{\"id\":\"59dc9869ce69f81448a2a13e\",\"name\":\"Test\",\"acl\":{\"*\":{\"find\":true,\"get\":true,\"insert\":true,\"update\":true,\"delete\":true}},\"internal\":false,\"fields\":[{\"id\":\"59dc9869ce69f81448a2a13f\",\"name\":\"count\",\"type\":2,\"internal\":false,\"security\":false,\"required\":false},{\"id\":\"59e970a212a0aa7f91bb0487\",\"name\":\"name\",\"type\":1,\"internal\":false,\"security\":false,\"required\":false}]}]}"; + JBApp.importData(data); + System.out.println("导入应用成功"); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +### 获取应用api调用统计 +使用者拥有了当前应用的`master`管理权限后,使用该方法可以获取当前应用`api`的调用统计,下面的查询是查询昨天和今天两天,来之`web端`(plat为js)的有关`_User` 的 `insert` 操作请求的统计: + +``` java +JBApp app = new JBApp(); +app.setId("59dc970bce69f81448a2a119"); +SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd"); +Calendar calendar = new GregorianCalendar(); +// 今天 例如20171106 +Date to = calendar.getTime(); +calendar.add(Calendar.DAY_OF_YEAR, -1); +// 昨天 例如20171105 +Date from = calendar.getTime(); +String fromString = simpleDateFormat.format(from); +String toString = simpleDateFormat.format(to); +JBApp.JBApiStat apiStat = new JBApp.JBApiStat("js", "_User", JBApp.JBApiMethod.INSERT, fromString, toString); +app.getApiStatInBackground(apiStat, new JBApiStatListCallback() { + @Override + public void done(boolean success, List list, JBException e) { + if (success) { + System.out.println(list); + } + } +}); +``` + +### 更新应用设置 +使用者拥有了当前应用的`master`管理权限后,使用该方法可以对当前应用的`config`信息进行修改: + +``` java +try { + JBApp.JBAppConfig config = new JBApp.JBAppConfig(); + config.setAppConfigKey(JBApp.JBAppConfigKey.PUSH_HANDLER_JPUSH_KEY); + config.setValue("jpushKey"); + JBApp.updateAppConfig(config); + System.out.println("设置成功"); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +### 查看应用config信息 +使用者拥有了当前应用的`master`管理权限后,使用该方法可以查看当前应用的一些`config`信息: + +``` java +try { + String value = JBApp.getAppConfig(JBApp.JBAppConfigKey.PUSH_HANDLER_JPUSH_KEY); + System.out.println(value); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +## JBClazz 表 +`JBClazz`主要处理在当前应用的`master`权限下,和表有关的操作。 + +>`JBClazz`的一些重要的属性如下: + +属性名|描述 +------------ | ------------ +id | 表id +app | 应用信息 +name | 表名称 +acl | 表级权限 +internal | 是否是内部类 +count | 当前表中文档数据量 + +>`JBClazz`提供的一些主要的方法为: + +序号| 方法 | 方法说明 +--- | --- | --- +1 | save() | [创建或更新表信息(同步)](java-sdk.md#创建或更新表信息) +2 | saveInBackdround(JBSaveCallback callback) | [创建或更新表信息(异步)](java-sdk.md#创建或更新表信息) +3 | delete() | [删除表信息(同步)](java-sdk.md#删除表信息) +4 | deleteInBackground(JBDeleteCallback callback) | [删除表信息(异步)](java-sdk.md#删除表信息) +5 | get(String name) | [获取表信息(同步)](java-sdk.md#获取表信息) +6 | getInBackground(String name, JBGetClazzCallback callback) | [获取表信息(异步)](java-sdk.md#获取表信息) +7 | updateClazzAcl() | [更新表级acl(同步)](java-sdk.md#更新表级acl) +8 | updateClazzAclInBackground(JBUpdateCallback callback) | [更新表级acl(异步)](java-sdk.md#更新表级acl) +9 | list() | [获取表列表信息(同步)](java-sdk.md#获取表列表信息) +10 | listInBackground(JBClazzListCallback callback) | [获取表列表信息(异步)](java-sdk.md#获取表列表信息) +11 | export(String className) | [导出表结构信息(同步)](java-sdk.md#导出表结构信息) +12 | exportInBackground(String className, JBClazzExportCallback callback) | [导出表结构信息(异步)](java-sdk.md#导出表结构信息) +13 | importData(String data) | [导入表结构信息(同步)](java-sdk.md#导入表结构信息) +14 | importDataInBackground(String data, JBImportCallback callback) | [导入表结构信息(异步)](java-sdk.md#导入表结构信息) + +### 创建或更新表信息 +使用者拥有了当前应用的`master`管理权限后,可以创建或更新表信息。 + +``` java +try { + JBClazz clazz = new JBClazz("Sound"); + // 创建clazz的时候可以通过设置JBClazzAcl加强对clazz的控制,如果不设置,默认clazz的所有acl为public true + JBClazz.JBClazzAcl acl = new JBClazz.JBClazzAcl(); + acl.setAccess(JBClazz.ClazzAclMethod.DELETE, "userId", true); + acl.setPublicAccess(JBClazz.ClazzAclMethod.FIND, true); + acl.setPublicAccess(JBClazz.ClazzAclMethod.GET, true); + clazz.setAcl(acl); + clazz.save(); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +新建的`clazz`数据: + +```json +{ + "_id" : ObjectId("5a015ad3fa0a5737c68c1c9d"), + "_class" : "com.javabaas.server.admin.entity.Clazz", + "name" : "Sound", + "acl" : { + "userId" : { + "delete" : true + }, + "*" : { + "find" : true, + "get" : true + } + }, + "internal" : false, + "count" : NumberLong(0), + "app" : { + "$ref" : "app", + "$id" : ObjectId("594895b0b55198292ae266f1") + } +} +``` + +### 删除表信息 +使用者拥有了当前应用的`master`管理权限后,可以删除表信息。 + +``` java +JBClazz clazz = new JBClazz("Sound"); +clazz.deleteInBackground(new JBDeleteCallback() { + @Override + public void done(boolean success, JBException e) { + // code + } +}); +``` + +### 获取表信息 +使用者拥有了当前应用的`master`管理权限后,可以根据表名称获取表结构信息。 + +``` java +JBClazz.getInBackground("Sound", new JBGetClazzCallback() { + @Override + public void done(boolean success, JBClazz clazz, JBException e) { + // code + } +}); +``` +### 更新表级acl +使用者拥有了当前应用的`master`管理权限后,可以更新表级`acl`。表级`acl`包括对表的`insert`新增文档,`update`修改文档,`get`获取单个文档信息,`find`查询表文档,`delete`删除文档等,如果没有单独设置表级acl,则表级acl所有权限均为`public true`。而如果五个权限中只设置了其中的一些,则未设置的权限为`public false`。另外,每次更新标记acl,新的`acl`会替换旧的`acl`,而不是对旧的acl进行补充设置(类似于求并集),所以比如,即使你只是想改变`insert`的权限,而不想改变之前其他四种权限的设置,你也需要在更新时候对其他权限进行重新设置。 + +``` java +JBClazz clazz = new JBClazz("Sound"); +JBClazz.JBClazzAcl acl = new JBClazz.JBClazzAcl(); +acl.setPublicAccess(JBClazz.ClazzAclMethod.INSERT, false); +acl.setPublicAccess(JBClazz.ClazzAclMethod.UPDATE, true); +acl.setPublicAccess(JBClazz.ClazzAclMethod.GET, true); +acl.setPublicAccess(JBClazz.ClazzAclMethod.FIND, true); +acl.setPublicAccess(JBClazz.ClazzAclMethod.DELETE, true); +clazz.setAcl(acl); +clazz.updateClazzAclInBackground(new JBUpdateCallback() { + @Override + public void done(boolean success, JBException e) { + // code + } +}); +``` + +### 获取表列表信息 +使用者拥有了当前应用的`master`管理权限后,可以查询全部表的列表信息。 + +```java +JBClazz.listInBackground(new JBClazzListCallback() { + @Override + public void done(boolean success, List list, JBException e) { + // code + } +}); +``` + +### 导出表结构信息 +使用者拥有了当前应用的`master`管理权限后,可以导出表结构信息,需要注意的是只是导出表结构信息,不含表中文档内容。 + +```java +try { + JBClazz.JBClazzExport export = JBClazz.export("Sound"); + // JBUtils.writeValueAsString是JavaSDK提供的工具类的方法 + System.out.println(JBUtils.writeValueAsString(export)); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +导出结果为: + +```json +{ + "id":"5a015ad3fa0a5737c68c1c9d", + "name":"Sound", + "acl":{ + "userId":{ + "delete":true + }, + "*":{ + "find":true, + "get":true + } + }, + "internal":false, + "fields":[ + { + "id":"5a016241fa0a5737c68c1c9e", + "name":"title", + "type":1, + "internal":false, + "security":false, + "required":false + } + ] +} +``` + +### 导入表结构信息 +使用者拥有了当前应用的`master`管理权限后,可以导入表结构信息,需要注意的是只是导入表结构信息,不含表中文档内容。 + +```java +String data = "{\"id\":\"5a015ad3fa0a5737c68c1c9d\",\"name\":\"Sound\",\"acl\":{\"userId\":{\"delete\":true},\"*\":{\"find\":true,\"get\":true}},\"internal\":false,\"fields\":[{\"id\":\"5a016241fa0a5737c68c1c9e\",\"name\":\"title\",\"type\":1,\"internal\":false,\"security\":false,\"required\":false}]}"; +JBClazz.importDataInBackground(data, new JBImportCallback() { + @Override + public void done(boolean success, JBException e) { + //code + } +}); +``` + + +## JBField 字段 +`JBField`主要处理在当前应用的 `master` 权限下,和字段有关的操作。 + +>`JBField`的一些重要的属性如下: + +属性名|描述 +------------ | ------------ +id | 表id +clazz | 表信息 +name | 字段名称 +type | 字段类型(详见 [字段类型说明](java-sdk.md#字段类型说明)) +internal | 是否是内建字段,内建字段不能进行删除字段操作 +security | 是否是安全字段,安全字段必须需要 master 管理权限才可以修改 +required | 是否是必填字段 + +>`JBField`提供的一些主要的方法为: + +序号| 方法 | 方法说明 +--- | --- | --- +1 | save() | [创建或更新字段信息(同步)](java-sdk.md#创建或更新字段信息) +2 | saveInBackground(JBSaveCallback callback) | [创建或更新字段信息(异步)](java-sdk.md#创建或更新字段信息) +3 | delete() | [删除字段信息(同步)](java-sdk.md#删除字段信息) +4 | deleteInBackground(JBDeleteCallback callback) | [删除字段信息(异步)](java-sdk.md#删除字段信息) +5 | update() | [更新字段信息(同步)](java-sdk.md#更新字段信息) +6 | updateInBackground(JBUpdateCallback callback) | [更新字段信息(异步)](java-sdk.md#更新字段信息) +7 | get(String className, String fieldName) | [获取字段信息(同步)](java-sdk.md#获取字段信息) +8 | getInBackground(String className, String fieldName, JBGetFieldCallback callback) | [获取字段信息(异步)](java-sdk.md#获取字段信息) +9 | list(String className) | [获取字段列表信息(同步)](java-sdk.md#获取字段列表信息) +10 | listInBackground(String className, JBFieldListCallback callback) | [获取字段列表信息(异步)](java-sdk.md#获取字段列表信息) + +### 创建或更新字段信息 +使用者拥有了当前应用的`master`管理权限后,可以创建或者更新字段信息,`JavaSDK` 目前提供8种字段类型: + +序号| 字段类型 | 说明 +--- | --- | --- +1 | String | 字符串 +2 | Number | 数字 +3 | Boolean | 布尔型 +4 | Date | 日期 +5 | File | 文件 +6 | Object | 对象 +7 | Array | 数组 +8 | Pointer | 指针 + +```java +try { + // type 为字段类型的序号 + JBField field = new JBField(1, "title"); + field.setClazz(new JBClazz("Sound")); + // 是否必填,默认为false + field.setRequired(true); + // 是否内建,默认为false + field.setInternal(true); + // 是否为安全字段,安全字段信息在获取数据时不会带出,默认为false + field.setSecurity(true); + field.save(); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +### 删除字段信息 +使用者拥有了当前应用的`master`管理权限后,可以删除字段信息,需要注意的是,因为`mongoDB`本身没有字段概念,只有`key`,本方法只是删除了`JavaBaas`中的字段的定义,不会删除文档中相关的key和对应的value,但是在用户查询过程中,该key和对应的value不在对用户展示。 + +```java +try { + JBField field = new JBField(); + field.setName("Sound"); + field.delete(); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +### 更新字段信息 +使用者拥有了当前应用的`master`管理权限后,可以对字段信息进行更新,目前更新字段信息只限于更新字段的`security`,`required`属性。 + +```java +try { + JBField field = new JBField(); + field.setName("Sound"); + field.setSecurity(false); + field.update(); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +### 获取字段信息 +使用者拥有了当前应用的`master`管理权限后,可以查询字段信息。 + +```java +try { + // 两个参数分别为表名和字段名 + JBField field = JBField.get("Sound", "title"); +} catch (JBException e) { + System.out.println(e.getMessage()); +} +``` + +### 获取字段列表信息 +使用者拥有了当前应用的`master`管理权限后,可以查看某个表中所有字段信息。 + +```java +JBField.listInBackground("Sound", new JBFieldListCallback() { + @Override + public void done(boolean success, List list, JBException e) { + // code + } +}); +``` diff --git a/doc/manual/rest_api.md b/doc/manual/rest_api.md index ac5be37..e757130 100644 --- a/doc/manual/rest_api.md +++ b/doc/manual/rest_api.md @@ -33,18 +33,19 @@ baas.auth.key = V1hwT1UyRkhUblZpUjNoclVWTlZlbEpEVlhwU1FTVXpSQ1V6UkElM0QlM0Qc3Rhc Content-Type | 必须为 application/json JB-Plat | 调用接口的平台 取值为js或android或ios JB-Timestamp | 客户端产生本次请求的 unix 时间戳,精确到毫秒。 +JB-Nonce | 本次请求的校验码。无规则不重复随机字符串。 JB-AppId | 调用应用的AppId,用以表示正在操作哪一个应用。(当使用管理授权或普通授权时需要) -JB-AdminSign(三选一)|将adminKey加上":"再加上timestamp组成的字符串,再对它做 MD5 签名后的结果。 -JB-MasterSign(三选一) | 将masterKey加上":"再加上timestamp组成的字符串,再对它做 MD5 签名后的结果。 -JB-Sign(三选一) | 将key加上":"再加上timestamp组成的字符串,再对它做 MD5 签名后的结果。 +JB-AdminSign(三选一)|将adminKey:JB-Timestamp:JB-Nonce组成的字符串,再对它做 MD5 签名后的结果。 +JB-MasterSign(三选一) | 将masterKey:JB-Timestamp:JB-Nonce组成的字符串,再对它做 MD5 签名后的结果。 +JB-Sign(三选一) | 将key:JB-Timestamp:JB-Nonce组成的字符串,再对它做 MD5 签名后的结果。 其中`JB-AdminSign` `JB-MasterSign` `JB-Sign`为三选一。使用`JB-AdminSign`时为超级授权、使用`JB-MasterSign`时为管理授权、使用`JB-Sign`时为普通授权。使用管理授权或普通授权时为了指定被操作的App,因此必须有`JB-AppId`。 加密计算实现(Java): ```java -public String encrypt(String key, String timeStamp) { - return md5(key + ":" + timeStamp); +public String encrypt(String key, String timeStamp, String nonce) { + return md5(key + ":" + timeStamp + ":" + nonce); } ``` @@ -54,9 +55,9 @@ public String encrypt(String key, String timeStamp) { ``` Server-IP: http://127.0.0.1:8080/ -JB-AppId: 56cd5194c6db7c372fd1563f -key: 8fdd2c7fad56430688f192ca835b524b -masterKey: 53a0b6967e2f4ac399341c4ac93f2db3 +JB-AppId: 594895b0b55198292ae266f1 +key: a8c18441d7ab4dcd9ed78477015ab8b2 +masterKey: cebde78a2d2d48c9870cf4887cbb3eb1 ``` ##响应格式 @@ -73,7 +74,6 @@ URL|METHOD|描述 /object/{className}|POST|[创建对象](rest_api.md#创建对象) /object/{className}/{id}|GET|[获取对象](rest_api.md#获取对象) /object/{className}/{id}|PUT|[更新对象](rest_api.md#更新对象) -/object/{className}/{id}/inc|PUT|[对象原子操作](rest_api.md#对象原子操作) /object/{className}|GET|[查询对象](rest_api.md#查询对象) /object/{className}/count|GET|[查询对象个数](rest_api.md#查询对象个数) /object/{className}/{id}|DELETE|[删除对象](rest_api.md#删除对象) @@ -121,6 +121,9 @@ URL|METHOD|描述 /user/{id}/updatePassword|PUT|[修改用户密码](rest_api.md#修改用户密码) /user/login|GET|[用户登录](rest_api.md#用户登录) /user/loginWithSns/{platform}|POST|[第三方登录](rest_api.md#第三方登录) +/user/registerWithSns/{platform}|POST|[第三方注册](rest_api.md#第三方注册) +/user/getSmsCode/{phone}|GET|[获取注册登录短信验证码](rest_api.md#获取注册登录短信验证码) +/user/loginWithPhone |POST|[手机验证码注册登录](rest_api.md#手机验证码注册登录) /user/{id}/resetSessionToken|PUT|[重置用户SessionToken](rest_api.md#重置用户SessionToken) ###文件(管理权限 普通权限) @@ -207,9 +210,10 @@ http://127.0.0.1:8080/api/object/Sound/6e929370b8674fd885a191052a34c259 ``` curl -X POST \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{"title":"音频名称","length":300,"content":"音频的描述"}' \ @@ -242,9 +246,10 @@ curl -X POST \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/object/Sound/b54aa8a1ab5945649c628b63b65c1db9 @@ -276,9 +281,10 @@ curl -X GET \ ``` curl -X PUT \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{"title":"修改后的音频名称"}' \ @@ -316,18 +322,19 @@ curl -X PUT \ } ``` -###对象原子操作 -对于Nuber类型的字段,例如我们需要记录某个音频的打开次数(readCount),然而对于一个热门音频,可能会有很多并发打开音频操作,如果每次我们都是通过请求获取改音频目前的readCount,然后加1后再通过请求写到后台,那么这极容易造成数据脏读,引发冲突和覆盖,最终导致结果不准。对于这种场景,JavaBaas提供了对象的原子操作: +### 对象原子操作 +原子操作是对象更新的一种,对于Nuber类型的字段,例如我们需要记录某个音频的打开次数(readCount),然而对于一个热门音频,可能会有很多并发打开音频操作,如果每次我们都是通过请求获取改音频目前的readCount,然后加1后再通过请求写到后台,那么这极容易造成数据脏读,引发冲突和覆盖,最终导致结果不准。对于这种场景,JavaBaas提供了对象的原子操作: ``` curl -X PUT \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ - -d '{"readCount":1}' \ - http://127.0.0.1:8080/api/object/Sound/b54aa8a1ab5945649c628b63b65c1db9/inc + -d '{"readCount":{"__op":"Increment", "amount":1}}' \ + http://127.0.0.1:8080/api/object/Sound/b54aa8a1ab5945649c628b63b65c1db9 ``` 请求成功后,通过 [获取对象](rest_api.md#获取对象) 可以看到之前创建的一条Sound对象中 `readCount` 字段已经被加1: @@ -352,14 +359,28 @@ curl -X PUT \ } ``` +包括上面的原子操作,JavaBaas共提供了六种原子操作。 + +__op| 附加参数 | 描述 +--- | --- | --- +Delete | 无 | 删除字段 +Add | objects | Array类型字段添加值 +AddUnique | objects | Array类型字段添加与之前不重复的值 +Remove | objects | Array类型字段删除值 +Increment | amount | Number类型字段原子增加或原子减少 +Multiply | amount | Number类型字段原子倍数增加 + + + ###查询对象 我们通过发送一个 GET 请求到类的 URL 上,从而一次获取多个对象: ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/object/Sound @@ -428,9 +449,10 @@ curl -X GET \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -455,9 +477,10 @@ curl -X GET \ ``` curl -X DELETE \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/object/Sound/b54aa8a1ab5945649c628b63b65c1db9 @@ -480,9 +503,10 @@ curl -X DELETE \ ``` curl -X DELETE \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -502,9 +526,10 @@ curl -X DELETE \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -568,10 +593,11 @@ $sub | 子查询 ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ - -H "JB-Plat:js" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ + -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ --data-urlencode 'where={"readCount":{"$lt":5}}' \ @@ -602,9 +628,10 @@ curl -X GET \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -645,9 +672,10 @@ curl -X GET \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -659,9 +687,10 @@ curl -X GET \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -708,9 +737,10 @@ curl -X GET \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -724,9 +754,10 @@ curl -X GET \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -779,9 +810,10 @@ curl -X GET \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -807,9 +839,10 @@ JavaBaas提供了一种字段类型 `Pointer` ,`Pointer` 类型是用来设定 ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -846,9 +879,10 @@ curl -X GET \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -892,9 +926,10 @@ curl -X GET \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -907,9 +942,10 @@ curl -X GET \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -927,9 +963,10 @@ curl -X GET \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -943,9 +980,10 @@ curl -X GET \ ``` curl -X GET \ - -H "JB-Timestamp:1458726351581" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:4bf9845332d1f6256341abcd269b074e" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -G \ @@ -964,6 +1002,7 @@ curl -X GET \ curl -X POST \ -H "JB-Timestamp:1459134010861" \ -H "JB-AdminSign:984df38bc629c55aade4b1951631f6b9" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{"name":"NewApp"}' \ @@ -994,6 +1033,7 @@ curl -X POST \ curl -X GET \ -H "JB-Timestamp:1459134010861" \ -H "JB-AdminSign:984df38bc629c55aade4b1951631f6b9" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/admin/app @@ -1033,6 +1073,7 @@ curl -X GET \ curl -X GET \ -H "JB-Timestamp:1459134010861" \ -H "JB-AdminSign:984df38bc629c55aade4b1951631f6b9" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/admin/app/56f89eb7ffe4f21c3d3e8f5e @@ -1044,6 +1085,7 @@ curl -X GET \ curl -X DELETE \ -H "JB-Timestamp:1459134010861" \ -H "JB-AdminSign:984df38bc629c55aade4b1951631f6b9" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/admin/app/56f89eb7ffe4f21c3d3e8f5e @@ -1055,6 +1097,7 @@ curl -X DELETE \ curl -X PUT \ -H "JB-Timestamp:1459134010861" \ -H "JB-AdminSign:984df38bc629c55aade4b1951631f6b9" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/admin/app/56cd5194c6db7c372fd1563f/resetKey @@ -1067,6 +1110,7 @@ curl -X PUT \ curl -X PUT \ -H "JB-Timestamp:1459134010861" \ -H "JB-AdminSign:984df38bc629c55aade4b1951631f6b9" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/admin/app/56cd5194c6db7c372fd1563f/resetMasterKey @@ -1079,6 +1123,7 @@ curl -X PUT \ curl -X GET \ -H "JB-Timestamp:1459134010861" \ -H "JB-AdminSign:984df38bc629c55aade4b1951631f6b9" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/admin/app/56cd5194c6db7c372fd1563f/export @@ -1134,6 +1179,7 @@ curl -X GET \ curl -X POST \ -H "JB-Timestamp:1459134010861" \ -H "JB-AdminSign:984df38bc629c55aade4b1951631f6b9" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{这里是应用备份数据的 json 串}' \ @@ -1150,6 +1196,7 @@ curl -X POST \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{"name":"NewClass"}' \ @@ -1163,6 +1210,7 @@ curl -X GET \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/master/clazz @@ -1237,6 +1285,7 @@ curl -X GET \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/master/clazz/Sound @@ -1249,6 +1298,7 @@ curl -X DELETE \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/master/clazz/_User @@ -1262,6 +1312,7 @@ curl -X GET \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/master/clazz/Sound/export @@ -1307,6 +1358,7 @@ curl -X POST \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{这里是类结构化数据的 json 串}' \ @@ -1320,6 +1372,7 @@ curl -X POST \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{"a6159350c5964cebbe523d679b9889ae":{"find":true,"insert":true}}' \ @@ -1337,6 +1390,7 @@ curl -X POST \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{"name":"newFiled","type":1}' \ @@ -1350,6 +1404,7 @@ curl -X GET \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/master/clazz/Sound/field @@ -1402,6 +1457,7 @@ curl -X GET \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/master/clazz/Sound/field/newFiled @@ -1414,6 +1470,7 @@ curl -X PUT \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{"security":true}' \ @@ -1429,6 +1486,7 @@ curl -X DELETE \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/master/clazz/Sound/field/newFiled @@ -1446,9 +1504,10 @@ curl -X DELETE \ ``` curl -X POST \ - -H "JB-Timestamp:1459823352367" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:3f0473567b1635a0b83648a75e895ff7" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "Content-Type: application/json" \ -d '{"username":"codi","password":"123456","nickname":"Codi"}' \ http://127.0.0.1:8080/api/users @@ -1476,9 +1535,10 @@ curl -X POST \ ``` curl -X GET \ - -H "JB-Timestamp:1459823352367" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:3f0473567b1635a0b83648a75e895ff7" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "Content-Type: application/json" \ -G \ --data-urlencode 'username=codi' \ @@ -1516,9 +1576,10 @@ curl -X GET \ ``` curl -X POST \ - -H "JB-Timestamp:1459823352367" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:3f0473567b1635a0b83648a75e895ff7" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-SessionToken:9ce57fb007544d318b642d084989bc40" \ -H "Content-Type: application/json" \ -d '{"accessToken":"69B307BA98F8C8D2455CC8D9040A6A96","uid":"AB782D5190C50B588B536145FEEF6A0F"}' \ @@ -1537,9 +1598,10 @@ curl -X POST \ ``` curl -X DELETE \ - -H "JB-Timestamp:1459823352367" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:3f0473567b1635a0b83648a75e895ff7" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-SessionToken:9ce57fb007544d318b642d084989bc40" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/a6159350c5964cebbe523d679b9889ae/release/{platform} @@ -1554,9 +1616,10 @@ curl -X DELETE \ 你可以通过发送请求修改用户信息: ``` curl -X PUT \ - -H "JB-Timestamp:1459823352367" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:3f0473567b1635a0b83648a75e895ff7" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-SessionToken:9ce57fb007544d318b642d084989bc40" \ -H "Content-Type: application/json" \ -d '{"oldPassword":"123456","newPassword":"654321"}' \ @@ -1568,9 +1631,10 @@ curl -X PUT \ ``` curl -X PUT \ - -H "JB-Timestamp:1459823352367" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:3f0473567b1635a0b83648a75e895ff7" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-SessionToken:9ce57fb007544d318b642d084989bc40" \ -H "Content-Type: application/json" \ -d '{"oldPassword":"123456","newPassword":"654321"}' \ @@ -1583,23 +1647,64 @@ curl -X PUT \ * new_password:用户的新密码 ###第三方登录 -用户于第三方平台绑定后,可以使用第三方平台授权信息进行登录操作。登录成功后,会获得所有的用户信息。 +用户于第三方平台绑定后,可以使用第三方平台授权信息进行登录操作。登录成功后,会获得所有的用户信息。
+ +微博: ``` curl -X POST \ - -H "JB-Timestamp:1459823352367" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:3f0473567b1635a0b83648a75e895ff7" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "Content-Type: application/json" \ -d '{"accessToken":"69B307BA98F8C8D2455CC8D9040A6A96","uid":"AB782D5190C50B588B536145FEEF6A0F"}' \ - http://127.0.0.1:8080/api/user/loginWithSns/{platform} + http://127.0.0.1:8080/api/user/loginWithSns/1 +``` +qq: + +``` +curl -X POST \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ + -H "Content-Type: application/json" \ + -d '{"accessToken":"69B307BA98F8C8D2455CC8D9040A6A96","openId":"AB782D5190C50B588B536145FEEF6A0F"}' \ + http://127.0.0.1:8080/api/user/loginWithSns/2 +``` +微信: + +``` +curl -X POST \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ + -H "Content-Type: application/json" \ + -d '{"accessToken":"69B307BA98F8C8D2455CC8D9040A6A96","uninoId":"AB782D5190C50B588B536145FEEF6A0F"}' \ + http://127.0.0.1:8080/api/user/loginWithSns/3 +``` +微信小程序: + +``` +curl -X POST \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ + -H "Content-Type: application/json" \ + -d '{"uninoId":"AB782D5190C50B588B536145FEEF6A0F", "encryptedData":"HSUEJ2D5190CJEIKFHBWJWK45OEPQLSM","iv":"JSUEJSHSBWWK"}' \ + http://127.0.0.1:8080/api/user/loginWithSns/4 ``` 其中: -* platform:第三方平台的名称,微博:weibo、qq:qq、微信:weixin。 -* accessToken:使用第三方平台授权时获取的token -* uid:使用第三方平台授权时获取的用户身份表示,其中微博取uid字段,qq、微信取openId字段 +* platform:数值,1:微博,2:qq,3:微信,4:微信小程序 +* accessToken:使用微博、qq、微信第三方平台授权时获取的token,微信小程序登录不需要提交。 +* uid:微博注册登录需要,为微博授权后返回的uid +* openId、unionId:qq、微信、微信小程序注册登录需要,openId和unionId同时都提交时,优先使用unionId。 +* encryptedData、code、iv:微信小程序注册登录需要。 返回用户信息。 @@ -1620,6 +1725,51 @@ curl -X POST \ } ``` +### 第三方注册 +如过希望在第三方登录时,没有注册过自动注册新用户,可以通过下面的请求: + +``` +curl -X POST \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ + -H "Content-Type: application/json" \ + -d '{"accessToken":"69B307BA98F8C8D2455CC8D9040A6A96","uninoId":"AB782D5190C50B588B536145FEEF6A0F"}' \ + http://127.0.0.1:8080/api/user/registerWithSns/3 +``` + +该请求是微信注册登录,其他平台可参考[第三方登录](rest_api.md#第三方登录)。 + +### 获取注册登录短信验证码 +通过下面的请求可以获取注册登录短信验证码。 + +``` +curl -X GET \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ + -H "Content-Type: application/json" \ + http://127.0.0.1:8080/api/user/getSmsCode/{phone} +``` + +* phone:手机号 + +### 手机验证码注册登录 +使用下面的请求可以进行手机验证码注册登录 + +``` +curl -X POST \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ + -H "Content-Type: application/json" \ + -d '{"phone":"13888888888","code":"123242"}' \ + http://127.0.0.1:8080/api/user/loginWithPhone +``` + ##文件 JavaBaas 目前的文件系统使用第三方的 [七牛云存储](http://www.qiniu.com) 。 @@ -1629,9 +1779,10 @@ JavaBaas 目前的文件系统使用第三方的 [七牛云存储](http://www.qi ``` curl -X GET \ - -H "JB-Timestamp:1459137092965" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/file/getToken?fileName=filename&platform=qiniu @@ -1662,6 +1813,7 @@ curl -X POST \ -H "JB-Timestamp:1459137092965" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/file/master/process?fileId=481&a91a43496ae3a16d8e9457cf8n90&platform=qiniu @@ -1678,6 +1830,7 @@ curl -X POST \ -H "JB-Timestamp:1459829784178" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:8a1afca2fbd8ef89e52211cbcf799812" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{"cloudFunctions":["cloudMethod1","cloudMethod2"],"hookSettings":{"Sound":{"afterInsert":true,"afterDelete":true}}}' \ @@ -1692,6 +1845,7 @@ curl -X DELETE \ -H "JB-Timestamp:1459829784178" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:8a1afca2fbd8ef89e52211cbcf799812" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/master/cloud @@ -1705,6 +1859,7 @@ curl -X GET \ -H "JB-Timestamp:1459829784178" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:8a1afca2fbd8ef89e52211cbcf799812" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ http://127.0.0.1:8080/api/cloud/cloudMethod1 @@ -1716,9 +1871,10 @@ JavaBaas提供了接口,供注册和记录设备,从而用于消息推送活 ``` curl -X POST \ - -H "JB-Timestamp:1459137092965" \ - -H "JB-AppId:56cd5194c6db7c372fd1563f" \ - -H "JB-Sign:a869a91a43496ae3a16d8e9b07cf8b69" \ + -H "JB-Timestamp:1510221226269" \ + -H "JB-AppId:594895b0b55198292ae266f1" \ + -H "JB-Sign:5e65a127a4f976d1edfac0e2abaa3383" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{"deviceType":"ios","deviceToken":"72383872abb322122ba7788999b8839"}' \ @@ -1736,6 +1892,7 @@ curl -X POST \ -H "JB-Timestamp:1459829784178" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:8a1afca2fbd8ef89e52211cbcf799812" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{"type":4,"objectId":"62873a95570c429aaadb971e0d2dea25"}' \ @@ -1752,6 +1909,7 @@ curl -X PUT \ -H "JB-Timestamp:1459829784178" \ -H "JB-AppId:56cd5194c6db7c372fd1563f" \ -H "JB-MasterSign:8a1afca2fbd8ef89e52211cbcf799812" \ + -H "JB-Nonce:0613edd636ac4e99aa20aeaab04be15c" \ -H "JB-Plat:js" \ -H "Content-Type: application/json" \ -d '{"key":"ahsfh392223jjk49034kjh98","secret":"kskhhhj987663902"}' \ diff --git a/doc/navigation.md b/doc/navigation.md index 3dcf3f1..49a92b9 100644 --- a/doc/navigation.md +++ b/doc/navigation.md @@ -1,5 +1,4 @@ #JavaBaas -[gimmick:ForkMeOnGitHub](https://github.com/JavaBaas/JavaBaasServer) [主页](index.md) [功能概述]() @@ -9,7 +8,8 @@ * [命令行工具](manual/command_line.md) * [REST API](manual/rest_api.md) - * [Android SDK](manual/android-adk_api.md) - * [iOS SDK](manual/ios-adk_api.md) + * [Android SDK](manual/android-sdk.md) + * [iOS SDK](manual/ios-sdk.md) + * [Java SDK](manual/java-sdk.md) [下载](download.md) diff --git a/doc/overview/object.md b/doc/overview/object.md index c207f24..4b7fc20 100644 --- a/doc/overview/object.md +++ b/doc/overview/object.md @@ -16,6 +16,9 @@ JavaBaas使用MongoDB作为数据存储数据库。虽然MongoDB为无模式数 |_User|用户 |_Installation|设备 |_File|文件 +|_PushLog|推送 +|_SmsLog|短信 + ###字段 在类中创建字段以存储数据。字段的名称必须使用英文字母开头且名称中只能包含数字与英文字母。每个字段在创建时,必须选择一个取值类型,值的类型可以是字符串、数字、日期等类型(参见`数据类型`),字段类型一旦设置无法更改。每个类在创建后,系统会自动创建`id` `createdAt` `updatedAt` `acl`四个内建字段,系统内建字段禁止删除。