概述

服务编排是Fizz网关提供的一个强大的功能,能够基于现有的业务微服务通过在线配置的方式快速的生成一个聚合接口,减少中间层胶水代码以及降低编码投入。在服务编排中支持使用函数,本进阶教程中我们分三篇文章(上篇:列表展开&合并、中篇:列表提取&关联、下篇:列表字段重命名&字段移除)来介绍数据列表类函数的使用。

本文为服务编排处理列表数据系列的中篇。

函数

函数是服务编排提供的一个强大又便捷的功能,通过将一些常用的逻辑封装成函数,在服务编排中使用函数对服务编排过程的数据进行处理,从而简化我们的配置又能实现复杂的功能。

函数分类

版本要求:v2.3或以上版本

函数以fn.开头,如fn.date.timestamp(), date为类别, 网关内置了以下几大类函数

  • 公共类 fn.common
  • 日期类 fn.date
  • 字符串类 fn.string
  • 编解码类 fn.codec
  • 数学类 fn.math
  • 数据列表类 fn.list

引用值

在函数里支持使用引用值,如:

fn.string.concat({step1.result.channelCode},{step1.result.nonce})

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段_02

{step1.result.channelCode} 表示引用值, 引用step1的结果

fn.string.concat({step1.result.channelCode},{g.account.name})

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段_02

{g.account.name} 表示引用值, 引用公共资源“account.name”, 以g开头表示引用公共资源

嵌套调用

支持多重嵌套调用,如:

fn.codec.md5(fn.date.add(fn.date.add("2021-07-09 22:44:55", "yyyy-MM-dd HH:mm:ss", 1, fn.math.addExact(999,1)), "yyyy-MM-dd HH:mm:ss", fn.math.addExact(0,1), 1000))

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段_02

fn.string.toUpperCase(fn.codec.sha256(fn.string.concat({step1.result.channelCode},{step1.result.nonce},{step1.result.timestamp},{step1.result.appSecret})))

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段_02

数据列表类函数

函数

返回值类型

用途

参数说明

fn.list.expand(

List<List<Object>> data)

List<Object>

将二维数组(列表)展开为一维数组(列表),

如:

data=[[{a:1}],[{a:2}],[{a:3}]]

fn.list.expand(data)

返回:[{a:1},{a:2},{a:3}]

data: 二维数组(列表)

fn.list.merge(

List<Object>... data)

List<Object>

将多个列表合并成一个,如:

data1=[{a:1}]

data2=[{a:2}]

data3=[{a:3}]

fn.list.merge(data1,data2,data3)

返回:[{a:1},{a:2},{a:3}]

data: 列表,可多个

fn.list.extract(

List<Map<String, Object>> data,

String... fields)

List<Map<String, Object>>

只提取列表里的部分字段,如:

data=[

{a:1,b:4,c:7},

{a:2,b:5,c:8},

{a:3,b:6,c:9}

]

fn.list.extract(data, "a", "c")

返回:[

{a:1,c:7},

{a:2,c:8},

{a:3,c:9}

]

data: 列表

fields: 【可选】字段,可多个

fn.list.join(

List<Map<String, Object>> dest,

List<Map<String, Object>> src,

String joinField,

String... fields)

List<Map<String, Object>>

合并2个列表字段,可只合并指定字段,如:

dest=[

{a:1,b:4,c:7},

{a:2,b:5,c:8},

{a:3,b:6,c:9}

]

src=[

{a:1,d:444,e:777},

{a:2,d:555,e:888}

]

fn.list.join(dest,src, "a", "d")

返回:[

{a:1,b:4,c:7,d:444},

{a:2,b:5,c:8,d:555},

{a:3,b:6,c:9}

]

dest: 目标列表

src: 被合并的列表

joinField: 两个列表关联的字段

格式:

dest列表的关联字段:src列表的

关联字段,如:userName:uname,

如果两个列表的关联字段一样可

只填一个,如:userName

fields: 【可选】被合并列表里需合并的字段,可多个,不填则合并所有字段

fn.list.rename(

List<Map<String, Object>> data,

String... fieldPairs)

List<Map<String, Object>>

重命名列表里的部分字段,如:

data=[

{a:1,b:4,c:7},

{a:2,b:5,c:8},

{a:3,b:6,c:9}

]

fn.list.rename(data, "a:apple", "c:cat")

返回:[

{apple:1,b:4,cat:7},

{apple:2,b:5,cat:8},

{apple:3,b:6,cat:9}

]

data: 列表

fieldPairs: 【可选】需重命名

的字段对,可多个。格式:

原字段名:新字段名,如:c:cat

fn.list.removeFields(

List<Map<String, Object>> data,

String... fields)

