全部产品
云市场

数据总线

更新时间:2019-07-18 13:34:54

1. 数据集成介绍

数据集成标准化的目标是规范应用之间数据的传递方式和表达方式。

  • 传递方式:即应用之间的数据如何流通。平台提供了对数据进行增删改查的4个API,以及HTTP2方式的消息订阅机制。
  • 表达方式:即应用之间如何对数据内容有一致的理解。为了实现这个目标,需要做到如下两点,一是数据结构需要由小二后台统一管控(目前全部由小二后台录入,未来会引入审核机制);二是应用集成对接之前(比如应用上架的时候)需要声明本应用对哪些数据模型产生什么样的数据操作(如查询、新增,或者订阅)。

基于以上逻辑,为了实现应用的数据集成能力,分别需要执行相应的应用声明、应用开发、应用集成。
image.png

2. 应用声明

应用的声明是指应用在上架到市场时,由应用开发者自行声明的,包含两部分声明内容:应用涉及到的数据模型;以及对这些模型所做的相应的操作。这里指出应用对数据模型的操作,目的有两个,一是用户可以感知应用对数据的操作范围,二是平台根据声明的操作决定对应用的操作权限。
image.png

3. 应用集成

所谓的“数据集成”,是指应用之间数据共享的方式,比如两个应用,当涉及到相同的数据模型时,是共享一份数据,还是独立管理各自的数据。通过应用声明,应用在上架到应用市场之后,用户就能感知应用与数据之间的关系。目前通用的集成方案是以项目为隔离维度的。也就是说,在一个项目内的所有应用,他们关联的相同的数据模型,会被默认放在同一个隔离区域ScopeID内。

4. 应用开发 - 数据操作

应用之间共享数据时,需要向提平台操作数据,或者从平台订阅数据。数据操作方面,这里主要涉及4个接口:新增数据、查询数据、删除数据、修改数据。详见后面的API参考。同时,为了便于应用开发,平台提供了SDK,简化开发。

4.1 SDK介绍

4.1.1 Java SDK

1. 依赖

  1. <dependency>
  2. <groupId>com.aliyun.api.gateway</groupId>
  3. <artifactId>sdk-core-java</artifactId>
  4. <version>1.0.4</version>
  5. </dependency>

2. 示例代码

  1. SyncApiClient syncClient = SyncApiClient.newBuilder()
  2. .appKey("1234567")
  3. .appSecret("6726732dsfdsdsfdsfds")
  4. .build();
  5. IoTApiRequest request = new IoTApiRequest();
  6. //设置api的版本
  7. request.setApiVer("0.1.0");
  8. // 接口参数
  9. request.putParam("json","{}");
  10. request.putParam("productKey","a1ILGykZVhP");
  11. request.putParam("deviceName","Dxb3lv1E78mg5dsVLUQW");
  12. request.putParam("serviceName","kkp");
  13. //请求参数域名、path、request
  14. ApiResponse response = syncClient.postBody("test123-cn-shanghai.alicloudapi.com",
  15. "/invokeThingService", request);
  16. System.out.println("response code = " + response.getStatusCode() + " response content = " + new String(response.getBody(),
  17. "utf-8"));
  18. }

4.1.2 Python SDK

1. 依赖

依赖的三方库: 无

  1. 示例代码
    Step 1: 下载示例工程代码。示例工程在基于Python 2.7,Python3请自行适配。
    1. git clone https://github.com/aliyun/api-gateway-demo-sign-python.git

Step 2:
修改signature_composer.py文件第49行

  1. 修改前: string_to_sign.append(_build_resource(uri=uri, body=body))
  2. 修改后: string_to_sign.append(uri)

