同步器 Json&REST同步器组件(JsonRESTSynchronizer) - jingjiajie/FrontWork GitHub Wiki

  Json&REST同步器组件(JsonRESTSynchronizer)是FrontWork中的一款同步器组件,它提供了以HTTP作为API接口协议,Json作为数据传输格式的后端API的同步能力。Json&REST同步器组件如下:

JsonREST同步组件

  FrontWork中的同步器都是实现了ISynchronizer接口的,所以可以使用PullFromServer()方法来从服务器拉取数据,和PushToServer()方法将用户在前端改变的数据同步到后端服务器上。

  JsonRESTSynchronizer同步器包含了两个属性:Model和Configuration。显然,Model就是同步器需要将数据同步到的目的地之一。而Configuration就是用户的配置。

JsonREST同步器属性

  有没有疑惑,既然同步器是需要将Model和服务器数据进行同步的,为什么没有见到服务器的身影呢?答案就藏在Configuration中。是的,当前版本的FrontWork将HTTP接口的配置设计在了配置中心里。我们需要将HTTP的API信息书写在配置中心里。下面让我们来看一下HTTP api的配置。

配置截图

  这是一个最为简单的查询API配置了。让我们来讲解其中的配置项:

httpAPIs: 配置中心里配置httpAPI的配置项,数组类型,其中每一项为一个API的配置。

type: API的类型,截图中是"pull",在JsonRESTSynchronizer中,type的值还可以为以下几种:
 "pull" 查询API
 "add" 增加数据API
 "update" 更新数据API
 "remove" 删除数据API

url: API的URL地址

method: HTTP方法,可能为以下几种值:
 "GET" "POST" "PUT" "DELETE"

requestBody: 请求体内容,HTTP API执行时向服务器发送的HTTP请求的请求体的内容

responseBody: 相应体内容,后端服务器响应HTTP API发送的响应体的内容