List<Map<String, Object>>

删除列表里的部分字段,如:

data=[

{a:1,b:4,c:7},

{a:2,b:5,c:8},

{a:3,b:6,c:9}

]

fn.list.removeFields(data, "b")

返回:[

{a:1,c:7},

{a:2,c:8},

{a:3,c:9}

]

data: 列表

fields: 【可选】需删除的

字段,可多个

资料准备

Fizz网关安装

底层服务接口

本文服务编排调用的底层服务接口源码可从github(https://github.com/wehotel/fizz-examples)获取。从github克隆最新的fizz-examples源码,并启动fizz-examples-rest-api服务。

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段_09

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_引用类型_10

管理后台(菜单位置:RPC管理->服务声明)配置服务声明,如图所示。

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_List_11

新增编排接口

管理后台,菜单位置:服务编辑->接口列表,点击新增。

列表提取 fn.list.extract

本例子在编排接口中调用底层fizz-examples-rest-api服务的/fn-list/user-basic-info-list-by-role/{role}接口(接口源码:FnListController )来获取用户基本信息列表,并对该接口的响应数据进行列表提取以满足我们想要的数据格式。

基础信息

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_引用类型_12

配置输入

在本例子中我们不需要入参,全留空。

配置步骤

新增1个步骤step1,然后在步骤step1里新增1个请求request1,服务选择fizz-examples-rest-api,请求/fn-list/user-basic-info-list-by-role/admin接口。

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_引用类型_13

配置输出

配置要返回给前端的响应报文,这里配置了响应体有以下字段:

code:引用类型,值为步骤step1中请求request1的响应的code字段;

message:引用类型,值为步骤step1中请求request1的响应的message字段;

data:引用类型,值为步骤step1中请求request1的响应的data字段并用fn.list.extract函数对其进行提取,只保留id、name字段。

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段_14

测试

直接调用/fn-list/user-basic-info-list-by-role/admin接口得到的响应如图所示。

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_List_15

测试接口得到响应如图所示。

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段_16

从测试接口的响应可以看出服务编排接口已完成了对/fn-list/user-basic-info-list-by-role/admin接口的请求并正确对响应的data字段的列表进行了字段提取。

列表关联 fn.list.join

本例子在编排接口中调用底层fizz-examples-rest-api服务的/fn-list/user-basic-info-list-by-role/{role}接口(接口源码:FnListController )来获取用户基本信息列表,之后调用底层fizz-examples-rest-api服务的/fn-list/user-private-list-by-user-ids/{{userIds}接口(接口源码:FnListController )来获取用户的私人信息列表,并对两个接口的调用响应数据进行列表关联以满足我们想要的数据格式。

基础信息

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_引用类型_17

配置输入

在本例子中我们不需要入参,全留空。

配置步骤

新增1个步骤step1,在步骤step1里新增1个请求request1,服务选择fizz-examples-rest-api,请求/fn-list/user-basic-info-list-by-role/admin接口。新增1个步骤step2,在步骤step2里新增1个请求request1,服务选择fizz-examples-rest-api,请求/fn-list/user-private-list-by-user-ids/{step1.request1.response.body.ids}接口。

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段_18

这里为了在step2中能够获取到userIds,对step1的request1响应进行了配置,增加了ids字段,配置为 fn.string.replace(fn.string.replace(fn.string.toString({step1.request1.response.body.data[*].id}), "[", ""), "]", "") 。

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_字段_19

配置输出

配置要返回给前端的响应报文,这里配置了响应体有以下字段:

code:引用类型,值为步骤step1中请求request1的响应的code字段;

message:引用类型,值为步骤step1中请求request1的响应的message字段;

data:引用类型,值为步骤step1中请求request1的响应的data字段与step2中请求request1的响应的data字段并用fn.list.join函数以id:userId进行关联。

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_引用类型_20

测试

直接调用/fn-list/user-basic-info-list-by-role/admin接口得到的响应如图所示。

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_引用类型_21

直接调用/fn-list/user-private-list-by-user-ids/1,2接口得到的响应如图所示。

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_引用类型_22

测试接口得到响应如图所示。

微服务数据库连接池与mysql数据库连接数 微服务 数据关联_引用类型_23

从测试接口的响应可以看出服务编排接口已完成了对/fn-list/user-basic-info-list-by-role/admin接口的请求和对/fn-list/user-private-list-by-user-ids/1,2接口的请求并正确对两次调用的响应的data字段的列表进行了关联。

Fizz网关介绍

Fizz Gateway 是一个基于 Java开发的微服务聚合网关,能够实现热服务编排聚合、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理、回调管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。


作者:ZHONG.J