Step 3: 修改ClientDemo.py如下,执行调用

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import os
  4. import sys
  5. import json
  6. sys_path = sys.path[0]
  7. if not os.path.isdir(sys_path):
  8. sys_path = os.path.dirname(sys_path)
  9. os.chdir(sys_path)
  10. from com.aliyun.api.gateway.sdk import client
  11. from com.aliyun.api.gateway.sdk.http import request
  12. from com.aliyun.api.gateway.sdk.common import constant
  13. host = "https://api.link.aliyun.com"
  14. url = "/data/model/data/query"
  15. cli = client.DefaultClient(app_key="1234567", app_secret="abcdefghijklmnopq")
  16. req_post = request.Request(host=host, protocol=constant.HTTPS, url=url, method="POST", time_out=30000)
  17. req_post.set_content_type(constant.CONTENT_TYPE_STREAM)
  18. body = {
  19. "request":{
  20. "apiVer":"0.0.2"
  21. },
  22. "params":{
  23. "modelId":"EMPLOYEE",
  24. "returnFields":["employee_no", "name"],
  25. "conditions":[{"fieldName":"id","value":"1","operate":"mt"}],
  26. "pageSize": 100,
  27. "pageNum": 1
  28. },
  29. "version":"1.0"
  30. }
  31. bb = json.dumps(body).encode("utf-8")
  32. req_post.set_body(bb)
  33. print '==================================================='
  34. print str(cli.execute(req_post)).decode('string_escape')
  35. print '==================================================='

4.1.3 JS SDK

1. 依赖

  1. $ # save into package.json dependencies with -S
  2. $ npm install aliyun-api-gateway -S
  3. $ # you can use cnpm for fast install
  4. $ cnpm install aliyun-api-gateway -S

2. 示例代码

  1. 'use strict';
  2. const co = require('co');
  3. const Client = require('aliyun-api-gateway').Client;
  4. const client = new Client('YOUR_APP_KEY','YOUR_APP_SECRET');
  5. co(function* () {
  6. var url = 'http://apiqingdaohttps.foundai.com/test1234';
  7. var result = yield client.post(url, {
  8. data: {
  9. 'testtest': 'query1Value'
  10. },
  11. headers: {
  12. accept: 'application/json'
  13. }
  14. });
  15. console.log(JSON.stringify(result));
  16. });

4.2 数据操作API

4.2.1 API 描述

API名称 API描述 API Path API 版本
新增数据 基于已经创建且被授权写入的模型,进行数据的新增。 /data/model/data/insert 0.0.3
删除数据 基于已经创建且被授权删除的模型,进行数据的更新。 /data/model/data/delete 0.0.2
修改数据 基于已经创建且被授权更新的模型,进行数据的更新。 /data/model/data/update 0.0.2
查询数据 基于已经创建且被授权查询的模型,进行数据的查询。 /data/model/data/query 0.0.3
获取文件上传地址 对于模型中指定为“图片”标签的字段,在该字段需要填写文件名,并且文件名需要通过该接口获取,该接口同时还会返回一个URL供用户上传文件。该地址有效期是10秒。 /data/model/data/upload 0.0.1
获取文件下载地址 对于模型中指定为“图片”标签的字段,在该字段的内容是一个系统分配的文件名,用户可以通过本接口,传入这个文件名,获取真实的文件下载地址。该地址有效期是10秒。 /data/model/data/download 0.0.1

4.2.2 API 约定

  1. 日期类型的参数传入格式:当前时间到格林威治时间1970年01月01日00时00分00秒的毫秒数。
  2. 数量查询的一些约定:
    1. 单次查询最多返回200条数据,未指定分页参数情况下,查询返回满足条件的前200条,可根据返回参数中的hasNext判断是否有更多数据。
    2. 若需要按照指定条件返回数据总数,则指定返回参数为COUNT,API返回参数中会带有COUNT以及对应的值。
    3. 若需要按照指定条件,及按照字段分组进行数量查询,则指定返回参数为COUNT(分组字段1,分组字段2),API返回参数中会带有COUNT以及对应的值。
  3. 更新删除的约定:单次操作,最多支持200条数据。
  4. 运算符定义:
运算符 含义 备注
eq equals 相等
neq not equals 不相等
lt less than 小于
lteq less than or equals 小于等于
mt more than 大于
mteq more than or equals 大于等于
bt between 在..之间
in in 在..之内
nin not in 不在..之内
nul is null 为空
nnul is not null 不为空
  1. 数据包括系统属性,API中不允许赋值和更新系统属性,系统属性如下:
属性 描述
id 数据主键
creator 数据创建者
modifier 数据修改者
gmt_create 数据创建时间
gmt_modified 数据修改时间