响应体参数

  图示的API(*http://localhost/person/*)是我们为了演示而临时搭建的一个后端服务器。API中的url,method都很容易理解。在这里我们要讲解一下responseBody:"$data"是什么意思。
  用浏览器访问一下上图的API,服务器会返回一些数据,让我们看一下后端传回的数据
回传数据
  整理后数据如下:

[
    {"id":19,"name":"Peter","password":"******","role":"VIP","authorityString":""},
    {"id":27,"name":"Bob","password":"abc","role":"管理员","authorityString":"发"},
    {"id":28,"name":"Jeremy","password":"2","role":"普通用户","authorityString":"3"},
    {"id":31,"name":"小明","password":"123","role":"普通用户","authorityString":"1234"},
    {"id":45,"name":"小华","password":"trradasd","role":"普通用户","authorityString":"321"},
    {"id":52,"name":"小李","password":"1111111","role":"普通用户","authorityString":"asd"}
]

  可以看到,这个API返回数据的形式是一个Json数组,其中每一项是一个对象,代表一个人。JsonRESTSynchronizer同步器并不能直接识别这段数据,因为它不知道这段数据就是我们所需要的结果数组,还是需要在数据中进行一些搜索和分析。我们在responseBody(响应体)中使用了$data关键变量来标识我们的目标数据的位置,告诉JsonRESTSynchronizer同步器,我们所需要的数据就在$data关键变量所在的位置。在上面这个API中,由于返回数据整个就是我们需要的结果数组,所以直接用"$data"就可以了。下面举个例子,如果返回数据是如下形式:

{   
    "errno":0,
    "message":"successed",
    "return_data":[
        {"name":"peter","age":"18", ...},
        {"name":"jeremy","age":"20", ...}
    ]
}

  那么我们需要将responseBody写作如下形式:

{responseBody:"{return_data:$data}"}

  这样,JsonREST同步器就可以根据你所书写的路径在API返回的数据中搜索到你需要的数据,并将其同步到Model了。是不是很容易理解?

请求参数

  可能看到这里你会有一个疑问,我们调用后端API进行查询的时候,并不需要将所有的数据都查询出来。我们的API本身是带参数的,如URL路径参数,和请求体中的参数。我们需要根据参数来查询我们所需要的数据,同步器能做到吗?当然可以。

  JsonRestSynchronizer同步器提供的请求参数功能中包含两种:"路径参数"和"请求体参数"。接下来让我们分别来看一下如何在API中设置路径参数或者请求体参数。

路径参数

  现在我们需要查询所有姓名为"Peter"的人,我们需要将查询条件作为URL路径参数传给后端。我们可以稍微修改一下我们的API: URL路径参数API
  我们在URL路径中插入了一个$myCondition变量。请注意,这里的大括号{}可不是JSON的意思,而是字符串插值的意思。而$myCondition这个变量,是我们要插入的变量。那么,我们需要如何设定$myCondition这个变量呢?让我们使用下面这个两个函数来设定请求参数:

//设置普通的请求参数
public void SetRequestParameter(string name,object value);

//设置JSON对象的请求参数
public void SetJsonRequestParameter(string name,string value);

  顾名思义,第一个是设定一个普通的值作为请求参数,而第二个是传入一个字符串,自动将字符串转换成JSON对象,作为请求参数。让我们举例说明。我们设定"{name:'Peter'}"这个JSON对象作为请求参数。如果我们使用第一种:

synchronizer.SetRequestParameter("$myCondition","{name:'Peter'}");

  那么我们最终访问的URL是:http://localhost/person/"{name:'Peter'}"
  而如果我们使用第二种:

synchronizer.SetJsonRequestParameter("$myCondition","{name:'Peter'}");

  那么我们最终访问的URL是:http://localhost/person/{"name":"Peter"}

  看明白了吧。前者是将设置的参数按原样保存,而后者是将设置的字符串参数转换为JSON对象存储。我们只需要利用修改请求参数变量的方式,就可以实现随意改变查询条件的功能。你不太明白,难道每次变换查询条件都需要我们手动地利用SetRequestParameter()手动地修改请求参数吗?当然不会,如果你使用搜索视图(SearchView),搜索视图会自动地根据用户选择的搜索条件,排序条件等,来自动地生成和更新请求参数,从而达到真正的按条件搜索。

请求体参数

  通常来说,基于REST格式的查询接口,都使用GET方法,采用上面的路径参数方式来传输查询条件。但假如你的项目采用的是非REST接口,利用POST等方式传输查询请求,或者即便是REST接口,我们需要使用POST或PUT方法来传输增加/修改请求,那么请求体参数,就是解决这些问题的完美方案。

  下面我们来举一个添加人员API的例子。
增加API   我们可以看到,在这个增加API中,method改为了"POST",这往往意味着我们将要使用请求体来传输数据。注意requestBody。为了演示请求体参数的功能,我们特意为请求体设置了两个字段,作为我们模拟的后端API的接口数据格式。其中第一个server字段是一个静态值,设为了'main-server'。后面的persons字段对应的值是一个请求体参数:$data。当我们使用PushToServer()的时候,Model中的数据改变会利用"add"/"update"/"remove"类型的api进行同步。在这三个type的api里,JsonRESTSynchronizer同步器会在请求参数中自动预置$data这个关键变量,代表需要同步的数据。$data的类型是数组,每一项为一条待同步数据。

  需要注意的是,使用type为"pull"类型的API时,JsonRESTSynchronizer同步器不会预置$data请求参数。而是预置了$data响应体参数,这是因为我们的pull请求并不涉及到Model中数据改变的推送,而是仅仅从服务器拉取数据到Model中。所以请求参数没有必要设置$data。而响应体参数中的$data,仅仅是与请求体参数的$data同名,两者并不是同一个变量。关于响应体变量$data,请参考上一部分对此的详细介绍。

  一般来说,add的API不能够独立存在,因为用户在视图上增加一行的时候,往往是空行,用户会在空行上逐个填写数据,这就涉及到update的API。当我们按上图的模式同时设置好了add和update的API后,当我们使用PushToServer()推送用户新增的数据时,同步器可以发送如下格式的HTTP请求:

POST http://localhost/person/
请求体:
{
    "server":"main-server",
    "persons":[
        {"name":"Peter","age":18, ...},
        {"name":"Jeremy","age":20, ...}
    ]
}
⚠️ **GitHub.com Fallback** ⚠️