4.2.3 数据新增API

1. 请求参数

参数 类型 描述 是否必传
modelId String 数据模型id
properties JSON 数据字段键值对,增加的字段的键只能是模型包含的字段,否则会报错,
其中 Boolean属性的property传入”true”和”false”或者0和1。
如:{“name”:”xxx”,”age”:18}
scopeId String 经常是项目的id,该参数非必填,一般上架应用被授权之后,会被默认绑定到一个scope中,因此当前操作会被默认操作到被绑定到的这一个scope中。但是,对于集成应用,也有可能被绑定到多个scope中,此时该操作需要填入scopeId。
appId String 对于SaaS应用,需要填该值

2. 返回参数

参数 类型 描述
data Long 数据主键id

3. 请求示例

  1. {
  2. "request": {
  3. "apiVer": "0.0.3" // api版本号
  4. },
  5. "id": 1508212818676,// request里的全局唯一id透传
  6. "params": {
  7. "modelId":"XXX123", //数据模型id
  8. "scopeId":"fdbsdj1dfjdubgxxx", //数据模型id
  9. "properties":{
  10. "BRAND":"BMW",
  11. "MODE":"5",
  12. "CREATE_DATE":1526969423,
  13. "LONG_SIZE":3.3,
  14. "LONG_SIZE":2.2
  15. }
  16. },
  17. "version": "1.0" // 请求协议版本
  18. }

4. 返回示例

  1. {
  2. "code": 200,
  3. "message": "success",
  4. "localizedMsg": null,
  5. "data": 12345
  6. }

5. 返回码

状态码 描述 其他说明
200 成功
460 参数验证异常 会带有验证异常的详细说明
500 服务异常 server error
52002 无访问权限
52005 找不到目标存储
52009 参数和模型定义不匹配
52011 数据类型校验错误

4.2.4 数据删除API

1. 请求参数

参数 类型 是否必传 描述
modelId String 数据模型id
conditions JSON 数据条件,由字段名、运算符、比较值组成一个condition。如:[{“fieldName”: “id”,”operate”: “eq”,”value”: 7}]
appId String 对于SaaS应用,需要填该值
scopeId String 经常是项目的id,该参数非必填,一般上架应用被授权之后,会被默认绑定到一个scope中,因此当前操作会被默认操作到被绑定到的这一个scope中。但是,对于集成应用,也有可能被绑定到多个scope中,此时该操作需要填入scopeId。

其中condition针对不同类型的属性支持的运算符:

属性 支持的运算符
Integer eq,neq,lt,lteq,mt,mteq,bt,in,nin,nnull
String eq,neq,,nnul,in,nin
Double eq,neq,lt,lteq,mt,mteq,bt,in,nin,nnull
Boolean eq,nnul
Date eq,neq,lt,lteq,mt,mteq,bt,nnul

2. 返回参数

参数 类型 描述
data Integer 删除数据的条数

3. 请求示例

  1. {
  2. "request": {
  3. "apiVer": "0.1.0" // api版本号
  4. },
  5. "id": 1508212818676,// request里的全局唯一id透传
  6. "params": {
  7. "modelId":"XXX123",
  8. "conditions":[
  9. {"fieldName":"BRAND","value":"BMW","operate":"eq"},
  10. {"fieldName":"MODE","value":"X5","operate":"eq"}
  11. ]
  12. },
  13. "version": "1.0" // 请求协议版本
  14. }

4. 返回示例

  1. {
  2. "code": 200,
  3. "message": "success",
  4. "localizedMsg": null,
  5. "data":100
  6. }

5. 返回码

状态码 描述 说明
200 成功
460 参数验证异常 会带有验证异常的详细说明
500 服务异常 server error
52002 无访问权限

4.2.5 数据修改API

1. 请求参数

参数 类型 是否必传 描述
modelId String 数据模型id
updateDetails JSON 更新的具体字段和值,字段需要是模型中包含的字段,否则会报错,
其中 Boolean属性的property传入”true”和”false”或者0和1。如:{“name”:”xxxx”,”age”:20}
conditions JSON 条件,由字段名、运算符、比较值组成一个condition,格式如下:
[{“fieldName”: “id”,”operate”: “eq”,”value”: 7}]
fieldName表示 字段的名称
operate表示操作符,操作符见上表
value表示值
appId String 对于SaaS应用,需要填该值
scopeId String 经常是项目的id,该参数非必填,一般上架应用被授权之后,会被默认绑定到一个scope中,因此当前操作会被默认操作到被绑定到的这一个scope中。但是,对于集成应用,也有可能被绑定到多个scope中,此时该操作需要填入scopeId。

其中condition针对不同类型的属性支持的运算符:

属性 支持的运算符
Integer eq,neq,lt,lteq,mt,mteq,bt,in,nin,nnull
String eq,neq,,nnul,in,nin
Double eq,neq,lt,lteq,mt,mteq,bt,in,nin,nnull
Boolean eq,nnul
Date eq,neq,lt,lteq,mt,mteq,bt,nnul

2. 返回参数

参数 类型 描述
data Integer 更新数据的条数

3. 请求示例

  1. {
  2. "request": {
  3. "apiVer": "0.0.3" // api版本号
  4. },
  5. "id": 1508212818676,// request里的全局唯一id透传
  6. "params": {
  7. "modelId":"XXX123",
  8. "conditions":[
  9. {"fieldName":"BRAND","value":"BMW","operate":"eq"},
  10. {"fieldName":"MODE","value":"X5","operate":"eq"}
  11. ],
  12. "updateDetails":{
  13. "LONG_SIZE":4,
  14. "WIDTH_SIZE":3
  15. }
  16. },
  17. "version": "1.0" // 请求协议版本
  18. }

4. 返回示例

  1. {
  2. "code": 200,
  3. "message": "success",
  4. "localizedMsg": null,
  5. "data":100
  6. }

5. 返回码

状态码 描述
200 成功
460 参数验证异常 会带有验证异常的详细说明
500 服务异常 server error
52002 无访问权限
52006 资源更新错误
52011 数据类型校验错误

4.2.6 数据查询API

1. 请求参数

参数 类型 是否必传 说明
modelId String 数据模型ID
returnFields JSON 指定返回的字段
1.若期望返回所有字段,则传入参数为{““}
2.若期望返回数据总数,则传入参数为{“COUNT”}
2.若期望按照字段分组返回数据总数,则传入参数为{“COUNT(分组字段1,分组字段2)”}。
如:[“
“]或者[“name”,”age”]
[COUNT]
[COUNT(name)]
conditions JSON 条件,由字段名、运算符、比较值组成一个condition。如:[{“fieldName”: “id”,”operate”: “eq”,”value”: 7}]
orderBy JSON 排序条件,由增序或降序以及排序字段组成。如:{“asc”:”true”,”orderByFields”:[“name”,”age”]}
pageNum Integer 分页页数
pageSize Integer 分页每页数量
appId String 对于SaaS应用,需要填该值
scopeId String 经常是项目的id,该参数非必填,一般上架应用被授权之后,会被默认绑定到一个scope中,因此当前操作会被默认操作到被绑定到的这一个scope中。但是,对于集成应用,也有可能被绑定到多个scope中,此时该操作需要填入scopeId。

其中returnFields支持的函数类型:

函数名称 描述 实例
COUNT 函数返回匹配指定条件的行数 {“COUNT(分组字段1,分组字段2)”}
DATE_FORMAT 函数按照format字符串格式化字段值 {“DATE_FORMAT(分组字段, format)”}
SUM 函数返回数值列的总数 {“SUM(分组字段)”}
AVG 函数返回数值列的平均值 {“AVG(分组字段)”}
MIN 函数返回数值列的最小值 {“MIN(分组字段)”}
MAX 函数返回数值列的最大值 {“MAX(分组字段)”}

DATE_FORMAT支持的format修饰符

修饰符名称 描述
%Y
%Y-%m 年月
%Y-%m-%d 年月日
%Y-%m-%d %H 年月日时
%Y-%m-%d %H:%i 年月日时分
%Y-%m-%d %H:%i:%s 年月日时分秒

其中condition针对不同类型的属性支持的运算符:

属性 支持的运算符
Integer eq,neq,lt,lteq,mt,mteq,bt,in,nin,nnull
String eq,neq,,nnul,in,nin
Double eq,neq,lt,lteq,mt,mteq,bt,in,nin,nnull
Boolean eq,nnul
Date eq,neq,lt,lteq,mt,mteq,bt,nnul

2. 返回参数

参数 类型 描述
data String 查询返回数据内容,其中,Boolean类型的属性返回值为0或1

3. 请求示例-1

  1. {
  2. "request": {
  3. "apiVer": "0.0.2" // api版本号
  4. },
  5. "id": 1508212818676,// request里的全局唯一id透传
  6. "params": {
  7. "modelId":"XXX123",
  8. "returnFields":["MODE","ENGINE"],
  9. "conditions":[
  10. {"fieldName":"BRAND","value":"BMW","operate":"eq"},
  11. {"fieldName":"WIDTH_SIZE","value":1,"value2":2,"operate":"bt"},
  12. {"fieldName":"LONG_SIZE","value":"3","operate":"mt"}
  13. ],
  14. "orderBy":{
  15. "asc":true,
  16. "orderByFields":["CREATE_DATA","MODE"]
  17. },
  18. "pageNum":1,
  19. "pageSize":10
  20. }
  21. },
  22. "version": "1.0" // 请求协议版本
  23. }

4. 返回示例-1

  1. {
  2. "code": 200,
  3. "localizedMsg": null,
  4. "data": "{\"count\":1,
  5. \"hasNext\":false,
  6. \"items\":[{\"gmt_create\":1551872701000,\"MODE\":\"33\",\"ENGINE\":\"44\",\"id\":2,\"gmt_modified\":1551872714000}],
  7. \"pageNum\":1,
  8. \"pageSize\":10}",
  9. "message": "success"
  10. }

5. 请求示例-2

  1. {
  2. "request": {
  3. "apiVer": "0.1.0" // api版本号
  4. },
  5. "id": 1508212818676,// request里的全局唯一id透传
  6. "params": {
  7. "modelId":"XXX123",
  8. "returnFields":["COUNT",
  9. "conditions":[
  10. {"fieldName":"BRAND","value":"BMW","operate":"eq"},
  11. {"fieldName":"WIDTH_SIZE","value":1,"value2":2,"operate":"bt"},
  12. {"fieldName":"LONG_SIZE","value":"3","operate":"mt"}
  13. ],
  14. "pageNum":1,
  15. "pageSize":10
  16. }
  17. },
  18. "version": "1.0" // 请求协议版本
  19. }

6. 返回示例-2

  1. {
  2. "code": 200,
  3. "localizedMsg": null,
  4. "data": "{
  5. \"hasNext\":false,
  6. \"items\":[{
  7. \"COUNT\":100
  8. }]
  9. }"
  10. "message": "success"
  11. }

7. 请求示例-分组数量查询

  1. {
  2. "request": {
  3. "apiVer": "0.1.0" // api版本号
  4. },
  5. "id": 1508212818676,// request里的全局唯一id透传
  6. "params": {
  7. "modelId":"XXX123",
  8. "returnFields":["COUNT(BRAND,NAME)"],
  9. "conditions":[
  10. {"fieldName":"BRAND","value":"BMW","operate":"eq"},
  11. {"fieldName":"WIDTH_SIZE","value":1,"value2":2,"operate":"bt"},
  12. {"fieldName":"LONG_SIZE","value":"3","operate":"mt"}
  13. ],
  14. "pageNum":1,
  15. "pageSize":10
  16. }
  17. },
  18. "version": "1.0" // 请求协议版本
  19. }

8. 返回示例分组数量查询

  1. {
  2. "code": 200,
  3. "localizedMsg": null,
  4. "message": "success",
  5. "data": "{
  6. \"hasNext\":false,
  7. \"items\":[
  8. {
  9. \"COUNT\":100,
  10. \"BRAND\":\"BMW\",
  11. \"NAME\":\"X1\"
  12. },{
  13. \"COUNT\":200,
  14. \"BRAND\":\"JEEP\",
  15. \"NAME\":\"M2\"
  16. }
  17. ]
  18. }"
  19. }

9. 返回码

状态码 描述
200 成功
460 参数验证异常 会带有验证异常的详细说明
500 服务异常 server error
52002 无访问权限
52005 目标存储未找到

4.2.7 获取文件上传地址API

1. 请求参数

参数 类型 是否必传 描述
modelId String 数据模型id
version String 数据模型的版本号
fileSize Integer 文件大小,以字节为单位,目前系统不支持5M以上文件
attrName String 属性名称,模型中包含的属性名称,不包含会报错进行提示
fileType String 文件类型,目前系统只支持bmp、png、gif、jpg
appId String 对于SaaS应用,需要填该值
scopeId String 经常是项目的id,该参数非必填,一般上架应用被授权之后,会被默认绑定到一个scope中,因此当前操作会被默认操作到被绑定到的这一个scope中。但是,对于集成应用,也有可能被绑定到多个scope中,此时该操作需要填入scopeId。

2. 返回参数

参数 类型 描述
url String 数据上传的url,url有效时间10s
fileName String 文件名称,系统随机分配的文件名称,用户在得到这个文件名之后,应该将其放在相应模型数据的文件类型的字段上,例如: xxxxx.jpg

3. 请求示例

  1. {
  2. "request": {
  3. "apiVer": "0.0.1" // api版本号
  4. },
  5. "id": 1508212818671, // request里的全局唯一id透传
  6. "params": {
  7. "modelId":"XXX123", //数据模型id
  8. "fileSize":"3.2", //文件大小
  9. "attrName":"name", //属性名称
  10. "fileType":"jpg", //文件类型
  11. "version":"1.0", //模型版本
  12. },
  13. "version": "1.0" // 请求协议版本
  14. }

4. 返回示例

  1. {
  2. "code": 200, //返回是否成功,只要不是200说明返回不成功
  3. "message": "success", //如果失败 会返回失败的信息描述
  4. "localizedMsg": null,
  5. "data": {"url":"http://xxx.xxx.xx","fileName":"xxx.jpg"} 返回的数据
  6. }

5. 返回码

状态码 描述
200 成功
460 参数验证异常 会带有验证异常的详细说明
500 服务异常 server error
52002 无访问权限
52005 找不到目标存储
52009 参数和模型定义不匹配
52011 数据类型校验错误
52064 属性字段没有相应的图片标签
52063 文件大小不能大于5M

4.2.8 获取文件下载地址API

1. 请求参数

参数 类型 是否必传 描述
modelId String 数据模型id
version String 数据模型的版本号
attrName String 属性名称,模型中包含的属性名称,不包含会报错进行提示
fileType String 文件类型,目前系统只支持bmp、png、gif、jpg
appId String 对于SaaS应用,需要填该值
scopeId String 经常是项目的id,该参数非必填,一般上架应用被授权之后,会被默认绑定到一个scope中,因此当前操作会被默认操作到被绑定到的这一个scope中。但是,对于集成应用,也有可能被绑定到多个scope中,此时该操作需要填入scopeId。

2. 返回参数

参数 类型 描述
url String 数据上传的url,url有效时间10s

3. 请求示例

  1. {
  2. "request": {
  3. "apiVer": "0.0.1" // api版本号
  4. },
  5. "id": 1508212818671,// request里的全局唯一id透传
  6. "params": {
  7. "modelId":"XXX123", //数据模型id
  8. "scopeId":"fdbsdj1dfjdubgxxx", //业务隔离id
  9. "attrName":"name", //属性名称
  10. "fileName":"xdsfxv.jpg", //文件类型
  11. "version":"1.0", //模型版本
  12. },
  13. "version": "1.0" // 请求协议版本
  14. }

4. 返回示例

  1. {
  2. "code": 200, //返回是否成功,只要不是200说明返回不成功
  3. "message": "success", //如果失败 会返回失败的信息描述
  4. "localizedMsg": null,
  5. "data": {"url":"http://xxx.xxx.xx"} 返回的数据下载查看的url
  6. }

5. 返回码

状态码 描述
200 成功
460 参数验证异常 会带有验证异常的详细说明
500 服务异常 server error
52002 无访问权限
52005 找不到目标存储
52009 参数和模型定义不匹配
52011 数据类型校验错误
52064 属性字段没有相应的图片标签

5. 应用开发 - 数据订阅

应用可以通过HTTP2方式,订阅数据的变更消息(新增、删除、修改)。应用自身不需要发布数据的变更消息到通道中,这些消息的产生是由应用通过上面的数据操作API,对数据进行操作之后,由平台产生。平台产生时间之后,会将消息通过订阅关系发送到订阅方。
在这个消息通信中,每一个应用实例,由AppKey标识身份。对于单租户型的应用,每一个AppKey代表了一次应用分发的实例;但是,对于SaaS应用,他的一个AppKey代表了该应用对应的所有租户的身份,因此,在SaaS应用按照AppKey得到消息之后,需要自行根据订阅到的数据内容中的AppID字段,将数据对应到不用的用户中。

5.1 SDK介绍

5.1.1 Java SDK

1. 依赖引用

在工程中添加 maven 依赖接入 SDK。

  1. <dependency>
  2. <groupId>com.aliyun.openservices</groupId>
  3. <artifactId>iot-client-message</artifactId>
  4. <version>1.1.3</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.aliyun</groupId>
  8. <artifactId>aliyun-java-sdk-core</artifactId>
  9. <version>3.7.1</version>
  10. </dependency>

2. 身份认证

使用服务端订阅功能,需要基于AppKey进行身份认证并建立连接。该AppKey根据应用类型不同,有两种来源:

  • 对于独立单租户托管并分发的应用,该AppKey是由托管平台在应用实例化分发部署应用时,自动产生,并注入在主机的环境变量中,应用事先并不知道该值,需要动态从环境变量中获取。
  • 对于共享型应用,该AppKey是该SaaS应用在注册多租户接口时,从平台创建,并硬编码在应用中。
  1. String appKey = "XXXXXX";
  2. String appSecret = "XXXXXXXXXXXXXXXXXXXXXXX";
  3. String endpoint = String.format("https://%s.iot-as-http2.cn-shanghai.aliyuncs.com:443", appKey);
  4. // 连接配置
  5. Profile profile = Profile.getAppKeyProfile(endpoint, appKey, appSecret);
  6. // 构造客户端
  7. MessageClient client = MessageClientFactory.messageClient(profile);
  8. // 数据接收
  9. client.connect(messageToken -> {
  10. System.out.println(messageToken.getMessage());
  11. return MessageCallback.Action.CommitSuccess;
  12. });
  13. Thread.sleep(1000000);

*注意:关于上述代码中的“connect”方法,需要额外说明的是该方法在未经过授权的情况下,会调用失败。所以请务必做好重试逻辑,以便应用一旦被授权之后,可以及时得到订阅消息。

3. 设置消息接受接口

连接建立后,服务端会立即向 SDK 推送已订阅的消息。因此,建立链接时,需要提供消息接收接口,用于处理未设置回调的消息。建议在connect之前,调用 setMessageListener 设置消息回调。
您需要通过 MessageCallback 接口的consume方法,和调用 messageClientsetMessageListener()方法来设置消息接收接口。
consume 方法的返回值决定 SDK 是否发送 ACK。
设置消息接收接口的方法如下:

  1. MessageCallback messageCallback = new MessageCallback() {
  2. @Override
  3. public Action consume(MessageToken messageToken) {
  4. Message m = messageToken.getMessage();
  5. log.info("receive : " + new String(messageToken.getMessage().getPayload()));
  6. // TODO: 处理消息逻辑
  7. return MessageCallback.Action.CommitSuccess;
  8. }
  9. };
  10. String topic = String.format("/sys/%s/dop/model/data/change", appKey);
  11. messageClient.setMessageListener(topic,messageCallback);

其中,Message消息字段如下:

  1. // 消息体
  2. byte[] payload;
  3. // Topic
  4. String topic;
  5. // 消息ID
  6. String messageId;
  7. // QoS
  8. int qos;

payload内容是一个JSON对象字符串,字段信息如下:

  1. // 模型ID
  2. String modelId;
  3. // 变更数据的ID
  4. List<Long> dataIds;
  5. // 操作类型: insert/update/delete
  6. String operateType;
  7. // 订阅的appId, 以appKey授权时为空
  8. String appId;

若有收获,就赏束稻谷吧