diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..1418293 --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,27 @@ +# This workflow will build a Java project with Maven +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Java CI with Maven + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + paths-ignore: + - README.md + - .gitignore + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build with Maven + run: mvn -B package --file pom.xml diff --git a/README.md b/README.md index 39ac4fa..0795277 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,24 @@ +

Welcome to Fizz Gateway

+

+ Version + + Documentation + + + License: GPL--3.0 + + + Java CI with Maven + +

+ A Managerment API Gateway in Java . Fizz Gateway 是一个基于 Java开发的微服务网关,能够实现热服务编排、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。 -### Fizz的设计 +## Fizz的设计 - + -### 产品特性 +## 产品特性 - 集群管理:Fizz网关节点是无状态的,配置信息自动同步,支持节点水平拓展和多集群部署。 - 服务编排:支持热服务编排能力,支持前后端编码,随时随地更新API。 @@ -20,7 +34,7 @@ A Managerment API Gateway in Java . Fizz Gateway 是一个基于 Java开发的 - 版本控制:支持操作的发布和多次回滚。 - 管理后台:通过管理后台界面对网关集群进行各项配置。 -### 基准测试 +## 基准测试 我们将Fizz与Spring官方spring-cloud-gateway进行比较,使用相同的环境和条件,测试对象均为单个节点。 @@ -35,22 +49,146 @@ A Managerment API Gateway in Java . Fizz Gateway 是一个基于 Java开发的 | fizz-gateway | 5927.13 | 19.86 | | spring-cloud-gateway | 5044.04 | 22.91 | +## 版本对照 + +- Fizz-gateway-community: 社区版 + +- Fizz-manager-professional:管理后台专业版(服务端) + +- Fizz-admin-professional:管理后台专业版(前端) + +| Fizz-gateway-community | Fizz-manager-professional | Fizz-admin-professional | +| ---------------------- | ------------------------- | ----------------------- | +| v1.0.0 | v1.0.0 | v1.0.0 | +| v1.1.0 | v1.1.0 | v1.1.0 | + +请根据社区版的版本下载对应的管理后台版本 + + +## 部署说明 + +[详细部署教程>>>](https://wehotel.github.io/fizz-gateway-community/guide/installation/) + +### 安装依赖 + +安装以下依赖软件: + +- Redis 2.8或以上版本 +- MySQL 5.7或以上版本 +- Apollo配置中心 (可选) +- Eureka服务注册中心 + +依赖的安装可参考详细部署教程 + +### 安装Fizz + +#### 管理后台 + +从github的releases(https://github.com/wehotel/fizz-gateway-community/releases)下载 fizz-manager-professional 和 fizz-admin-professional 的安装包 + +##### 管理后台服务端(fizz-manager-professional) + +1. 首次安装执行`fizz-manager-professional-1.1.0-mysql.sql`数据库脚本 +2. 将`application-prod.yml`、`boot.sh`、`fizz-manager-professional-1.1.0.jar`拷贝到`/data/webapps/fizz-manager-professional`目录下 +3. 修改`application-prod.yml`文件,将相关配置修改成部署环境的配置 +4. 修改`boot.sh`文件,将`RUN_CMD`变量值修改成部署环境的JAVA实际路径 +5. 执行 `chmod +x boot.sh` 命令给`boot.sh`增加执行权限 +6. 执行 `./boot.sh start` 命令启动服务,支持 start/stop/restart/status命令 +7. 服务启动后访问 http://IP:8000/fizz-manager (将IP替换成服务部署机器IP地址),使用超级管理员账户`admin`密码`Aa123!`登录 + +##### 管理后台前端(fizz-admin-professional) + +zip资源包解压后,取文件夹【fizzAdmin】放置于服务器静态数据存放目录 如:/home/data/ + +nginx配置 + +``` +server { + listen 9000; + server_name localhost:9000; + location / { + root /home/data/fizzAdmin; + } + location ^~ /api { + rewrite ^/api/(.*) /$1 break; + proxy_pass http://127.0.0.1:8000; + } +} + +# 注:root中地址需与资源包存放目录路径一致 +# 注:http://127.0.0.1:8000 为管理后台(fizz-manager-professional)的访问地址 +``` + +访问地址 + +【资源部署服务器IP + 端口号】如:http://127.0.0.1:9000/ + +(端口号与nginx配置端口号一致) + +#### fizz-gateway-community社区版 + +说明:如果使用apollo配置中心,可把application.yml文件内容迁到配置中心(apollo上应用名为:fizz-gateway);使用不使用apollo可去掉下面启动命令里的apollo参数。 + +方式一:脚本启动: + +1. 下载fizz-gateway-community的最新代码,修改application.yml配置文件里eureka、redis的配置,使用maven命令`mvn clean package -DskipTests=true`构建并把构建好的fizz-gateway-community-1.1.0.jar和boot.sh放同一目录 +2. 修改boot.sh脚本的apollo连接,JVM内存配置 +3. 执行 `./boot.sh start` 命令启动服务,支持 start/stop/restart/status命令 + +方式二:IDE启动: + +1. 本地clone仓库上的最新代码 +2. 将项目fizz-gateway导入IDE +3. 导入完成后设置项目启动配置及修改application.yml配置文件里eureka、redis的配置,在VM选项中加入`-Denv=dev -Dapollo.meta=http://localhost:66`(Apollo配置中心地址) + +方式三:jar启动: + +1. 本地clone仓库上的最新代码,修改application.yml配置文件里eureka、redis的配置 +2. 在项目根目录fizz-gateway-community下执行Maven命令`mvn clean package -DskipTests=true`打包 +3. 进入target目录,使用命令`java -jar -Denv=DEV -Dapollo.meta=http://localhost:66 fizz-gateway-community-1.1.0.jar`启动服务 + +网关访问地址格式: + +http://127.0.0.1:8600/proxy/[服务名]/[API Path] -### 部署说明 +## 官方技术交流群 -[部署教程](https://wehotel.github.io/fizz-gateway-community/guide/installation/) +Fizz官方技术交流①群(已满) + +Fizz官方技术交流②群(已满) + +Fizz官方技术交流③群:512164278 + +![](https://user-images.githubusercontent.com/184315/97130743-3572d100-177d-11eb-97c8-7599a22c7c04.png) -### 官方技术交流群 -![](https://github.com/wehotel/fizz-gateway-community/blob/master/docs/fizz_qq_group.png) +## 相关文章 -### 授权说明 +[服务器减少50%,研发效率提高86%,我们的管理型网关Fizz自研之路](https://www.infoq.cn/article/9wdfiOILJ0CYsVyBQFpl) + +[微服务之聚合网关Fizz安装教程](https://www.jianshu.com/p/96c1f306aa2b) + + + +## 授权说明 1. 网关核心项目fizz-gateway-community社区版本以GNU v3的方式进行的开放,可以免费使用。 2. 管理后台项目(fizz-manager-professional和fizz-admin-professional)作为商业版本仅开放二进制包 [免费下载](https://github.com/wehotel/fizz-gateway-community/releases),而商业项目请联系我们(524423586@qq.com)进行授权。 + +## 系统截图 + +![](https://user-images.githubusercontent.com/184315/97131368-f5ace900-177e-11eb-9e00-24e73d4e24f5.png) + +![](https://user-images.githubusercontent.com/184315/97131376-f9407000-177e-11eb-8c17-4922b3df5d48.png) + +![](https://user-images.githubusercontent.com/184315/97131378-f9d90680-177e-11eb-92b4-6fc67550daca.png) + +![](https://user-images.githubusercontent.com/184315/97131381-fba2ca00-177e-11eb-9e59-688dafa76aea.png) + +![](https://user-images.githubusercontent.com/184315/97131382-fc3b6080-177e-11eb-908a-a5ffc8b08459.png) \ No newline at end of file diff --git a/docs/404.html b/docs/404.html index 9e1baf4..a6783d0 100644 --- a/docs/404.html +++ b/docs/404.html @@ -7,13 +7,13 @@ - + -

404

There's nothing here.
+ - + diff --git a/docs/assets/js/10.983fb026.js b/docs/assets/js/10.1253731e.js similarity index 93% rename from docs/assets/js/10.983fb026.js rename to docs/assets/js/10.1253731e.js index 046f936..4b410c6 100644 --- a/docs/assets/js/10.983fb026.js +++ b/docs/assets/js/10.1253731e.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{355:function(t,e,v){"use strict";v.r(e);var n=v(42),r=Object(n.a)({},(function(){var t=this,e=t.$createElement,v=t._self._c||e;return v("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[v("p",[t._v("1.创建服务")]),t._v(" "),v("p",[t._v("此服务是一个分组的概念,可以包含多个聚合接口,类似于微服务体系里的服务")]),t._v(" "),v("p",[t._v("2.创建服务编排接口")]),t._v(" "),v("p",[t._v("3.开通网关白名单和配置访问策略和插件")]),t._v(" "),v("p",[t._v("4.测试服务编排接口")]),t._v(" "),v("p",[t._v("5.发布接口")]),t._v(" "),v("p",[t._v("界面总览")]),t._v(" "),v("p",[v("img",{attrs:{src:"/fizz-gateway-community/aggr_overview1.png",alt:""}})]),t._v(" "),v("p",[v("img",{attrs:{src:"/fizz-gateway-community/aggr_overview2.png",alt:""}})])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{371:function(t,e,v){"use strict";v.r(e);var n=v(42),r=Object(n.a)({},(function(){var t=this,e=t.$createElement,v=t._self._c||e;return v("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[v("p",[t._v("1.创建服务")]),t._v(" "),v("p",[t._v("此服务是一个分组的概念,可以包含多个聚合接口,类似于微服务体系里的服务")]),t._v(" "),v("p",[t._v("2.创建服务编排接口")]),t._v(" "),v("p",[t._v("3.开通网关白名单和配置访问策略和插件")]),t._v(" "),v("p",[t._v("4.测试服务编排接口")]),t._v(" "),v("p",[t._v("5.发布接口")]),t._v(" "),v("p",[t._v("界面总览")]),t._v(" "),v("p",[v("img",{attrs:{src:"/fizz-gateway-community/aggr_overview1.png",alt:""}})]),t._v(" "),v("p",[v("img",{attrs:{src:"/fizz-gateway-community/aggr_overview2.png",alt:""}})])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/11.c6208cce.js b/docs/assets/js/11.8c833bde.js similarity index 97% rename from docs/assets/js/11.c6208cce.js rename to docs/assets/js/11.8c833bde.js index 66dd715..411b8fa 100644 --- a/docs/assets/js/11.c6208cce.js +++ b/docs/assets/js/11.8c833bde.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{358:function(t,_,a){"use strict";a.r(_);var v=a(42),e=Object(v.a)({},(function(){var t=this,_=t.$createElement,a=t._self._c||_;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h2",{attrs:{id:"基准测试结果"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#基准测试结果"}},[t._v("#")]),t._v(" 基准测试结果")]),t._v(" "),a("p",[t._v("我们将Fizz与Spring官方spring-cloud-gateway进行比较,使用相同的环境和条件,测试对象均为单个节点。")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",{staticStyle:{"text-align":"center"}},[t._v("产品")]),t._v(" "),a("th",[t._v("QPS")]),t._v(" "),a("th",[t._v("90% Latency(ms)")])])]),t._v(" "),a("tbody",[a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("直接访问后端服务")]),t._v(" "),a("td",[t._v("9087.46")]),t._v(" "),a("td",[t._v("10.76")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("fizz-gateway")]),t._v(" "),a("td",[t._v("5927.13")]),t._v(" "),a("td",[t._v("19.86")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("spring-cloud-gateway")]),t._v(" "),a("td",[t._v("5044.04")]),t._v(" "),a("td",[t._v("22.91")])])])]),t._v(" "),a("h2",{attrs:{id:"基准测试详情"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#基准测试详情"}},[t._v("#")]),t._v(" 基准测试详情")]),t._v(" "),a("h3",{attrs:{id:"硬件环境"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#硬件环境"}},[t._v("#")]),t._v(" 硬件环境")]),t._v(" "),a("p",[t._v("后端服务所在服务器:")]),t._v(" "),a("p",[t._v("4核8G内存")]),t._v(" "),a("p",[t._v("Intel(R) Xeon(R) CPU X5675 @ 3.07GHz * 4")]),t._v(" "),a("p",[t._v("Linux version 3.10.0-327.el7.x86_64")]),t._v(" "),a("p",[t._v("节点所在服务器:")]),t._v(" "),a("p",[t._v("4核8G内存")]),t._v(" "),a("p",[t._v("Intel(R) Xeon(R) CPU X5675 @ 3.07GHz * 4")]),t._v(" "),a("p",[t._v("Linux version 3.10.0-327.el7.x86_64")]),t._v(" "),a("p",[t._v("压测程序所在服务器:")]),t._v(" "),a("p",[t._v("4核8G内存")]),t._v(" "),a("p",[t._v("Intel(R) Xeon(R) CPU X5675 @ 3.07GHz * 4")]),t._v(" "),a("p",[t._v("Linux version 3.10.0-327.el7.x86_64")]),t._v(" "),a("h3",{attrs:{id:"压测工具"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#压测工具"}},[t._v("#")]),t._v(" 压测工具")]),t._v(" "),a("p",[t._v("压测软件:wrk")]),t._v(" "),a("p",[t._v("并发连接: 100")]),t._v(" "),a("h3",{attrs:{id:"压测结果截图"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#压测结果截图"}},[t._v("#")]),t._v(" 压测结果截图")]),t._v(" "),a("ul",[a("li",[a("p",[t._v("直接访问后端服务:\n"),a("img",{attrs:{src:"/fizz-gateway-community/benchmark_backend.png",alt:""}})])]),t._v(" "),a("li",[a("p",[t._v("fizz-gateway:\n"),a("img",{attrs:{src:"/fizz-gateway-community/benchmark_fizz.png",alt:""}})])]),t._v(" "),a("li",[a("p",[t._v("spring-cloud-gateway:\n"),a("img",{attrs:{src:"/fizz-gateway-community/benchmark_scgw.png",alt:""}})])])])])}),[],!1,null,null,null);_.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{374:function(t,_,a){"use strict";a.r(_);var v=a(42),e=Object(v.a)({},(function(){var t=this,_=t.$createElement,a=t._self._c||_;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h2",{attrs:{id:"基准测试结果"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#基准测试结果"}},[t._v("#")]),t._v(" 基准测试结果")]),t._v(" "),a("p",[t._v("我们将Fizz与Spring官方spring-cloud-gateway进行比较,使用相同的环境和条件,测试对象均为单个节点。")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",{staticStyle:{"text-align":"center"}},[t._v("产品")]),t._v(" "),a("th",[t._v("QPS")]),t._v(" "),a("th",[t._v("90% Latency(ms)")])])]),t._v(" "),a("tbody",[a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("直接访问后端服务")]),t._v(" "),a("td",[t._v("9087.46")]),t._v(" "),a("td",[t._v("10.76")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("fizz-gateway")]),t._v(" "),a("td",[t._v("5927.13")]),t._v(" "),a("td",[t._v("19.86")])]),t._v(" "),a("tr",[a("td",{staticStyle:{"text-align":"center"}},[t._v("spring-cloud-gateway")]),t._v(" "),a("td",[t._v("5044.04")]),t._v(" "),a("td",[t._v("22.91")])])])]),t._v(" "),a("h2",{attrs:{id:"基准测试详情"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#基准测试详情"}},[t._v("#")]),t._v(" 基准测试详情")]),t._v(" "),a("h3",{attrs:{id:"硬件环境"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#硬件环境"}},[t._v("#")]),t._v(" 硬件环境")]),t._v(" "),a("p",[t._v("后端服务所在服务器:")]),t._v(" "),a("p",[t._v("4核8G内存")]),t._v(" "),a("p",[t._v("Intel(R) Xeon(R) CPU X5675 @ 3.07GHz * 4")]),t._v(" "),a("p",[t._v("Linux version 3.10.0-327.el7.x86_64")]),t._v(" "),a("p",[t._v("节点所在服务器:")]),t._v(" "),a("p",[t._v("4核8G内存")]),t._v(" "),a("p",[t._v("Intel(R) Xeon(R) CPU X5675 @ 3.07GHz * 4")]),t._v(" "),a("p",[t._v("Linux version 3.10.0-327.el7.x86_64")]),t._v(" "),a("p",[t._v("压测程序所在服务器:")]),t._v(" "),a("p",[t._v("4核8G内存")]),t._v(" "),a("p",[t._v("Intel(R) Xeon(R) CPU X5675 @ 3.07GHz * 4")]),t._v(" "),a("p",[t._v("Linux version 3.10.0-327.el7.x86_64")]),t._v(" "),a("h3",{attrs:{id:"压测工具"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#压测工具"}},[t._v("#")]),t._v(" 压测工具")]),t._v(" "),a("p",[t._v("压测软件:wrk")]),t._v(" "),a("p",[t._v("并发连接: 100")]),t._v(" "),a("h3",{attrs:{id:"压测结果截图"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#压测结果截图"}},[t._v("#")]),t._v(" 压测结果截图")]),t._v(" "),a("ul",[a("li",[a("p",[t._v("直接访问后端服务:\n"),a("img",{attrs:{src:"/fizz-gateway-community/benchmark_backend.png",alt:""}})])]),t._v(" "),a("li",[a("p",[t._v("fizz-gateway:\n"),a("img",{attrs:{src:"/fizz-gateway-community/benchmark_fizz.png",alt:""}})])]),t._v(" "),a("li",[a("p",[t._v("spring-cloud-gateway:\n"),a("img",{attrs:{src:"/fizz-gateway-community/benchmark_scgw.png",alt:""}})])])])])}),[],!1,null,null,null);_.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/12.4c03285a.js b/docs/assets/js/12.61089982.js similarity index 76% rename from docs/assets/js/12.4c03285a.js rename to docs/assets/js/12.61089982.js index d67ec8d..f96114d 100644 --- a/docs/assets/js/12.4c03285a.js +++ b/docs/assets/js/12.61089982.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{357:function(a,t,s){"use strict";s.r(t);var e=s(42),r=Object(e.a)({},(function(){var a=this,t=a.$createElement,s=a._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[s("h2",{attrs:{id:"安装依赖"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#安装依赖"}},[a._v("#")]),a._v(" 安装依赖")]),a._v(" "),s("p",[a._v("安装以下依赖软件:")]),a._v(" "),s("ul",[s("li",[a._v("Redis 2.8或以上版本")]),a._v(" "),s("li",[a._v("MySQL 5.7或以上版本")]),a._v(" "),s("li",[a._v("Apollo配置中心 (可选)")]),a._v(" "),s("li",[a._v("Eureka服务注册中心")])]),a._v(" "),s("h3",{attrs:{id:"安装mysql"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#安装mysql"}},[a._v("#")]),a._v(" 安装MySQL")]),a._v(" "),s("ul",[s("li",[a._v("操作系统 CentOS 6.5")]),a._v(" "),s("li",[a._v("MySQL 5.7.30")])]),a._v(" "),s("ol",[s("li",[a._v("下载MySQL")])]),a._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[a._v("wget")]),a._v(" https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-1.el6.x86_64.rpm-bundle.tar\n")])])]),s("ol",{attrs:{start:"2"}},[s("li",[a._v("解压")])]),a._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[a._v("tar")]),a._v(" -xvf mysql-5.7.30-1.el6.x86_64.rpm-bundle.tar\n")])])]),s("ol",{attrs:{start:"3"}},[s("li",[a._v("安装")])]),a._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[a._v("sudo")]),a._v(" yum "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("install")]),a._v(" mysql-community-"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("server,client,common,libs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("-*\n")])])]),s("ol",{attrs:{start:"4"}},[s("li",[a._v("启动")])]),a._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[a._v("sudo")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("service")]),a._v(" mysqld start\n")])])]),s("p",[a._v("启动成功会显示以下信息:")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("[root@localhost ~]# sudo service mysqld start\nInitializing MySQL database: [ OK ]\nStarting mysqld: [ OK ]\n")])])]),s("ol",{attrs:{start:"5"}},[s("li",[a._v("初始密码")])]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("sudo grep 'temporary password' /var/log/mysqld.log\n")])])]),s("ol",{attrs:{start:"6"}},[s("li",[a._v("使用初始密码登录")])]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("mysql -uroot -p\n")])])]),s("ol",{attrs:{start:"7"}},[s("li",[a._v("修改密码")])]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyNewPass4!';\n")])])]),s("ol",{attrs:{start:"8"}},[s("li",[a._v("退出登录")])]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("quit\n")])])]),s("h3",{attrs:{id:"安装redis-6-0-8"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#安装redis-6-0-8"}},[a._v("#")]),a._v(" 安装Redis 6.0.8")]),a._v(" "),s("ol",[s("li",[a._v("下载解压并编译")])]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("$ wget http://download.redis.io/releases/redis-6.0.8.tar.gz\n$ tar xzf redis-6.0.8.tar.gz\n$ cd redis-6.0.8\n$ make\n")])])]),s("ol",{attrs:{start:"2"}},[s("li",[a._v("启动redis")])]),a._v(" "),s("p",[a._v("运行编译后的文件:")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("$ src/redis-server\n")])])]),s("ol",{attrs:{start:"3"}},[s("li",[a._v("客户端连接")])]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v('$ src/redis-cli\nredis> set foo bar\nOK\nredis> get foo\n"bar"\n')])])]),s("h3",{attrs:{id:"安装apollo配置中心"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#安装apollo配置中心"}},[a._v("#")]),a._v(" 安装Apollo配置中心")]),a._v(" "),s("p",[a._v("说明: apollo是可选组件,如果不使用apollo可使用本地配置文件(application.yml), 如果不使用apollo可跳过此步骤。")]),a._v(" "),s("p",[a._v("安装步骤详见apollo官方文档: "),s("a",{attrs:{href:"https://github.com/ctripcorp/apollo/wiki/Quick-Start",target:"_blank",rel:"noopener noreferrer"}},[s("OutboundLink")],1)]),a._v(" "),s("h3",{attrs:{id:"安装eureka服务注册中心"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#安装eureka服务注册中心"}},[a._v("#")]),a._v(" 安装Eureka服务注册中心")]),a._v(" "),s("p",[a._v("环境要求:")]),a._v(" "),s("ul",[s("li",[a._v("JDK 1.8 或以上版本")]),a._v(" "),s("li",[a._v("Tomcat 6.0.10 或以上版本 (如使用spring cloud已内置)")])]),a._v(" "),s("ol",[s("li",[a._v("安装JDK 1.8")])]),a._v(" "),s("p",[a._v("1)下载JDK,如: jdk-8u192-linux-x64.tar.gz")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("tar -zxvf jdk-8u192-linux-x64.tar.gz\nmv jdk1.8.0_192 /usr/local/\n\n")])])]),s("p",[a._v("2)设置JDK环境变量,将下面内容追回到/etc/profile文件后面")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("JAVA_HOME=/usr/local/jdk/jdk1.8.0_192\nJRE_HOME=$JAVA_HOME/jre\nPATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin\nCLASSPATH=:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib/dt.jar\nexport JAVA_HOME JRE_HOME PATH CLASSPATH\n\n")])])]),s("p",[a._v("3)执行以下命令全环境变量生效:")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("source /etc/profile\n\n")])])]),s("p",[a._v("4)查看是否安装成功")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("java -version\n")])])]),s("ol",{attrs:{start:"2"}},[s("li",[a._v("安装eureka")])]),a._v(" "),s("p",[a._v("1)使用IDE创建一个spring boot项目,如:sc-eureka-server")]),a._v(" "),s("p",[a._v("pom.xml:")]),a._v(" "),s("div",{staticClass:"language-xml extra-class"},[s("pre",{pre:!0,attrs:{class:"language-xml"}},[s("code",[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("dependency")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("groupId")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("org.springframework.cloud"),s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")])]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("artifactId")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("spring-cloud-starter-netflix-eureka-server"),s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")])]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")])]),a._v("\n")])])]),s("p",[a._v("在启动类上添加@EnableEurekaServer注解来启用Euerka注册中心功能:")]),a._v(" "),s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[a._v("@SpringBootApplication")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[a._v("@EnableEurekaServer")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("public")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("class")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("ScEurekaServerApplication")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("public")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("static")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("void")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("]")]),a._v(" args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("SpringApplication")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("run")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("ScEurekaServerApplication")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("class")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),s("p",[a._v("application.properties配置文件:")]),a._v(" "),s("div",{staticClass:"language-properties extra-class"},[s("pre",{pre:!0,attrs:{class:"language-properties"}},[s("code",[s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("spring.application.name")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("sc-eureka-server")]),a._v("\n\n"),s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("server.port")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("8761")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("eureka.instance.hostname")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("localhost")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("eureka.client.registerWithEureka")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("false")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("eureka.client.fetchRegistry")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("false")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("eureka.server.enableSelfPreservation")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("false")]),a._v("\n")])])]),s("p",[a._v("2) maven构建并运行sc-eureka-server应用, 启动后访问地址http://localhost:8761/可以看到Eureka注册中心的界面")]),a._v(" "),s("p",[a._v("3)把target/sc-eureka-server-1.0.0.jar传到linux服务器上运行. (仅以单机部署为例)")]),a._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[a._v("nohub java -jar sc-eureka-server-1.0.0.jar "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("&")]),a._v(" \n")])])]),s("p",[a._v("4)eureka客户端的注册地址为:http://localhost:8761/eureka/ (替换localhost为服务器的IP)")]),a._v(" "),s("div",{staticClass:"language-properties extra-class"},[s("pre",{pre:!0,attrs:{class:"language-properties"}},[s("code",[s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("eureka.client.serviceUrl.defaultZone")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("http://localhost:8761/eureka/")]),a._v("\n")])])]),s("h2",{attrs:{id:"安装fizz"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#安装fizz"}},[a._v("#")]),a._v(" 安装Fizz")]),a._v(" "),s("h3",{attrs:{id:"管理后台"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#管理后台"}},[a._v("#")]),a._v(" 管理后台")]),a._v(" "),s("p",[a._v("从github的releases(https://github.com/wehotel/fizz-gateway-community/releases)下载 fizz-manager-professional 和 fizz-admin-professional 的安装包")]),a._v(" "),s("ul",[s("li",[a._v("管理后台服务端(fizz-manager-professional)")])]),a._v(" "),s("ol",[s("li",[a._v("首次安装执行"),s("code",[a._v("fizz-manager-professional-1.0.0-mysql.sql")]),a._v("数据库脚本")]),a._v(" "),s("li",[a._v("将"),s("code",[a._v("application-prod.yml")]),a._v("、"),s("code",[a._v("boot.sh")]),a._v("、"),s("code",[a._v("fizz-manager-professional-1.0.0.jar")]),a._v("拷贝到"),s("code",[a._v("/data/webapps/fizz-manager-professional")]),a._v("目录下")]),a._v(" "),s("li",[a._v("修改"),s("code",[a._v("application-prod.yml")]),a._v("文件,将相关配置修改成部署环境的配置")]),a._v(" "),s("li",[a._v("修改"),s("code",[a._v("boot.sh")]),a._v("文件,将"),s("code",[a._v("RUN_CMD")]),a._v("变量值修改成部署环境的JAVA实际路径")]),a._v(" "),s("li",[a._v("执行 "),s("code",[a._v("chmod +x boot.sh")]),a._v(" 命令给"),s("code",[a._v("boot.sh")]),a._v("增加执行权限")]),a._v(" "),s("li",[a._v("执行 "),s("code",[a._v("./boot.sh start")]),a._v(" 命令启动服务,支持 start/stop/restart/status命令")]),a._v(" "),s("li",[a._v("服务启动后访问 http://IP:8000/fizz-manager (将IP替换成服务部署机器IP地址),使用超级管理员账户"),s("code",[a._v("admin")]),a._v("密码"),s("code",[a._v("Aa123!")]),a._v("登录")])]),a._v(" "),s("ul",[s("li",[a._v("管理后台前端(fizz-admin-professional)")])]),a._v(" "),s("p",[a._v("zip资源包解压后,取文件夹【fizzAdmin】放置于服务器静态数据存放目录 如:/home/data/")]),a._v(" "),s("p",[a._v("nginx配置")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("server {\n listen 9000;\n server_name localhost:9000;\n location / {\n root /home/data/fizzAdmin;\n }\n location ^~ /api {\n rewrite ^/api/(.*) /$1 break;\n proxy_pass http://127.0.0.1:8000;\n }\n}\n\n# 注:root中地址需与资源包存放目录路径一致\n# 注:http://127.0.0.1:8000 为管理后台(fizz-manager-professional)的访问地址\n")])])]),s("p",[a._v("访问地址")]),a._v(" "),s("p",[a._v("【资源部署服务器IP + 端口号】如:http://127.0.0.1:9000/")]),a._v(" "),s("p",[a._v("(端口号与nginx配置端口号一致)")]),a._v(" "),s("h3",{attrs:{id:"fizz-gateway-community社区版"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#fizz-gateway-community社区版"}},[a._v("#")]),a._v(" fizz-gateway-community社区版")]),a._v(" "),s("p",[a._v("说明:如果使用apollo配置中心,可把application.yml文件内容迁到配置中心(apollo上应用名为:fizz-gateway);使用不使用apollo可去掉下面启动命令里的apollo参数。")]),a._v(" "),s("p",[a._v("脚本启动:")]),a._v(" "),s("ol",[s("li",[a._v("下载fizz-gateway-community的最新代码,修改application.yml配置文件里eureka、redis的配置,使用maven构建好并把构建好的fizz-gateway-community-1.0.0.jar和boot.sh放同一目录")]),a._v(" "),s("li",[a._v("修改boot.sh脚本的apollo连接,JVM内存配置,")]),a._v(" "),s("li",[a._v("执行 "),s("code",[a._v("./boot.sh start")]),a._v(" 命令启动服务,支持 start/stop/restart/status命令")])]),a._v(" "),s("p",[a._v("IDE启动:")]),a._v(" "),s("ol",[s("li",[a._v("本地clone仓库上的最新代码")]),a._v(" "),s("li",[a._v("将项目fizz-gateway导入IDE")]),a._v(" "),s("li",[a._v("导入完成后设置项目启动配置及修改application.yml配置文件里eureka、redis的配置,在VM选项中加入"),s("code",[a._v("-Denv=dev -Dapollo.meta=http://localhost:66")]),a._v("(Apollo配置中心地址)")])]),a._v(" "),s("p",[a._v("jar启动:")]),a._v(" "),s("ol",[s("li",[a._v("本地clone仓库上的最新代码,修改application.yml配置文件里eureka、redis的配置")]),a._v(" "),s("li",[a._v("在项目根目录fizz-gateway-community下执行Maven命令"),s("code",[a._v("mvn clean package -DskipTests=true")]),a._v("打包")]),a._v(" "),s("li",[a._v("进入target目录,使用命令"),s("code",[a._v("java -jar -Denv=DEV -Dapollo.meta=http://localhost:66 fizz-gateway-community-1.0.0.jar")]),a._v("启动服务")])]),a._v(" "),s("p",[a._v("网关访问地址格式:")]),a._v(" "),s("p",[a._v("http://127.0.0.1:8600/proxy/[服务名]/[API Path]")])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{356:function(a,t,s){"use strict";s.r(t);var e=s(42),r=Object(e.a)({},(function(){var a=this,t=a.$createElement,s=a._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[s("h2",{attrs:{id:"安装依赖"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#安装依赖"}},[a._v("#")]),a._v(" 安装依赖")]),a._v(" "),s("p",[a._v("安装以下依赖软件:")]),a._v(" "),s("ul",[s("li",[a._v("Redis 2.8或以上版本")]),a._v(" "),s("li",[a._v("MySQL 5.7或以上版本")]),a._v(" "),s("li",[a._v("Apollo配置中心 (可选)")]),a._v(" "),s("li",[a._v("Eureka服务注册中心")])]),a._v(" "),s("h3",{attrs:{id:"安装mysql"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#安装mysql"}},[a._v("#")]),a._v(" 安装MySQL")]),a._v(" "),s("ul",[s("li",[a._v("操作系统 CentOS 6.5")]),a._v(" "),s("li",[a._v("MySQL 5.7.30")])]),a._v(" "),s("ol",[s("li",[a._v("下载MySQL")])]),a._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[a._v("wget")]),a._v(" https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-1.el6.x86_64.rpm-bundle.tar\n")])])]),s("ol",{attrs:{start:"2"}},[s("li",[a._v("解压")])]),a._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[a._v("tar")]),a._v(" -xvf mysql-5.7.30-1.el6.x86_64.rpm-bundle.tar\n")])])]),s("ol",{attrs:{start:"3"}},[s("li",[a._v("安装")])]),a._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[a._v("sudo")]),a._v(" yum "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("install")]),a._v(" mysql-community-"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("server,client,common,libs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("-*\n")])])]),s("ol",{attrs:{start:"4"}},[s("li",[a._v("启动")])]),a._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[a._v("sudo")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("service")]),a._v(" mysqld start\n")])])]),s("p",[a._v("启动成功会显示以下信息:")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("[root@localhost ~]# sudo service mysqld start\nInitializing MySQL database: [ OK ]\nStarting mysqld: [ OK ]\n")])])]),s("ol",{attrs:{start:"5"}},[s("li",[a._v("初始密码")])]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("sudo grep 'temporary password' /var/log/mysqld.log\n")])])]),s("ol",{attrs:{start:"6"}},[s("li",[a._v("使用初始密码登录")])]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("mysql -uroot -p\n")])])]),s("ol",{attrs:{start:"7"}},[s("li",[a._v("修改密码")])]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyNewPass4!';\n")])])]),s("ol",{attrs:{start:"8"}},[s("li",[a._v("退出登录")])]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("quit\n")])])]),s("h3",{attrs:{id:"安装redis-6-0-8"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#安装redis-6-0-8"}},[a._v("#")]),a._v(" 安装Redis 6.0.8")]),a._v(" "),s("ol",[s("li",[a._v("下载解压并编译")])]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("$ wget http://download.redis.io/releases/redis-6.0.8.tar.gz\n$ tar xzf redis-6.0.8.tar.gz\n$ cd redis-6.0.8\n$ make\n")])])]),s("ol",{attrs:{start:"2"}},[s("li",[a._v("启动redis")])]),a._v(" "),s("p",[a._v("运行编译后的文件:")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("$ src/redis-server\n")])])]),s("ol",{attrs:{start:"3"}},[s("li",[a._v("客户端连接")])]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v('$ src/redis-cli\nredis> set foo bar\nOK\nredis> get foo\n"bar"\n')])])]),s("h3",{attrs:{id:"安装apollo配置中心"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#安装apollo配置中心"}},[a._v("#")]),a._v(" 安装Apollo配置中心")]),a._v(" "),s("p",[a._v("说明: apollo是可选组件,如果不使用apollo可使用本地配置文件(application.yml), 如果不使用apollo可跳过此步骤。")]),a._v(" "),s("p",[a._v("安装步骤详见apollo官方文档: "),s("a",{attrs:{href:"https://github.com/ctripcorp/apollo/wiki/Quick-Start",target:"_blank",rel:"noopener noreferrer"}},[s("OutboundLink")],1)]),a._v(" "),s("h3",{attrs:{id:"安装eureka服务注册中心"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#安装eureka服务注册中心"}},[a._v("#")]),a._v(" 安装Eureka服务注册中心")]),a._v(" "),s("p",[a._v("环境要求:")]),a._v(" "),s("ul",[s("li",[a._v("JDK 1.8 或以上版本")]),a._v(" "),s("li",[a._v("Tomcat 6.0.10 或以上版本 (如使用spring cloud已内置)")])]),a._v(" "),s("ol",[s("li",[a._v("安装JDK 1.8")])]),a._v(" "),s("p",[a._v("1)下载JDK,如: jdk-8u192-linux-x64.tar.gz")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("tar -zxvf jdk-8u192-linux-x64.tar.gz\nmv jdk1.8.0_192 /usr/local/\n\n")])])]),s("p",[a._v("2)设置JDK环境变量,将下面内容追回到/etc/profile文件后面")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("JAVA_HOME=/usr/local/jdk/jdk1.8.0_192\nJRE_HOME=$JAVA_HOME/jre\nPATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin\nCLASSPATH=:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib/dt.jar\nexport JAVA_HOME JRE_HOME PATH CLASSPATH\n\n")])])]),s("p",[a._v("3)执行以下命令全环境变量生效:")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("source /etc/profile\n\n")])])]),s("p",[a._v("4)查看是否安装成功")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("java -version\n")])])]),s("ol",{attrs:{start:"2"}},[s("li",[a._v("安装eureka")])]),a._v(" "),s("p",[a._v("1)使用IDE创建一个spring boot项目,如:sc-eureka-server")]),a._v(" "),s("p",[a._v("pom.xml:")]),a._v(" "),s("div",{staticClass:"language-xml extra-class"},[s("pre",{pre:!0,attrs:{class:"language-xml"}},[s("code",[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("dependency")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("groupId")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("org.springframework.cloud"),s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")])]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("<")]),a._v("artifactId")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(">")])]),a._v("spring-cloud-starter-netflix-eureka-server"),s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")])]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token tag"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("")])]),a._v("\n")])])]),s("p",[a._v("在启动类上添加@EnableEurekaServer注解来启用Euerka注册中心功能:")]),a._v(" "),s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[a._v("@SpringBootApplication")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[a._v("@EnableEurekaServer")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("public")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("class")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("ScEurekaServerApplication")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("public")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("static")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("void")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("]")]),a._v(" args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("SpringApplication")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("run")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("ScEurekaServerApplication")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("class")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),s("p",[a._v("application.properties配置文件:")]),a._v(" "),s("div",{staticClass:"language-properties extra-class"},[s("pre",{pre:!0,attrs:{class:"language-properties"}},[s("code",[s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("spring.application.name")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("sc-eureka-server")]),a._v("\n\n"),s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("server.port")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("8761")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("eureka.instance.hostname")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("localhost")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("eureka.client.registerWithEureka")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("false")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("eureka.client.fetchRegistry")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("false")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("eureka.server.enableSelfPreservation")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("false")]),a._v("\n")])])]),s("p",[a._v("2) maven构建并运行sc-eureka-server应用, 启动后访问地址http://localhost:8761/可以看到Eureka注册中心的界面")]),a._v(" "),s("p",[a._v("3)把target/sc-eureka-server-1.0.0.jar传到linux服务器上运行. (仅以单机部署为例)")]),a._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[a._v("nohub java -jar sc-eureka-server-1.0.0.jar "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("&")]),a._v(" \n")])])]),s("p",[a._v("4)eureka客户端的注册地址为:http://localhost:8761/eureka/ (替换localhost为服务器的IP)")]),a._v(" "),s("div",{staticClass:"language-properties extra-class"},[s("pre",{pre:!0,attrs:{class:"language-properties"}},[s("code",[s("span",{pre:!0,attrs:{class:"token attr-name"}},[a._v("eureka.client.serviceUrl.defaultZone")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("=")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token attr-value"}},[a._v("http://localhost:8761/eureka/")]),a._v("\n")])])]),s("h2",{attrs:{id:"安装fizz"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#安装fizz"}},[a._v("#")]),a._v(" 安装Fizz")]),a._v(" "),s("h3",{attrs:{id:"管理后台"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#管理后台"}},[a._v("#")]),a._v(" 管理后台")]),a._v(" "),s("p",[a._v("从github的releases(https://github.com/wehotel/fizz-gateway-community/releases)下载 fizz-manager-professional 和 fizz-admin-professional 的安装包")]),a._v(" "),s("ul",[s("li",[a._v("管理后台服务端(fizz-manager-professional)")])]),a._v(" "),s("ol",[s("li",[a._v("首次安装执行"),s("code",[a._v("fizz-manager-professional-1.1.0-mysql.sql")]),a._v("数据库脚本,低版本升级执行"),s("code",[a._v("update")]),a._v("目录下的升级脚本")]),a._v(" "),s("li",[a._v("将"),s("code",[a._v("application-prod.yml")]),a._v("、"),s("code",[a._v("boot.sh")]),a._v("、"),s("code",[a._v("fizz-manager-professional-1.1.0.jar")]),a._v("拷贝到"),s("code",[a._v("/data/webapps/fizz-manager-professional")]),a._v("目录下")]),a._v(" "),s("li",[a._v("修改"),s("code",[a._v("application-prod.yml")]),a._v("文件,将相关配置修改成部署环境的配置")]),a._v(" "),s("li",[a._v("修改"),s("code",[a._v("boot.sh")]),a._v("文件,将"),s("code",[a._v("RUN_CMD")]),a._v("变量值修改成部署环境的JAVA实际路径")]),a._v(" "),s("li",[a._v("执行 "),s("code",[a._v("chmod +x boot.sh")]),a._v(" 命令给"),s("code",[a._v("boot.sh")]),a._v("增加执行权限")]),a._v(" "),s("li",[a._v("执行 "),s("code",[a._v("./boot.sh start")]),a._v(" 命令启动服务,支持 start/stop/restart(升级发布时需要手动kill原进程)/status命令")]),a._v(" "),s("li",[a._v("服务启动后访问前端登录地址,使用超级管理员账户"),s("code",[a._v("admin")]),a._v("密码"),s("code",[a._v("Aa123!")]),a._v("登录")])]),a._v(" "),s("ul",[s("li",[a._v("管理后台前端(fizz-admin-professional)")])]),a._v(" "),s("p",[a._v("zip资源包解压后,取文件夹【fizzAdmin】放置于服务器静态数据存放目录 如:/home/data/")]),a._v(" "),s("p",[a._v("nginx配置")]),a._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[a._v("server {\n listen 9000;\n server_name localhost:9000;\n location / {\n root /home/data/fizzAdmin;\n }\n location ^~ /api {\n rewrite ^/api/(.*) /$1 break;\n proxy_pass http://127.0.0.1:8000;\n }\n}\n\n# 注:root中地址需与资源包存放目录路径一致\n# 注:http://127.0.0.1:8000 为管理后台(fizz-manager-professional)的访问地址\n")])])]),s("p",[a._v("访问地址")]),a._v(" "),s("p",[a._v("【资源部署服务器IP + 端口号】如:http://127.0.0.1:9000/")]),a._v(" "),s("p",[a._v("(端口号与nginx配置端口号一致)")]),a._v(" "),s("h3",{attrs:{id:"fizz-gateway-community社区版"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#fizz-gateway-community社区版"}},[a._v("#")]),a._v(" fizz-gateway-community社区版")]),a._v(" "),s("p",[a._v("说明:如果使用apollo配置中心,可把application.yml文件内容迁到配置中心(apollo上应用名为:fizz-gateway);使用不使用apollo可去掉下面启动命令里的apollo参数。")]),a._v(" "),s("p",[a._v("脚本启动:")]),a._v(" "),s("ol",[s("li",[a._v("下载fizz-gateway-community的最新代码,修改application.yml配置文件里eureka、redis的配置,使用maven构建好并把构建好的fizz-gateway-community-1.0.0.jar和boot.sh放同一目录")]),a._v(" "),s("li",[a._v("修改boot.sh脚本的apollo连接,JVM内存配置,")]),a._v(" "),s("li",[a._v("执行 "),s("code",[a._v("./boot.sh start")]),a._v(" 命令启动服务,支持 start/stop/restart/status命令")])]),a._v(" "),s("p",[a._v("IDE启动:")]),a._v(" "),s("ol",[s("li",[a._v("本地clone仓库上的最新代码")]),a._v(" "),s("li",[a._v("将项目fizz-gateway导入IDE")]),a._v(" "),s("li",[a._v("导入完成后设置项目启动配置及修改application.yml配置文件里eureka、redis的配置,在VM选项中加入"),s("code",[a._v("-Denv=dev -Dapollo.meta=http://localhost:66")]),a._v("(Apollo配置中心地址)")])]),a._v(" "),s("p",[a._v("jar启动:")]),a._v(" "),s("ol",[s("li",[a._v("本地clone仓库上的最新代码,修改application.yml配置文件里eureka、redis的配置")]),a._v(" "),s("li",[a._v("在项目根目录fizz-gateway-community下执行Maven命令"),s("code",[a._v("mvn clean package -DskipTests=true")]),a._v("打包")]),a._v(" "),s("li",[a._v("进入target目录,使用命令"),s("code",[a._v("java -jar -Denv=DEV -Dapollo.meta=http://localhost:66 fizz-gateway-community-1.0.0.jar")]),a._v("启动服务")])]),a._v(" "),s("p",[a._v("网关访问地址格式:")]),a._v(" "),s("p",[a._v("http://127.0.0.1:8600/proxy/[服务名]/[API Path]")])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/13.ce1fb161.js b/docs/assets/js/13.25760eda.js similarity index 97% rename from docs/assets/js/13.ce1fb161.js rename to docs/assets/js/13.25760eda.js index 56a87e7..ae81819 100644 --- a/docs/assets/js/13.ce1fb161.js +++ b/docs/assets/js/13.25760eda.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{361:function(t,a,i){"use strict";i.r(a);var v=i(42),_=Object(v.a)({},(function(){var t=this,a=t.$createElement,i=t._self._c||a;return i("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[i("h2",{attrs:{id:"什么是fizz网关"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#什么是fizz网关"}},[t._v("#")]),t._v(" 什么是Fizz网关")]),t._v(" "),i("p",[t._v("A Managerment API Gateway in Java . Fizz Gateway 是一个基于 Java开发的微服务网关,能够实现热服务编排、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。")]),t._v(" "),i("h2",{attrs:{id:"fizz的设计"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#fizz的设计"}},[t._v("#")]),t._v(" Fizz的设计")]),t._v(" "),i("p",[i("img",{attrs:{src:"/fizz-gateway-community/fizz_design.png",alt:""}})]),t._v(" "),i("h2",{attrs:{id:"产品特性"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#产品特性"}},[t._v("#")]),t._v(" 产品特性")]),t._v(" "),i("ul",[i("li",[t._v("集群管理:Fizz网关节点是无状态的,配置信息自动同步,支持节点水平拓展和多集群部署。")]),t._v(" "),i("li",[t._v("服务编排:支持热服务编排能力,支持前后端编码,随时随地更新API。")]),t._v(" "),i("li",[t._v("负载均衡:支持round-robin负载均衡。")]),t._v(" "),i("li",[t._v("服务发现:支持从Eureka注册中心发现后端服务器。")]),t._v(" "),i("li",[t._v("配置中心:支持接入apollo配置中心。")]),t._v(" "),i("li",[t._v("HTTP反向代理:隐藏真实后端服务,支持 Rest API反向代理。")]),t._v(" "),i("li",[t._v("访问策略:支持不同策略访问不同的API、配置不同的鉴权等。")]),t._v(" "),i("li",[t._v("IP黑白名单:支持配置IP黑白名单。")]),t._v(" "),i("li",[t._v("自定义插件:强大的插件机制支持自由扩展。")]),t._v(" "),i("li",[t._v("可扩展:简单易用的插件机制方便扩展功能。")]),t._v(" "),i("li",[t._v("高性能:性能在众多网关之中表现优异。")]),t._v(" "),i("li",[t._v("版本控制:支持操作的发布和多次回滚。")]),t._v(" "),i("li",[t._v("管理后台:通过管理后台界面对网关集群进行各项配置。")])])])}),[],!1,null,null,null);a.default=_.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{375:function(t,a,i){"use strict";i.r(a);var v=i(42),_=Object(v.a)({},(function(){var t=this,a=t.$createElement,i=t._self._c||a;return i("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[i("h2",{attrs:{id:"什么是fizz网关"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#什么是fizz网关"}},[t._v("#")]),t._v(" 什么是Fizz网关")]),t._v(" "),i("p",[t._v("A Managerment API Gateway in Java . Fizz Gateway 是一个基于 Java开发的微服务网关,能够实现热服务编排、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。")]),t._v(" "),i("h2",{attrs:{id:"fizz的设计"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#fizz的设计"}},[t._v("#")]),t._v(" Fizz的设计")]),t._v(" "),i("p",[i("img",{attrs:{src:"/fizz-gateway-community/fizz_design.png",alt:""}})]),t._v(" "),i("h2",{attrs:{id:"产品特性"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#产品特性"}},[t._v("#")]),t._v(" 产品特性")]),t._v(" "),i("ul",[i("li",[t._v("集群管理:Fizz网关节点是无状态的,配置信息自动同步,支持节点水平拓展和多集群部署。")]),t._v(" "),i("li",[t._v("服务编排:支持热服务编排能力,支持前后端编码,随时随地更新API。")]),t._v(" "),i("li",[t._v("负载均衡:支持round-robin负载均衡。")]),t._v(" "),i("li",[t._v("服务发现:支持从Eureka注册中心发现后端服务器。")]),t._v(" "),i("li",[t._v("配置中心:支持接入apollo配置中心。")]),t._v(" "),i("li",[t._v("HTTP反向代理:隐藏真实后端服务,支持 Rest API反向代理。")]),t._v(" "),i("li",[t._v("访问策略:支持不同策略访问不同的API、配置不同的鉴权等。")]),t._v(" "),i("li",[t._v("IP黑白名单:支持配置IP黑白名单。")]),t._v(" "),i("li",[t._v("自定义插件:强大的插件机制支持自由扩展。")]),t._v(" "),i("li",[t._v("可扩展:简单易用的插件机制方便扩展功能。")]),t._v(" "),i("li",[t._v("高性能:性能在众多网关之中表现优异。")]),t._v(" "),i("li",[t._v("版本控制:支持操作的发布和多次回滚。")]),t._v(" "),i("li",[t._v("管理后台:通过管理后台界面对网关集群进行各项配置。")])])])}),[],!1,null,null,null);a.default=_.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/14.cc27c55a.js b/docs/assets/js/14.cc27c55a.js new file mode 100644 index 0000000..3185c2f --- /dev/null +++ b/docs/assets/js/14.cc27c55a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{357:function(a,t,s){"use strict";s.r(t);var r=s(42),e=Object(r.a)({},(function(){var a=this,t=a.$createElement,s=a._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[s("h2",{attrs:{id:"概述"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[a._v("#")]),a._v(" 概述")]),a._v(" "),s("p",[a._v("接口列表功能用于维护聚合接口,聚合接口从外部调用方角度看是一个简单的接口,通过入参请求获取响应结果,内部实现会调用多个底层后端服务,将多个调用结果聚合转换成外部调用方想要的数据格式,更多详情请查看服务编排介绍,下面介绍接口列表功能的操作。")]),a._v(" "),s("h2",{attrs:{id:"接口列表"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#接口列表"}},[a._v("#")]),a._v(" 接口列表")]),a._v(" "),s("p",[a._v("菜单位置:服务编排 > 接口列表。点击菜单后进入接口列表页面,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_list_query.png",alt:"manager_aggregate_list_query"}})]),a._v(" "),s("h2",{attrs:{id:"新增接口"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#新增接口"}},[a._v("#")]),a._v(" 新增接口")]),a._v(" "),s("p",[a._v("点击 新增 按钮弹出新增窗口,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_1.png",alt:"manager_aggregate_add_1"}})]),a._v(" "),s("h3",{attrs:{id:"基础信息"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#基础信息"}},[a._v("#")]),a._v(" 基础信息")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_2.png",alt:"manager_aggregate_add_2"}})]),a._v(" "),s("p",[a._v("所属服务:接口所属服务,更多详情请查看服务管理功能介绍,必选;")]),a._v(" "),s("p",[a._v("接口名:接口名称,用于展示使用,长度不能超过200个字符,必填;")]),a._v(" "),s("p",[a._v("方法:接口请求方法类型,可选GET|POST,必选;")]),a._v(" "),s("p",[a._v("路径:接口请求路径后缀,长度不能超过2000个字符,必填;")]),a._v(" "),s("p",[a._v("开发人员:接口对应负责的开发人员,长度不能超过200个字符;")]),a._v(" "),s("p",[a._v("描述:接口功能描述,长度不能超过2000个字符;")]),a._v(" "),s("p",[a._v("举个例子,所属服务设置my-test-service,方法设置POST,路径设置test-aggregate-post,对应的聚合接口请求为 POST http://{Fizz网关ip地址}:{port端口}/proxy/my-test-service/test-aggregate-post。")]),a._v(" "),s("h3",{attrs:{id:"配置输入"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置输入"}},[a._v("#")]),a._v(" 配置输入")]),a._v(" "),s("p",[a._v("聚合接口的入参大部分是通过JSON Schema来定义的,下面先简单地介绍下JSON Schema。")]),a._v(" "),s("h4",{attrs:{id:"json-schema介绍"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#json-schema介绍"}},[a._v("#")]),a._v(" JSON Schema介绍")]),a._v(" "),s("p",[a._v("JSON Schema实际上也是JSON数据,用于标注和验证JSON文档,可以类比于XML Schema,当前最新版本2019-09。")]),a._v(" "),s("p",[a._v("作为普通用户,我们并不需要去了解JSON Schema的规范内容,只要能够构建JSON Schema即可。")]),a._v(" "),s("blockquote",[s("p",[a._v("要理解JSON Schema,首先要理解什么是JSON。JSON是JavaScript Object Notation的缩写,一种简单的数据交换格式。最初JSON是基于JavaScript,广泛的应用于万维网。由于其简洁和清晰的层次结构、易于人阅读等特性,使得越来越多的场景下被采用。")]),a._v(" "),s("p",[a._v("JSON包含以下数据结构:")]),a._v(" "),s("ul",[s("li",[a._v("object:"),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"key1"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"value1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"key2"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"value2"')]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])])]),a._v(" "),s("li",[a._v("array:"),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("[")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"first"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"second"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"third"')]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("]")]),a._v("\n")])])])]),a._v(" "),s("li",[a._v("number:"),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token number"}},[a._v("42")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token number"}},[a._v("3.1415926")]),a._v("\n")])])])]),a._v(" "),s("li",[a._v("string:"),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"This is a string"')]),a._v("\n")])])])]),a._v(" "),s("li",[a._v("boolean:"),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token boolean"}},[a._v("true")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token boolean"}},[a._v("false")]),a._v("\n")])])])]),a._v(" "),s("li",[a._v("null:"),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("null")]),a._v("\n")])])])])]),a._v(" "),s("p",[a._v("通过以上的简单数据类型,就能构造复杂的结构化数据了。下面举两个例子:")]),a._v(" "),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"name"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"George Washington"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"birthday"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"February 22, 1732"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"address"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"Mount Vernon, Virginia, United States"')]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"first_name"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"George"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"last_name"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"Washington"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"birthday"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"1732-02-22"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"address"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"street_address"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"3200 Mount Vernon Memorial Highway"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"city"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"Mount Vernon"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"state"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"Virginia"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"country"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"United States"')]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),s("p",[a._v("以上两个例子都是有效的JSON数据,包含一样的有效信息,但是当程序读取数据时,需要准确的知道数据是怎么组织的,比如哪些字段是必须,这些字段是什么类型。这时候JSON Schema就派上用场了,看以下JSON Schema例子:")]),a._v(" "),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"object"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"properties"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"first_name"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"string"')]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"last_name"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"string"')]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"birthday"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"string"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"format"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"date"')]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"address"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"object"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"properties"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"street_address"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"string"')]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"city"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"string"')]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"state"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"string"')]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"country"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),a._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"string"')]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),s("p",[a._v("用以上JSON Schema验证第一个例子时,验证失败;但是第二个例子验证通过。")]),a._v(" "),s("p",[a._v("JSON Schema本身也是通过JSON编写,其本身也是数据,不是一个计算机程序,只是一种“描述其它数据的结构”的声明格式。这既是长处,也是弱点,JSON Schema可以简洁地描述数据的结构并且自动验证数据,但是对于数据元素间的关系表达就力不能及了。")])]),a._v(" "),s("p",[a._v("更多JSON Schema知识可以阅读"),s("a",{attrs:{href:"https://json-schema.org/understanding-json-schema/",target:"_blank",rel:"noopener noreferrer"}},[a._v("Understanding JSON Schema"),s("OutboundLink")],1),a._v("。")]),a._v(" "),s("h4",{attrs:{id:"请求头部"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#请求头部"}},[a._v("#")]),a._v(" 请求头部")]),a._v(" "),s("p",[a._v("定义聚合接口的请求Header参数。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_3.png",alt:"manager_aggregate_add_3"}})]),a._v(" "),s("p",[a._v("举个例子:")]),a._v(" "),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"object"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"properties"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"headerParam1"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"string"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"title"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"请求头参数1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"titleEn"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"headerParam1"')]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"required"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("[")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"headerParam1"')]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("]")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),s("p",[a._v("以上例子定义了必传请求头参数"),s("code",[a._v("headerParam1")]),a._v("。")]),a._v(" "),s("p",[s("code",[a._v("title")]),a._v("字段用于验证失败时提示使用,例如请求接口时没传请求头时会提示“请求头参数1不能为空”(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_input_header_1.png",alt:"manager_aggregate_add_input_header_1"}})]),a._v(" "),s("p",[a._v("当定义了语言配置(详情请查看后文的语言配置介绍)选项为英文时会使用"),s("code",[a._v("titleEn")]),a._v("字段用于验证失败时提示使用,例如请求接口时没传请求头时会提示“headerParam1 is missing but it is required”(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_input_header_2.png",alt:"manager_aggregate_add_input_header_2"}})]),a._v(" "),s("h4",{attrs:{id:"请求体"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#请求体"}},[a._v("#")]),a._v(" 请求体")]),a._v(" "),s("p",[a._v("定义聚合接口的请求体参数。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_4.png",alt:"manager_aggregate_add_4"}})]),a._v(" "),s("p",[a._v("举个例子:")]),a._v(" "),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"object"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"properties"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"bodyParam1"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"string"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"title"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"请求体参数1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"titleEn"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"bodyParam1"')]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"required"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("[")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"bodyParam1"')]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("]")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),s("p",[a._v("以上例子定义了必传请求体参数"),s("code",[a._v("bodyParam1")]),a._v("。")]),a._v(" "),s("p",[s("code",[a._v("title")]),a._v("字段用于验证失败时提示使用,例如请求接口时没传请求体参数时会提示“请求体参数1不能为空”(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_input_body_1.png",alt:"manager_aggregate_add_input_body_1"}})]),a._v(" "),s("p",[a._v("当定义了语言配置(详情请查看后文的语言配置介绍)选项为英文时会使用"),s("code",[a._v("titleEn")]),a._v("字段用于验证失败时提示使用,例如请求接口时没传请求体参数时会提示“bodyParam1 is missing but it is required”(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_input_body_2.png",alt:"manager_aggregate_add_input_body_2"}})]),a._v(" "),s("h4",{attrs:{id:"query参数"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#query参数"}},[a._v("#")]),a._v(" Query参数")]),a._v(" "),s("p",[a._v("定义聚合接口的Query参数。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_5.png",alt:"manager_aggregate_add_5"}})]),a._v(" "),s("p",[a._v("举个例子:")]),a._v(" "),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"object"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"properties"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"queryParam1"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"type"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"string"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"title"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"query参数1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"titleEn"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"queryParam1"')]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"required"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("[")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"queryParam1"')]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("]")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),s("p",[a._v("以上例子定义了必传Query参数"),s("code",[a._v("queryParam1")]),a._v("。")]),a._v(" "),s("p",[s("code",[a._v("title")]),a._v("字段用于验证失败时提示使用,例如请求接口时没传Query参数时会提示“query参数1不能为空”(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_input_query_1.png",alt:"manager_aggregate_add_input_query_1"}})]),a._v(" "),s("p",[a._v("当定义了语言配置(详情请查看后文的语言配置介绍)选项为英文时会使用"),s("code",[a._v("titleEn")]),a._v("字段用于验证失败时提示使用,例如请求接口时没传Query参数时会提示“queryParam1 is missing but it is required”(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_input_query_2.png",alt:"manager_aggregate_add_input_query_2"}})]),a._v(" "),s("h4",{attrs:{id:"脚本校验"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#脚本校验"}},[a._v("#")]),a._v(" 脚本校验")]),a._v(" "),s("p",[a._v("对于JSON Schema规范无法覆盖的校验场景可以使用脚本对入参进行更加灵活的处理。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_6.png",alt:"manager_aggregate_add_6"}})]),a._v(" "),s("p",[a._v("点击 新增 按钮后弹出脚本配置窗口,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_7.png",alt:"manager_aggregate_add_7"}})]),a._v(" "),s("p",[a._v("脚本类型:可选javascript|groovy,必选;")]),a._v(" "),s("p",[a._v("脚本内容:所选的脚本类型语言编写的入参验证脚本,必填。")]),a._v(" "),s("p",[a._v("举个例子:")]),a._v(" "),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// javascript脚本函数名不能修改")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("function")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("dyFunc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[a._v("paramsJsonStr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// 上下文, 数据结构请参考 context.js")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("var")]),a._v(" context "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[a._v("JSON")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("parse")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("paramsJsonStr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[a._v("'context'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// common为内置的上下文便捷操作工具类,详情请参考common.js;例如:")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// var data = common.getStepRespBody(context, 'step2', 'request1', 'data');")]),a._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// do something")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("var")]),a._v(" headerParam1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v(" common"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("getInputReqHeader")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v("'headerParam1'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("var")]),a._v(" bodyParam1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v(" common"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("getInputReqBody")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v("'bodyParam1'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("var")]),a._v(" queryParam1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v(" common"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("getInputReqParam")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[a._v("'queryParam1'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("var")]),a._v(" result "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("new")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[a._v("Array")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("if")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("headerParam1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("!=")]),a._v(" bodyParam1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"headerParam1与bodyParam1不一致"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("if")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("queryParam1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("!=")]),a._v(" bodyParam1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"queryParam1与bodyParam1不一致"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("if")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("headerParam1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("!=")]),a._v(" queryParam1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[a._v('"headerParam1与queryParam1不一致"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// 返回结果为Array或Object时要先转为json字符串")]),a._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("return")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[a._v("JSON")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[a._v("stringify")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(";")]),a._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n\n")])])]),s("p",[a._v("以上例子使用javascript编写参数校验,限制入参"),s("code",[a._v("headerParam1")]),a._v("、"),s("code",[a._v("bodyParam1")]),a._v("、"),s("code",[a._v("queryParam1")]),a._v("必须一致,不一致将提示错误信息(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_input_script.png",alt:"manager_aggregate_add_input_script"}})]),a._v(" "),s("h4",{attrs:{id:"语言配置"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#语言配置"}},[a._v("#")]),a._v(" 语言配置")]),a._v(" "),s("p",[a._v("聚合接口默认使用中文响应校验失败提示,通过配置可通过入参选择不同的提示语言,目前支持中文、英文提示(已满足我们的业务使用场景,有其他语言要求的小伙伴可以联系我们添加)。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_8.png",alt:"manager_aggregate_add_8"}})]),a._v(" "),s("p",[a._v("字段:入参字段值,例如"),s("code",[a._v("input.request.body.languageCode")]),a._v("使用请求体参数"),s("code",[a._v("languageCode")]),a._v("的值来决定使用哪种语言;")]),a._v(" "),s("p",[a._v("中文:中文与入参字段值的映射关系,例如配置"),s("code",[a._v("0")]),a._v(",当请求入参字段值为"),s("code",[a._v("0")]),a._v("时使用中文提示校验结果;")]),a._v(" "),s("p",[a._v("英文:英文与入参字段值的映射关系,例如配置"),s("code",[a._v("1")]),a._v(",当请求入参字段值为"),s("code",[a._v("1")]),a._v("时使用中文提示校验结果。")]),a._v(" "),s("h3",{attrs:{id:"配置步骤"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置步骤"}},[a._v("#")]),a._v(" 配置步骤")]),a._v(" "),s("p",[a._v("聚合接口调用底层服务是通过多个step实现的,多个step串行执行,每个step包含多个request(对底层服务接口的调用),同个step里的多个request并行执行,后执行的step可以获取已执行step的执行结果,更多详情请查看服务编排文章的介绍,下面介绍配置步骤的使用。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_9.png",alt:"manager_aggregate_add_9"}})]),a._v(" "),s("p",[a._v("是否执行完此步骤后结束:勾选后实际请求只执行完该步骤后即响应结果,不执行后续步骤,用于调试使用;")]),a._v(" "),s("p",[a._v("请求方法:调用底层服务接口的请求类型,可选GET|POST,必选;")]),a._v(" "),s("p",[a._v("默认URL:调用底层服务接口的默认URL,当Fizz网关启动环境没有配置URL时使用该默认URL;")]),a._v(" "),s("p",[a._v("开发环境URL:开发环境调用底层服务接口的URL,当Fizz网关启动使用spring.profiles.active=dev时使用该URL;")]),a._v(" "),s("p",[a._v("测试环境URL:测试环境调用底层服务接口的URL,当Fizz网关启动使用spring.profiles.active=test时使用该URL;")]),a._v(" "),s("p",[a._v("预生产环境URL:预生产环境调用底层服务接口的URL,当Fizz网关启动使用spring.profiles.active=pre时使用该URL;")]),a._v(" "),s("p",[a._v("生产环境URL:生产环境调用底层服务接口的URL,当Fizz网关启动使用spring.profiles.active=prod时使用该URL;")]),a._v(" "),s("p",[a._v("超时时间(毫秒):调用底层服务接口的超时时间,超时抛出异常,单位毫秒;")]),a._v(" "),s("p",[a._v("Fallback:可选stop|continue,控制当调用底层服务接口失败后是否继续执行后续操作;")]),a._v(" "),s("p",[a._v("请求预处理:勾选后可配置预处理脚本,预处理脚本返回true时才执行调用底层服务接口。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_10.png",alt:"manager_aggregate_add_10"}})]),a._v(" "),s("p",[a._v("配置入参:配置调用底层服务接口的请求参数;")]),a._v(" "),s("p",[a._v("配置响应:配置调用底层服务接口的响应内容。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_11.png",alt:"manager_aggregate_add_11"}})]),a._v(" "),s("p",[a._v("配置步骤结果:配置step执行完成后的响应内容。")]),a._v(" "),s("h3",{attrs:{id:"配置输出"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置输出"}},[a._v("#")]),a._v(" 配置输出")]),a._v(" "),s("p",[a._v("配置聚合接口调用完成的响应内容。在响应体、响应头配置中可以配置简单的响应固定值、响应引用值,对于需要逻辑处理得到结果的响应可以通过脚本配置灵活处理,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_12.png",alt:"manager_aggregate_add_12"}})]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_13.png",alt:"manager_aggregate_add_13"}})]),a._v(" "),s("h3",{attrs:{id:"校验结果"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#校验结果"}},[a._v("#")]),a._v(" 校验结果")]),a._v(" "),s("p",[a._v("配置聚合接口入参校验失败后的响应内容,在响应体、响应头配置中可以配置简单的响应固定值、响应引用值,对于需要逻辑处理得到结果的响应可以通过脚本配置灵活处理,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_14.png",alt:"manager_aggregate_add_14"}})]),a._v(" "),s("p",[a._v("校验结果有一个专用的引用值"),s("code",[a._v("validateMsg")]),a._v(",该引用值用于存放入参验证错误提示信息。")]),a._v(" "),s("h3",{attrs:{id:"保存接口"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#保存接口"}},[a._v("#")]),a._v(" 保存接口")]),a._v(" "),s("p",[a._v("所有配置完成后点击 保存 按钮,完成聚合接口的配置。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_add_15.png",alt:"manager_aggregate_add_15"}})]),a._v(" "),s("h2",{attrs:{id:"导出接口"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#导出接口"}},[a._v("#")]),a._v(" 导出接口")]),a._v(" "),s("p",[a._v("导出功能将聚合接口以配置文件的形式导出,导出的文件可通过导入功能重新导入系统,当我们的系统分多个环境时,可使用导出导入功能实现聚合接口的快速同步,下面介绍导出功能。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_export_1.png",alt:"manager_aggregate_export_1"}})]),a._v(" "),s("p",[a._v("勾选想到导出的接口,点击 导出 按钮弹出确认窗口,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_export_2.png",alt:"manager_aggregate_export_2"}})]),a._v(" "),s("p",[a._v("点击 确定 按钮,浏览器保存配置文件,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_export_3.png",alt:"manager_aggregate_export_3"}})]),a._v(" "),s("h2",{attrs:{id:"导入接口"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#导入接口"}},[a._v("#")]),a._v(" 导入接口")]),a._v(" "),s("p",[a._v("导入功能将配置文件中的聚合接口转化成后台的持久化存储,导入的文件可以通过导出功能获取或者通过编写好的聚合配置JSON文件转化得到(转换工具可以联系我们获取)。当我们的系统分多个环境时,可使用导出导入功能实现聚合接口的快速同步,下面介绍导出功能。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_import_1.png",alt:"manager_aggregate_import_1"}})]),a._v(" "),s("p",[a._v("点击 导入 按钮弹出导入配置窗口,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_import_2.png",alt:"manager_aggregate_import_2"}})]),a._v(" "),s("p",[a._v("点击 选取文件 按钮后选取要导入的配置文件;")]),a._v(" "),s("p",[a._v("强制覆盖:通过请求类型(GET|POST)、请求路径(/proxy/{service}/{apiPath})可以唯一确定一个聚合接口,当聚合接口已存在时,未勾选该选项时忽略该聚合接口导入,勾选该选项时覆盖已存在的聚合接口配置;")]),a._v(" "),s("p",[a._v("点击 确定 按钮后导入聚合接口配置。")]),a._v(" "),s("h2",{attrs:{id:"调试模式"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#调试模式"}},[a._v("#")]),a._v(" 调试模式")]),a._v(" "),s("p",[a._v("调试模式用于对接口开发过程中的调试使用,当打开调试模式后,Fizz网关会将聚合接口调用底层服务接口的请求响应信息以及耗时、聚合结果、步骤上下文打印到日志中,通过日志可以清楚的了解聚合接口的实际执行情况。调试模式会对网关性能造成影响,因此不建议在生产环境打开调试模式,当调试完成后及时关闭调试模式,避免打印过多日志造成资源浪费,下面介绍调试模式的使用。")]),a._v(" "),s("p",[a._v("勾选想要打开调试模式的接口,点击 打开调试模式 按钮弹出确认窗口,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_debug_mode_1.png",alt:"manager_aggregate_debug_mode_1"}})]),a._v(" "),s("p",[a._v("点击 确定 按钮确认打开调试模式。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_debug_mode_2.png",alt:"manager_aggregate_debug_mode_2"}})]),a._v(" "),s("p",[a._v("勾选想要关闭调试模式的接口,点击 关闭调试模式 按钮弹出确认窗口,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_debug_mode_3.png",alt:"manager_aggregate_debug_mode_3"}})]),a._v(" "),s("p",[a._v("点击 确定 按钮确认关闭调试模式。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_debug_mode_4.png",alt:"manager_aggregate_debug_mode_4"}})]),a._v(" "),s("h2",{attrs:{id:"编辑接口"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#编辑接口"}},[a._v("#")]),a._v(" 编辑接口")]),a._v(" "),s("p",[a._v("点击 编辑 按钮弹出编辑窗口,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_edit_1.png",alt:"manager_aggregate_edit_1"}})]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_edit_2.png",alt:"manager_aggregate_edit_2"}})]),a._v(" "),s("h2",{attrs:{id:"删除接口"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#删除接口"}},[a._v("#")]),a._v(" 删除接口")]),a._v(" "),s("p",[a._v("点击 删除 按钮弹出删除确认窗口,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_delete_1.png",alt:"manager_aggregate_delete_1"}})]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_delete_2.png",alt:"manager_aggregate_delete_2"}})]),a._v(" "),s("p",[a._v("点击 确定 按钮后删除接口,处于已发布状态的接口无法删除,需要下线后才能操作删除。")]),a._v(" "),s("h2",{attrs:{id:"发布-下线申请"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#发布-下线申请"}},[a._v("#")]),a._v(" 发布|下线申请")]),a._v(" "),s("p",[a._v("发布|下线申请用于聚合接口的发布或者下线申请,只有通过审核人审核后申请人才能执行发布|下线操作,避免误操作‘,保证接口的安全。")]),a._v(" "),s("p",[a._v("点击 发布|下线申请 按钮,弹出发布|下线申请窗口,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_apply_1.png",alt:"manager_aggregate_apply_1"}})]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_apply_2.png",alt:"manager_aggregate_apply_2"}})]),a._v(" "),s("p",[a._v("点击 添加 按钮后,弹出接口列表,勾选需要操作的接口,点击 确定 添加进申请中。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_apply_3.png",alt:"manager_aggregate_apply_3"}})]),a._v(" "),s("p",[a._v("标题:申请的标题,长度不能超过200个字符,必填;")]),a._v(" "),s("p",[a._v("类型:申请类型,可选发布|下线,必选;")]),a._v(" "),s("p",[a._v("申请原因:申请的原因,长度不能超过2000个字符;")]),a._v(" "),s("p",[a._v("选择审核人:选择有审核权限的人对申请进行审核,列表根据需要操作的接口动态变化(未添加接口时列表为空,拥有服务权限并且有待审核菜单权限的人、操作管理员角色的人为可选审核人),必选;")]),a._v(" "),s("p",[a._v("点击 确定 按钮后提交申请,选择的审核人会收到申请审核邮件(审核人邮箱地址通过用户管理设置,更多详情请查看用户管理功能介绍),如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_apply_4.png",alt:"manager_aggregate_apply_4"}})]),a._v(" "),s("h2",{attrs:{id:"接口测试"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#接口测试"}},[a._v("#")]),a._v(" 接口测试")]),a._v(" "),s("p",[a._v("后台提供了可视化的接口调用界面,聚合接口创建完成后可通过该界面对接口进行调用测试。通过点击接口详情页面的 测试 按钮打开接口测试页面,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_test_1.png",alt:"manager_aggregate_test_1"}})]),a._v(" "),s("p",[a._v("跳转页面的同时后台会将接口当前的最新配置推送给Fizz网关生成一个测试接口,请求路径为/proxytest/{service}/{apiPath}。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_test_2.png",alt:"manager_aggregate_test_2"}})]),a._v(" "),s("p",[a._v("点击 发送 按钮向指定接口发送一次请求,Response响应结果区域显示调用接口结果,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_test_3.png",alt:"manager_aggregate_test_3"}})]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_test_4.png",alt:"manager_aggregate_test_4"}})]),a._v(" "),s("p",[a._v("请求体tab用于配置请求的请求体参数。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_test_5.png",alt:"manager_aggregate_test_5"}})]),a._v(" "),s("p",[a._v("请求头tab用于配置请求的请求头参数。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_test_6.png",alt:"manager_aggregate_test_6"}})]),a._v(" "),s("p",[a._v("Query参数用于配置请求的Query参数。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_test_7.png",alt:"manager_aggregate_test_7"}})]),a._v(" "),s("p",[a._v("返回Context:Fizz网关中一次聚合接口的请求过程中内部会持有一个Context对象,该对象保存了本次请求过程的入参信息、底层服务接口调用信息、响应信息,通过勾选该选项,接口会将Context随接口响应一起返回,通过查看Context可以清楚地了解接口的实际调用过程。")]),a._v(" "),s("p",[a._v("未勾选 返回Context 选项时,接口按配置输出的设置响应结果,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_test_8.png",alt:"manager_aggregate_test_8"}})]),a._v(" "),s("p",[a._v("勾选 返回Context 选项后,接口会将Context随接口响应一起返回,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_test_9.png",alt:"manager_aggregate_test_9"}})]),a._v(" "),s("p",[a._v("测试接口:调用测试接口,请求路径为/proxytest/{service}/{apiPath};")]),a._v(" "),s("p",[a._v("正式接口:调用正式接口,请求路径为/proxy/{service}/{apiPath};")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_test_10.png",alt:"manager_aggregate_test_10"}})]),a._v(" "),s("p",[a._v("点击 保存 按钮会将本次测试请求数据保存下来,通过选取已保存的测试记录可以快速恢复请求数据,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_test_11.png",alt:"manager_aggregate_test_11"}})]),a._v(" "),s("p",[a._v("标题:本次测试数据保存时使用的标题,长度不能超过2000个字符,保存后在历史测试记录列表显示,如图所示。")]),a._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_test_12.png",alt:"manager_aggregate_test_12"}})])])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/15.c6e43d45.js b/docs/assets/js/15.c6e43d45.js new file mode 100644 index 0000000..19957f6 --- /dev/null +++ b/docs/assets/js/15.c6e43d45.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[15],{358:function(a,t,e){"use strict";e.r(t);var r=e(42),_=Object(r.a)({},(function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h2",{attrs:{id:"概述"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[a._v("#")]),a._v(" 概述")]),a._v(" "),e("p",[a._v("聚合接口的发布|下线操作需要提交发布|下线申请,审核通过后申请人才能执行发布|下线操作。待审核功能用于审核发布|下线申请,下面介绍待审核功能。")]),a._v(" "),e("h2",{attrs:{id:"审核列表"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#审核列表"}},[a._v("#")]),a._v(" 审核列表")]),a._v(" "),e("p",[a._v("菜单位置:发布申请 > 待审核。点击菜单后进入审核列表页面,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_approve_list_query.png",alt:"manager_aggregate_approve_list_query"}})]),a._v(" "),e("h2",{attrs:{id:"审核操作"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#审核操作"}},[a._v("#")]),a._v(" 审核操作")]),a._v(" "),e("p",[a._v("点击 查看 按钮可以查看发布|下线申请详情,详情页中可执行审核操作。")]),a._v(" "),e("p",[a._v("申请列表页提供快速审核操作,点击 审核 按钮后弹出审核确认窗口,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_approve_op_1.png",alt:"manager_aggregate_approve_op_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_approve_op_2.png",alt:"manager_aggregate_approve_op_2"}})]),a._v(" "),e("p",[a._v("审核结果:勾选通过,审核后申请能可执行申请的操作;勾选不通过,审核后申请失败,申请人不能执行申请的操作。")]),a._v(" "),e("p",[a._v("审核后申请人会收到审核结果邮件通知,如下图是审核通过的邮件通知。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_approve_op_3.png",alt:"manager_aggregate_approve_op_3"}})])])}),[],!1,null,null,null);t.default=_.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/16.d04bc2ac.js b/docs/assets/js/16.d04bc2ac.js new file mode 100644 index 0000000..89d13bf --- /dev/null +++ b/docs/assets/js/16.d04bc2ac.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{360:function(a,t,e){"use strict";e.r(t);var _=e(42),r=Object(_.a)({},(function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h2",{attrs:{id:"概述"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[a._v("#")]),a._v(" 概述")]),a._v(" "),e("p",[a._v("管理后台记录了发布|下线申请的审核操作日志,审核日志功能提供界面查询后台记录的审核操作日志。")]),a._v(" "),e("h2",{attrs:{id:"审核日志列表"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#审核日志列表"}},[a._v("#")]),a._v(" 审核日志列表")]),a._v(" "),e("p",[a._v("菜单位置:发布申请 > 审核日志。点击菜单后进入审核日志列表页面,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_approve_op_log_list_query.png",alt:"manager_aggregate_approve_op_log_list_query"}})]),a._v(" "),e("h2",{attrs:{id:"审核日志详情"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#审核日志详情"}},[a._v("#")]),a._v(" 审核日志详情")]),a._v(" "),e("p",[a._v("点击 查看 按钮弹出审核日志详情页面,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_approve_op_log_detail_1.png",alt:"manager_aggregate_approve_op_log_detail_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_approve_op_log_detail_2.png",alt:"manager_aggregate_approve_op_log_detail_2"}})])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/17.7cec28a6.js b/docs/assets/js/17.7cec28a6.js new file mode 100644 index 0000000..26b819a --- /dev/null +++ b/docs/assets/js/17.7cec28a6.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[17],{359:function(a,_,e){"use strict";e.r(_);var t=e(42),g=Object(t.a)({},(function(){var a=this,_=a.$createElement,e=a._self._c||_;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h2",{attrs:{id:"概述"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[a._v("#")]),a._v(" 概述")]),a._v(" "),e("p",[a._v("聚合接口的发布|下线操作需要提交发布|下线申请,审核通过后申请人才能执行发布|下线操作。我的申请功能用于发布|下线申请过程的相关操作,下面介绍我的申请功能。")]),a._v(" "),e("h2",{attrs:{id:"申请列表"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#申请列表"}},[a._v("#")]),a._v(" 申请列表")]),a._v(" "),e("p",[a._v("菜单位置:发布申请 > 我的申请。点击菜单后进入申请列表页面,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_my_apply_list_query.png",alt:"manager_aggregate_my_apply_list_query"}})]),a._v(" "),e("h2",{attrs:{id:"申请撤回"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#申请撤回"}},[a._v("#")]),a._v(" 申请撤回")]),a._v(" "),e("p",[a._v("对于已提交但未被审核的申请可执行撤回操作,点击 撤回 按钮弹出确认窗口,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_my_apply_revoke_1.png",alt:"manager_aggregate_my_apply_revoke_1"}})]),a._v(" "),e("p",[a._v("点击 确定 按钮后确认撤回申请,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_my_apply_revoke_2.png",alt:"manager_aggregate_my_apply_revoke_2"}})]),a._v(" "),e("p",[a._v("撤回后审核人会收到邮箱提醒无需再处理该申请,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_my_apply_revoke_3.png",alt:"manager_aggregate_my_apply_revoke_3"}})]),a._v(" "),e("p",[a._v("撤回后可对申请重新进行编辑后再次提交,点击 编辑 按钮后弹出编辑窗口,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_my_apply_revoke_4.png",alt:"manager_aggregate_my_apply_revoke_4"}})]),a._v(" "),e("p",[a._v("点击 确定 按钮后再次提交申请,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_my_apply_revoke_5.png",alt:"manager_aggregate_my_apply_revoke_5"}})]),a._v(" "),e("h2",{attrs:{id:"申请详情"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#申请详情"}},[a._v("#")]),a._v(" 申请详情")]),a._v(" "),e("p",[a._v("点击 查看 按钮查看申请详情。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_my_apply_detail_1.png",alt:"manager_aggregate_my_apply_detail_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_my_apply_detail_2.png",alt:"manager_aggregate_my_apply_detail_2"}})]),a._v(" "),e("p",[a._v("操作日志记录该申请的所有操作,包括申请提交、申请撤回、申请重新提交、审核不通过、审核通过、修改审核人、接口发布、接口下线 、接口回滚、接口撤回。")]),a._v(" "),e("p",[a._v("待审核状态申请可以更换审核人,点击 修改审核人 按钮后弹出修改审核人窗口,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_my_apply_detail_3.png",alt:"manager_aggregate_my_apply_detail_3"}})]),a._v(" "),e("p",[a._v("重新选择审核人后点击 确定 按钮,修改审核人完成。")]),a._v(" "),e("p",[a._v("修改后原审核人会收到邮件提醒无须再处理该申请。")]),a._v(" "),e("p",[a._v("修改后新的审核人会收到邮件提醒需要处理该申请。")]),a._v(" "),e("p",[a._v("审核通过后可以对接口进行发布操作,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_my_apply_detail_4.png",alt:"manager_aggregate_my_apply_detail_4"}})]),a._v(" "),e("p",[a._v("批量发布:对申请内的接口批量发布推送到Fizz网关。")]),a._v(" "),e("p",[a._v("批量回滚:对申请内的接口批量回滚到上一个版本,当发布后接口异常时该操作相当有用。")]),a._v(" "),e("p",[a._v("对于申请通过后又无须操作的接口可以执行撤回操作,撤回接口时必须填写备注信息用于回溯查询,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_my_apply_detail_5.png",alt:"manager_aggregate_my_apply_detail_5"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_my_apply_detail_6.png",alt:"manager_aggregate_my_apply_detail_6"}})])])}),[],!1,null,null,null);_.default=g.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/18.91abb322.js b/docs/assets/js/18.91abb322.js new file mode 100644 index 0000000..2cbb4cb --- /dev/null +++ b/docs/assets/js/18.91abb322.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[18],{366:function(a,t,e){"use strict";e.r(t);var _=e(42),r=Object(_.a)({},(function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h2",{attrs:{id:"概述"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[a._v("#")]),a._v(" 概述")]),a._v(" "),e("p",[a._v("管理后台记录了聚合接口的新增、修改、发布、下线、回滚、删除操作日志,通过查看操作日志可以清楚地掌握接口的操作轨迹。操作日志功能提供界面查询聚合接口的操作日志。")]),a._v(" "),e("h2",{attrs:{id:"操作日志列表"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#操作日志列表"}},[a._v("#")]),a._v(" 操作日志列表")]),a._v(" "),e("p",[a._v("菜单位置:服务编排 > 操作日志。点击菜单后进入操作日志列表页面,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_op_log_list_query.png",alt:"manager_aggregate_op_log_list_query"}})]),a._v(" "),e("h2",{attrs:{id:"查看日志详情"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#查看日志详情"}},[a._v("#")]),a._v(" 查看日志详情")]),a._v(" "),e("p",[a._v("点击 查看 按钮弹出操作日志详情页面,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_op_log_detail_1.png",alt:"manager_aggregate_op_log_detail_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_op_log_detail_2.png",alt:"manager_aggregate_op_log_detail_2"}})])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/19.a05f9317.js b/docs/assets/js/19.a05f9317.js new file mode 100644 index 0000000..fefe63e --- /dev/null +++ b/docs/assets/js/19.a05f9317.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{361:function(a,t,_){"use strict";_.r(t);var r=_(42),e=Object(r.a)({},(function(){var a=this,t=a.$createElement,_=a._self._c||t;return _("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[_("h2",{attrs:{id:"概述"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[a._v("#")]),a._v(" 概述")]),a._v(" "),_("p",[a._v("路由管理功能用于维护网关的路由规则,支持按请求路径转发、转发到指定后端服务两种转发规则,支持插件配置。下面介绍路由管理的操作。")]),a._v(" "),_("h2",{attrs:{id:"路由列表"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#路由列表"}},[a._v("#")]),a._v(" 路由列表")]),a._v(" "),_("p",[a._v("菜单位置:网关管理 > 路由管理。点击菜单后进入路由列表页面,如图所示。")]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_api_auth_list_query.png",alt:"manager_api_auth_list_query"}})]),a._v(" "),_("h2",{attrs:{id:"新增路由"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#新增路由"}},[a._v("#")]),a._v(" 新增路由")]),a._v(" "),_("p",[a._v("点击 新增 按钮弹出新增窗口,如图所示。")]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_api_auth_add_1.png",alt:"manager_api_auth_add_1"}})]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_api_auth_add_2.png",alt:"manager_api_auth_add_2"}})]),a._v(" "),_("p",[a._v("网关分组:选取路由关联的网关分组,只有属于所选分组的网关实例路由规则才会生效,必选;")]),a._v(" "),_("p",[a._v("服务:网关的请求路径格式为 http://{ip}:{port}/proxy/{service}{apiPath},服务对应{service}段,当 转发 选择 按请求路径转发 时服务需要是聚合配置的服务或者是Eureka注册的服务,当 转发 选择 转发到指定后端服务 时服务不需要是实际存在的服务,只用于路径匹配使用,长度不能超过50个字符,必填;")]),a._v(" "),_("p",[a._v("API方法:请求的method类型,可选GET|POST;")]),a._v(" "),_("p",[a._v('API Path:网关的请求路径格式为 http://{ip}:{port}/proxy/{service}{apiPath},API Path对应{apiPath}段,使用前缀匹配原则,例如"/api/"将匹配"/api/"、"/api/1"、"/api/1/1"等路径;')]),a._v(" "),_("p",[a._v("应用:选取路由关联的应用,网关使用选取应用的信息进行鉴权,更多详情请查看appID管理功能介绍;")]),a._v(" "),_("p",[a._v("访问:可选允许|禁止,必选;")]),a._v(" "),_("p",[a._v("转发:可选按请求路径转发|转发到指定后端服务,当选择 按请求路径转发 时,请求会按请求路径转发,例如网关请求 http://{ip}:{port}/proxy/my-service/api-path 将转发到 http://my-service/api-path;当选择 转发到指定后端服务 时,需要添加转发到的后端服务URL,请求会转发到配置的后端服务,例如配置了服务为 my-service,API Path为空,后端服务URL为 http://127.0.0.1:8080/forward-service/,网关请求 http://{ip}:{port}/proxy/my-service/api-path 将转发到 http://127.0.0.1:8080/forward-service/api-path。")]),a._v(" "),_("p",[a._v("点击 添加插件 按钮为路由添加插件,如图所示。")]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_api_auth_add_3.png",alt:"manager_api_auth_add_3"}})]),a._v(" "),_("p",[a._v("配置插件路由级别的自定义配置,表单界面来自于插件的表单定义,更多详情请查看插件管理功能介绍。")]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_api_auth_add_4.png",alt:"manager_api_auth_add_4"}})]),a._v(" "),_("p",[a._v("配置完成后点击 保存 按钮保存路由规则。")]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_api_auth_add_5.png",alt:"manager_api_auth_add_5"}})]),a._v(" "),_("h2",{attrs:{id:"编辑路由"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#编辑路由"}},[a._v("#")]),a._v(" 编辑路由")]),a._v(" "),_("p",[a._v("点击 编辑 按钮弹出编辑窗口,如图所示。")]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_api_auth_edit_1.png",alt:"manager_api_auth_edit_1"}})]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_api_auth_edit_2.png",alt:"manager_api_auth_edit_2"}})]),a._v(" "),_("h2",{attrs:{id:"删除路由"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#删除路由"}},[a._v("#")]),a._v(" 删除路由")]),a._v(" "),_("p",[a._v("点击 删除 按钮弹出删除确认窗口,如图所示。")]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_api_auth_delete_1.png",alt:"manager_api_auth_delete_1"}})]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_api_auth_delete_2.png",alt:"manager_api_auth_delete_2"}})])])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/20.e44fcf7d.js b/docs/assets/js/20.e44fcf7d.js new file mode 100644 index 0000000..efe45fd --- /dev/null +++ b/docs/assets/js/20.e44fcf7d.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[20],{362:function(a,_,p){"use strict";p.r(_);var t=p(42),e=Object(t.a)({},(function(){var a=this,_=a.$createElement,p=a._self._c||_;return p("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[p("h2",{attrs:{id:"概述"}},[p("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[a._v("#")]),a._v(" 概述")]),a._v(" "),p("p",[a._v("appID管理功能维护应用鉴权信息,可配置是否启用签名、是否启用IP白名单,AppID级别的自定义配置供自定义插件使用。appID用于在路由管理配置中关联路由规则,当对应路由规则触发时会对应用进行鉴权。")]),a._v(" "),p("h2",{attrs:{id:"appid列表"}},[p("a",{staticClass:"header-anchor",attrs:{href:"#appid列表"}},[a._v("#")]),a._v(" appID列表")]),a._v(" "),p("p",[a._v("菜单位置:网关管理 > appID管理。点击菜单后进入appID列表页面,如图所示。")]),a._v(" "),p("p",[p("img",{attrs:{src:"/fizz-gateway-community/manager_app_id_list_query.png",alt:"manager_app_id_list_query"}})]),a._v(" "),p("h2",{attrs:{id:"新增appid"}},[p("a",{staticClass:"header-anchor",attrs:{href:"#新增appid"}},[a._v("#")]),a._v(" 新增appID")]),a._v(" "),p("p",[a._v("点击 新增 按钮弹出新增窗口,如图所示。")]),a._v(" "),p("p",[p("img",{attrs:{src:"/fizz-gateway-community/manager_app_id_add_1.png",alt:"manager_app_id_add_1"}})]),a._v(" "),p("p",[p("img",{attrs:{src:"/fizz-gateway-community/manager_app_id_add_2.png",alt:"manager_app_id_add_2"}})]),a._v(" "),p("p",[a._v("appID:第三方应用唯一标识,长度不能超过64个字符,必填;")]),a._v(" "),p("p",[a._v("应用名:第三方应用名称,长度不能超过128个字符,必填;")]),a._v(" "),p("p",[a._v("是否启用签名:当启动时必须配置 认证方式 和 密钥;")]),a._v(" "),p("p",[a._v("认证方式:可选 密钥(使用网关内置鉴权方式验证)|自定义认证插件(使用自定义的鉴权逻辑),更多信息请查看Fizz网关的介绍;启用签名时必填;")]),a._v(" "),p("p",[a._v("密钥:第三方应用使用的密钥,可通过 生成随机密钥 按钮生成一个随机的密钥,启用签名时必填;")]),a._v(" "),p("p",[a._v("是否启用IP白名单:当启用时可以配置 IP白名单,网关会根据请求来源IP地址进行过滤;")]),a._v(" "),p("p",[a._v("IP白名单:IP段支持 1.2.3.100-120 和 1.2.3.*两种格式,仅最后一段可用范围或星号表示;")]),a._v(" "),p("p",[a._v("自定义配置:AppID级别的自定义配置供自定义插件使用,所有插件均可获取到此配置信息。")]),a._v(" "),p("h2",{attrs:{id:"编辑appid"}},[p("a",{staticClass:"header-anchor",attrs:{href:"#编辑appid"}},[a._v("#")]),a._v(" 编辑appID")]),a._v(" "),p("p",[a._v("点击 编辑 按钮弹出编辑窗口,如图所示。")]),a._v(" "),p("p",[p("img",{attrs:{src:"/fizz-gateway-community/manager_app_id_edit_1.png",alt:"manager_app_id_edit_1"}})]),a._v(" "),p("p",[p("img",{attrs:{src:"/fizz-gateway-community/manager_app_id_edit_2.png",alt:"manager_app_id_edit_2"}})]),a._v(" "),p("h2",{attrs:{id:"删除appid"}},[p("a",{staticClass:"header-anchor",attrs:{href:"#删除appid"}},[a._v("#")]),a._v(" 删除appID")]),a._v(" "),p("p",[a._v("点击 删除 按钮弹出删除确认窗口,如图所示。")]),a._v(" "),p("p",[p("img",{attrs:{src:"/fizz-gateway-community/manager_app_id_delete_1.png",alt:"manager_app_id_delete_1"}})]),a._v(" "),p("p",[p("img",{attrs:{src:"/fizz-gateway-community/manager_app_id_delete_2.png",alt:"manager_app_id_delete_2"}})]),a._v(" "),p("p",[a._v("点击 确定 按钮后删除appID,如果appID存在关联的路由配置时,对应关联的路由配置也会一起删除。")])])}),[],!1,null,null,null);_.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/21.8859e956.js b/docs/assets/js/21.8859e956.js new file mode 100644 index 0000000..01c49f2 --- /dev/null +++ b/docs/assets/js/21.8859e956.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[21],{363:function(a,t,e){"use strict";e.r(t);var _=e(42),r=Object(_.a)({},(function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h2",{attrs:{id:"概述"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[a._v("#")]),a._v(" 概述")]),a._v(" "),e("p",[a._v("网关缓存功能用于查询Fizz网关实例本地缓存的已发布接口信息,可以快速的了解当前网关实例生效的全部接口,同时通过查看后台接口发布版本号与网关实例本地缓存的接口版本号是否一致可以排查接口缓存问题,下面介绍网关缓存功能的操作。")]),a._v(" "),e("h2",{attrs:{id:"网关列表"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#网关列表"}},[a._v("#")]),a._v(" 网关列表")]),a._v(" "),e("p",[a._v("菜单位置:服务编排 > 网关缓存。点击菜单后进入网关列表页面,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_gateway_list_query.png",alt:"manager_aggregate_gateway_list_query"}})]),a._v(" "),e("p",[a._v("Fizz网关与后台注册到同一个eureka注册中心,后台通过eureka获取网关的实例列表。")]),a._v(" "),e("h2",{attrs:{id:"网关缓存列表"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#网关缓存列表"}},[a._v("#")]),a._v(" 网关缓存列表")]),a._v(" "),e("p",[a._v("点击 查看 按钮后弹出网关详情页面,该页面显示所选网关实例的接口缓存列表,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_gateway_cache_list_query_1.png",alt:"manager_aggregate_gateway_cache_list_query_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_gateway_cache_list_query_2.png",alt:"manager_aggregate_gateway_cache_list_query_2"}})]),a._v(" "),e("h2",{attrs:{id:"网关缓存详情"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#网关缓存详情"}},[a._v("#")]),a._v(" 网关缓存详情")]),a._v(" "),e("p",[a._v("点击 查看 按钮弹出所选接口的配置详情,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_gateway_cache_detail_1.png",alt:"manager_aggregate_gateway_cache_detail_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_aggregate_gateway_cache_detail_2.png",alt:"manager_aggregate_gateway_cache_detail_2"}})])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/22.69bbe610.js b/docs/assets/js/22.69bbe610.js new file mode 100644 index 0000000..9198f86 --- /dev/null +++ b/docs/assets/js/22.69bbe610.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[22],{364:function(a,t,_){"use strict";_.r(t);var r=_(42),e=Object(r.a)({},(function(){var a=this,t=a.$createElement,_=a._self._c||t;return _("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[_("h2",{attrs:{id:"概述"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[a._v("#")]),a._v(" 概述")]),a._v(" "),_("p",[a._v("网关分组功能用于维护分组元数据,将网关实例IP与分组关联,通过为不同的分组配置不同的路由策略,从而实现网关的分组管理。")]),a._v(" "),_("h2",{attrs:{id:"分组示例"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#分组示例"}},[a._v("#")]),a._v(" 分组示例")]),a._v(" "),_("p",[a._v("我们的线上业务涉及To C(个人用户)、To B(企业)、To T(第三方),对于不同业务会有对应的机器接受请求访问,不同的业务需要有各自的路由策略,因此进行了如下的分组划分。")]),a._v(" "),_("table",[_("thead",[_("tr",[_("th",[a._v("分组ID")]),a._v(" "),_("th",[a._v("分组名称")]),a._v(" "),_("th",[a._v("描述")])])]),a._v(" "),_("tbody",[_("tr",[_("td",[a._v("default")]),a._v(" "),_("td",[a._v("默认分组")]),a._v(" "),_("td",[a._v("默认分组是后台默认创建的分组,不用指定IP,不属于其它分组的机器都归到默认分组,默认分组不可修改或删除")])]),a._v(" "),_("tr",[_("td",[a._v("c")]),a._v(" "),_("td",[a._v("2c分组")]),a._v(" "),_("td",[a._v("只接受面向个人用户的请求")])]),a._v(" "),_("tr",[_("td",[a._v("b")]),a._v(" "),_("td",[a._v("2b分组")]),a._v(" "),_("td",[a._v("只接受面向企业的请求")])]),a._v(" "),_("tr",[_("td",[a._v("t")]),a._v(" "),_("td",[a._v("面向第三方的分组")]),a._v(" "),_("td",[a._v("只接受面向第三方的请求")])])])]),a._v(" "),_("p",[a._v("下面介绍网关分组功能的操作。")]),a._v(" "),_("h2",{attrs:{id:"分组列表"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#分组列表"}},[a._v("#")]),a._v(" 分组列表")]),a._v(" "),_("p",[a._v("菜单位置:网关管理 > 网关分组。点击菜单后进入分组列表页面,如图所示。")]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_gateway_group_list_query.png",alt:"manager_gateway_group_list_query"}})]),a._v(" "),_("h2",{attrs:{id:"新增分组"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#新增分组"}},[a._v("#")]),a._v(" 新增分组")]),a._v(" "),_("p",[a._v("点击 新增 按钮弹出新增窗口,如图所示。")]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_gateway_group_add_1.png",alt:"manager_gateway_group_add_1"}})]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_gateway_group_add_2.png",alt:"manager_gateway_group_add_2"}})]),a._v(" "),_("p",[a._v("分组ID:分组的唯一标识,长度不能超过32个字符,必填;")]),a._v(" "),_("p",[a._v("分组名称:分组的名称,用于在分组选项时展示,长度不能超过32个字符,必填;")]),a._v(" "),_("p",[a._v("网关实例IP:Fizz网关集群内的机器IP地址,多个IP地址使用逗号分隔。")]),a._v(" "),_("h2",{attrs:{id:"编辑分组"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#编辑分组"}},[a._v("#")]),a._v(" 编辑分组")]),a._v(" "),_("p",[a._v("点击 编辑 按钮弹出编辑窗口,如图所示。")]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_gateway_group_edit_1.png",alt:"manager_gateway_group_edit_1"}})]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_gateway_group_edit_2.png",alt:"manager_gateway_group_edit_2"}})]),a._v(" "),_("h2",{attrs:{id:"删除分组"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#删除分组"}},[a._v("#")]),a._v(" 删除分组")]),a._v(" "),_("p",[a._v("点击 删除 按钮弹出删除确认窗口,如图所示。")]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_gateway_group_delete_1.png",alt:"manager_gateway_group_delete_1"}})]),a._v(" "),_("p",[_("img",{attrs:{src:"/fizz-gateway-community/manager_gateway_group_delete_2.png",alt:"manager_gateway_group_delete_2"}})]),a._v(" "),_("p",[a._v("点击 确定 按钮后删除网关分组,如果网关分组存在关联的路由配置时,需要将关联的路由配置全部删除后才能删除分组。")])])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/23.d558c8c3.js b/docs/assets/js/23.d558c8c3.js new file mode 100644 index 0000000..b103d0e --- /dev/null +++ b/docs/assets/js/23.d558c8c3.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{365:function(v,_,i){"use strict";i.r(_);var a=i(42),t=Object(a.a)({},(function(){var v=this,_=v.$createElement,i=v._self._c||_;return i("ContentSlotsDistributor",{attrs:{"slot-key":v.$parent.slotKey}},[i("h2",{attrs:{id:"概述"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[v._v("#")]),v._v(" 概述")]),v._v(" "),i("p",[v._v("Fizz管理后台是Fizz网关的配套系统,基于Java、Vue开发,通过界面对Fizz网关集群进行各项配置。")]),v._v(" "),i("h2",{attrs:{id:"功能"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#功能"}},[v._v("#")]),v._v(" 功能")]),v._v(" "),i("p",[v._v("Fizz管理后台包含如下功能:")]),v._v(" "),i("ul",[i("li",[v._v("网关管理\n"),i("ul",[i("li",[v._v("网关分组:对Fizz网关集群内的机器进行逻辑上的分组,针对不同的分组可配置不同的路由策略。")]),v._v(" "),i("li",[v._v("插件管理:维护插件元数据,定义路由级别的自定义属性、插件级别的自定义配置信息。")]),v._v(" "),i("li",[v._v("appID管理:配置应用鉴权信息,可配置是否启用签名、是否启用IP白名单,AppID级别的自定义配置供自定义插件使用。")]),v._v(" "),i("li",[v._v("路由管理:配置服务或API路由规则,支持按请求路径转发、转发到指定后端服务两种转发规则,支持插件配置。")]),v._v(" "),i("li",[v._v("接口统计:Fizz网关接口访问统计功能,以图表的形式展示指定时间段内每日的接口总数、访问次数,可查看接口的历史访问总次数以及最近请求时间。")])])]),v._v(" "),i("li",[v._v("服务编排\n"),i("ul",[i("li",[v._v("服务管理:聚合接口归属于服务,服务通过该功能维护,创建人自动获得服务权限,服务权限可分配,拥有权限的用户才能操作对应的接口列表。")]),v._v(" "),i("li",[v._v("接口列表:基于现有的业务微服务使用在线配置的方式快速的生成一个聚合接口,同时提供在线测试功能,发布历史版本查看。")]),v._v(" "),i("li",[v._v("操作日志:查看聚合接口的新增、修改、发布、下线、回滚、删除操作日志。")]),v._v(" "),i("li",[v._v("网关缓存:查看Fizz网关当前在线的实例列表以及对应实例本地缓存的已发布接口信息。")])])]),v._v(" "),i("li",[v._v("发布申请\n"),i("ul",[i("li",[v._v("我的申请:提交接口发布|下线申请,审核通过后可以对相关接口执行发布|下线操作。")]),v._v(" "),i("li",[v._v("待审核:审核发布|下线申请。")]),v._v(" "),i("li",[v._v("审核日志:查看审核发布|下线申请操作日志。")])])]),v._v(" "),i("li",[v._v("权限管理\n"),i("ul",[i("li",[v._v("角色管理:维护角色数据,为角色分配权限。")])])]),v._v(" "),i("li",[v._v("系统管理\n"),i("ul",[i("li",[v._v("用户管理:维护用户数据,为用户分配角色。")])])])]),v._v(" "),i("h2",{attrs:{id:"界面"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#界面"}},[v._v("#")]),v._v(" 界面")]),v._v(" "),i("p",[i("img",{attrs:{src:"/fizz-gateway-community/manager_overview_1.png",alt:"manager_overview_1"}})]),v._v(" "),i("p",[i("img",{attrs:{src:"/fizz-gateway-community/manager_overview_2.png",alt:"manager_overview_2"}})])])}),[],!1,null,null,null);_.default=t.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/24.90d6ddb8.js b/docs/assets/js/24.90d6ddb8.js new file mode 100644 index 0000000..10dec7b --- /dev/null +++ b/docs/assets/js/24.90d6ddb8.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{367:function(t,s,a){"use strict";a.r(s);var n=a(42),r=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h2",{attrs:{id:"概述"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[t._v("#")]),t._v(" 概述")]),t._v(" "),a("p",[t._v("插件管理功能用于维护插件元数据,定义路由级别的自定义属性、插件级别的自定义配置信息。创建的插件用于路由管理设置时启用,当网关接受请求匹配路由规则时会触发启用的插件逻辑执行,插件逻辑中可获取到自定义的属性数据。")]),t._v(" "),a("h2",{attrs:{id:"插件列表"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#插件列表"}},[t._v("#")]),t._v(" 插件列表")]),t._v(" "),a("p",[t._v("菜单位置:网关管理 > 插件管理。点击菜单后进入插件管理列表页面,如图所示。")]),t._v(" "),a("p",[a("img",{attrs:{src:"/fizz-gateway-community/manager_plugin_list_query.png",alt:"manager_plugin_list_query"}})]),t._v(" "),a("h2",{attrs:{id:"新增插件"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#新增插件"}},[t._v("#")]),t._v(" 新增插件")]),t._v(" "),a("p",[t._v("点击 新增 按钮弹出新增窗口,如图所示。")]),t._v(" "),a("p",[a("img",{attrs:{src:"/fizz-gateway-community/manager_plugin_add_1.png",alt:"manager_plugin_add_1"}})]),t._v(" "),a("p",[a("img",{attrs:{src:"/fizz-gateway-community/manager_plugin_add_2.png",alt:"manager_plugin_add_2"}})]),t._v(" "),a("p",[t._v("插件名称:插件名称由英文字母、下划线或数字组成,不能以数字开头,长度不能超过50个字符,必填;")]),t._v(" "),a("p",[t._v("插件描述:插件的简要描述,长度不能超过50个字符,必填;")]),t._v(" "),a("p",[t._v("默认执行顺序:插件的默认执行顺序,按从小到大排序,值越小越先执行,取值范围0~255,必填;")]),t._v(" "),a("p",[t._v("表单定义:路由级别的自定义属性,在路由管理配置启用插件时前端会将表单定义转化为表单输入界面,更多信息请查看路由管理介绍。表单规范说明如下:")]),t._v(" "),a("div",{staticClass:"language-javascript extra-class"},[a("pre",{pre:!0,attrs:{class:"language-javascript"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*\n* plugin_config_design\n* 动态插件参考结构\n* */")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" pluginConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 必有字段 */")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"field"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"inputVal"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"输入框"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"component"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"input"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// input, select, radio, checkbox,")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"dataType"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// number(long, double), string, boolean, array")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 可选字段 */")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"desc"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"字段的说明文字"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"placeholder"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"placeholder文字"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"default"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Aa123"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 初始默认值")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"options"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// for select, radio, checkbox")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"选项1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// number(long, double), string, boolean,")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"选项2"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"rules"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// min|max / range / length / regex pattern")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"message"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"输入框不能为空"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"trigger"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"change"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// required 必填")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// { "min": 3, "ma x": 5, "message": "长度在 3 到 5 个字符", "trigger": "change" }, // range 长度范围(for dataType:"string")')]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// { "len": 8, "message": "长度需 8 个字符", "trigger": "change" }, // length 长度限制(for dataType:"string")')]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// { "type": "number", "message": "请输入数字类型"}, // for dataType:"number" 校验数值')]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// { "type": "integer", "message": "请输入整数数值", "trigger": "change" }, // for dataType:"long" 校验整数')]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// { "type": "float", "message": "请输入浮点数数值", "trigger": "change" }, // for dataType:"double" 校验浮点数')]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"pattern"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"^[A-Za-z\\\\d]+$"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"message"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"只能是字母或数字"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"trigger"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"change"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// regex pattern正则")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"field"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"selectVal"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"选择器"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"component"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"select"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"dataType"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"number"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"options"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"选项1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"选项2"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"选项3"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"desc"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"选择器的说明文字"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"placeholder"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"请选择"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"rules"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"message"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"选择器不能为空"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"trigger"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"change"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"field"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"radioVal"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"单选框"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"component"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"radio"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"dataType"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"boolean"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"default"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"options"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"是"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"否"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"desc"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"单选框的说明文字"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"rules"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"message"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"请选择单选框"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"trigger"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"change"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"field"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"checkboxVal"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"多选框"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"component"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"checkbox"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"dataType"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"array"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"options"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"选项1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("11")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"选项2"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("22")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"选项3"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("33")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"desc"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"多选框的说明文字"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"rules"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"message"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"请选择多选框"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"trigger"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"change"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// TODO 注意!!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// 组件 "checkbox" 的dataType = "array"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// 组件 "radio/select" 的实际值类型等于options内的value值类型')]),t._v("\n")])])]),a("p",[t._v("自定义配置:插件级别的自定义配置信息,插件逻辑中可获取到该信息。")]),t._v(" "),a("h2",{attrs:{id:"编辑插件"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#编辑插件"}},[t._v("#")]),t._v(" 编辑插件")]),t._v(" "),a("p",[t._v("点击 编辑 按钮弹出编辑窗口,如图所示。")]),t._v(" "),a("p",[a("img",{attrs:{src:"/fizz-gateway-community/manager_plugin_edit_1.png",alt:"manager_plugin_edit_1"}})]),t._v(" "),a("p",[a("img",{attrs:{src:"/fizz-gateway-community/manager_plugin_edit_2.png",alt:"manager_plugin_edit_2"}})]),t._v(" "),a("h2",{attrs:{id:"删除插件"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#删除插件"}},[t._v("#")]),t._v(" 删除插件")]),t._v(" "),a("p",[t._v("点击 删除 按钮弹出删除确认窗口,如图所示。")]),t._v(" "),a("p",[a("img",{attrs:{src:"/fizz-gateway-community/manager_plugin_delete_1.png",alt:"manager_plugin_delete_1"}})]),t._v(" "),a("p",[a("img",{attrs:{src:"/fizz-gateway-community/manager_plugin_delete_2.png",alt:"manager_plugin_delete_2"}})]),t._v(" "),a("p",[t._v("点击 确定 按钮后删除插件,如果插件存在关联的路由配置时,需要将关联的路由配置全部删除后才能删除插件。")])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/25.0f5aa895.js b/docs/assets/js/25.0f5aa895.js new file mode 100644 index 0000000..0428327 --- /dev/null +++ b/docs/assets/js/25.0f5aa895.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{369:function(a,t,r){"use strict";r.r(t);var _=r(42),e=Object(_.a)({},(function(){var a=this,t=a.$createElement,r=a._self._c||t;return r("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[r("h2",{attrs:{id:"概述"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[a._v("#")]),a._v(" 概述")]),a._v(" "),r("p",[a._v("角色管理功能维护角色元数据,通过配置角色拥有的菜单资源,限制用户只能操作拥有的角色对应的菜单资源,下面介绍角色管理功能的操作。")]),a._v(" "),r("h2",{attrs:{id:"角色列表"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#角色列表"}},[a._v("#")]),a._v(" 角色列表")]),a._v(" "),r("p",[a._v("菜单位置:权限管理 > 角色管理。点击菜单后进入角色列表页面,如图所示。")]),a._v(" "),r("p",[r("img",{attrs:{src:"/fizz-gateway-community/manager_role_list_query.png",alt:"manager_role_list_query"}})]),a._v(" "),r("h2",{attrs:{id:"添加角色"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#添加角色"}},[a._v("#")]),a._v(" 添加角色")]),a._v(" "),r("p",[a._v("点击 新增 按钮弹出新增窗口,如图所示。")]),a._v(" "),r("p",[r("img",{attrs:{src:"/fizz-gateway-community/manager_role_add_1.png",alt:"manager_role_add_1"}})]),a._v(" "),r("p",[r("img",{attrs:{src:"/fizz-gateway-community/manager_role_add_2.png",alt:"manager_role_add_2"}})]),a._v(" "),r("h2",{attrs:{id:"权限设置"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#权限设置"}},[a._v("#")]),a._v(" 权限设置")]),a._v(" "),r("p",[a._v("勾选需要分配权限的角色,点击 权限设置 按钮弹出角色权限配置窗口,如图所示。")]),a._v(" "),r("p",[r("img",{attrs:{src:"/fizz-gateway-community/manager_role_auth_1.png",alt:"manager_role_auth_1"}})]),a._v(" "),r("p",[r("img",{attrs:{src:"/fizz-gateway-community/manager_role_auth_2.png",alt:"manager_role_auth_2"}})]),a._v(" "),r("p",[a._v("勾选菜单后点击 确定 按钮确认给角色分配菜单权限。")]),a._v(" "),r("h2",{attrs:{id:"编辑角色"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#编辑角色"}},[a._v("#")]),a._v(" 编辑角色")]),a._v(" "),r("p",[a._v("点击 编辑 按钮弹出编辑窗口,如图所示。")]),a._v(" "),r("p",[r("img",{attrs:{src:"/fizz-gateway-community/manager_role_edit_1.png",alt:"manager_role_edit_1"}})]),a._v(" "),r("p",[r("img",{attrs:{src:"/fizz-gateway-community/manager_role_edit_2.png",alt:"manager_role_edit_2"}})]),a._v(" "),r("h2",{attrs:{id:"删除角色"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#删除角色"}},[a._v("#")]),a._v(" 删除角色")]),a._v(" "),r("p",[a._v("点击 删除 按钮弹出删除确认窗口,如图所示。")]),a._v(" "),r("p",[r("img",{attrs:{src:"/fizz-gateway-community/manager_role_delete_1.png",alt:"manager_role_delete_1"}})]),a._v(" "),r("p",[r("img",{attrs:{src:"/fizz-gateway-community/manager_role_delete_2.png",alt:"manager_role_delete_2"}})]),a._v(" "),r("p",[a._v("点击 确定 按钮后删除角色。")])])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/26.48d84783.js b/docs/assets/js/26.48d84783.js new file mode 100644 index 0000000..8148b3c --- /dev/null +++ b/docs/assets/js/26.48d84783.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[26],{368:function(a,t,e){"use strict";e.r(t);var _=e(42),r=Object(_.a)({},(function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h2",{attrs:{id:"概述"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[a._v("#")]),a._v(" 概述")]),a._v(" "),e("p",[a._v("服务管理功能维护服务元数据。服务编排中的服务是一个逻辑上的概念,用于对聚合接口的归类以及权限的分配。Fizz网关聚合接口的请求路径格式为 http://{ip}:{port}/proxy/{service}{apiPath},服务对应{service}段。")]),a._v(" "),e("h2",{attrs:{id:"服务列表"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#服务列表"}},[a._v("#")]),a._v(" 服务列表")]),a._v(" "),e("p",[a._v("菜单位置:服务编排 > 服务管理。点击菜单后进入服务列表页面,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_service_list_query.png",alt:"manager_service_list_query"}})]),a._v(" "),e("h2",{attrs:{id:"新增服务"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#新增服务"}},[a._v("#")]),a._v(" 新增服务")]),a._v(" "),e("p",[a._v("点击 新增 按钮弹出新增窗口,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_service_add_1.png",alt:"manager_service_add_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_service_add_2.png",alt:"manager_service_add_2"}})]),a._v(" "),e("p",[a._v("服务 ID:服务唯一标识,对应Fizz网关聚合接口请求路径(格式为 http://{ip}:{port}/proxy/{service}{apiPath})的{service}段,长度不能超过200个字符,必填;")]),a._v(" "),e("p",[a._v("服务名:服务名称,用于展示或者选项使用,必填;")]),a._v(" "),e("p",[a._v("团队:团队名称,长度不能超过200个字符;")]),a._v(" "),e("p",[a._v("负责人:负责人名称,长度不能超过200个字符;")]),a._v(" "),e("p",[a._v("描述:服务描述,长度不能超过2000个字符。")]),a._v(" "),e("h2",{attrs:{id:"编辑服务"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#编辑服务"}},[a._v("#")]),a._v(" 编辑服务")]),a._v(" "),e("p",[a._v("点击 编辑 按钮弹出编辑窗口,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_service_edit_1.png",alt:"manager_service_edit_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_service_edit_2.png",alt:"manager_service_edit_2"}})]),a._v(" "),e("h2",{attrs:{id:"删除服务"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#删除服务"}},[a._v("#")]),a._v(" 删除服务")]),a._v(" "),e("p",[a._v("点击 删除 按钮弹出删除确认窗口,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_service_delete_1.png",alt:"manager_service_delete_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_service_delete_2.png",alt:"manager_service_delete_2"}})]),a._v(" "),e("p",[a._v("点击 确定 按钮后删除服务,如果服务存在关联的聚合接口时,需要将关联的聚合接口全部删除后才能删除服务。")]),a._v(" "),e("h2",{attrs:{id:"服务权限分配"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#服务权限分配"}},[a._v("#")]),a._v(" 服务权限分配")]),a._v(" "),e("p",[a._v("点击 权限 按钮弹出权限配置窗口,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_service_auth_1.png",alt:"manager_service_auth_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_service_auth_2.png",alt:"manager_service_auth_2"}})]),a._v(" "),e("p",[a._v("服务创建人自动获得服务权限,服务权限可分配,拥有权限的用户才能操作对应的接口列表。")])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/27.b9f6747b.js b/docs/assets/js/27.b9f6747b.js new file mode 100644 index 0000000..81b6406 --- /dev/null +++ b/docs/assets/js/27.b9f6747b.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{372:function(t,a,s){"use strict";s.r(a);var _=s(42),r=Object(_.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h2",{attrs:{id:"概述"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[t._v("#")]),t._v(" 概述")]),t._v(" "),s("p",[t._v("Fizz网关会将访问请求数据(IP地址、网关分组、服务、应用、请求方法、API Path、请求时间)推送到Kafka中,管理后台消费Kafka消息统计接口访问数据。")]),t._v(" "),s("p",[t._v("接口统计功能以图表的形式展示指定时间段内每日的接口总数、访问次数,可查看接口的历史访问总次数以及最近请求时间。")]),t._v(" "),s("h2",{attrs:{id:"接口访问统计"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#接口访问统计"}},[t._v("#")]),t._v(" 接口访问统计")]),t._v(" "),s("p",[t._v("菜单位置:网关管理 > 接口统计。点击菜单后进入接口统计页面,如图所示。")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_source_statistics_1.png",alt:"manager_source_statistics_1.png"}})]),t._v(" "),s("p",[t._v("今天接口总数:从0时到当前时刻被调用不同接口的总数;")]),t._v(" "),s("p",[t._v("今天访问次数:从0时到当前时刻访问请求的总次数。")]),t._v(" "),s("p",[t._v("接口总数图表:显示指定时间段内每日被调用不同接口的总数曲线;")]),t._v(" "),s("p",[t._v("访问次数图表:显示指定时间段内每日访问请求的总次数曲线。")]),t._v(" "),s("h2",{attrs:{id:"请求统计"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#请求统计"}},[t._v("#")]),t._v(" 请求统计")]),t._v(" "),s("p",[t._v("接口统计界面下部为请求统计列表,如图所示。")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/manager_source_statistics_2.png",alt:"manager_source_statistics_2.png"}})]),t._v(" "),s("p",[t._v("来源IP:网关请求的实际入口IP地址;")]),t._v(" "),s("p",[t._v("请求次数:( 唯一[来源IP、网关分组、服务名、请求方法、appID、API Path])历史总请求次数;")]),t._v(" "),s("p",[t._v("最近请求时间:( 唯一[来源IP、网关分组、服务名、请求方法、appID、API Path])最近一次调用时间。")])])}),[],!1,null,null,null);a.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/28.79d861a5.js b/docs/assets/js/28.79d861a5.js new file mode 100644 index 0000000..2acfc6e --- /dev/null +++ b/docs/assets/js/28.79d861a5.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[28],{370:function(a,t,e){"use strict";e.r(t);var r=e(42),_=Object(r.a)({},(function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h2",{attrs:{id:"概述"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[a._v("#")]),a._v(" 概述")]),a._v(" "),e("p",[a._v("用户管理功能用于维护用户元数据,包括用户信息维护、密码维护、角色配置。")]),a._v(" "),e("h2",{attrs:{id:"用户列表"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#用户列表"}},[a._v("#")]),a._v(" 用户列表")]),a._v(" "),e("p",[a._v("菜单位置:系统管理 > 用户管理。点击菜单后进入用户列表页面,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_user_list_query.png",alt:"manager_user_list_query"}})]),a._v(" "),e("h2",{attrs:{id:"添加用户"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#添加用户"}},[a._v("#")]),a._v(" 添加用户")]),a._v(" "),e("p",[a._v("点击 新增 按钮弹出新增窗口,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_user_add_1.png",alt:"manager_user_add_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_user_add_2.png",alt:"manager_user_add_2"}})]),a._v(" "),e("p",[a._v("电子邮箱:用户用于接收电子邮件的邮箱地址,后台涉及邮件发送业务使用该字段设置的邮箱地址来进行邮箱发送。")]),a._v(" "),e("h2",{attrs:{id:"重置密码"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#重置密码"}},[a._v("#")]),a._v(" 重置密码")]),a._v(" "),e("p",[a._v("勾选用户后点击 密码重置 按钮可为用户重置密码。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_user_reset_password_1.png",alt:"manager_user_reset_password_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_user_reset_password_2.png",alt:"manager_user_reset_password_2"}})]),a._v(" "),e("p",[a._v("重置后的默认密码为"),e("code",[a._v("AsdF1234!")]),a._v("。")]),a._v(" "),e("h2",{attrs:{id:"编辑用户"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#编辑用户"}},[a._v("#")]),a._v(" 编辑用户")]),a._v(" "),e("p",[a._v("点击 编辑 按钮弹出编辑窗口,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_user_edit_1.png",alt:"manager_user_edit_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_user_edit_2.png",alt:"manager_user_edit_2"}})]),a._v(" "),e("h2",{attrs:{id:"删除用户"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#删除用户"}},[a._v("#")]),a._v(" 删除用户")]),a._v(" "),e("p",[a._v("点击 删除 按钮弹出删除确认窗口,如图所示。")]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_user_delete_1.png",alt:"manager_user_delete_1"}})]),a._v(" "),e("p",[e("img",{attrs:{src:"/fizz-gateway-community/manager_user_delete_2.png",alt:"manager_user_delete_2"}})])])}),[],!1,null,null,null);t.default=_.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/14.a144da4f.js b/docs/assets/js/29.338541e0.js similarity index 99% rename from docs/assets/js/14.a144da4f.js rename to docs/assets/js/29.338541e0.js index 83ae48e..bd151e5 100644 --- a/docs/assets/js/14.a144da4f.js +++ b/docs/assets/js/29.338541e0.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{360:function(t,s,a){"use strict";a.r(s);var n=a(42),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h2",{attrs:{id:"概述"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[t._v("#")]),t._v(" 概述")]),t._v(" "),a("p",[t._v("当需要在gateway中加入自定义的逻辑时,可通过fizz的插件机制实现,插件:"),a("br"),t._v("\n1、类似spring的WebFilter,是fizz内部的WebFilter,由fizz调度;"),a("br"),t._v("\n2、对不同的请求,可配置不同的上下文参数,可通过manager完成配置;"),a("br"),t._v("\n3、若有多个插件,当前插件可获取前面插件的执行结果。")]),t._v(" "),a("p",[t._v("插件的开发和应用,分gateway开发、manager配置两部分,下面以一个例子,依次介绍。")]),t._v(" "),a("h2",{attrs:{id:"gateway开发"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#gateway开发"}},[t._v("#")]),t._v(" gateway开发")]),t._v(" "),a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v(" 实现\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("abstract")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PluginFilter")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("abstract")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mono")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("doFilter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ServerWebExchange")]),t._v(" exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Map")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" fixedConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n 即定义了一个插件。\n \n 比如\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Component")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TestPluginFilter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("TEST_PLUGIN_FILTER"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TestPluginFilter")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PluginFilter")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("static")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Logger")]),t._v(" log "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("LoggerFactory")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getLogger")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TestPluginFilter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("static")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" TEST_PLUGIN_FILTER "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"testPlugin"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mono")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("doFilter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ServerWebExchange")]),t._v(" exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Map")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" fixedConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" rid "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRequest")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getId")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Boolean")]),t._v(" logReqId "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Boolean")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"logReqId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 是否记录请求id日志,可通过manager配置")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("logReqId "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" logReqId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n log"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("info")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRequest")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getURI")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('" 的请求id: "')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" rid"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Boolean")]),t._v(" appendFizzRsv "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Boolean")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"appendFizzRsv"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("appendFizzRsv "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" appendFizzRsv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WebUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("appendHeader")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FIZZ-RSV"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rid"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WebUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("transmitSuccessFilterResultAndEmptyMono")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TEST_PLUGIN_FILTER"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 保存插件执行结果,并返回")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n 这个插件,插件必须是一个spring的"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Component")]),t._v("(或子注解),且要有id,这个插件的id是testPlugin,它实现了两个功能,记录请求id日志,转发请求时添加FIZZ"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("RSV请求头,并且功能是可打开或关闭的。\n \n 另外可通过:\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WebUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getPrevFilterResult")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" 获取上一个插件的执行结果,\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WebUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getFilterResult")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"plugin.id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" 获取已执行的任意一个插件的执行结果。\n")])])]),a("h2",{attrs:{id:"manager配置"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#manager配置"}},[t._v("#")]),t._v(" manager配置")]),t._v(" "),a("p",[t._v("1、定义插件")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[t._v(" 在插件表中,定义上面的插件: \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INSERT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INTO")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("tb_plugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("eng_name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("chn_name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("order")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("VALUES")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'testPlugin'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'测试插件'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'[{\\"field\\":\\"logReqId\\",\\"label\\":\\"打印请求id日志\\",\\"component\\":\\"radio\\",\\"dataType\\":\\"boolean\\",\\"default\\":false,\\"options\\":[{\\"label\\":\\"是\\",\\"value\\":true},{\\"label\\":\\"否\\",\\"value\\":false}]},{\\"field\\":\\"appendFizzRsv\\",\\"label\\":\\"添加fizzRsv请求头\\",\\"component\\":\\"radio\\",\\"dataType\\":\\"boolean\\",\\"default\\":false,\\"options\\":[{\\"label\\":\\"是\\",\\"value\\":true},{\\"label\\":\\"否\\",\\"value\\":false}]}]\'')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("250")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("div",{staticClass:"language-json extra-class"},[a("pre",{pre:!0,attrs:{class:"language-json"}},[a("code",[t._v(" eng_name为插件的id,chn_name为插件中文名,order为插件的执行顺序,也是插件在界面上的显示顺序。\n \n config:\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"field"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"logReqId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"打印请求id日志"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"component"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"radio"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"dataType"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"boolean"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"default"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"options"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"是"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"否"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"field"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"appendFizzRsv"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"添加fizzRsv请求头"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"component"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"radio"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"dataType"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"boolean"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"default"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"options"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"是"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"否"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n 前端据此生成插件的配置表单,具体参前端说明。\n")])])]),a("p",[t._v("2、应用插件")]),t._v(" "),a("p",[t._v("如对\n"),a("img",{attrs:{src:"/fizz-gateway-community/xapi.png",alt:""}})]),t._v(" "),a("p",[t._v("接口应用插件:\n"),a("img",{attrs:{src:"/fizz-gateway-community/test-plugin.png",alt:""}})]),t._v(" "),a("p",[t._v('上面配置的"打印请求id日志"、"添加fizzRsv请求头",对应')]),t._v(" "),a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mono")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("doFilter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ServerWebExchange")]),t._v(" exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Map")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" fixedConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n")])])]),a("p",[t._v("中config的logReqId和appendFizzRsv key。")])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{373:function(t,s,a){"use strict";a.r(s);var n=a(42),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h2",{attrs:{id:"概述"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#概述"}},[t._v("#")]),t._v(" 概述")]),t._v(" "),a("p",[t._v("当需要在gateway中加入自定义的逻辑时,可通过fizz的插件机制实现,插件:"),a("br"),t._v("\n1、类似spring的WebFilter,是fizz内部的WebFilter,由fizz调度;"),a("br"),t._v("\n2、对不同的请求,可配置不同的上下文参数,可通过manager完成配置;"),a("br"),t._v("\n3、若有多个插件,当前插件可获取前面插件的执行结果。")]),t._v(" "),a("p",[t._v("插件的开发和应用,分gateway开发、manager配置两部分,下面以一个例子,依次介绍。")]),t._v(" "),a("h2",{attrs:{id:"gateway开发"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#gateway开发"}},[t._v("#")]),t._v(" gateway开发")]),t._v(" "),a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v(" 实现\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("abstract")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PluginFilter")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("abstract")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mono")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("doFilter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ServerWebExchange")]),t._v(" exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Map")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" fixedConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n 即定义了一个插件。\n \n 比如\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Component")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TestPluginFilter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("TEST_PLUGIN_FILTER"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TestPluginFilter")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PluginFilter")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("static")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Logger")]),t._v(" log "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("LoggerFactory")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getLogger")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TestPluginFilter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("static")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" TEST_PLUGIN_FILTER "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"testPlugin"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mono")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("doFilter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ServerWebExchange")]),t._v(" exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Map")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" fixedConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" rid "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRequest")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getId")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Boolean")]),t._v(" logReqId "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Boolean")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"logReqId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 是否记录请求id日志,可通过manager配置")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("logReqId "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" logReqId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n log"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("info")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRequest")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getURI")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('" 的请求id: "')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" rid"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Boolean")]),t._v(" appendFizzRsv "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Boolean")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"appendFizzRsv"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("appendFizzRsv "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" appendFizzRsv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WebUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("appendHeader")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FIZZ-RSV"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rid"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WebUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("transmitSuccessFilterResultAndEmptyMono")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TEST_PLUGIN_FILTER"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 保存插件执行结果,并返回")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n 这个插件,插件必须是一个spring的"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Component")]),t._v("(或子注解),且要有id,这个插件的id是testPlugin,它实现了两个功能,记录请求id日志,转发请求时添加FIZZ"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("RSV请求头,并且功能是可打开或关闭的。\n \n 另外可通过:\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WebUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getPrevFilterResult")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" 获取上一个插件的执行结果,\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WebUtils")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getFilterResult")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"plugin.id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" 获取已执行的任意一个插件的执行结果。\n")])])]),a("h2",{attrs:{id:"manager配置"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#manager配置"}},[t._v("#")]),t._v(" manager配置")]),t._v(" "),a("p",[t._v("1、定义插件")]),t._v(" "),a("div",{staticClass:"language-sql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-sql"}},[a("code",[t._v(" 在插件表中,定义上面的插件: \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INSERT")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("INTO")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("tb_plugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("eng_name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("chn_name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("order")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("`")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("VALUES")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'testPlugin'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'测试插件'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'[{\\"field\\":\\"logReqId\\",\\"label\\":\\"打印请求id日志\\",\\"component\\":\\"radio\\",\\"dataType\\":\\"boolean\\",\\"default\\":false,\\"options\\":[{\\"label\\":\\"是\\",\\"value\\":true},{\\"label\\":\\"否\\",\\"value\\":false}]},{\\"field\\":\\"appendFizzRsv\\",\\"label\\":\\"添加fizzRsv请求头\\",\\"component\\":\\"radio\\",\\"dataType\\":\\"boolean\\",\\"default\\":false,\\"options\\":[{\\"label\\":\\"是\\",\\"value\\":true},{\\"label\\":\\"否\\",\\"value\\":false}]}]\'')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("250")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("div",{staticClass:"language-json extra-class"},[a("pre",{pre:!0,attrs:{class:"language-json"}},[a("code",[t._v(" eng_name为插件的id,chn_name为插件中文名,order为插件的执行顺序,也是插件在界面上的显示顺序。\n \n config:\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"field"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"logReqId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"打印请求id日志"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"component"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"radio"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"dataType"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"boolean"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"default"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"options"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"是"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"否"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"field"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"appendFizzRsv"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"添加fizzRsv请求头"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"component"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"radio"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"dataType"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"boolean"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"default"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"options"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"是"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"否"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"value"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n 前端据此生成插件的配置表单,具体参前端说明。\n")])])]),a("p",[t._v("2、应用插件")]),t._v(" "),a("p",[t._v("如对\n"),a("img",{attrs:{src:"/fizz-gateway-community/xapi.png",alt:""}})]),t._v(" "),a("p",[t._v("接口应用插件:\n"),a("img",{attrs:{src:"/fizz-gateway-community/test-plugin.png",alt:""}})]),t._v(" "),a("p",[t._v('上面配置的"打印请求id日志"、"添加fizzRsv请求头",对应')]),t._v(" "),a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mono")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("doFilter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ServerWebExchange")]),t._v(" exchange"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Map")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Object")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" fixedConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n")])])]),a("p",[t._v("中config的logReqId和appendFizzRsv key。")])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/3.c15b449a.js b/docs/assets/js/3.a51774e3.js similarity index 87% rename from docs/assets/js/3.c15b449a.js rename to docs/assets/js/3.a51774e3.js index 30cbe80..231bae9 100644 --- a/docs/assets/js/3.c15b449a.js +++ b/docs/assets/js/3.a51774e3.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{317:function(t,e,n){},348:function(t,e,n){"use strict";var i=n(317);n.n(i).a},362:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:function(t,e){var n=e.props,i=e.slots;return t("span",{class:["badge",n.type],style:{verticalAlign:n.vertical}},n.text||i().default)}},r=(n(348),n(42)),a=Object(r.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{317:function(t,e,n){},348:function(t,e,n){"use strict";var i=n(317);n.n(i).a},377:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:function(t,e){var n=e.props,i=e.slots;return t("span",{class:["badge",n.type],style:{verticalAlign:n.vertical}},n.text||i().default)}},r=(n(348),n(42)),a=Object(r.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=a.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/15.ae9aceb7.js b/docs/assets/js/30.37a581ce.js similarity index 95% rename from docs/assets/js/15.ae9aceb7.js rename to docs/assets/js/30.37a581ce.js index e82f71a..5a485a1 100644 --- a/docs/assets/js/15.ae9aceb7.js +++ b/docs/assets/js/30.37a581ce.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[15],{359:function(t,e,s){"use strict";s.r(e);var a=s(42),r=Object(a.a)({},(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h2",{attrs:{id:"路由转发介绍"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#路由转发介绍"}},[t._v("#")]),t._v(" 路由转发介绍")]),t._v(" "),s("p",[t._v("路由转发也叫反向代理,为内部微服务提供统一的对外入口。支持以下功能:")]),t._v(" "),s("ul",[s("li",[t._v("支持服务注册与发现")]),t._v(" "),s("li",[t._v("支持负载均衡")]),t._v(" "),s("li",[t._v("支持黑白名单机制")]),t._v(" "),s("li",[t._v("支持配置插件")])]),t._v(" "),s("h2",{attrs:{id:"接入路由转发"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#接入路由转发"}},[t._v("#")]),t._v(" 接入路由转发")]),t._v(" "),s("ul",[s("li",[t._v("前提条件:接入Eureka注册中心")]),t._v(" "),s("li",[t._v("开通白名单,接入注册中心的服务默认不对公网开放 (白名单在配置文件里配置serviceWhiteList)")]),t._v(" "),s("li",[t._v("配置访问权限 (管理后台-接口代理-API查询)")])])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{376:function(t,e,s){"use strict";s.r(e);var a=s(42),r=Object(a.a)({},(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h2",{attrs:{id:"路由转发介绍"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#路由转发介绍"}},[t._v("#")]),t._v(" 路由转发介绍")]),t._v(" "),s("p",[t._v("路由转发也叫反向代理,为内部微服务提供统一的对外入口。支持以下功能:")]),t._v(" "),s("ul",[s("li",[t._v("支持服务注册与发现")]),t._v(" "),s("li",[t._v("支持负载均衡")]),t._v(" "),s("li",[t._v("支持黑白名单机制")]),t._v(" "),s("li",[t._v("支持配置插件")])]),t._v(" "),s("h2",{attrs:{id:"接入路由转发"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#接入路由转发"}},[t._v("#")]),t._v(" 接入路由转发")]),t._v(" "),s("ul",[s("li",[t._v("前提条件:接入Eureka注册中心")]),t._v(" "),s("li",[t._v("开通白名单,接入注册中心的服务默认不对公网开放 (白名单在配置文件里配置serviceWhiteList)")]),t._v(" "),s("li",[t._v("配置访问权限 (管理后台-接口代理-API查询)")])])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/6.b5dc0bcc.js b/docs/assets/js/6.ee90ff38.js similarity index 79% rename from docs/assets/js/6.b5dc0bcc.js rename to docs/assets/js/6.ee90ff38.js index f6f6a87..517cdf6 100644 --- a/docs/assets/js/6.b5dc0bcc.js +++ b/docs/assets/js/6.ee90ff38.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{353:function(t,e,n){"use strict";n.r(e);var s=n(42),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{355:function(t,e,n){"use strict";n.r(e);var s=n(42),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/7.c27e364c.js b/docs/assets/js/7.e3b70354.js similarity index 81% rename from docs/assets/js/7.c27e364c.js rename to docs/assets/js/7.e3b70354.js index c3da9f2..02f8ee4 100644 --- a/docs/assets/js/7.c27e364c.js +++ b/docs/assets/js/7.e3b70354.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{354:function(t,n,s){"use strict";s.r(n);var e=s(42),o=Object(e.a)({},(function(){var t=this.$createElement,n=this._self._c||t;return n("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[n("p",[this._v("coming soon")])])}),[],!1,null,null,null);n.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{352:function(t,n,s){"use strict";s.r(n);var e=s(42),o=Object(e.a)({},(function(){var t=this.$createElement,n=this._self._c||t;return n("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[n("p",[this._v("coming soon")])])}),[],!1,null,null,null);n.default=o.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/8.99888a6b.js b/docs/assets/js/8.834b8e71.js similarity index 97% rename from docs/assets/js/8.99888a6b.js rename to docs/assets/js/8.834b8e71.js index edbab21..fbd9466 100644 --- a/docs/assets/js/8.99888a6b.js +++ b/docs/assets/js/8.834b8e71.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[8],{352:function(t,a,r){"use strict";r.r(a);var s=r(42),e=Object(s.a)({},(function(){var t=this,a=t.$createElement,r=t._self._c||a;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h2",{attrs:{id:"什么是服务编排"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#什么是服务编排"}},[t._v("#")]),t._v(" 什么是服务编排")]),t._v(" "),r("p",[t._v("服务编排主要基于现有的业务微服务使用在线配置的方式快速的生成一个聚合接口。")]),t._v(" "),r("p",[t._v("特点: 在线API设计、在线测试、快速开发")]),t._v(" "),r("h2",{attrs:{id:"举例说明"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#举例说明"}},[t._v("#")]),t._v(" 举例说明")]),t._v(" "),r("p",[t._v("订单详情页面需要展示订单信息、商品信息和用户信息。可通过配置的方式生成一个接口先后调用底层微服务的订单详情接口、商品信息接口和用户信息接口,再从这3个接口的返回结果里提取需要的字段返回给前端页面。")]),t._v(" "),r("h2",{attrs:{id:"服务编排架构"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#服务编排架构"}},[t._v("#")]),t._v(" 服务编排架构")]),t._v(" "),r("p",[r("img",{attrs:{src:"/fizz-gateway-community/fizz_aggregate.jpg",alt:""}})]),t._v(" "),r("h2",{attrs:{id:"适用场景"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#适用场景"}},[t._v("#")]),t._v(" 适用场景")]),t._v(" "),r("h3",{attrs:{id:"前端"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#前端"}},[t._v("#")]),t._v(" 前端")]),t._v(" "),r("p",[t._v("1、一个页面调用多个接口时,可以编排好返回聚合结果,提高页面数据的加载速度")]),t._v(" "),r("p",[t._v("2、移动设备计算能力有限,可以把数据计算或业务处理逻辑放到服务端完成,加快页面响应")]),t._v(" "),r("h3",{attrs:{id:"后端"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#后端"}},[t._v("#")]),t._v(" 后端")]),t._v(" "),r("p",[t._v("1、替换应用层的聚合接口,减少应用层的胶水代码")]),t._v(" "),r("p",[t._v("2、快速生成透传数据类型的接口")]),t._v(" "),r("p",[t._v("3、数据转换和映射")])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[8],{353:function(t,a,r){"use strict";r.r(a);var s=r(42),e=Object(s.a)({},(function(){var t=this,a=t.$createElement,r=t._self._c||a;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h2",{attrs:{id:"什么是服务编排"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#什么是服务编排"}},[t._v("#")]),t._v(" 什么是服务编排")]),t._v(" "),r("p",[t._v("服务编排主要基于现有的业务微服务使用在线配置的方式快速的生成一个聚合接口。")]),t._v(" "),r("p",[t._v("特点: 在线API设计、在线测试、快速开发")]),t._v(" "),r("h2",{attrs:{id:"举例说明"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#举例说明"}},[t._v("#")]),t._v(" 举例说明")]),t._v(" "),r("p",[t._v("订单详情页面需要展示订单信息、商品信息和用户信息。可通过配置的方式生成一个接口先后调用底层微服务的订单详情接口、商品信息接口和用户信息接口,再从这3个接口的返回结果里提取需要的字段返回给前端页面。")]),t._v(" "),r("h2",{attrs:{id:"服务编排架构"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#服务编排架构"}},[t._v("#")]),t._v(" 服务编排架构")]),t._v(" "),r("p",[r("img",{attrs:{src:"/fizz-gateway-community/fizz_aggregate.jpg",alt:""}})]),t._v(" "),r("h2",{attrs:{id:"适用场景"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#适用场景"}},[t._v("#")]),t._v(" 适用场景")]),t._v(" "),r("h3",{attrs:{id:"前端"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#前端"}},[t._v("#")]),t._v(" 前端")]),t._v(" "),r("p",[t._v("1、一个页面调用多个接口时,可以编排好返回聚合结果,提高页面数据的加载速度")]),t._v(" "),r("p",[t._v("2、移动设备计算能力有限,可以把数据计算或业务处理逻辑放到服务端完成,加快页面响应")]),t._v(" "),r("h3",{attrs:{id:"后端"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#后端"}},[t._v("#")]),t._v(" 后端")]),t._v(" "),r("p",[t._v("1、替换应用层的聚合接口,减少应用层的胶水代码")]),t._v(" "),r("p",[t._v("2、快速生成透传数据类型的接口")]),t._v(" "),r("p",[t._v("3、数据转换和映射")])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/9.5ff00875.js b/docs/assets/js/9.5f299cef.js similarity index 99% rename from docs/assets/js/9.5ff00875.js rename to docs/assets/js/9.5f299cef.js index c9f2ebe..661293a 100644 --- a/docs/assets/js/9.5ff00875.js +++ b/docs/assets/js/9.5f299cef.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[9],{356:function(t,a,s){"use strict";s.r(a);var n=s(42),e=Object(n.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h2",{attrs:{id:"创建服务"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#创建服务"}},[t._v("#")]),t._v(" 创建服务")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_newservice.png",alt:""}})]),t._v(" "),s("h2",{attrs:{id:"创建聚合接口"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#创建聚合接口"}},[t._v("#")]),t._v(" 创建聚合接口")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_newapi0.png",alt:""}}),t._v(" "),s("img",{attrs:{src:"/fizz-gateway-community/aggr_newapi.png",alt:""}})]),t._v(" "),s("h2",{attrs:{id:"配置输入"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置输入"}},[t._v("#")]),t._v(" 配置输入")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_input.png",alt:""}})]),t._v(" "),s("ul",[s("li",[t._v("配置输入的定义包括3部分:请求头、请求体和Query参数")]),t._v(" "),s("li",[t._v("基于JSON Schema规范")]),t._v(" "),s("li",[t._v("自带校验规则")]),t._v(" "),s("li",[t._v("支持自定义脚本实现复杂的逻辑校验")])]),t._v(" "),s("p",[t._v("JSON Schema规范,详见:")]),t._v(" "),s("p",[s("a",{attrs:{href:"http://json-schema.org/specification.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("http://json-schema.org/specification.html"),s("OutboundLink")],1)]),t._v(" "),s("p",[s("a",{attrs:{href:"http://json-schema.org/understanding-json-schema/",target:"_blank",rel:"noopener noreferrer"}},[t._v("http://json-schema.org/understanding-json-schema/"),s("OutboundLink")],1)]),t._v(" "),s("h2",{attrs:{id:"配置校验结果"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置校验结果"}},[t._v("#")]),t._v(" 配置校验结果")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_input_validate_result.png",alt:""}})]),t._v(" "),s("ul",[s("li",[t._v("校验不通过时,Fizz会把校验失败的原因(如:订单ID不能为空)放到上下文的validateMsg字段里")]),t._v(" "),s("li",[t._v("可以自定义返回给调用方的报文格式,如 msgCode, message")]),t._v(" "),s("li",[t._v("支持自定义响应头")]),t._v(" "),s("li",[t._v("支持自定义脚本处理校验结果")])]),t._v(" "),s("h2",{attrs:{id:"配置步骤"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置步骤"}},[t._v("#")]),t._v(" 配置步骤")]),t._v(" "),s("h3",{attrs:{id:"配置步骤的基础信息"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置步骤的基础信息"}},[t._v("#")]),t._v(" 配置步骤的基础信息")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step1.png",alt:""}})]),t._v(" "),s("h3",{attrs:{id:"配置步骤的接口入出参"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置步骤的接口入出参"}},[t._v("#")]),t._v(" 配置步骤的接口入出参")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step2.png",alt:""}})]),t._v(" "),s("h3",{attrs:{id:"步骤说明"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#步骤说明"}},[t._v("#")]),t._v(" 步骤说明")]),t._v(" "),s("ul",[s("li",[t._v("一个聚合接口可包含多个步骤")]),t._v(" "),s("li",[t._v("一个步骤可包含多个请求(即调用多个接口)")]),t._v(" "),s("li",[t._v("步骤间是串联顺序执行")]),t._v(" "),s("li",[t._v("一个步骤内的多个请求并行执行")])]),t._v(" "),s("h3",{attrs:{id:"数据转换"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#数据转换"}},[t._v("#")]),t._v(" 数据转换")]),t._v(" "),s("p",[t._v("支持配置固定值,引用值和脚本")]),t._v(" "),s("h4",{attrs:{id:"固定值"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#固定值"}},[t._v("#")]),t._v(" 固定值")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_mapping_1.png",alt:""}})]),t._v(" "),s("h4",{attrs:{id:"引用值"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#引用值"}},[t._v("#")]),t._v(" 引用值")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_mapping_2.png",alt:""}})]),t._v(" "),s("h4",{attrs:{id:"脚本"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#脚本"}},[t._v("#")]),t._v(" 脚本")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_mapping_3.png",alt:""}})]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_mapping_4.png",alt:""}})]),t._v(" "),s("h4",{attrs:{id:"星号"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#星号"}},[t._v("#")]),t._v(" 星号 *")]),t._v(" "),s("p",[t._v("星号通配符可以接收一个返回对象类型的引用值,返回对象里的字段会合并到目标对象里")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_mapping_5.png",alt:""}})]),t._v(" "),s("p",[t._v('样例:userInfo = {"userName": "Fizz", "userID": 1234}')]),t._v(" "),s("h4",{attrs:{id:"优先级与覆盖顺序"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#优先级与覆盖顺序"}},[t._v("#")]),t._v(" 优先级与覆盖顺序")]),t._v(" "),s("p",[t._v("固定值 < 引用值 < 脚本 < 星号*")]),t._v(" "),s("p",[t._v("当一个字段配置了多种类型的值时按以上顺序覆盖,星号优先级最高")]),t._v(" "),s("h4",{attrs:{id:"引用值规范"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#引用值规范"}},[t._v("#")]),t._v(" 引用值规范")]),t._v(" "),s("div",{staticClass:"language-properties extra-class"},[s("pre",{pre:!0,attrs:{class:"language-properties"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 获取入参请求头aaa的值")]),t._v("\ninput.request.headers.aaa\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 获取入参请求体bbb字段的值")]),t._v("\ninput.request.body.bbb\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 获取入参URL Query参数fff字段的值")]),t._v("\ninput.request.params.fff\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 获取步骤1里request1的请求头ccc的值")]),t._v("\nstep1.request1.request.headers.ccc\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 获取步骤1里request1的响应体ddd的值")]),t._v("\nstep1.request1.response.body.ddd\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 获取步骤1结果里eee的值")]),t._v("\nstep1.result.eee\n\n")])])]),s("ul",[s("li",[t._v("支持单值引用,如:string,int等")]),t._v(" "),s("li",[t._v("支持对象类型的引用")])]),t._v(" "),s("p",[t._v("input: 表示调用方的输入数据,如H5页面提交上来的参数")]),t._v(" "),s("p",[t._v("stepN.requestN: 表示步骤N里调用接口N的相关参数")]),t._v(" "),s("p",[t._v("stepN.result: 表示步骤N的转换结果")]),t._v(" "),s("h4",{attrs:{id:"fallback与预处理条件"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#fallback与预处理条件"}},[t._v("#")]),t._v(" Fallback与预处理条件")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_fallback.png",alt:""}})]),t._v(" "),s("p",[t._v("Fallback:")]),t._v(" "),s("p",[t._v("当调用接口发生异常(如超时、网络或系统异常)可配置fallback方案:")]),t._v(" "),s("ul",[s("li",[t._v("Stop: 终止请求并立即返回")]),t._v(" "),s("li",[t._v("Continue: 继续后续的操作,且要设置默认的fallback json")])]),t._v(" "),s("p",[t._v("预处理: 根据条件判断是否要调用接口,脚本返回true时才调用接口")]),t._v(" "),s("h4",{attrs:{id:"配置步骤结果处理"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置步骤结果处理"}},[t._v("#")]),t._v(" 配置步骤结果处理")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_result.png",alt:""}})]),t._v(" "),s("ul",[s("li",[s("p",[t._v("支持对步骤里调用的每一个接口的返回结果做数据转换,如果配置数据转换规则原样返回并存储到上下文里供后续使用")])]),t._v(" "),s("li",[s("p",[t._v("支持对步骤里调用的一个或多个接口的返回结果做处理,并把处理完的结果存储到上下文里供后续使用,不配置则不处理")])])]),t._v(" "),s("h2",{attrs:{id:"配置输出"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置输出"}},[t._v("#")]),t._v(" 配置输出")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_output.png",alt:""}})]),t._v(" "),s("p",[t._v("配置返回给调用方的结果")]),t._v(" "),s("ul",[s("li",[t._v("支持配置响应头")]),t._v(" "),s("li",[t._v("支持配置响应体")]),t._v(" "),s("li",[t._v("支持自定脚本处理复杂的业务逻辑")])]),t._v(" "),s("h2",{attrs:{id:"脚本-2"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#脚本-2"}},[t._v("#")]),t._v(" 脚本")]),t._v(" "),s("p",[t._v("目前支持以下脚本语言:")]),t._v(" "),s("p",[t._v("Javascript (推荐) - ECMAScript 5标准")]),t._v(" "),s("p",[t._v("JS脚本只支持单函数,且函数名不可变,在创建脚本时系统会自动生成初始模板,模板里包含相关使用说明")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_script_1.png",alt:""}})]),t._v(" "),s("p",[t._v("Groovy")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_script_2.png",alt:""}})]),t._v(" "),s("h3",{attrs:{id:"common-js-提供了操作context上下文的便捷操作函数"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#common-js-提供了操作context上下文的便捷操作函数"}},[t._v("#")]),t._v(" common.js 提供了操作context上下文的便捷操作函数")]),t._v(" "),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * context 上下文便捷操作函数\n *\n */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" common "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* *********** private function begin *********** */")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获取上下文中客户端请求对象")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getInputReq")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'input'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'input'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'request'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'input'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'request'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获取上下文步骤中请求接口的请求对象")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepReq")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("stepName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'request'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'request'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获取上下文步骤中请求接口的响应对象")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepResp")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("stepName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'response'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'response'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* *********** private function end *********** */")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* *********** input begin ************ */")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取客户端请求头\n * @param {*} ctx 上下文 【必填】\n * @param {*} headerName 请求头字段名 【选填】,不传时返回所有请求头\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getInputReqHeader")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" headerName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getInputReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" headers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'headers'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" headerName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("headerName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取客户端URL请求参数(query string)\n * @param {*} ctx 上下文 【必填】\n * @param {*} paramName URL参数名 【选填】,不传时返回所有请求参数\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getInputReqParam")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" paramName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getInputReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" params "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'params'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" paramName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("paramName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取客户端请求体\n * @param {*} ctx 上下文 【必填】\n * @param {*} field 字段名 【选填】,不传时返回整个请求体\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getInputReqBody")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getInputReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" body "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'body'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" field "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取返回给客户端的响应头\n * @param {*} ctx 上下文 【必填】\n * @param {*} headerName 响应头字段名 【选填】,不传时返回所有响应头\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getInputRespHeader")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" headerName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getInputReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" headers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'headers'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" headerName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("headerName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取返回给客户端的响应体\n * @param {*} ctx 上下文 【必填】\n * @param {*} field 字段名 【选填】,不传时返回整个响应体\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getInputRespBody")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getInputReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" body "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'body'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" field "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* *********** input begin ************ */")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* *********** step request begin ************ */")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取步骤中调用的接口的请求头\n * @param {*} ctx 上下文 【必填】\n * @param {*} stepName 步骤名【必填】\n * @param {*} requestName 请求的接口名 【必填】\n * @param {*} headerName 请求头字段名 【选填】,不传时返回所有请求头\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepReqHeader")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" headerName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getStepReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" headers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'headers'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" headerName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("headerName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取步骤中调用的接口的URL参数\n * @param {*} ctx 上下文 【必填】\n * @param {*} stepName 步骤名【必填】\n * @param {*} requestName 请求的接口名 【必填】\n * @param {*} paramName URL参数名 【选填】,不传时返回所有URL参数\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepReqParam")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" paramName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getStepReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" params "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'params'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" paramName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("paramName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取步骤中调用的接口的请求体\n * @param {*} ctx 上下文 【必填】\n * @param {*} stepName 步骤名【必填】\n * @param {*} requestName 请求的接口名 【必填】\n * @param {*} field 字段名 【选填】,不传时返回整个请求体\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepReqBody")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getStepReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" body "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'body'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" field "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取步骤中调用的接口的响应头\n * @param {*} ctx 上下文 【必填】\n * @param {*} stepName 步骤名【必填】\n * @param {*} requestName 请求的接口名 【必填】\n * @param {*} headerName 响应头字段名 【选填】,不传时返回所有响应头\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepRespHeader")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" headerName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" resp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getStepResp")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" headers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" resp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'headers'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" headerName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("headerName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取步骤中调用的接口的响应头\n * @param {*} ctx 上下文 【必填】\n * @param {*} stepName 步骤名【必填】\n * @param {*} requestName 请求的接口名 【必填】\n * @param {*} field 字段名 【选填】,不传时返回整个响应头\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepRespBody")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" resp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getStepResp")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" body "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" resp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'body'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" field "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取步骤结果\n * @param {*} ctx 上下文 【必填】\n * @param {*} stepName 步骤名【必填】\n * @param {*} field 字段名 【选填】,不传时返回整个步骤结果对象\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("stepName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" result "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'result'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" field "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* *********** step request end ************ */")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])]),s("h3",{attrs:{id:"context-js-数据结构"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#context-js-数据结构"}},[t._v("#")]),t._v(" context.js 数据结构")]),t._v(" "),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 上下文,用于保存客户输入输出和每个步骤的输入与输出结果")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" context "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 是否DEBUG模式")]),t._v("\n\tdebug"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 各个操作的耗时")]),t._v("\n\telapsedTimes"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("actionName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("123")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 操作名称:耗时")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 客户输入和接口的返回结果")]),t._v("\n input"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n request"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n path"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n method"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET/POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n headers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n params"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n response"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 聚合接口的响应")]),t._v("\n headers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 步骤")]),t._v("\n step1"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n requests"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接口1")]),t._v("\n request1"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 请求相关参数")]),t._v("\n request"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n url"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n method"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET/POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n headers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 根据转换规则转换后的接口响应")]),t._v("\n response"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n headers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接口2")]),t._v("\n request2"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n request"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n url"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n method"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET/POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n headers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n response"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n headers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 步骤结果")]),t._v("\n result"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])]),s("h2",{attrs:{id:"异常处理"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#异常处理"}},[t._v("#")]),t._v(" 异常处理")]),t._v(" "),s("p",[t._v("当要在脚本里中止请求时可以通过以下方式来实现")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_exception.png",alt:""}})]),t._v(" "),s("p",[t._v("返回一个对象且这个对象包含一个_stopAndResponse等于true的属性,Fizz会终止后续的操作并把这个对象返回给调用方。")]),t._v(" "),s("h2",{attrs:{id:"在线测试"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#在线测试"}},[t._v("#")]),t._v(" 在线测试")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_test.png",alt:""}})]),t._v(" "),s("ul",[s("li",[t._v("支持在线实时测试")]),t._v(" "),s("li",[t._v("支持测试接口和正式接口隔离")]),t._v(" "),s("li",[t._v("支持返回上下文,可以查看整个执行过程中各个步骤及请求的输入与输出")]),t._v(" "),s("li",[t._v("支持保存历史测试记录")])]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_test2.png",alt:""}})]),t._v(" "),s("p",[t._v("支持调试模式,在测试接口和正式接口均可使用,修改后重新发布可实时生效,在调试模式下会打印请求日志及报文,主要用于排查线上问题")]),t._v(" "),s("h2",{attrs:{id:"导入导出"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#导入导出"}},[t._v("#")]),t._v(" 导入导出")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_import_export.png",alt:""}})]),t._v(" "),s("p",[t._v("导入导出主要用于在各个环境间同步接口配置,在开发环境配置好后导到测试环境中测试,测试完后导到生产环境进行发布")]),t._v(" "),s("h2",{attrs:{id:"发布-下线和审核"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#发布-下线和审核"}},[t._v("#")]),t._v(" 发布|下线和审核")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_release_1.png",alt:""}})]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_release_2.png",alt:""}})]),t._v(" "),s("p",[t._v("目前发布|下线申请有以上两个入口。")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_release_rollback1.png",alt:""}})]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_release_rollback.png",alt:""}})]),t._v(" "),s("ul",[s("li",[t._v("批量发布:对发布单里的接口进行批量发布")]),t._v(" "),s("li",[t._v("批量回滚:对发布单里的接口进行批量回滚")]),t._v(" "),s("li",[t._v("发布:实时发布到网关")]),t._v(" "),s("li",[t._v("回滚:支持回滚到历史任何一个版本,可在发布历史里指定一个版本进行回滚")]),t._v(" "),s("li",[t._v("下线:从网关删除接口,在后台可以通过发布功能再次上线")])]),t._v(" "),s("h3",{attrs:{id:"发布流程说明"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#发布流程说明"}},[t._v("#")]),t._v(" 发布流程说明")]),t._v(" "),s("p",[t._v("申请发布、审核、发布和下线功能的权限可根据需要灵活分配给不同角色,如:开发人员只能申请发布,上级领导审核,运维或测试人员执行发布、回滚或下线。在开发、测试和预生产环境为了方便开发人员调试也可把申请发布、审核、发布和下线功能都分配给开发人员。")])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[9],{354:function(t,a,s){"use strict";s.r(a);var n=s(42),e=Object(n.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h2",{attrs:{id:"创建服务"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#创建服务"}},[t._v("#")]),t._v(" 创建服务")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_newservice.png",alt:""}})]),t._v(" "),s("h2",{attrs:{id:"创建聚合接口"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#创建聚合接口"}},[t._v("#")]),t._v(" 创建聚合接口")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_newapi0.png",alt:""}}),t._v(" "),s("img",{attrs:{src:"/fizz-gateway-community/aggr_newapi.png",alt:""}})]),t._v(" "),s("h2",{attrs:{id:"配置输入"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置输入"}},[t._v("#")]),t._v(" 配置输入")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_input.png",alt:""}})]),t._v(" "),s("ul",[s("li",[t._v("配置输入的定义包括3部分:请求头、请求体和Query参数")]),t._v(" "),s("li",[t._v("基于JSON Schema规范")]),t._v(" "),s("li",[t._v("自带校验规则")]),t._v(" "),s("li",[t._v("支持自定义脚本实现复杂的逻辑校验")])]),t._v(" "),s("p",[t._v("JSON Schema规范,详见:")]),t._v(" "),s("p",[s("a",{attrs:{href:"http://json-schema.org/specification.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("http://json-schema.org/specification.html"),s("OutboundLink")],1)]),t._v(" "),s("p",[s("a",{attrs:{href:"http://json-schema.org/understanding-json-schema/",target:"_blank",rel:"noopener noreferrer"}},[t._v("http://json-schema.org/understanding-json-schema/"),s("OutboundLink")],1)]),t._v(" "),s("h2",{attrs:{id:"配置校验结果"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置校验结果"}},[t._v("#")]),t._v(" 配置校验结果")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_input_validate_result.png",alt:""}})]),t._v(" "),s("ul",[s("li",[t._v("校验不通过时,Fizz会把校验失败的原因(如:订单ID不能为空)放到上下文的validateMsg字段里")]),t._v(" "),s("li",[t._v("可以自定义返回给调用方的报文格式,如 msgCode, message")]),t._v(" "),s("li",[t._v("支持自定义响应头")]),t._v(" "),s("li",[t._v("支持自定义脚本处理校验结果")])]),t._v(" "),s("h2",{attrs:{id:"配置步骤"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置步骤"}},[t._v("#")]),t._v(" 配置步骤")]),t._v(" "),s("h3",{attrs:{id:"配置步骤的基础信息"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置步骤的基础信息"}},[t._v("#")]),t._v(" 配置步骤的基础信息")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step1.png",alt:""}})]),t._v(" "),s("h3",{attrs:{id:"配置步骤的接口入出参"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置步骤的接口入出参"}},[t._v("#")]),t._v(" 配置步骤的接口入出参")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step2.png",alt:""}})]),t._v(" "),s("h3",{attrs:{id:"步骤说明"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#步骤说明"}},[t._v("#")]),t._v(" 步骤说明")]),t._v(" "),s("ul",[s("li",[t._v("一个聚合接口可包含多个步骤")]),t._v(" "),s("li",[t._v("一个步骤可包含多个请求(即调用多个接口)")]),t._v(" "),s("li",[t._v("步骤间是串联顺序执行")]),t._v(" "),s("li",[t._v("一个步骤内的多个请求并行执行")])]),t._v(" "),s("h3",{attrs:{id:"数据转换"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#数据转换"}},[t._v("#")]),t._v(" 数据转换")]),t._v(" "),s("p",[t._v("支持配置固定值,引用值和脚本")]),t._v(" "),s("h4",{attrs:{id:"固定值"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#固定值"}},[t._v("#")]),t._v(" 固定值")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_mapping_1.png",alt:""}})]),t._v(" "),s("h4",{attrs:{id:"引用值"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#引用值"}},[t._v("#")]),t._v(" 引用值")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_mapping_2.png",alt:""}})]),t._v(" "),s("h4",{attrs:{id:"脚本"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#脚本"}},[t._v("#")]),t._v(" 脚本")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_mapping_3.png",alt:""}})]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_mapping_4.png",alt:""}})]),t._v(" "),s("h4",{attrs:{id:"星号"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#星号"}},[t._v("#")]),t._v(" 星号 *")]),t._v(" "),s("p",[t._v("星号通配符可以接收一个返回对象类型的引用值,返回对象里的字段会合并到目标对象里")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_mapping_5.png",alt:""}})]),t._v(" "),s("p",[t._v('样例:userInfo = {"userName": "Fizz", "userID": 1234}')]),t._v(" "),s("h4",{attrs:{id:"优先级与覆盖顺序"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#优先级与覆盖顺序"}},[t._v("#")]),t._v(" 优先级与覆盖顺序")]),t._v(" "),s("p",[t._v("固定值 < 引用值 < 脚本 < 星号*")]),t._v(" "),s("p",[t._v("当一个字段配置了多种类型的值时按以上顺序覆盖,星号优先级最高")]),t._v(" "),s("h4",{attrs:{id:"引用值规范"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#引用值规范"}},[t._v("#")]),t._v(" 引用值规范")]),t._v(" "),s("div",{staticClass:"language-properties extra-class"},[s("pre",{pre:!0,attrs:{class:"language-properties"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 获取入参请求头aaa的值")]),t._v("\ninput.request.headers.aaa\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 获取入参请求体bbb字段的值")]),t._v("\ninput.request.body.bbb\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 获取入参URL Query参数fff字段的值")]),t._v("\ninput.request.params.fff\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 获取步骤1里request1的请求头ccc的值")]),t._v("\nstep1.request1.request.headers.ccc\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 获取步骤1里request1的响应体ddd的值")]),t._v("\nstep1.request1.response.body.ddd\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 获取步骤1结果里eee的值")]),t._v("\nstep1.result.eee\n\n")])])]),s("ul",[s("li",[t._v("支持单值引用,如:string,int等")]),t._v(" "),s("li",[t._v("支持对象类型的引用")])]),t._v(" "),s("p",[t._v("input: 表示调用方的输入数据,如H5页面提交上来的参数")]),t._v(" "),s("p",[t._v("stepN.requestN: 表示步骤N里调用接口N的相关参数")]),t._v(" "),s("p",[t._v("stepN.result: 表示步骤N的转换结果")]),t._v(" "),s("h4",{attrs:{id:"fallback与预处理条件"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#fallback与预处理条件"}},[t._v("#")]),t._v(" Fallback与预处理条件")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_fallback.png",alt:""}})]),t._v(" "),s("p",[t._v("Fallback:")]),t._v(" "),s("p",[t._v("当调用接口发生异常(如超时、网络或系统异常)可配置fallback方案:")]),t._v(" "),s("ul",[s("li",[t._v("Stop: 终止请求并立即返回")]),t._v(" "),s("li",[t._v("Continue: 继续后续的操作,且要设置默认的fallback json")])]),t._v(" "),s("p",[t._v("预处理: 根据条件判断是否要调用接口,脚本返回true时才调用接口")]),t._v(" "),s("h4",{attrs:{id:"配置步骤结果处理"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置步骤结果处理"}},[t._v("#")]),t._v(" 配置步骤结果处理")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_step_result.png",alt:""}})]),t._v(" "),s("ul",[s("li",[s("p",[t._v("支持对步骤里调用的每一个接口的返回结果做数据转换,如果配置数据转换规则原样返回并存储到上下文里供后续使用")])]),t._v(" "),s("li",[s("p",[t._v("支持对步骤里调用的一个或多个接口的返回结果做处理,并把处理完的结果存储到上下文里供后续使用,不配置则不处理")])])]),t._v(" "),s("h2",{attrs:{id:"配置输出"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#配置输出"}},[t._v("#")]),t._v(" 配置输出")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_output.png",alt:""}})]),t._v(" "),s("p",[t._v("配置返回给调用方的结果")]),t._v(" "),s("ul",[s("li",[t._v("支持配置响应头")]),t._v(" "),s("li",[t._v("支持配置响应体")]),t._v(" "),s("li",[t._v("支持自定脚本处理复杂的业务逻辑")])]),t._v(" "),s("h2",{attrs:{id:"脚本-2"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#脚本-2"}},[t._v("#")]),t._v(" 脚本")]),t._v(" "),s("p",[t._v("目前支持以下脚本语言:")]),t._v(" "),s("p",[t._v("Javascript (推荐) - ECMAScript 5标准")]),t._v(" "),s("p",[t._v("JS脚本只支持单函数,且函数名不可变,在创建脚本时系统会自动生成初始模板,模板里包含相关使用说明")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_script_1.png",alt:""}})]),t._v(" "),s("p",[t._v("Groovy")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_script_2.png",alt:""}})]),t._v(" "),s("h3",{attrs:{id:"common-js-提供了操作context上下文的便捷操作函数"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#common-js-提供了操作context上下文的便捷操作函数"}},[t._v("#")]),t._v(" common.js 提供了操作context上下文的便捷操作函数")]),t._v(" "),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * context 上下文便捷操作函数\n *\n */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" common "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* *********** private function begin *********** */")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获取上下文中客户端请求对象")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getInputReq")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'input'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'input'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'request'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'input'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'request'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获取上下文步骤中请求接口的请求对象")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepReq")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("stepName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'request'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'request'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获取上下文步骤中请求接口的响应对象")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepResp")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("stepName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'response'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'requests'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'response'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* *********** private function end *********** */")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* *********** input begin ************ */")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取客户端请求头\n * @param {*} ctx 上下文 【必填】\n * @param {*} headerName 请求头字段名 【选填】,不传时返回所有请求头\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getInputReqHeader")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" headerName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getInputReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" headers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'headers'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" headerName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("headerName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取客户端URL请求参数(query string)\n * @param {*} ctx 上下文 【必填】\n * @param {*} paramName URL参数名 【选填】,不传时返回所有请求参数\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getInputReqParam")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" paramName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getInputReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" params "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'params'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" paramName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("paramName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取客户端请求体\n * @param {*} ctx 上下文 【必填】\n * @param {*} field 字段名 【选填】,不传时返回整个请求体\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getInputReqBody")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getInputReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" body "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'body'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" field "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取返回给客户端的响应头\n * @param {*} ctx 上下文 【必填】\n * @param {*} headerName 响应头字段名 【选填】,不传时返回所有响应头\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getInputRespHeader")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" headerName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getInputReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" headers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'headers'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" headerName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("headerName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取返回给客户端的响应体\n * @param {*} ctx 上下文 【必填】\n * @param {*} field 字段名 【选填】,不传时返回整个响应体\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getInputRespBody")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getInputReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" body "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'body'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" field "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* *********** input begin ************ */")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* *********** step request begin ************ */")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取步骤中调用的接口的请求头\n * @param {*} ctx 上下文 【必填】\n * @param {*} stepName 步骤名【必填】\n * @param {*} requestName 请求的接口名 【必填】\n * @param {*} headerName 请求头字段名 【选填】,不传时返回所有请求头\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepReqHeader")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" headerName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getStepReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" headers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'headers'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" headerName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("headerName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取步骤中调用的接口的URL参数\n * @param {*} ctx 上下文 【必填】\n * @param {*} stepName 步骤名【必填】\n * @param {*} requestName 请求的接口名 【必填】\n * @param {*} paramName URL参数名 【选填】,不传时返回所有URL参数\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepReqParam")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" paramName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getStepReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" params "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'params'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" paramName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("paramName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取步骤中调用的接口的请求体\n * @param {*} ctx 上下文 【必填】\n * @param {*} stepName 步骤名【必填】\n * @param {*} requestName 请求的接口名 【必填】\n * @param {*} field 字段名 【选填】,不传时返回整个请求体\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepReqBody")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" req "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getStepReq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" body "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'body'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" field "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取步骤中调用的接口的响应头\n * @param {*} ctx 上下文 【必填】\n * @param {*} stepName 步骤名【必填】\n * @param {*} requestName 请求的接口名 【必填】\n * @param {*} headerName 响应头字段名 【选填】,不传时返回所有响应头\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepRespHeader")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" headerName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" resp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getStepResp")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" headers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" resp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'headers'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" headerName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("headerName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" headers"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取步骤中调用的接口的响应头\n * @param {*} ctx 上下文 【必填】\n * @param {*} stepName 步骤名【必填】\n * @param {*} requestName 请求的接口名 【必填】\n * @param {*} field 字段名 【选填】,不传时返回整个响应头\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepRespBody")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" resp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getStepResp")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" requestName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" body "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" resp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'body'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" field "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" body"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * 获取步骤结果\n * @param {*} ctx 上下文 【必填】\n * @param {*} stepName 步骤名【必填】\n * @param {*} field 字段名 【选填】,不传时返回整个步骤结果对象\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function-variable function"}},[t._v("getStepResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("stepName "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" result "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("stepName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'result'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" field "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* *********** step request end ************ */")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])]),s("h3",{attrs:{id:"context-js-数据结构"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#context-js-数据结构"}},[t._v("#")]),t._v(" context.js 数据结构")]),t._v(" "),s("div",{staticClass:"language-javascript extra-class"},[s("pre",{pre:!0,attrs:{class:"language-javascript"}},[s("code",[t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 上下文,用于保存客户输入输出和每个步骤的输入与输出结果")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" context "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 是否DEBUG模式")]),t._v("\n\tdebug"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 各个操作的耗时")]),t._v("\n\telapsedTimes"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("actionName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("123")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 操作名称:耗时")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 客户输入和接口的返回结果")]),t._v("\n input"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n request"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n path"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n method"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET/POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n headers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n params"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n response"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 聚合接口的响应")]),t._v("\n headers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 步骤")]),t._v("\n step1"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n requests"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接口1")]),t._v("\n request1"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 请求相关参数")]),t._v("\n request"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n url"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n method"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET/POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n headers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 根据转换规则转换后的接口响应")]),t._v("\n response"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n headers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接口2")]),t._v("\n request2"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n request"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n url"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n method"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET/POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n headers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n response"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n headers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 步骤结果")]),t._v("\n result"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])]),s("h2",{attrs:{id:"异常处理"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#异常处理"}},[t._v("#")]),t._v(" 异常处理")]),t._v(" "),s("p",[t._v("当要在脚本里中止请求时可以通过以下方式来实现")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_exception.png",alt:""}})]),t._v(" "),s("p",[t._v("返回一个对象且这个对象包含一个_stopAndResponse等于true的属性,Fizz会终止后续的操作并把这个对象返回给调用方。")]),t._v(" "),s("h2",{attrs:{id:"在线测试"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#在线测试"}},[t._v("#")]),t._v(" 在线测试")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_test.png",alt:""}})]),t._v(" "),s("ul",[s("li",[t._v("支持在线实时测试")]),t._v(" "),s("li",[t._v("支持测试接口和正式接口隔离")]),t._v(" "),s("li",[t._v("支持返回上下文,可以查看整个执行过程中各个步骤及请求的输入与输出")]),t._v(" "),s("li",[t._v("支持保存历史测试记录")])]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_test2.png",alt:""}})]),t._v(" "),s("p",[t._v("支持调试模式,在测试接口和正式接口均可使用,修改后重新发布可实时生效,在调试模式下会打印请求日志及报文,主要用于排查线上问题")]),t._v(" "),s("h2",{attrs:{id:"导入导出"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#导入导出"}},[t._v("#")]),t._v(" 导入导出")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_config_import_export.png",alt:""}})]),t._v(" "),s("p",[t._v("导入导出主要用于在各个环境间同步接口配置,在开发环境配置好后导到测试环境中测试,测试完后导到生产环境进行发布")]),t._v(" "),s("h2",{attrs:{id:"发布-下线和审核"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#发布-下线和审核"}},[t._v("#")]),t._v(" 发布|下线和审核")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_release_1.png",alt:""}})]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_release_2.png",alt:""}})]),t._v(" "),s("p",[t._v("目前发布|下线申请有以上两个入口。")]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_release_rollback1.png",alt:""}})]),t._v(" "),s("p",[s("img",{attrs:{src:"/fizz-gateway-community/aggr_release_rollback.png",alt:""}})]),t._v(" "),s("ul",[s("li",[t._v("批量发布:对发布单里的接口进行批量发布")]),t._v(" "),s("li",[t._v("批量回滚:对发布单里的接口进行批量回滚")]),t._v(" "),s("li",[t._v("发布:实时发布到网关")]),t._v(" "),s("li",[t._v("回滚:支持回滚到历史任何一个版本,可在发布历史里指定一个版本进行回滚")]),t._v(" "),s("li",[t._v("下线:从网关删除接口,在后台可以通过发布功能再次上线")])]),t._v(" "),s("h3",{attrs:{id:"发布流程说明"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#发布流程说明"}},[t._v("#")]),t._v(" 发布流程说明")]),t._v(" "),s("p",[t._v("申请发布、审核、发布和下线功能的权限可根据需要灵活分配给不同角色,如:开发人员只能申请发布,上级领导审核,运维或测试人员执行发布、回滚或下线。在开发、测试和预生产环境为了方便开发人员调试也可把申请发布、审核、发布和下线功能都分配给开发人员。")])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/app.46dfc836.js b/docs/assets/js/app.bf39d9b6.js similarity index 53% rename from docs/assets/js/app.46dfc836.js rename to docs/assets/js/app.bf39d9b6.js index f81d43a..650d810 100644 --- a/docs/assets/js/app.46dfc836.js +++ b/docs/assets/js/app.bf39d9b6.js @@ -1,13 +1,13 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,u=e[0],c=e[1],s=e[2],l=0,p=[];l0?o(r(t),9007199254740991):0}},function(t,e){var n=Array.isArray;t.exports=n},function(t,e,n){var r=n(31),o=n(23);t.exports=function(t){return r(o(t))}},function(t,e,n){var r=n(140),o="object"==typeof self&&self&&self.Object===Object&&self,i=r||o||Function("return this")();t.exports=i},function(t,e,n){var r=n(6),o=n(1),i=n(7),a=Object.defineProperty,u={},c=function(t){throw t};t.exports=function(t,e){if(i(u,t))return u[t];e||(e={});var n=[][t],s=!!i(e,"ACCESSORS")&&e.ACCESSORS,f=i(e,0)?e[0]:c,l=i(e,1)?e[1]:void 0;return u[t]=!!n&&!o((function(){if(s&&!r)return!0;var t={length:-1};s?a(t,1,{enumerable:!0,get:c}):t[1]=1,n.call(t,f,l)}))}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e,n){var r=n(110),o=n(3),i=function(t){return"function"==typeof t?t:void 0};t.exports=function(t,e){return arguments.length<2?i(r[t])||i(o[t]):r[t]&&r[t][e]||o[t]&&o[t][e]}},function(t,e){t.exports=!1},function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(String(t)+" is not a function");return t}},function(t,e,n){var r=n(220),o=n(223);t.exports=function(t,e){var n=o(t,e);return r(n)?n:void 0}},function(t,e){t.exports=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t}},function(t,e,n){"use strict";var r=n(0),o=n(29).filter,i=n(51),a=n(17),u=i("filter"),c=a("filter");r({target:"Array",proto:!0,forced:!u||!c},{filter:function(t){return o(this,t,arguments.length>1?arguments[1]:void 0)}})},function(t,e,n){var r=n(6),o=n(75),i=n(32),a=n(15),u=n(44),c=n(7),s=n(105),f=Object.getOwnPropertyDescriptor;e.f=r?f:function(t,e){if(t=a(t),e=u(e,!0),s)try{return f(t,e)}catch(t){}if(c(t,e))return i(!o.f.call(t,e),t[e])}},function(t,e){t.exports=function(t){return null!=t&&"object"==typeof t}},function(t,e,n){"use strict";var r=n(128).charAt,o=n(28),i=n(111),a=o.set,u=o.getterFor("String Iterator");i(String,"String",(function(t){a(this,{type:"String Iterator",string:String(t),index:0})}),(function(){var t,e=u(this),n=e.string,o=e.index;return o>=n.length?{value:void 0,done:!0}:(t=r(n,o),e.index+=t.length,{value:t,done:!1})}))},function(t,e,n){var r,o,i,a=n(180),u=n(3),c=n(4),s=n(11),f=n(7),l=n(48),p=n(34),h=u.WeakMap;if(a){var d=new h,v=d.get,y=d.has,g=d.set;r=function(t,e){return g.call(d,t,e),e},o=function(t){return v.call(d,t)||{}},i=function(t){return y.call(d,t)}}else{var m=l("state");p[m]=!0,r=function(t,e){return s(t,m,e),e},o=function(t){return f(t,m)?t[m]:{}},i=function(t){return f(t,m)}}t.exports={set:r,get:o,has:i,enforce:function(t){return i(t)?o(t):r(t,{})},getterFor:function(t){return function(e){var n;if(!c(e)||(n=o(e)).type!==t)throw TypeError("Incompatible receiver, "+t+" required");return n}}}},function(t,e,n){var r=n(50),o=n(31),i=n(12),a=n(13),u=n(127),c=[].push,s=function(t){var e=1==t,n=2==t,s=3==t,f=4==t,l=6==t,p=5==t||l;return function(h,d,v,y){for(var g,m,b=i(h),_=o(b),x=r(d,v,3),w=a(_.length),O=0,S=y||u,j=e?S(h,w):n?S(h,0):void 0;w>O;O++)if((p||O in _)&&(m=x(g=_[O],O,b),t))if(e)j[O]=m;else if(m)switch(t){case 3:return!0;case 5:return g;case 6:return O;case 2:c.call(j,g)}else if(f)return!1;return l?-1:s||f?f:j}};t.exports={forEach:s(0),map:s(1),filter:s(2),some:s(3),every:s(4),find:s(5),findIndex:s(6)}},function(t,e,n){var r=n(39),o=n(205),i=n(206),a=r?r.toStringTag:void 0;t.exports=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":a&&a in Object(t)?o(t):i(t)}},function(t,e,n){var r=n(1),o=n(18),i="".split;t.exports=r((function(){return!Object("z").propertyIsEnumerable(0)}))?function(t){return"String"==o(t)?i.call(t,""):Object(t)}:Object},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){var r,o=n(5),i=n(179),a=n(73),u=n(34),c=n(109),s=n(70),f=n(48),l=f("IE_PROTO"),p=function(){},h=function(t){return" +

coming soon

上次更新: 2020-9-8 15:3
+ diff --git a/docs/guide/aggregate/configuration.html b/docs/guide/aggregate/configuration.html index d68f1de..656536b 100644 --- a/docs/guide/aggregate/configuration.html +++ b/docs/guide/aggregate/configuration.html @@ -7,7 +7,7 @@ - + @@ -23,7 +23,7 @@ 使用文档
查看源码 -

# 创建服务

# 创建聚合接口

# 配置输入

JSON Schema规范,详见:

http://json-schema.org/specification.html

http://json-schema.org/understanding-json-schema/

# 配置校验结果

# 配置步骤

# 配置步骤的基础信息

# 配置步骤的接口入出参

# 步骤说明

# 数据转换

支持配置固定值,引用值和脚本

# 固定值

# 引用值

# 脚本

# 星号 *

星号通配符可以接收一个返回对象类型的引用值,返回对象里的字段会合并到目标对象里

样例:userInfo = {"userName": "Fizz", "userID": 1234}

# 优先级与覆盖顺序

固定值 < 引用值 < 脚本 < 星号*

当一个字段配置了多种类型的值时按以上顺序覆盖,星号优先级最高

# 引用值规范

# 获取入参请求头aaa的值
+        

# 创建服务

# 创建聚合接口

# 配置输入

  • 配置输入的定义包括3部分:请求头、请求体和Query参数
  • 基于JSON Schema规范
  • 自带校验规则
  • 支持自定义脚本实现复杂的逻辑校验

JSON Schema规范,详见:

http://json-schema.org/specification.html

http://json-schema.org/understanding-json-schema/

# 配置校验结果

  • 校验不通过时,Fizz会把校验失败的原因(如:订单ID不能为空)放到上下文的validateMsg字段里
  • 可以自定义返回给调用方的报文格式,如 msgCode, message
  • 支持自定义响应头
  • 支持自定义脚本处理校验结果

# 配置步骤

# 配置步骤的基础信息

# 配置步骤的接口入出参

# 步骤说明

  • 一个聚合接口可包含多个步骤
  • 一个步骤可包含多个请求(即调用多个接口)
  • 步骤间是串联顺序执行
  • 一个步骤内的多个请求并行执行

# 数据转换

支持配置固定值,引用值和脚本

# 固定值

# 引用值

# 脚本

# 星号 *

星号通配符可以接收一个返回对象类型的引用值,返回对象里的字段会合并到目标对象里

样例:userInfo = {"userName": "Fizz", "userID": 1234}

# 优先级与覆盖顺序

固定值 < 引用值 < 脚本 < 星号*

当一个字段配置了多种类型的值时按以上顺序覆盖,星号优先级最高

# 引用值规范

# 获取入参请求头aaa的值
 input.request.headers.aaa
 
 # 获取入参请求体bbb字段的值
@@ -301,6 +301,6 @@ step1.result.eee
       
       →
     

- + diff --git a/docs/guide/aggregate/index.html b/docs/guide/aggregate/index.html index 7b1edd3..463982d 100644 --- a/docs/guide/aggregate/index.html +++ b/docs/guide/aggregate/index.html @@ -7,7 +7,7 @@ - + @@ -23,7 +23,7 @@ 使用文档 查看源码 -

# 什么是服务编排

服务编排主要基于现有的业务微服务使用在线配置的方式快速的生成一个聚合接口。

特点: 在线API设计、在线测试、快速开发

# 举例说明

订单详情页面需要展示订单信息、商品信息和用户信息。可通过配置的方式生成一个接口先后调用底层微服务的订单详情接口、商品信息接口和用户信息接口,再从这3个接口的返回结果里提取需要的字段返回给前端页面。

# 服务编排架构

# 适用场景

# 前端

1、一个页面调用多个接口时,可以编排好返回聚合结果,提高页面数据的加载速度

2、移动设备计算能力有限,可以把数据计算或业务处理逻辑放到服务端完成,加快页面响应

# 后端

1、替换应用层的聚合接口,减少应用层的胶水代码

2、快速生成透传数据类型的接口

3、数据转换和映射

上次更新: 2020-9-9 17:26
- + diff --git a/docs/guide/aggregate/overview.html b/docs/guide/aggregate/overview.html index f74e1ca..3361607 100644 --- a/docs/guide/aggregate/overview.html +++ b/docs/guide/aggregate/overview.html @@ -7,7 +7,7 @@ - + @@ -23,7 +23,7 @@ 使用文档 查看源码 -

1.创建服务

此服务是一个分组的概念,可以包含多个聚合接口,类似于微服务体系里的服务

2.创建服务编排接口

3.开通网关白名单和配置访问策略和插件

4.测试服务编排接口

5.发布接口

界面总览

上次更新: 2020-9-9 17:26
- + diff --git a/docs/guide/benchmark/index.html b/docs/guide/benchmark/index.html index d61a032..8374339 100644 --- a/docs/guide/benchmark/index.html +++ b/docs/guide/benchmark/index.html @@ -7,7 +7,7 @@ - + @@ -23,14 +23,18 @@ 使用文档 查看源码 -

# 基准测试结果

我们将Fizz与Spring官方spring-cloud-gateway进行比较,使用相同的环境和条件,测试对象均为单个节点。

产品 QPS 90% Latency(ms)
直接访问后端服务 9087.46 10.76
fizz-gateway 5927.13 19.86
spring-cloud-gateway 5044.04 22.91

# 基准测试详情

# 硬件环境

后端服务所在服务器:

4核8G内存

Intel(R) Xeon(R) CPU X5675 @ 3.07GHz * 4

Linux version 3.10.0-327.el7.x86_64

节点所在服务器:

4核8G内存

Intel(R) Xeon(R) CPU X5675 @ 3.07GHz * 4

Linux version 3.10.0-327.el7.x86_64

压测程序所在服务器:

4核8G内存

Intel(R) Xeon(R) CPU X5675 @ 3.07GHz * 4

Linux version 3.10.0-327.el7.x86_64

# 压测工具

压测软件:wrk

并发连接: 100

# 压测结果截图

- + + 管理后台简介 + + → +

+ diff --git a/docs/guide/index.html b/docs/guide/index.html index 7bc5dc7..5bab2b2 100644 --- a/docs/guide/index.html +++ b/docs/guide/index.html @@ -7,7 +7,7 @@ - + @@ -23,7 +23,7 @@ 使用文档 查看源码 -
上次更新: 2020-7-31 17:12
- +
上次更新: 2020-7-31 17:12
+ diff --git a/docs/guide/installation/index.html b/docs/guide/installation/index.html index de60425..85144c4 100644 --- a/docs/guide/installation/index.html +++ b/docs/guide/installation/index.html @@ -7,7 +7,7 @@ - + @@ -23,7 +23,7 @@ 使用文档 查看源码 -

# 安装依赖

安装以下依赖软件:

  • Redis 2.8或以上版本
  • MySQL 5.7或以上版本
  • Apollo配置中心 (可选)
  • Eureka服务注册中心

# 安装MySQL

  • 操作系统 CentOS 6.5
  • MySQL 5.7.30
  1. 下载MySQL
wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-1.el6.x86_64.rpm-bundle.tar
+        

# 安装依赖

安装以下依赖软件:

  • Redis 2.8或以上版本
  • MySQL 5.7或以上版本
  • Apollo配置中心 (可选)
  • Eureka服务注册中心

# 安装MySQL

  • 操作系统 CentOS 6.5
  • MySQL 5.7.30
  1. 下载MySQL
wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-1.el6.x86_64.rpm-bundle.tar
 
  1. 解压
tar -xvf mysql-5.7.30-1.el6.x86_64.rpm-bundle.tar
 
  1. 安装
sudo yum install mysql-community-{server,client,common,libs}-*
 
  1. 启动
sudo service mysqld start
@@ -78,7 +78,7 @@ export JAVA_HOME JRE_HOME PATH CLASSPATH
 eureka.server.enableSelfPreservation=false
 

2) maven构建并运行sc-eureka-server应用, 启动后访问地址http://localhost:8761/可以看到Eureka注册中心的界面

3)把target/sc-eureka-server-1.0.0.jar传到linux服务器上运行. (仅以单机部署为例)

nohub java -jar sc-eureka-server-1.0.0.jar & 
 

4)eureka客户端的注册地址为:http://localhost:8761/eureka/ (替换localhost为服务器的IP)

eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka/
-

# 安装Fizz

# 管理后台

从github的releases(https://github.com/wehotel/fizz-gateway-community/releases)下载 fizz-manager-professional 和 fizz-admin-professional 的安装包

  • 管理后台服务端(fizz-manager-professional)
  1. 首次安装执行fizz-manager-professional-1.0.0-mysql.sql数据库脚本
  2. application-prod.ymlboot.shfizz-manager-professional-1.0.0.jar拷贝到/data/webapps/fizz-manager-professional目录下
  3. 修改application-prod.yml文件,将相关配置修改成部署环境的配置
  4. 修改boot.sh文件,将RUN_CMD变量值修改成部署环境的JAVA实际路径
  5. 执行 chmod +x boot.sh 命令给boot.sh增加执行权限
  6. 执行 ./boot.sh start 命令启动服务,支持 start/stop/restart/status命令
  7. 服务启动后访问 http://IP:8000/fizz-manager (将IP替换成服务部署机器IP地址),使用超级管理员账户admin密码Aa123!登录
  • 管理后台前端(fizz-admin-professional)

zip资源包解压后,取文件夹【fizzAdmin】放置于服务器静态数据存放目录 如:/home/data/

nginx配置

server {
+

# 安装Fizz

# 管理后台

从github的releases(https://github.com/wehotel/fizz-gateway-community/releases)下载 fizz-manager-professional 和 fizz-admin-professional 的安装包

  • 管理后台服务端(fizz-manager-professional)
  1. 首次安装执行fizz-manager-professional-1.1.0-mysql.sql数据库脚本,低版本升级执行update目录下的升级脚本
  2. application-prod.ymlboot.shfizz-manager-professional-1.1.0.jar拷贝到/data/webapps/fizz-manager-professional目录下
  3. 修改application-prod.yml文件,将相关配置修改成部署环境的配置
  4. 修改boot.sh文件,将RUN_CMD变量值修改成部署环境的JAVA实际路径
  5. 执行 chmod +x boot.sh 命令给boot.sh增加执行权限
  6. 执行 ./boot.sh start 命令启动服务,支持 start/stop/restart(升级发布时需要手动kill原进程)/status命令
  7. 服务启动后访问前端登录地址,使用超级管理员账户admin密码Aa123!登录
  • 管理后台前端(fizz-admin-professional)

zip资源包解压后,取文件夹【fizzAdmin】放置于服务器静态数据存放目录 如:/home/data/

nginx配置

server {
   listen 9000;
   server_name localhost:9000;
   location / {
@@ -92,7 +92,7 @@ export JAVA_HOME JRE_HOME PATH CLASSPATH
 
 # 注:root中地址需与资源包存放目录路径一致
 # 注:http://127.0.0.1:8000 为管理后台(fizz-manager-professional)的访问地址
-

访问地址

【资源部署服务器IP + 端口号】如:http://127.0.0.1:9000/

(端口号与nginx配置端口号一致)

# fizz-gateway-community社区版

说明:如果使用apollo配置中心,可把application.yml文件内容迁到配置中心(apollo上应用名为:fizz-gateway);使用不使用apollo可去掉下面启动命令里的apollo参数。

脚本启动:

  1. 下载fizz-gateway-community的最新代码,修改application.yml配置文件里eureka、redis的配置,使用maven构建好并把构建好的fizz-gateway-community-1.0.0.jar和boot.sh放同一目录
  2. 修改boot.sh脚本的apollo连接,JVM内存配置,
  3. 执行 ./boot.sh start 命令启动服务,支持 start/stop/restart/status命令

IDE启动:

  1. 本地clone仓库上的最新代码
  2. 将项目fizz-gateway导入IDE
  3. 导入完成后设置项目启动配置及修改application.yml配置文件里eureka、redis的配置,在VM选项中加入-Denv=dev -Dapollo.meta=http://localhost:66(Apollo配置中心地址)

jar启动:

  1. 本地clone仓库上的最新代码,修改application.yml配置文件里eureka、redis的配置
  2. 在项目根目录fizz-gateway-community下执行Maven命令mvn clean package -DskipTests=true打包
  3. 进入target目录,使用命令java -jar -Denv=DEV -Dapollo.meta=http://localhost:66 fizz-gateway-community-1.0.0.jar启动服务

网关访问地址格式:

http://127.0.0.1:8600/proxy/[服务名]/[API Path]

上次更新: 2020-9-21 13:6

访问地址

【资源部署服务器IP + 端口号】如:http://127.0.0.1:9000/

(端口号与nginx配置端口号一致)

# fizz-gateway-community社区版

说明:如果使用apollo配置中心,可把application.yml文件内容迁到配置中心(apollo上应用名为:fizz-gateway);使用不使用apollo可去掉下面启动命令里的apollo参数。

脚本启动:

  1. 下载fizz-gateway-community的最新代码,修改application.yml配置文件里eureka、redis的配置,使用maven构建好并把构建好的fizz-gateway-community-1.0.0.jar和boot.sh放同一目录
  2. 修改boot.sh脚本的apollo连接,JVM内存配置,
  3. 执行 ./boot.sh start 命令启动服务,支持 start/stop/restart/status命令

IDE启动:

  1. 本地clone仓库上的最新代码
  2. 将项目fizz-gateway导入IDE
  3. 导入完成后设置项目启动配置及修改application.yml配置文件里eureka、redis的配置,在VM选项中加入-Denv=dev -Dapollo.meta=http://localhost:66(Apollo配置中心地址)

jar启动:

  1. 本地clone仓库上的最新代码,修改application.yml配置文件里eureka、redis的配置
  2. 在项目根目录fizz-gateway-community下执行Maven命令mvn clean package -DskipTests=true打包
  3. 进入target目录,使用命令java -jar -Denv=DEV -Dapollo.meta=http://localhost:66 fizz-gateway-community-1.0.0.jar启动服务

网关访问地址格式:

http://127.0.0.1:8600/proxy/[服务名]/[API Path]

上次更新: 2020-10-27 14:46
- + diff --git a/docs/guide/intro/index.html b/docs/guide/intro/index.html index eb33fe0..c46fb0e 100644 --- a/docs/guide/intro/index.html +++ b/docs/guide/intro/index.html @@ -7,7 +7,7 @@ - + @@ -23,11 +23,11 @@ 使用文档 查看源码 -

# 什么是Fizz网关

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

# Fizz的设计

# 产品特性

  • 集群管理:Fizz网关节点是无状态的,配置信息自动同步,支持节点水平拓展和多集群部署。
  • 服务编排:支持热服务编排能力,支持前后端编码,随时随地更新API。
  • 负载均衡:支持round-robin负载均衡。
  • 服务发现:支持从Eureka注册中心发现后端服务器。
  • 配置中心:支持接入apollo配置中心。
  • HTTP反向代理:隐藏真实后端服务,支持 Rest API反向代理。
  • 访问策略:支持不同策略访问不同的API、配置不同的鉴权等。
  • IP黑白名单:支持配置IP黑白名单。
  • 自定义插件:强大的插件机制支持自由扩展。
  • 可扩展:简单易用的插件机制方便扩展功能。
  • 高性能:性能在众多网关之中表现优异。
  • 版本控制:支持操作的发布和多次回滚。
  • 管理后台:通过管理后台界面对网关集群进行各项配置。
上次更新: 2020-9-9 17:26
- + diff --git a/docs/guide/manager/manager_aggregate.html b/docs/guide/manager/manager_aggregate.html new file mode 100644 index 0000000..446e7ae --- /dev/null +++ b/docs/guide/manager/manager_aggregate.html @@ -0,0 +1,143 @@ + + + + + + 接口列表 | Fizz Gateway + + + + + + + +

# 概述

接口列表功能用于维护聚合接口,聚合接口从外部调用方角度看是一个简单的接口,通过入参请求获取响应结果,内部实现会调用多个底层后端服务,将多个调用结果聚合转换成外部调用方想要的数据格式,更多详情请查看服务编排介绍,下面介绍接口列表功能的操作。

# 接口列表

菜单位置:服务编排 > 接口列表。点击菜单后进入接口列表页面,如图所示。

manager_aggregate_list_query

# 新增接口

点击 新增 按钮弹出新增窗口,如图所示。

manager_aggregate_add_1

# 基础信息

manager_aggregate_add_2

所属服务:接口所属服务,更多详情请查看服务管理功能介绍,必选;

接口名:接口名称,用于展示使用,长度不能超过200个字符,必填;

方法:接口请求方法类型,可选GET|POST,必选;

路径:接口请求路径后缀,长度不能超过2000个字符,必填;

开发人员:接口对应负责的开发人员,长度不能超过200个字符;

描述:接口功能描述,长度不能超过2000个字符;

举个例子,所属服务设置my-test-service,方法设置POST,路径设置test-aggregate-post,对应的聚合接口请求为 POST http://{Fizz网关ip地址}:{port端口}/proxy/my-test-service/test-aggregate-post。

# 配置输入

聚合接口的入参大部分是通过JSON Schema来定义的,下面先简单地介绍下JSON Schema。

# JSON Schema介绍

JSON Schema实际上也是JSON数据,用于标注和验证JSON文档,可以类比于XML Schema,当前最新版本2019-09。

作为普通用户,我们并不需要去了解JSON Schema的规范内容,只要能够构建JSON Schema即可。

要理解JSON Schema,首先要理解什么是JSON。JSON是JavaScript Object Notation的缩写,一种简单的数据交换格式。最初JSON是基于JavaScript,广泛的应用于万维网。由于其简洁和清晰的层次结构、易于人阅读等特性,使得越来越多的场景下被采用。

JSON包含以下数据结构:

  • object:
    { "key1": "value1", "key2": "value2" }
    +
  • array:
    [ "first", "second", "third" ]
    +
  • number:
    42
    +3.1415926
    +
  • string:
    "This is a string"
    +
  • boolean:
    true
    +false
    +
  • null:
    null
    +

通过以上的简单数据类型,就能构造复杂的结构化数据了。下面举两个例子:

{
+  "name": "George Washington",
+  "birthday": "February 22, 1732",
+  "address": "Mount Vernon, Virginia, United States"
+}
+
{
+  "first_name": "George",
+  "last_name": "Washington",
+  "birthday": "1732-02-22",
+  "address": {
+    "street_address": "3200 Mount Vernon Memorial Highway",
+    "city": "Mount Vernon",
+    "state": "Virginia",
+    "country": "United States"
+  }
+}
+

以上两个例子都是有效的JSON数据,包含一样的有效信息,但是当程序读取数据时,需要准确的知道数据是怎么组织的,比如哪些字段是必须,这些字段是什么类型。这时候JSON Schema就派上用场了,看以下JSON Schema例子:

{
+  "type": "object",
+  "properties": {
+    "first_name": { "type": "string" },
+    "last_name": { "type": "string" },
+    "birthday": { "type": "string", "format": "date" },
+    "address": {
+      "type": "object",
+      "properties": {
+        "street_address": { "type": "string" },
+        "city": { "type": "string" },
+        "state": { "type": "string" },
+        "country": { "type" : "string" }
+      }
+    }
+  }
+}
+

用以上JSON Schema验证第一个例子时,验证失败;但是第二个例子验证通过。

JSON Schema本身也是通过JSON编写,其本身也是数据,不是一个计算机程序,只是一种“描述其它数据的结构”的声明格式。这既是长处,也是弱点,JSON Schema可以简洁地描述数据的结构并且自动验证数据,但是对于数据元素间的关系表达就力不能及了。

更多JSON Schema知识可以阅读Understanding JSON Schema

# 请求头部

定义聚合接口的请求Header参数。

manager_aggregate_add_3

举个例子:

{
+  "type": "object",
+  "properties": {
+    "headerParam1": {
+      "type": "string",
+      "title": "请求头参数1",
+      "titleEn": "headerParam1"
+    }
+  },
+  "required": [
+    "headerParam1"
+  ]
+}
+

以上例子定义了必传请求头参数headerParam1

title字段用于验证失败时提示使用,例如请求接口时没传请求头时会提示“请求头参数1不能为空”(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。

manager_aggregate_add_input_header_1

当定义了语言配置(详情请查看后文的语言配置介绍)选项为英文时会使用titleEn字段用于验证失败时提示使用,例如请求接口时没传请求头时会提示“headerParam1 is missing but it is required”(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。

manager_aggregate_add_input_header_2

# 请求体

定义聚合接口的请求体参数。

manager_aggregate_add_4

举个例子:

{
+  "type": "object",
+  "properties": {
+    "bodyParam1": {
+      "type": "string",
+      "title": "请求体参数1",
+      "titleEn": "bodyParam1"
+    }
+  },
+  "required": [
+    "bodyParam1"
+  ]
+}
+

以上例子定义了必传请求体参数bodyParam1

title字段用于验证失败时提示使用,例如请求接口时没传请求体参数时会提示“请求体参数1不能为空”(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。

manager_aggregate_add_input_body_1

当定义了语言配置(详情请查看后文的语言配置介绍)选项为英文时会使用titleEn字段用于验证失败时提示使用,例如请求接口时没传请求体参数时会提示“bodyParam1 is missing but it is required”(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。

manager_aggregate_add_input_body_2

# Query参数

定义聚合接口的Query参数。

manager_aggregate_add_5

举个例子:

{
+  "type": "object",
+  "properties": {
+    "queryParam1": {
+      "type": "string",
+      "title": "query参数1",
+      "titleEn": "queryParam1"
+    }
+  },
+  "required": [
+    "queryParam1"
+  ]
+}
+

以上例子定义了必传Query参数queryParam1

title字段用于验证失败时提示使用,例如请求接口时没传Query参数时会提示“query参数1不能为空”(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。

manager_aggregate_add_input_query_1

当定义了语言配置(详情请查看后文的语言配置介绍)选项为英文时会使用titleEn字段用于验证失败时提示使用,例如请求接口时没传Query参数时会提示“queryParam1 is missing but it is required”(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。

manager_aggregate_add_input_query_2

# 脚本校验

对于JSON Schema规范无法覆盖的校验场景可以使用脚本对入参进行更加灵活的处理。

manager_aggregate_add_6

点击 新增 按钮后弹出脚本配置窗口,如图所示。

manager_aggregate_add_7

脚本类型:可选javascript|groovy,必选;

脚本内容:所选的脚本类型语言编写的入参验证脚本,必填。

举个例子:

// javascript脚本函数名不能修改
+function dyFunc(paramsJsonStr) {
+  // 上下文, 数据结构请参考 context.js
+  var context = JSON.parse(paramsJsonStr)['context'];
+  // common为内置的上下文便捷操作工具类,详情请参考common.js;例如:
+  // var data = common.getStepRespBody(context, 'step2', 'request1', 'data');
+
+  // do something
+  var headerParam1 = common.getInputReqHeader(context, 'headerParam1');
+  var bodyParam1 = common.getInputReqBody(context, 'bodyParam1');
+  var queryParam1 = common.getInputReqParam(context, 'queryParam1');
+  var result = new Array();
+  if (headerParam1 != bodyParam1) {
+    result.push("headerParam1与bodyParam1不一致");
+  }
+  if (queryParam1 != bodyParam1) {
+    result.push("queryParam1与bodyParam1不一致");
+  }
+  if (headerParam1 != queryParam1) {
+    result.push("headerParam1与queryParam1不一致");
+  }
+
+  // 返回结果为Array或Object时要先转为json字符串
+  return JSON.stringify(result);
+}
+
+

以上例子使用javascript编写参数校验,限制入参headerParam1bodyParam1queryParam1必须一致,不一致将提示错误信息(错误提示输出通过校验结果配置,详情请看后文介绍),如图所示。

manager_aggregate_add_input_script

# 语言配置

聚合接口默认使用中文响应校验失败提示,通过配置可通过入参选择不同的提示语言,目前支持中文、英文提示(已满足我们的业务使用场景,有其他语言要求的小伙伴可以联系我们添加)。

manager_aggregate_add_8

字段:入参字段值,例如input.request.body.languageCode使用请求体参数languageCode的值来决定使用哪种语言;

中文:中文与入参字段值的映射关系,例如配置0,当请求入参字段值为0时使用中文提示校验结果;

英文:英文与入参字段值的映射关系,例如配置1,当请求入参字段值为1时使用中文提示校验结果。

# 配置步骤

聚合接口调用底层服务是通过多个step实现的,多个step串行执行,每个step包含多个request(对底层服务接口的调用),同个step里的多个request并行执行,后执行的step可以获取已执行step的执行结果,更多详情请查看服务编排文章的介绍,下面介绍配置步骤的使用。

manager_aggregate_add_9

是否执行完此步骤后结束:勾选后实际请求只执行完该步骤后即响应结果,不执行后续步骤,用于调试使用;

请求方法:调用底层服务接口的请求类型,可选GET|POST,必选;

默认URL:调用底层服务接口的默认URL,当Fizz网关启动环境没有配置URL时使用该默认URL;

开发环境URL:开发环境调用底层服务接口的URL,当Fizz网关启动使用spring.profiles.active=dev时使用该URL;

测试环境URL:测试环境调用底层服务接口的URL,当Fizz网关启动使用spring.profiles.active=test时使用该URL;

预生产环境URL:预生产环境调用底层服务接口的URL,当Fizz网关启动使用spring.profiles.active=pre时使用该URL;

生产环境URL:生产环境调用底层服务接口的URL,当Fizz网关启动使用spring.profiles.active=prod时使用该URL;

超时时间(毫秒):调用底层服务接口的超时时间,超时抛出异常,单位毫秒;

Fallback:可选stop|continue,控制当调用底层服务接口失败后是否继续执行后续操作;

请求预处理:勾选后可配置预处理脚本,预处理脚本返回true时才执行调用底层服务接口。

manager_aggregate_add_10

配置入参:配置调用底层服务接口的请求参数;

配置响应:配置调用底层服务接口的响应内容。

manager_aggregate_add_11

配置步骤结果:配置step执行完成后的响应内容。

# 配置输出

配置聚合接口调用完成的响应内容。在响应体、响应头配置中可以配置简单的响应固定值、响应引用值,对于需要逻辑处理得到结果的响应可以通过脚本配置灵活处理,如图所示。

manager_aggregate_add_12

manager_aggregate_add_13

# 校验结果

配置聚合接口入参校验失败后的响应内容,在响应体、响应头配置中可以配置简单的响应固定值、响应引用值,对于需要逻辑处理得到结果的响应可以通过脚本配置灵活处理,如图所示。

manager_aggregate_add_14

校验结果有一个专用的引用值validateMsg,该引用值用于存放入参验证错误提示信息。

# 保存接口

所有配置完成后点击 保存 按钮,完成聚合接口的配置。

manager_aggregate_add_15

# 导出接口

导出功能将聚合接口以配置文件的形式导出,导出的文件可通过导入功能重新导入系统,当我们的系统分多个环境时,可使用导出导入功能实现聚合接口的快速同步,下面介绍导出功能。

manager_aggregate_export_1

勾选想到导出的接口,点击 导出 按钮弹出确认窗口,如图所示。

manager_aggregate_export_2

点击 确定 按钮,浏览器保存配置文件,如图所示。

manager_aggregate_export_3

# 导入接口

导入功能将配置文件中的聚合接口转化成后台的持久化存储,导入的文件可以通过导出功能获取或者通过编写好的聚合配置JSON文件转化得到(转换工具可以联系我们获取)。当我们的系统分多个环境时,可使用导出导入功能实现聚合接口的快速同步,下面介绍导出功能。

manager_aggregate_import_1

点击 导入 按钮弹出导入配置窗口,如图所示。

manager_aggregate_import_2

点击 选取文件 按钮后选取要导入的配置文件;

强制覆盖:通过请求类型(GET|POST)、请求路径(/proxy/{service}/{apiPath})可以唯一确定一个聚合接口,当聚合接口已存在时,未勾选该选项时忽略该聚合接口导入,勾选该选项时覆盖已存在的聚合接口配置;

点击 确定 按钮后导入聚合接口配置。

# 调试模式

调试模式用于对接口开发过程中的调试使用,当打开调试模式后,Fizz网关会将聚合接口调用底层服务接口的请求响应信息以及耗时、聚合结果、步骤上下文打印到日志中,通过日志可以清楚的了解聚合接口的实际执行情况。调试模式会对网关性能造成影响,因此不建议在生产环境打开调试模式,当调试完成后及时关闭调试模式,避免打印过多日志造成资源浪费,下面介绍调试模式的使用。

勾选想要打开调试模式的接口,点击 打开调试模式 按钮弹出确认窗口,如图所示。

manager_aggregate_debug_mode_1

点击 确定 按钮确认打开调试模式。

manager_aggregate_debug_mode_2

勾选想要关闭调试模式的接口,点击 关闭调试模式 按钮弹出确认窗口,如图所示。

manager_aggregate_debug_mode_3

点击 确定 按钮确认关闭调试模式。

manager_aggregate_debug_mode_4

# 编辑接口

点击 编辑 按钮弹出编辑窗口,如图所示。

manager_aggregate_edit_1

manager_aggregate_edit_2

# 删除接口

点击 删除 按钮弹出删除确认窗口,如图所示。

manager_aggregate_delete_1

manager_aggregate_delete_2

点击 确定 按钮后删除接口,处于已发布状态的接口无法删除,需要下线后才能操作删除。

# 发布|下线申请

发布|下线申请用于聚合接口的发布或者下线申请,只有通过审核人审核后申请人才能执行发布|下线操作,避免误操作‘,保证接口的安全。

点击 发布|下线申请 按钮,弹出发布|下线申请窗口,如图所示。

manager_aggregate_apply_1

manager_aggregate_apply_2

点击 添加 按钮后,弹出接口列表,勾选需要操作的接口,点击 确定 添加进申请中。

manager_aggregate_apply_3

标题:申请的标题,长度不能超过200个字符,必填;

类型:申请类型,可选发布|下线,必选;

申请原因:申请的原因,长度不能超过2000个字符;

选择审核人:选择有审核权限的人对申请进行审核,列表根据需要操作的接口动态变化(未添加接口时列表为空,拥有服务权限并且有待审核菜单权限的人、操作管理员角色的人为可选审核人),必选;

点击 确定 按钮后提交申请,选择的审核人会收到申请审核邮件(审核人邮箱地址通过用户管理设置,更多详情请查看用户管理功能介绍),如图所示。

manager_aggregate_apply_4

# 接口测试

后台提供了可视化的接口调用界面,聚合接口创建完成后可通过该界面对接口进行调用测试。通过点击接口详情页面的 测试 按钮打开接口测试页面,如图所示。

manager_aggregate_test_1

跳转页面的同时后台会将接口当前的最新配置推送给Fizz网关生成一个测试接口,请求路径为/proxytest/{service}/{apiPath}。

manager_aggregate_test_2

点击 发送 按钮向指定接口发送一次请求,Response响应结果区域显示调用接口结果,如图所示。

manager_aggregate_test_3

manager_aggregate_test_4

请求体tab用于配置请求的请求体参数。

manager_aggregate_test_5

请求头tab用于配置请求的请求头参数。

manager_aggregate_test_6

Query参数用于配置请求的Query参数。

manager_aggregate_test_7

返回Context:Fizz网关中一次聚合接口的请求过程中内部会持有一个Context对象,该对象保存了本次请求过程的入参信息、底层服务接口调用信息、响应信息,通过勾选该选项,接口会将Context随接口响应一起返回,通过查看Context可以清楚地了解接口的实际调用过程。

未勾选 返回Context 选项时,接口按配置输出的设置响应结果,如图所示。

manager_aggregate_test_8

勾选 返回Context 选项后,接口会将Context随接口响应一起返回,如图所示。

manager_aggregate_test_9

测试接口:调用测试接口,请求路径为/proxytest/{service}/{apiPath};

正式接口:调用正式接口,请求路径为/proxy/{service}/{apiPath};

manager_aggregate_test_10

点击 保存 按钮会将本次测试请求数据保存下来,通过选取已保存的测试记录可以快速恢复请求数据,如图所示。

manager_aggregate_test_11

标题:本次测试数据保存时使用的标题,长度不能超过2000个字符,保存后在历史测试记录列表显示,如图所示。

manager_aggregate_test_12

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/manager/manager_aggregate_approve.html b/docs/guide/manager/manager_aggregate_approve.html new file mode 100644 index 0000000..e4f65b8 --- /dev/null +++ b/docs/guide/manager/manager_aggregate_approve.html @@ -0,0 +1,37 @@ + + + + + + 待审核 | Fizz Gateway + + + + + + + +

# 概述

聚合接口的发布|下线操作需要提交发布|下线申请,审核通过后申请人才能执行发布|下线操作。待审核功能用于审核发布|下线申请,下面介绍待审核功能。

# 审核列表

菜单位置:发布申请 > 待审核。点击菜单后进入审核列表页面,如图所示。

manager_aggregate_approve_list_query

# 审核操作

点击 查看 按钮可以查看发布|下线申请详情,详情页中可执行审核操作。

申请列表页提供快速审核操作,点击 审核 按钮后弹出审核确认窗口,如图所示。

manager_aggregate_approve_op_1

manager_aggregate_approve_op_2

审核结果:勾选通过,审核后申请能可执行申请的操作;勾选不通过,审核后申请失败,申请人不能执行申请的操作。

审核后申请人会收到审核结果邮件通知,如下图是审核通过的邮件通知。

manager_aggregate_approve_op_3

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/manager/manager_aggregate_approve_op_log.html b/docs/guide/manager/manager_aggregate_approve_op_log.html new file mode 100644 index 0000000..6120f2b --- /dev/null +++ b/docs/guide/manager/manager_aggregate_approve_op_log.html @@ -0,0 +1,37 @@ + + + + + + 审核日志 | Fizz Gateway + + + + + + + + + + + diff --git a/docs/guide/manager/manager_aggregate_my_apply.html b/docs/guide/manager/manager_aggregate_my_apply.html new file mode 100644 index 0000000..cb6e78f --- /dev/null +++ b/docs/guide/manager/manager_aggregate_my_apply.html @@ -0,0 +1,37 @@ + + + + + + 我的申请 | Fizz Gateway + + + + + + + +

# 概述

聚合接口的发布|下线操作需要提交发布|下线申请,审核通过后申请人才能执行发布|下线操作。我的申请功能用于发布|下线申请过程的相关操作,下面介绍我的申请功能。

# 申请列表

菜单位置:发布申请 > 我的申请。点击菜单后进入申请列表页面,如图所示。

manager_aggregate_my_apply_list_query

# 申请撤回

对于已提交但未被审核的申请可执行撤回操作,点击 撤回 按钮弹出确认窗口,如图所示。

manager_aggregate_my_apply_revoke_1

点击 确定 按钮后确认撤回申请,如图所示。

manager_aggregate_my_apply_revoke_2

撤回后审核人会收到邮箱提醒无需再处理该申请,如图所示。

manager_aggregate_my_apply_revoke_3

撤回后可对申请重新进行编辑后再次提交,点击 编辑 按钮后弹出编辑窗口,如图所示。

manager_aggregate_my_apply_revoke_4

点击 确定 按钮后再次提交申请,如图所示。

manager_aggregate_my_apply_revoke_5

# 申请详情

点击 查看 按钮查看申请详情。

manager_aggregate_my_apply_detail_1

manager_aggregate_my_apply_detail_2

操作日志记录该申请的所有操作,包括申请提交、申请撤回、申请重新提交、审核不通过、审核通过、修改审核人、接口发布、接口下线 、接口回滚、接口撤回。

待审核状态申请可以更换审核人,点击 修改审核人 按钮后弹出修改审核人窗口,如图所示。

manager_aggregate_my_apply_detail_3

重新选择审核人后点击 确定 按钮,修改审核人完成。

修改后原审核人会收到邮件提醒无须再处理该申请。

修改后新的审核人会收到邮件提醒需要处理该申请。

审核通过后可以对接口进行发布操作,如图所示。

manager_aggregate_my_apply_detail_4

批量发布:对申请内的接口批量发布推送到Fizz网关。

批量回滚:对申请内的接口批量回滚到上一个版本,当发布后接口异常时该操作相当有用。

对于申请通过后又无须操作的接口可以执行撤回操作,撤回接口时必须填写备注信息用于回溯查询,如图所示。

manager_aggregate_my_apply_detail_5

manager_aggregate_my_apply_detail_6

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/manager/manager_aggregate_op_log.html b/docs/guide/manager/manager_aggregate_op_log.html new file mode 100644 index 0000000..488b671 --- /dev/null +++ b/docs/guide/manager/manager_aggregate_op_log.html @@ -0,0 +1,37 @@ + + + + + + 操作日志 | Fizz Gateway + + + + + + + +

# 概述

管理后台记录了聚合接口的新增、修改、发布、下线、回滚、删除操作日志,通过查看操作日志可以清楚地掌握接口的操作轨迹。操作日志功能提供界面查询聚合接口的操作日志。

# 操作日志列表

菜单位置:服务编排 > 操作日志。点击菜单后进入操作日志列表页面,如图所示。

manager_aggregate_op_log_list_query

# 查看日志详情

点击 查看 按钮弹出操作日志详情页面,如图所示。

manager_aggregate_op_log_detail_1

manager_aggregate_op_log_detail_2

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/manager/manager_api_auth.html b/docs/guide/manager/manager_api_auth.html new file mode 100644 index 0000000..9032114 --- /dev/null +++ b/docs/guide/manager/manager_api_auth.html @@ -0,0 +1,37 @@ + + + + + + 路由管理 | Fizz Gateway + + + + + + + +

# 概述

路由管理功能用于维护网关的路由规则,支持按请求路径转发、转发到指定后端服务两种转发规则,支持插件配置。下面介绍路由管理的操作。

# 路由列表

菜单位置:网关管理 > 路由管理。点击菜单后进入路由列表页面,如图所示。

manager_api_auth_list_query

# 新增路由

点击 新增 按钮弹出新增窗口,如图所示。

manager_api_auth_add_1

manager_api_auth_add_2

网关分组:选取路由关联的网关分组,只有属于所选分组的网关实例路由规则才会生效,必选;

服务:网关的请求路径格式为 http://{ip}:{port}/proxy/{service}{apiPath},服务对应{service}段,当 转发 选择 按请求路径转发 时服务需要是聚合配置的服务或者是Eureka注册的服务,当 转发 选择 转发到指定后端服务 时服务不需要是实际存在的服务,只用于路径匹配使用,长度不能超过50个字符,必填;

API方法:请求的method类型,可选GET|POST;

API Path:网关的请求路径格式为 http://{ip}:{port}/proxy/{service}{apiPath},API Path对应{apiPath}段,使用前缀匹配原则,例如"/api/"将匹配"/api/"、"/api/1"、"/api/1/1"等路径;

应用:选取路由关联的应用,网关使用选取应用的信息进行鉴权,更多详情请查看appID管理功能介绍;

访问:可选允许|禁止,必选;

转发:可选按请求路径转发|转发到指定后端服务,当选择 按请求路径转发 时,请求会按请求路径转发,例如网关请求 http://{ip}:{port}/proxy/my-service/api-path 将转发到 http://my-service/api-path;当选择 转发到指定后端服务 时,需要添加转发到的后端服务URL,请求会转发到配置的后端服务,例如配置了服务为 my-service,API Path为空,后端服务URL为 http://127.0.0.1:8080/forward-service/,网关请求 http://{ip}:{port}/proxy/my-service/api-path 将转发到 http://127.0.0.1:8080/forward-service/api-path。

点击 添加插件 按钮为路由添加插件,如图所示。

manager_api_auth_add_3

配置插件路由级别的自定义配置,表单界面来自于插件的表单定义,更多详情请查看插件管理功能介绍。

manager_api_auth_add_4

配置完成后点击 保存 按钮保存路由规则。

manager_api_auth_add_5

# 编辑路由

点击 编辑 按钮弹出编辑窗口,如图所示。

manager_api_auth_edit_1

manager_api_auth_edit_2

# 删除路由

点击 删除 按钮弹出删除确认窗口,如图所示。

manager_api_auth_delete_1

manager_api_auth_delete_2

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/manager/manager_app_id.html b/docs/guide/manager/manager_app_id.html new file mode 100644 index 0000000..ba78751 --- /dev/null +++ b/docs/guide/manager/manager_app_id.html @@ -0,0 +1,37 @@ + + + + + + appID管理 | Fizz Gateway + + + + + + + +

# 概述

appID管理功能维护应用鉴权信息,可配置是否启用签名、是否启用IP白名单,AppID级别的自定义配置供自定义插件使用。appID用于在路由管理配置中关联路由规则,当对应路由规则触发时会对应用进行鉴权。

# appID列表

菜单位置:网关管理 > appID管理。点击菜单后进入appID列表页面,如图所示。

manager_app_id_list_query

# 新增appID

点击 新增 按钮弹出新增窗口,如图所示。

manager_app_id_add_1

manager_app_id_add_2

appID:第三方应用唯一标识,长度不能超过64个字符,必填;

应用名:第三方应用名称,长度不能超过128个字符,必填;

是否启用签名:当启动时必须配置 认证方式 和 密钥;

认证方式:可选 密钥(使用网关内置鉴权方式验证)|自定义认证插件(使用自定义的鉴权逻辑),更多信息请查看Fizz网关的介绍;启用签名时必填;

密钥:第三方应用使用的密钥,可通过 生成随机密钥 按钮生成一个随机的密钥,启用签名时必填;

是否启用IP白名单:当启用时可以配置 IP白名单,网关会根据请求来源IP地址进行过滤;

IP白名单:IP段支持 1.2.3.100-120 和 1.2.3.*两种格式,仅最后一段可用范围或星号表示;

自定义配置:AppID级别的自定义配置供自定义插件使用,所有插件均可获取到此配置信息。

# 编辑appID

点击 编辑 按钮弹出编辑窗口,如图所示。

manager_app_id_edit_1

manager_app_id_edit_2

# 删除appID

点击 删除 按钮弹出删除确认窗口,如图所示。

manager_app_id_delete_1

manager_app_id_delete_2

点击 确定 按钮后删除appID,如果appID存在关联的路由配置时,对应关联的路由配置也会一起删除。

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/manager/manager_gateway_aggregate_cache.html b/docs/guide/manager/manager_gateway_aggregate_cache.html new file mode 100644 index 0000000..a4bc5b4 --- /dev/null +++ b/docs/guide/manager/manager_gateway_aggregate_cache.html @@ -0,0 +1,37 @@ + + + + + + 网关缓存 | Fizz Gateway + + + + + + + +

# 概述

网关缓存功能用于查询Fizz网关实例本地缓存的已发布接口信息,可以快速的了解当前网关实例生效的全部接口,同时通过查看后台接口发布版本号与网关实例本地缓存的接口版本号是否一致可以排查接口缓存问题,下面介绍网关缓存功能的操作。

# 网关列表

菜单位置:服务编排 > 网关缓存。点击菜单后进入网关列表页面,如图所示。

manager_aggregate_gateway_list_query

Fizz网关与后台注册到同一个eureka注册中心,后台通过eureka获取网关的实例列表。

# 网关缓存列表

点击 查看 按钮后弹出网关详情页面,该页面显示所选网关实例的接口缓存列表,如图所示。

manager_aggregate_gateway_cache_list_query_1

manager_aggregate_gateway_cache_list_query_2

# 网关缓存详情

点击 查看 按钮弹出所选接口的配置详情,如图所示。

manager_aggregate_gateway_cache_detail_1

manager_aggregate_gateway_cache_detail_2

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/manager/manager_gateway_group.html b/docs/guide/manager/manager_gateway_group.html new file mode 100644 index 0000000..163ab7f --- /dev/null +++ b/docs/guide/manager/manager_gateway_group.html @@ -0,0 +1,37 @@ + + + + + + 网关分组 | Fizz Gateway + + + + + + + +

# 概述

网关分组功能用于维护分组元数据,将网关实例IP与分组关联,通过为不同的分组配置不同的路由策略,从而实现网关的分组管理。

# 分组示例

我们的线上业务涉及To C(个人用户)、To B(企业)、To T(第三方),对于不同业务会有对应的机器接受请求访问,不同的业务需要有各自的路由策略,因此进行了如下的分组划分。

分组ID 分组名称 描述
default 默认分组 默认分组是后台默认创建的分组,不用指定IP,不属于其它分组的机器都归到默认分组,默认分组不可修改或删除
c 2c分组 只接受面向个人用户的请求
b 2b分组 只接受面向企业的请求
t 面向第三方的分组 只接受面向第三方的请求

下面介绍网关分组功能的操作。

# 分组列表

菜单位置:网关管理 > 网关分组。点击菜单后进入分组列表页面,如图所示。

manager_gateway_group_list_query

# 新增分组

点击 新增 按钮弹出新增窗口,如图所示。

manager_gateway_group_add_1

manager_gateway_group_add_2

分组ID:分组的唯一标识,长度不能超过32个字符,必填;

分组名称:分组的名称,用于在分组选项时展示,长度不能超过32个字符,必填;

网关实例IP:Fizz网关集群内的机器IP地址,多个IP地址使用逗号分隔。

# 编辑分组

点击 编辑 按钮弹出编辑窗口,如图所示。

manager_gateway_group_edit_1

manager_gateway_group_edit_2

# 删除分组

点击 删除 按钮弹出删除确认窗口,如图所示。

manager_gateway_group_delete_1

manager_gateway_group_delete_2

点击 确定 按钮后删除网关分组,如果网关分组存在关联的路由配置时,需要将关联的路由配置全部删除后才能删除分组。

上次更新: 2020-10-27 14:43
+ + + diff --git a/docs/guide/manager/manager_overview.html b/docs/guide/manager/manager_overview.html new file mode 100644 index 0000000..2fd899f --- /dev/null +++ b/docs/guide/manager/manager_overview.html @@ -0,0 +1,42 @@ + + + + + + 管理后台简介 | Fizz Gateway + + + + + + + +

# 概述

Fizz管理后台是Fizz网关的配套系统,基于Java、Vue开发,通过界面对Fizz网关集群进行各项配置。

# 功能

Fizz管理后台包含如下功能:

  • 网关管理 +
    • 网关分组:对Fizz网关集群内的机器进行逻辑上的分组,针对不同的分组可配置不同的路由策略。
    • 插件管理:维护插件元数据,定义路由级别的自定义属性、插件级别的自定义配置信息。
    • appID管理:配置应用鉴权信息,可配置是否启用签名、是否启用IP白名单,AppID级别的自定义配置供自定义插件使用。
    • 路由管理:配置服务或API路由规则,支持按请求路径转发、转发到指定后端服务两种转发规则,支持插件配置。
    • 接口统计:Fizz网关接口访问统计功能,以图表的形式展示指定时间段内每日的接口总数、访问次数,可查看接口的历史访问总次数以及最近请求时间。
  • 服务编排 +
    • 服务管理:聚合接口归属于服务,服务通过该功能维护,创建人自动获得服务权限,服务权限可分配,拥有权限的用户才能操作对应的接口列表。
    • 接口列表:基于现有的业务微服务使用在线配置的方式快速的生成一个聚合接口,同时提供在线测试功能,发布历史版本查看。
    • 操作日志:查看聚合接口的新增、修改、发布、下线、回滚、删除操作日志。
    • 网关缓存:查看Fizz网关当前在线的实例列表以及对应实例本地缓存的已发布接口信息。
  • 发布申请 +
    • 我的申请:提交接口发布|下线申请,审核通过后可以对相关接口执行发布|下线操作。
    • 待审核:审核发布|下线申请。
    • 审核日志:查看审核发布|下线申请操作日志。
  • 权限管理 +
    • 角色管理:维护角色数据,为角色分配权限。
  • 系统管理 +
    • 用户管理:维护用户数据,为用户分配角色。

# 界面

manager_overview_1

manager_overview_2

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/manager/manager_plugin.html b/docs/guide/manager/manager_plugin.html new file mode 100644 index 0000000..65a5462 --- /dev/null +++ b/docs/guide/manager/manager_plugin.html @@ -0,0 +1,148 @@ + + + + + + 插件管理 | Fizz Gateway + + + + + + + +

# 概述

插件管理功能用于维护插件元数据,定义路由级别的自定义属性、插件级别的自定义配置信息。创建的插件用于路由管理设置时启用,当网关接受请求匹配路由规则时会触发启用的插件逻辑执行,插件逻辑中可获取到自定义的属性数据。

# 插件列表

菜单位置:网关管理 > 插件管理。点击菜单后进入插件管理列表页面,如图所示。

manager_plugin_list_query

# 新增插件

点击 新增 按钮弹出新增窗口,如图所示。

manager_plugin_add_1

manager_plugin_add_2

插件名称:插件名称由英文字母、下划线或数字组成,不能以数字开头,长度不能超过50个字符,必填;

插件描述:插件的简要描述,长度不能超过50个字符,必填;

默认执行顺序:插件的默认执行顺序,按从小到大排序,值越小越先执行,取值范围0~255,必填;

表单定义:路由级别的自定义属性,在路由管理配置启用插件时前端会将表单定义转化为表单输入界面,更多信息请查看路由管理介绍。表单规范说明如下:

/*
+* plugin_config_design
+* 动态插件参考结构
+* */
+
+const pluginConfig = [
+  {
+	/* 必有字段 */
+	"field": "inputVal",
+	"label": "输入框",
+	"component": "input", // input, select, radio, checkbox,
+	"dataType": "string", // number(long, double), string, boolean, array
+	/* 可选字段 */
+	"desc": "字段的说明文字",
+	"placeholder": "placeholder文字",
+	"default": "Aa123", // 初始默认值
+	"options": [ // for select, radio, checkbox
+	  {
+		"label": "选项1",
+		"value": 1  // number(long, double), string, boolean,
+	  },
+	  {
+		"label": "选项2",
+		"value": 2
+	  }
+	],
+	"rules": [ // min|max / range / length / regex pattern
+	  { "required": true, "message": "输入框不能为空", "trigger": "change" }, // required 必填
+	  // { "min": 3, "ma x": 5, "message": "长度在 3 到 5 个字符", "trigger": "change" }, // range 长度范围(for dataType:"string")
+	  // { "len": 8, "message": "长度需 8 个字符", "trigger": "change" }, // length 长度限制(for dataType:"string")
+	  // { "type": "number", "message": "请输入数字类型"}, // for dataType:"number" 校验数值
+	  // { "type": "integer", "message": "请输入整数数值", "trigger": "change" }, // for dataType:"long" 校验整数
+	  // { "type": "float", "message": "请输入浮点数数值", "trigger": "change" }, // for dataType:"double" 校验浮点数
+	  { "pattern": "^[A-Za-z\\d]+$", "message": "只能是字母或数字", "trigger": "change" } // regex pattern正则
+	]
+  },
+  {
+	"field": "selectVal",
+	"label": "选择器",
+	"component": "select",
+	"dataType": "number",
+	"options": [
+	  {
+		"label": "选项1",
+		"value": 1
+	  },
+	  {
+		"label": "选项2",
+		"value": 2
+	  },
+	  {
+		"label": "选项3",
+		"value": 3
+	  }
+	],
+	"desc": "选择器的说明文字",
+	"placeholder": "请选择",
+	"rules": [
+	  { "required": true, "message": "选择器不能为空", "trigger": "change" }
+	]
+  },
+  {
+	"field": "radioVal",
+	"label": "单选框",
+	"component": "radio",
+	"dataType": "boolean",
+	"default": true,
+	"options": [
+	  {
+		"label": "是",
+		"value": true
+	  },
+	  {
+		"label": "否",
+		"value": false
+	  }
+	],
+	"desc": "单选框的说明文字",
+	"rules": [
+	  { "required": true, "message": "请选择单选框", "trigger": "change" }
+	]
+  },
+  {
+	"field": "checkboxVal",
+	"label": "多选框",
+	"component": "checkbox",
+	"dataType": "array",
+	"options": [
+	  {
+		"label": "选项1",
+		"value": 11
+	  },
+	  {
+		"label": "选项2",
+		"value": 22
+	  },
+	  {
+		"label": "选项3",
+		"value": 33
+	  }
+	],
+	"desc": "多选框的说明文字",
+	"rules": [
+	  { "required": true, "message": "请选择多选框", "trigger": "change" }
+	]
+  }
+];
+
+// TODO 注意!!
+//  组件 "checkbox" 的dataType = "array"
+//  组件 "radio/select" 的实际值类型等于options内的value值类型
+

自定义配置:插件级别的自定义配置信息,插件逻辑中可获取到该信息。

# 编辑插件

点击 编辑 按钮弹出编辑窗口,如图所示。

manager_plugin_edit_1

manager_plugin_edit_2

# 删除插件

点击 删除 按钮弹出删除确认窗口,如图所示。

manager_plugin_delete_1

manager_plugin_delete_2

点击 确定 按钮后删除插件,如果插件存在关联的路由配置时,需要将关联的路由配置全部删除后才能删除插件。

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/manager/manager_role.html b/docs/guide/manager/manager_role.html new file mode 100644 index 0000000..d6d6015 --- /dev/null +++ b/docs/guide/manager/manager_role.html @@ -0,0 +1,37 @@ + + + + + + 角色管理 | Fizz Gateway + + + + + + + +

# 概述

角色管理功能维护角色元数据,通过配置角色拥有的菜单资源,限制用户只能操作拥有的角色对应的菜单资源,下面介绍角色管理功能的操作。

# 角色列表

菜单位置:权限管理 > 角色管理。点击菜单后进入角色列表页面,如图所示。

manager_role_list_query

# 添加角色

点击 新增 按钮弹出新增窗口,如图所示。

manager_role_add_1

manager_role_add_2

# 权限设置

勾选需要分配权限的角色,点击 权限设置 按钮弹出角色权限配置窗口,如图所示。

manager_role_auth_1

manager_role_auth_2

勾选菜单后点击 确定 按钮确认给角色分配菜单权限。

# 编辑角色

点击 编辑 按钮弹出编辑窗口,如图所示。

manager_role_edit_1

manager_role_edit_2

# 删除角色

点击 删除 按钮弹出删除确认窗口,如图所示。

manager_role_delete_1

manager_role_delete_2

点击 确定 按钮后删除角色。

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/manager/manager_service.html b/docs/guide/manager/manager_service.html new file mode 100644 index 0000000..1b56189 --- /dev/null +++ b/docs/guide/manager/manager_service.html @@ -0,0 +1,37 @@ + + + + + + 服务管理 | Fizz Gateway + + + + + + + +

# 概述

服务管理功能维护服务元数据。服务编排中的服务是一个逻辑上的概念,用于对聚合接口的归类以及权限的分配。Fizz网关聚合接口的请求路径格式为 http://{ip}:{port}/proxy/{service}{apiPath},服务对应{service}段。

# 服务列表

菜单位置:服务编排 > 服务管理。点击菜单后进入服务列表页面,如图所示。

manager_service_list_query

# 新增服务

点击 新增 按钮弹出新增窗口,如图所示。

manager_service_add_1

manager_service_add_2

服务 ID:服务唯一标识,对应Fizz网关聚合接口请求路径(格式为 http://{ip}:{port}/proxy/{service}{apiPath})的{service}段,长度不能超过200个字符,必填;

服务名:服务名称,用于展示或者选项使用,必填;

团队:团队名称,长度不能超过200个字符;

负责人:负责人名称,长度不能超过200个字符;

描述:服务描述,长度不能超过2000个字符。

# 编辑服务

点击 编辑 按钮弹出编辑窗口,如图所示。

manager_service_edit_1

manager_service_edit_2

# 删除服务

点击 删除 按钮弹出删除确认窗口,如图所示。

manager_service_delete_1

manager_service_delete_2

点击 确定 按钮后删除服务,如果服务存在关联的聚合接口时,需要将关联的聚合接口全部删除后才能删除服务。

# 服务权限分配

点击 权限 按钮弹出权限配置窗口,如图所示。

manager_service_auth_1

manager_service_auth_2

服务创建人自动获得服务权限,服务权限可分配,拥有权限的用户才能操作对应的接口列表。

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/manager/manager_source_statistics.html b/docs/guide/manager/manager_source_statistics.html new file mode 100644 index 0000000..b26af18 --- /dev/null +++ b/docs/guide/manager/manager_source_statistics.html @@ -0,0 +1,29 @@ + + + + + + 接口统计 | Fizz Gateway + + + + + + + +

# 概述

Fizz网关会将访问请求数据(IP地址、网关分组、服务、应用、请求方法、API Path、请求时间)推送到Kafka中,管理后台消费Kafka消息统计接口访问数据。

接口统计功能以图表的形式展示指定时间段内每日的接口总数、访问次数,可查看接口的历史访问总次数以及最近请求时间。

# 接口访问统计

菜单位置:网关管理 > 接口统计。点击菜单后进入接口统计页面,如图所示。

manager_source_statistics_1.png

今天接口总数:从0时到当前时刻被调用不同接口的总数;

今天访问次数:从0时到当前时刻访问请求的总次数。

接口总数图表:显示指定时间段内每日被调用不同接口的总数曲线;

访问次数图表:显示指定时间段内每日访问请求的总次数曲线。

# 请求统计

接口统计界面下部为请求统计列表,如图所示。

manager_source_statistics_2.png

来源IP:网关请求的实际入口IP地址;

请求次数:( 唯一[来源IP、网关分组、服务名、请求方法、appID、API Path])历史总请求次数;

最近请求时间:( 唯一[来源IP、网关分组、服务名、请求方法、appID、API Path])最近一次调用时间。

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/manager/manager_user.html b/docs/guide/manager/manager_user.html new file mode 100644 index 0000000..82c876f --- /dev/null +++ b/docs/guide/manager/manager_user.html @@ -0,0 +1,33 @@ + + + + + + 用户管理 | Fizz Gateway + + + + + + + +

# 概述

用户管理功能用于维护用户元数据,包括用户信息维护、密码维护、角色配置。

# 用户列表

菜单位置:系统管理 > 用户管理。点击菜单后进入用户列表页面,如图所示。

manager_user_list_query

# 添加用户

点击 新增 按钮弹出新增窗口,如图所示。

manager_user_add_1

manager_user_add_2

电子邮箱:用户用于接收电子邮件的邮箱地址,后台涉及邮件发送业务使用该字段设置的邮箱地址来进行邮箱发送。

# 重置密码

勾选用户后点击 密码重置 按钮可为用户重置密码。

manager_user_reset_password_1

manager_user_reset_password_2

重置后的默认密码为AsdF1234!

# 编辑用户

点击 编辑 按钮弹出编辑窗口,如图所示。

manager_user_edit_1

manager_user_edit_2

# 删除用户

点击 删除 按钮弹出删除确认窗口,如图所示。

manager_user_delete_1

manager_user_delete_2

上次更新: 2020-10-26 18:40
+ + + diff --git a/docs/guide/plugin/index.html b/docs/guide/plugin/index.html index 0604f7b..4d023a7 100644 --- a/docs/guide/plugin/index.html +++ b/docs/guide/plugin/index.html @@ -7,7 +7,7 @@ - + @@ -23,7 +23,7 @@ 使用文档 查看源码 -

# 概述

当需要在gateway中加入自定义的逻辑时,可通过fizz的插件机制实现,插件:
+

# 概述

当需要在gateway中加入自定义的逻辑时,可通过fizz的插件机制实现,插件:
1、类似spring的WebFilter,是fizz内部的WebFilter,由fizz调度;
2、对不同的请求,可配置不同的上下文参数,可通过manager完成配置;
3、若有多个插件,当前插件可获取前面插件的执行结果。

插件的开发和应用,分gateway开发、manager配置两部分,下面以一个例子,依次介绍。

# gateway开发

    实现
@@ -120,6 +120,6 @@
       
       →
     

- + diff --git a/docs/guide/proxy/index.html b/docs/guide/proxy/index.html index 254cce7..f1bb5da 100644 --- a/docs/guide/proxy/index.html +++ b/docs/guide/proxy/index.html @@ -7,7 +7,7 @@ - + @@ -23,7 +23,7 @@ 使用文档 查看源码 -

# 路由转发介绍

路由转发也叫反向代理,为内部微服务提供统一的对外入口。支持以下功能:

  • 支持服务注册与发现
  • 支持负载均衡
  • 支持黑白名单机制
  • 支持配置插件

# 接入路由转发

  • 前提条件:接入Eureka注册中心
  • 开通白名单,接入注册中心的服务默认不对公网开放 (白名单在配置文件里配置serviceWhiteList)
  • 配置访问权限 (管理后台-接口代理-API查询)
上次更新: 2020-9-8 15:3
- + diff --git a/docs/index.html b/docs/index.html index cc8d59c..e068b2b 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,7 +7,7 @@ - + @@ -32,6 +32,6 @@

智能路由

支持服务注册与发现,支持负载均衡,支持配置插件和黑白名单。

服务编排

基于现有的业务微服务通过在线配置的方式快速的生成一个聚合接口。减少中间层胶水代码以及降低编码投入

插件机制

强大的插件系统,内置通用常用插件,同时支持自定义插件开发。

- + diff --git a/docs/manager_aggregate_add_1.png b/docs/manager_aggregate_add_1.png new file mode 100644 index 0000000..6041352 Binary files /dev/null and b/docs/manager_aggregate_add_1.png differ diff --git a/docs/manager_aggregate_add_10.png b/docs/manager_aggregate_add_10.png new file mode 100644 index 0000000..ab7293d Binary files /dev/null and b/docs/manager_aggregate_add_10.png differ diff --git a/docs/manager_aggregate_add_11.png b/docs/manager_aggregate_add_11.png new file mode 100644 index 0000000..0b1a51d Binary files /dev/null and b/docs/manager_aggregate_add_11.png differ diff --git a/docs/manager_aggregate_add_12.png b/docs/manager_aggregate_add_12.png new file mode 100644 index 0000000..a7017b2 Binary files /dev/null and b/docs/manager_aggregate_add_12.png differ diff --git a/docs/manager_aggregate_add_13.png b/docs/manager_aggregate_add_13.png new file mode 100644 index 0000000..aa3f205 Binary files /dev/null and b/docs/manager_aggregate_add_13.png differ diff --git a/docs/manager_aggregate_add_14.png b/docs/manager_aggregate_add_14.png new file mode 100644 index 0000000..28f02f7 Binary files /dev/null and b/docs/manager_aggregate_add_14.png differ diff --git a/docs/manager_aggregate_add_15.png b/docs/manager_aggregate_add_15.png new file mode 100644 index 0000000..66d9225 Binary files /dev/null and b/docs/manager_aggregate_add_15.png differ diff --git a/docs/manager_aggregate_add_2.png b/docs/manager_aggregate_add_2.png new file mode 100644 index 0000000..77fdf91 Binary files /dev/null and b/docs/manager_aggregate_add_2.png differ diff --git a/docs/manager_aggregate_add_3.png b/docs/manager_aggregate_add_3.png new file mode 100644 index 0000000..2c377d6 Binary files /dev/null and b/docs/manager_aggregate_add_3.png differ diff --git a/docs/manager_aggregate_add_4.png b/docs/manager_aggregate_add_4.png new file mode 100644 index 0000000..46a935b Binary files /dev/null and b/docs/manager_aggregate_add_4.png differ diff --git a/docs/manager_aggregate_add_5.png b/docs/manager_aggregate_add_5.png new file mode 100644 index 0000000..8e101c6 Binary files /dev/null and b/docs/manager_aggregate_add_5.png differ diff --git a/docs/manager_aggregate_add_6.png b/docs/manager_aggregate_add_6.png new file mode 100644 index 0000000..32fb14e Binary files /dev/null and b/docs/manager_aggregate_add_6.png differ diff --git a/docs/manager_aggregate_add_7.png b/docs/manager_aggregate_add_7.png new file mode 100644 index 0000000..735641e Binary files /dev/null and b/docs/manager_aggregate_add_7.png differ diff --git a/docs/manager_aggregate_add_8.png b/docs/manager_aggregate_add_8.png new file mode 100644 index 0000000..0c55dbc Binary files /dev/null and b/docs/manager_aggregate_add_8.png differ diff --git a/docs/manager_aggregate_add_9.png b/docs/manager_aggregate_add_9.png new file mode 100644 index 0000000..a416688 Binary files /dev/null and b/docs/manager_aggregate_add_9.png differ diff --git a/docs/manager_aggregate_add_input_body_1.png b/docs/manager_aggregate_add_input_body_1.png new file mode 100644 index 0000000..e34fa58 Binary files /dev/null and b/docs/manager_aggregate_add_input_body_1.png differ diff --git a/docs/manager_aggregate_add_input_body_2.png b/docs/manager_aggregate_add_input_body_2.png new file mode 100644 index 0000000..0d23459 Binary files /dev/null and b/docs/manager_aggregate_add_input_body_2.png differ diff --git a/docs/manager_aggregate_add_input_header_1.png b/docs/manager_aggregate_add_input_header_1.png new file mode 100644 index 0000000..7b40898 Binary files /dev/null and b/docs/manager_aggregate_add_input_header_1.png differ diff --git a/docs/manager_aggregate_add_input_header_2.png b/docs/manager_aggregate_add_input_header_2.png new file mode 100644 index 0000000..357195c Binary files /dev/null and b/docs/manager_aggregate_add_input_header_2.png differ diff --git a/docs/manager_aggregate_add_input_query_1.png b/docs/manager_aggregate_add_input_query_1.png new file mode 100644 index 0000000..acc5077 Binary files /dev/null and b/docs/manager_aggregate_add_input_query_1.png differ diff --git a/docs/manager_aggregate_add_input_query_2.png b/docs/manager_aggregate_add_input_query_2.png new file mode 100644 index 0000000..e520bfb Binary files /dev/null and b/docs/manager_aggregate_add_input_query_2.png differ diff --git a/docs/manager_aggregate_add_input_script.png b/docs/manager_aggregate_add_input_script.png new file mode 100644 index 0000000..4f4eb3e Binary files /dev/null and b/docs/manager_aggregate_add_input_script.png differ diff --git a/docs/manager_aggregate_apply_1.png b/docs/manager_aggregate_apply_1.png new file mode 100644 index 0000000..2cc2f06 Binary files /dev/null and b/docs/manager_aggregate_apply_1.png differ diff --git a/docs/manager_aggregate_apply_2.png b/docs/manager_aggregate_apply_2.png new file mode 100644 index 0000000..65ff714 Binary files /dev/null and b/docs/manager_aggregate_apply_2.png differ diff --git a/docs/manager_aggregate_apply_3.png b/docs/manager_aggregate_apply_3.png new file mode 100644 index 0000000..1e5a70f Binary files /dev/null and b/docs/manager_aggregate_apply_3.png differ diff --git a/docs/manager_aggregate_apply_4.png b/docs/manager_aggregate_apply_4.png new file mode 100644 index 0000000..dcb4ac3 Binary files /dev/null and b/docs/manager_aggregate_apply_4.png differ diff --git a/docs/manager_aggregate_approve_list_query.png b/docs/manager_aggregate_approve_list_query.png new file mode 100644 index 0000000..2584cd9 Binary files /dev/null and b/docs/manager_aggregate_approve_list_query.png differ diff --git a/docs/manager_aggregate_approve_op_1.png b/docs/manager_aggregate_approve_op_1.png new file mode 100644 index 0000000..8c40f21 Binary files /dev/null and b/docs/manager_aggregate_approve_op_1.png differ diff --git a/docs/manager_aggregate_approve_op_2.png b/docs/manager_aggregate_approve_op_2.png new file mode 100644 index 0000000..ec6e954 Binary files /dev/null and b/docs/manager_aggregate_approve_op_2.png differ diff --git a/docs/manager_aggregate_approve_op_3.png b/docs/manager_aggregate_approve_op_3.png new file mode 100644 index 0000000..fc87e17 Binary files /dev/null and b/docs/manager_aggregate_approve_op_3.png differ diff --git a/docs/manager_aggregate_approve_op_log_detail_1.png b/docs/manager_aggregate_approve_op_log_detail_1.png new file mode 100644 index 0000000..aed288e Binary files /dev/null and b/docs/manager_aggregate_approve_op_log_detail_1.png differ diff --git a/docs/manager_aggregate_approve_op_log_detail_2.png b/docs/manager_aggregate_approve_op_log_detail_2.png new file mode 100644 index 0000000..12b9fb2 Binary files /dev/null and b/docs/manager_aggregate_approve_op_log_detail_2.png differ diff --git a/docs/manager_aggregate_approve_op_log_list_query.png b/docs/manager_aggregate_approve_op_log_list_query.png new file mode 100644 index 0000000..9325638 Binary files /dev/null and b/docs/manager_aggregate_approve_op_log_list_query.png differ diff --git a/docs/manager_aggregate_debug_mode_1.png b/docs/manager_aggregate_debug_mode_1.png new file mode 100644 index 0000000..05790e1 Binary files /dev/null and b/docs/manager_aggregate_debug_mode_1.png differ diff --git a/docs/manager_aggregate_debug_mode_2.png b/docs/manager_aggregate_debug_mode_2.png new file mode 100644 index 0000000..45be5a9 Binary files /dev/null and b/docs/manager_aggregate_debug_mode_2.png differ diff --git a/docs/manager_aggregate_debug_mode_3.png b/docs/manager_aggregate_debug_mode_3.png new file mode 100644 index 0000000..198f4f3 Binary files /dev/null and b/docs/manager_aggregate_debug_mode_3.png differ diff --git a/docs/manager_aggregate_debug_mode_4.png b/docs/manager_aggregate_debug_mode_4.png new file mode 100644 index 0000000..e0479c8 Binary files /dev/null and b/docs/manager_aggregate_debug_mode_4.png differ diff --git a/docs/manager_aggregate_delete_1.png b/docs/manager_aggregate_delete_1.png new file mode 100644 index 0000000..70ee50e Binary files /dev/null and b/docs/manager_aggregate_delete_1.png differ diff --git a/docs/manager_aggregate_delete_2.png b/docs/manager_aggregate_delete_2.png new file mode 100644 index 0000000..86d597d Binary files /dev/null and b/docs/manager_aggregate_delete_2.png differ diff --git a/docs/manager_aggregate_edit_1.png b/docs/manager_aggregate_edit_1.png new file mode 100644 index 0000000..1244b82 Binary files /dev/null and b/docs/manager_aggregate_edit_1.png differ diff --git a/docs/manager_aggregate_edit_2.png b/docs/manager_aggregate_edit_2.png new file mode 100644 index 0000000..2905092 Binary files /dev/null and b/docs/manager_aggregate_edit_2.png differ diff --git a/docs/manager_aggregate_export_1.png b/docs/manager_aggregate_export_1.png new file mode 100644 index 0000000..e785657 Binary files /dev/null and b/docs/manager_aggregate_export_1.png differ diff --git a/docs/manager_aggregate_export_2.png b/docs/manager_aggregate_export_2.png new file mode 100644 index 0000000..b785eb8 Binary files /dev/null and b/docs/manager_aggregate_export_2.png differ diff --git a/docs/manager_aggregate_export_3.png b/docs/manager_aggregate_export_3.png new file mode 100644 index 0000000..e049b95 Binary files /dev/null and b/docs/manager_aggregate_export_3.png differ diff --git a/docs/manager_aggregate_gateway_cache_detail_1.png b/docs/manager_aggregate_gateway_cache_detail_1.png new file mode 100644 index 0000000..584a58a Binary files /dev/null and b/docs/manager_aggregate_gateway_cache_detail_1.png differ diff --git a/docs/manager_aggregate_gateway_cache_detail_2.png b/docs/manager_aggregate_gateway_cache_detail_2.png new file mode 100644 index 0000000..46d293b Binary files /dev/null and b/docs/manager_aggregate_gateway_cache_detail_2.png differ diff --git a/docs/manager_aggregate_gateway_cache_list_query_1.png b/docs/manager_aggregate_gateway_cache_list_query_1.png new file mode 100644 index 0000000..a7b26d3 Binary files /dev/null and b/docs/manager_aggregate_gateway_cache_list_query_1.png differ diff --git a/docs/manager_aggregate_gateway_cache_list_query_2.png b/docs/manager_aggregate_gateway_cache_list_query_2.png new file mode 100644 index 0000000..2a861ea Binary files /dev/null and b/docs/manager_aggregate_gateway_cache_list_query_2.png differ diff --git a/docs/manager_aggregate_gateway_list_query.png b/docs/manager_aggregate_gateway_list_query.png new file mode 100644 index 0000000..b093a3b Binary files /dev/null and b/docs/manager_aggregate_gateway_list_query.png differ diff --git a/docs/manager_aggregate_import_1.png b/docs/manager_aggregate_import_1.png new file mode 100644 index 0000000..800ea68 Binary files /dev/null and b/docs/manager_aggregate_import_1.png differ diff --git a/docs/manager_aggregate_import_2.png b/docs/manager_aggregate_import_2.png new file mode 100644 index 0000000..5550600 Binary files /dev/null and b/docs/manager_aggregate_import_2.png differ diff --git a/docs/manager_aggregate_list_query.png b/docs/manager_aggregate_list_query.png new file mode 100644 index 0000000..cb5416f Binary files /dev/null and b/docs/manager_aggregate_list_query.png differ diff --git a/docs/manager_aggregate_my_apply_detail_1.png b/docs/manager_aggregate_my_apply_detail_1.png new file mode 100644 index 0000000..89493d9 Binary files /dev/null and b/docs/manager_aggregate_my_apply_detail_1.png differ diff --git a/docs/manager_aggregate_my_apply_detail_2.png b/docs/manager_aggregate_my_apply_detail_2.png new file mode 100644 index 0000000..af3d90f Binary files /dev/null and b/docs/manager_aggregate_my_apply_detail_2.png differ diff --git a/docs/manager_aggregate_my_apply_detail_3.png b/docs/manager_aggregate_my_apply_detail_3.png new file mode 100644 index 0000000..286ad50 Binary files /dev/null and b/docs/manager_aggregate_my_apply_detail_3.png differ diff --git a/docs/manager_aggregate_my_apply_detail_4.png b/docs/manager_aggregate_my_apply_detail_4.png new file mode 100644 index 0000000..e61f5fb Binary files /dev/null and b/docs/manager_aggregate_my_apply_detail_4.png differ diff --git a/docs/manager_aggregate_my_apply_detail_5.png b/docs/manager_aggregate_my_apply_detail_5.png new file mode 100644 index 0000000..63541e7 Binary files /dev/null and b/docs/manager_aggregate_my_apply_detail_5.png differ diff --git a/docs/manager_aggregate_my_apply_detail_6.png b/docs/manager_aggregate_my_apply_detail_6.png new file mode 100644 index 0000000..a48075a Binary files /dev/null and b/docs/manager_aggregate_my_apply_detail_6.png differ diff --git a/docs/manager_aggregate_my_apply_list_query.png b/docs/manager_aggregate_my_apply_list_query.png new file mode 100644 index 0000000..9e82fb1 Binary files /dev/null and b/docs/manager_aggregate_my_apply_list_query.png differ diff --git a/docs/manager_aggregate_my_apply_revoke_1.png b/docs/manager_aggregate_my_apply_revoke_1.png new file mode 100644 index 0000000..75bc28c Binary files /dev/null and b/docs/manager_aggregate_my_apply_revoke_1.png differ diff --git a/docs/manager_aggregate_my_apply_revoke_2.png b/docs/manager_aggregate_my_apply_revoke_2.png new file mode 100644 index 0000000..55ccb9d Binary files /dev/null and b/docs/manager_aggregate_my_apply_revoke_2.png differ diff --git a/docs/manager_aggregate_my_apply_revoke_3.png b/docs/manager_aggregate_my_apply_revoke_3.png new file mode 100644 index 0000000..0e22434 Binary files /dev/null and b/docs/manager_aggregate_my_apply_revoke_3.png differ diff --git a/docs/manager_aggregate_my_apply_revoke_4.png b/docs/manager_aggregate_my_apply_revoke_4.png new file mode 100644 index 0000000..d6302a8 Binary files /dev/null and b/docs/manager_aggregate_my_apply_revoke_4.png differ diff --git a/docs/manager_aggregate_my_apply_revoke_5.png b/docs/manager_aggregate_my_apply_revoke_5.png new file mode 100644 index 0000000..08fc1ee Binary files /dev/null and b/docs/manager_aggregate_my_apply_revoke_5.png differ diff --git a/docs/manager_aggregate_op_log_detail_1.png b/docs/manager_aggregate_op_log_detail_1.png new file mode 100644 index 0000000..de2d35e Binary files /dev/null and b/docs/manager_aggregate_op_log_detail_1.png differ diff --git a/docs/manager_aggregate_op_log_detail_2.png b/docs/manager_aggregate_op_log_detail_2.png new file mode 100644 index 0000000..09e7086 Binary files /dev/null and b/docs/manager_aggregate_op_log_detail_2.png differ diff --git a/docs/manager_aggregate_op_log_list_query.png b/docs/manager_aggregate_op_log_list_query.png new file mode 100644 index 0000000..9db6e84 Binary files /dev/null and b/docs/manager_aggregate_op_log_list_query.png differ diff --git a/docs/manager_aggregate_test_1.png b/docs/manager_aggregate_test_1.png new file mode 100644 index 0000000..b2b9658 Binary files /dev/null and b/docs/manager_aggregate_test_1.png differ diff --git a/docs/manager_aggregate_test_10.png b/docs/manager_aggregate_test_10.png new file mode 100644 index 0000000..2adee66 Binary files /dev/null and b/docs/manager_aggregate_test_10.png differ diff --git a/docs/manager_aggregate_test_11.png b/docs/manager_aggregate_test_11.png new file mode 100644 index 0000000..b74df26 Binary files /dev/null and b/docs/manager_aggregate_test_11.png differ diff --git a/docs/manager_aggregate_test_12.png b/docs/manager_aggregate_test_12.png new file mode 100644 index 0000000..62b4e16 Binary files /dev/null and b/docs/manager_aggregate_test_12.png differ diff --git a/docs/manager_aggregate_test_2.png b/docs/manager_aggregate_test_2.png new file mode 100644 index 0000000..64b7ff2 Binary files /dev/null and b/docs/manager_aggregate_test_2.png differ diff --git a/docs/manager_aggregate_test_3.png b/docs/manager_aggregate_test_3.png new file mode 100644 index 0000000..023e254 Binary files /dev/null and b/docs/manager_aggregate_test_3.png differ diff --git a/docs/manager_aggregate_test_4.png b/docs/manager_aggregate_test_4.png new file mode 100644 index 0000000..3db699a Binary files /dev/null and b/docs/manager_aggregate_test_4.png differ diff --git a/docs/manager_aggregate_test_5.png b/docs/manager_aggregate_test_5.png new file mode 100644 index 0000000..20ed473 Binary files /dev/null and b/docs/manager_aggregate_test_5.png differ diff --git a/docs/manager_aggregate_test_6.png b/docs/manager_aggregate_test_6.png new file mode 100644 index 0000000..8c710aa Binary files /dev/null and b/docs/manager_aggregate_test_6.png differ diff --git a/docs/manager_aggregate_test_7.png b/docs/manager_aggregate_test_7.png new file mode 100644 index 0000000..5c63539 Binary files /dev/null and b/docs/manager_aggregate_test_7.png differ diff --git a/docs/manager_aggregate_test_8.png b/docs/manager_aggregate_test_8.png new file mode 100644 index 0000000..86a5dbf Binary files /dev/null and b/docs/manager_aggregate_test_8.png differ diff --git a/docs/manager_aggregate_test_9.png b/docs/manager_aggregate_test_9.png new file mode 100644 index 0000000..835639e Binary files /dev/null and b/docs/manager_aggregate_test_9.png differ diff --git a/docs/manager_api_auth_add_1.png b/docs/manager_api_auth_add_1.png new file mode 100644 index 0000000..02663cd Binary files /dev/null and b/docs/manager_api_auth_add_1.png differ diff --git a/docs/manager_api_auth_add_2.png b/docs/manager_api_auth_add_2.png new file mode 100644 index 0000000..78a7344 Binary files /dev/null and b/docs/manager_api_auth_add_2.png differ diff --git a/docs/manager_api_auth_add_3.png b/docs/manager_api_auth_add_3.png new file mode 100644 index 0000000..13b8db3 Binary files /dev/null and b/docs/manager_api_auth_add_3.png differ diff --git a/docs/manager_api_auth_add_4.png b/docs/manager_api_auth_add_4.png new file mode 100644 index 0000000..33d3ba3 Binary files /dev/null and b/docs/manager_api_auth_add_4.png differ diff --git a/docs/manager_api_auth_add_5.png b/docs/manager_api_auth_add_5.png new file mode 100644 index 0000000..2bdeb9a Binary files /dev/null and b/docs/manager_api_auth_add_5.png differ diff --git a/docs/manager_api_auth_delete_1.png b/docs/manager_api_auth_delete_1.png new file mode 100644 index 0000000..22e38ac Binary files /dev/null and b/docs/manager_api_auth_delete_1.png differ diff --git a/docs/manager_api_auth_delete_2.png b/docs/manager_api_auth_delete_2.png new file mode 100644 index 0000000..8043c05 Binary files /dev/null and b/docs/manager_api_auth_delete_2.png differ diff --git a/docs/manager_api_auth_edit_1.png b/docs/manager_api_auth_edit_1.png new file mode 100644 index 0000000..8922df5 Binary files /dev/null and b/docs/manager_api_auth_edit_1.png differ diff --git a/docs/manager_api_auth_edit_2.png b/docs/manager_api_auth_edit_2.png new file mode 100644 index 0000000..666e471 Binary files /dev/null and b/docs/manager_api_auth_edit_2.png differ diff --git a/docs/manager_api_auth_list_query.png b/docs/manager_api_auth_list_query.png new file mode 100644 index 0000000..f9aa0bd Binary files /dev/null and b/docs/manager_api_auth_list_query.png differ diff --git a/docs/manager_app_id_add_1.png b/docs/manager_app_id_add_1.png new file mode 100644 index 0000000..bee8a07 Binary files /dev/null and b/docs/manager_app_id_add_1.png differ diff --git a/docs/manager_app_id_add_2.png b/docs/manager_app_id_add_2.png new file mode 100644 index 0000000..30ff412 Binary files /dev/null and b/docs/manager_app_id_add_2.png differ diff --git a/docs/manager_app_id_delete_1.png b/docs/manager_app_id_delete_1.png new file mode 100644 index 0000000..c80ae6d Binary files /dev/null and b/docs/manager_app_id_delete_1.png differ diff --git a/docs/manager_app_id_delete_2.png b/docs/manager_app_id_delete_2.png new file mode 100644 index 0000000..1002250 Binary files /dev/null and b/docs/manager_app_id_delete_2.png differ diff --git a/docs/manager_app_id_edit_1.png b/docs/manager_app_id_edit_1.png new file mode 100644 index 0000000..69ee38e Binary files /dev/null and b/docs/manager_app_id_edit_1.png differ diff --git a/docs/manager_app_id_edit_2.png b/docs/manager_app_id_edit_2.png new file mode 100644 index 0000000..1ca5a58 Binary files /dev/null and b/docs/manager_app_id_edit_2.png differ diff --git a/docs/manager_app_id_list_query.png b/docs/manager_app_id_list_query.png new file mode 100644 index 0000000..b038ed2 Binary files /dev/null and b/docs/manager_app_id_list_query.png differ diff --git a/docs/manager_gateway_group_add_1.png b/docs/manager_gateway_group_add_1.png new file mode 100644 index 0000000..654b0bf Binary files /dev/null and b/docs/manager_gateway_group_add_1.png differ diff --git a/docs/manager_gateway_group_add_2.png b/docs/manager_gateway_group_add_2.png new file mode 100644 index 0000000..2798120 Binary files /dev/null and b/docs/manager_gateway_group_add_2.png differ diff --git a/docs/manager_gateway_group_delete_1.png b/docs/manager_gateway_group_delete_1.png new file mode 100644 index 0000000..3e5170a Binary files /dev/null and b/docs/manager_gateway_group_delete_1.png differ diff --git a/docs/manager_gateway_group_delete_2.png b/docs/manager_gateway_group_delete_2.png new file mode 100644 index 0000000..ef0ca72 Binary files /dev/null and b/docs/manager_gateway_group_delete_2.png differ diff --git a/docs/manager_gateway_group_edit_1.png b/docs/manager_gateway_group_edit_1.png new file mode 100644 index 0000000..b37b868 Binary files /dev/null and b/docs/manager_gateway_group_edit_1.png differ diff --git a/docs/manager_gateway_group_edit_2.png b/docs/manager_gateway_group_edit_2.png new file mode 100644 index 0000000..2f6b253 Binary files /dev/null and b/docs/manager_gateway_group_edit_2.png differ diff --git a/docs/manager_gateway_group_list_query.png b/docs/manager_gateway_group_list_query.png new file mode 100644 index 0000000..9ecc87e Binary files /dev/null and b/docs/manager_gateway_group_list_query.png differ diff --git a/docs/manager_overview_1.png b/docs/manager_overview_1.png new file mode 100644 index 0000000..5e4cce8 Binary files /dev/null and b/docs/manager_overview_1.png differ diff --git a/docs/manager_overview_2.png b/docs/manager_overview_2.png new file mode 100644 index 0000000..fdd4ab7 Binary files /dev/null and b/docs/manager_overview_2.png differ diff --git a/docs/manager_plugin_add_1.png b/docs/manager_plugin_add_1.png new file mode 100644 index 0000000..8a80fb3 Binary files /dev/null and b/docs/manager_plugin_add_1.png differ diff --git a/docs/manager_plugin_add_2.png b/docs/manager_plugin_add_2.png new file mode 100644 index 0000000..0f700a9 Binary files /dev/null and b/docs/manager_plugin_add_2.png differ diff --git a/docs/manager_plugin_delete_1.png b/docs/manager_plugin_delete_1.png new file mode 100644 index 0000000..bda77fc Binary files /dev/null and b/docs/manager_plugin_delete_1.png differ diff --git a/docs/manager_plugin_delete_2.png b/docs/manager_plugin_delete_2.png new file mode 100644 index 0000000..a2e9473 Binary files /dev/null and b/docs/manager_plugin_delete_2.png differ diff --git a/docs/manager_plugin_edit_1.png b/docs/manager_plugin_edit_1.png new file mode 100644 index 0000000..bbc22c1 Binary files /dev/null and b/docs/manager_plugin_edit_1.png differ diff --git a/docs/manager_plugin_edit_2.png b/docs/manager_plugin_edit_2.png new file mode 100644 index 0000000..828787a Binary files /dev/null and b/docs/manager_plugin_edit_2.png differ diff --git a/docs/manager_plugin_list_query.png b/docs/manager_plugin_list_query.png new file mode 100644 index 0000000..2346eb3 Binary files /dev/null and b/docs/manager_plugin_list_query.png differ diff --git a/docs/manager_role_add_1.png b/docs/manager_role_add_1.png new file mode 100644 index 0000000..4aa55ee Binary files /dev/null and b/docs/manager_role_add_1.png differ diff --git a/docs/manager_role_add_2.png b/docs/manager_role_add_2.png new file mode 100644 index 0000000..61ba935 Binary files /dev/null and b/docs/manager_role_add_2.png differ diff --git a/docs/manager_role_auth_1.png b/docs/manager_role_auth_1.png new file mode 100644 index 0000000..70076bd Binary files /dev/null and b/docs/manager_role_auth_1.png differ diff --git a/docs/manager_role_auth_2.png b/docs/manager_role_auth_2.png new file mode 100644 index 0000000..398b298 Binary files /dev/null and b/docs/manager_role_auth_2.png differ diff --git a/docs/manager_role_delete_1.png b/docs/manager_role_delete_1.png new file mode 100644 index 0000000..6f854e5 Binary files /dev/null and b/docs/manager_role_delete_1.png differ diff --git a/docs/manager_role_delete_2.png b/docs/manager_role_delete_2.png new file mode 100644 index 0000000..998b2c2 Binary files /dev/null and b/docs/manager_role_delete_2.png differ diff --git a/docs/manager_role_edit_1.png b/docs/manager_role_edit_1.png new file mode 100644 index 0000000..58dc3b4 Binary files /dev/null and b/docs/manager_role_edit_1.png differ diff --git a/docs/manager_role_edit_2.png b/docs/manager_role_edit_2.png new file mode 100644 index 0000000..0677d93 Binary files /dev/null and b/docs/manager_role_edit_2.png differ diff --git a/docs/manager_role_list_query.png b/docs/manager_role_list_query.png new file mode 100644 index 0000000..9729783 Binary files /dev/null and b/docs/manager_role_list_query.png differ diff --git a/docs/manager_service_add_1.png b/docs/manager_service_add_1.png new file mode 100644 index 0000000..71806d4 Binary files /dev/null and b/docs/manager_service_add_1.png differ diff --git a/docs/manager_service_add_2.png b/docs/manager_service_add_2.png new file mode 100644 index 0000000..4ebe681 Binary files /dev/null and b/docs/manager_service_add_2.png differ diff --git a/docs/manager_service_auth_1.png b/docs/manager_service_auth_1.png new file mode 100644 index 0000000..9d78dde Binary files /dev/null and b/docs/manager_service_auth_1.png differ diff --git a/docs/manager_service_auth_2.png b/docs/manager_service_auth_2.png new file mode 100644 index 0000000..cd7ede7 Binary files /dev/null and b/docs/manager_service_auth_2.png differ diff --git a/docs/manager_service_delete_1.png b/docs/manager_service_delete_1.png new file mode 100644 index 0000000..f8c3abc Binary files /dev/null and b/docs/manager_service_delete_1.png differ diff --git a/docs/manager_service_delete_2.png b/docs/manager_service_delete_2.png new file mode 100644 index 0000000..3e65628 Binary files /dev/null and b/docs/manager_service_delete_2.png differ diff --git a/docs/manager_service_edit_1.png b/docs/manager_service_edit_1.png new file mode 100644 index 0000000..2bcc623 Binary files /dev/null and b/docs/manager_service_edit_1.png differ diff --git a/docs/manager_service_edit_2.png b/docs/manager_service_edit_2.png new file mode 100644 index 0000000..5c345fc Binary files /dev/null and b/docs/manager_service_edit_2.png differ diff --git a/docs/manager_service_list_query.png b/docs/manager_service_list_query.png new file mode 100644 index 0000000..3b762cf Binary files /dev/null and b/docs/manager_service_list_query.png differ diff --git a/docs/manager_source_statistics_1.png b/docs/manager_source_statistics_1.png new file mode 100644 index 0000000..8873e80 Binary files /dev/null and b/docs/manager_source_statistics_1.png differ diff --git a/docs/manager_source_statistics_2.png b/docs/manager_source_statistics_2.png new file mode 100644 index 0000000..aced270 Binary files /dev/null and b/docs/manager_source_statistics_2.png differ diff --git a/docs/manager_user_add_1.png b/docs/manager_user_add_1.png new file mode 100644 index 0000000..2827108 Binary files /dev/null and b/docs/manager_user_add_1.png differ diff --git a/docs/manager_user_add_2.png b/docs/manager_user_add_2.png new file mode 100644 index 0000000..7ac623a Binary files /dev/null and b/docs/manager_user_add_2.png differ diff --git a/docs/manager_user_delete_1.png b/docs/manager_user_delete_1.png new file mode 100644 index 0000000..4638f5d Binary files /dev/null and b/docs/manager_user_delete_1.png differ diff --git a/docs/manager_user_delete_2.png b/docs/manager_user_delete_2.png new file mode 100644 index 0000000..95cf5a3 Binary files /dev/null and b/docs/manager_user_delete_2.png differ diff --git a/docs/manager_user_edit_1.png b/docs/manager_user_edit_1.png new file mode 100644 index 0000000..2424aaf Binary files /dev/null and b/docs/manager_user_edit_1.png differ diff --git a/docs/manager_user_edit_2.png b/docs/manager_user_edit_2.png new file mode 100644 index 0000000..353720f Binary files /dev/null and b/docs/manager_user_edit_2.png differ diff --git a/docs/manager_user_list_query.png b/docs/manager_user_list_query.png new file mode 100644 index 0000000..74bd861 Binary files /dev/null and b/docs/manager_user_list_query.png differ diff --git a/docs/manager_user_reset_password_1.png b/docs/manager_user_reset_password_1.png new file mode 100644 index 0000000..394ebf1 Binary files /dev/null and b/docs/manager_user_reset_password_1.png differ diff --git a/docs/manager_user_reset_password_2.png b/docs/manager_user_reset_password_2.png new file mode 100644 index 0000000..a2ed18b Binary files /dev/null and b/docs/manager_user_reset_password_2.png differ diff --git a/docs/ui_intro_aggr1.png b/docs/ui_intro_aggr1.png new file mode 100644 index 0000000..93ac5d0 Binary files /dev/null and b/docs/ui_intro_aggr1.png differ diff --git a/docs/ui_intro_aggr2.png b/docs/ui_intro_aggr2.png new file mode 100644 index 0000000..812d074 Binary files /dev/null and b/docs/ui_intro_aggr2.png differ diff --git a/docs/ui_intro_appid.png b/docs/ui_intro_appid.png new file mode 100644 index 0000000..0ef9ca7 Binary files /dev/null and b/docs/ui_intro_appid.png differ diff --git a/docs/ui_intro_plugin.png b/docs/ui_intro_plugin.png new file mode 100644 index 0000000..3f75a80 Binary files /dev/null and b/docs/ui_intro_plugin.png differ diff --git a/docs/ui_intro_route.png b/docs/ui_intro_route.png new file mode 100644 index 0000000..094ca69 Binary files /dev/null and b/docs/ui_intro_route.png differ diff --git a/lib/json-schema-validator-i18n-support-1.0.39_1.jar b/lib/json-schema-validator-i18n-support-1.0.39_3.jar similarity index 83% rename from lib/json-schema-validator-i18n-support-1.0.39_1.jar rename to lib/json-schema-validator-i18n-support-1.0.39_3.jar index 6446081..58aca0f 100644 Binary files a/lib/json-schema-validator-i18n-support-1.0.39_1.jar and b/lib/json-schema-validator-i18n-support-1.0.39_3.jar differ diff --git a/pom.xml b/pom.xml index 09a80f4..6f6fd32 100644 --- a/pom.xml +++ b/pom.xml @@ -5,13 +5,13 @@ org.springframework.boot spring-boot-starter-parent - 2.2.9.RELEASEaabb + 2.2.10.RELEASE we fizz-gateway-community - 1.0.0 - fizz-gateway + 1.1.0 + fizz-gateway-community @@ -35,20 +35,17 @@ 1.8 2.13.3 - + 4.1.53.Final + 4.5.13 com.networknt json-schema-validator-i18n-support - 1.0.39_1 + 1.0.39_3 system - ${project.basedir}/lib/json-schema-validator-i18n-support-1.0.39_1.jar + ${project.basedir}/lib/json-schema-validator-i18n-support-1.0.39_3.jar org.springframework.boot @@ -65,16 +62,11 @@ org.springframework.boot spring-boot-starter-log4j2 - com.alibaba fastjson - 1.2.73 + 1.2.74 @@ -141,13 +133,7 @@ commons-io commons-io - 2.6 - - - - commons-codec - commons-codec - 1.14 + 2.8.0 @@ -159,7 +145,7 @@ org.springframework.cloud spring-cloud-starter-netflix-eureka-client - 2.2.4.RELEASE + 2.2.5.RELEASE diff --git a/sh/boot.sh b/sh/boot.sh index e1b3c26..1403247 100644 --- a/sh/boot.sh +++ b/sh/boot.sh @@ -6,7 +6,7 @@ cd `dirname $0` #变量定义 APOLLO_META_SERVER=http://localhost:66 ENV=dev -APP_NAME=fizz-gateway-community-1.0.0.jar +APP_NAME=fizz-gateway-community-1.1.0.jar APP_DEP_DIR=/data/webapps/fizz-gateway APP_LOG_DIR=/data/logs/fizz-gateway JAVA_CMD=/usr/local/java/bin/java diff --git a/src/main/java/we/FizzAppContext.java b/src/main/java/we/FizzAppContext.java new file mode 100644 index 0000000..f9647a7 --- /dev/null +++ b/src/main/java/we/FizzAppContext.java @@ -0,0 +1,9 @@ +package we; + +import org.springframework.context.ConfigurableApplicationContext; + +public class FizzAppContext { + + public static ConfigurableApplicationContext appContext; + +} diff --git a/src/main/java/we/FizzGatewayApplication.java b/src/main/java/we/FizzGatewayApplication.java index a45c023..319b5ed 100644 --- a/src/main/java/we/FizzGatewayApplication.java +++ b/src/main/java/we/FizzGatewayApplication.java @@ -1,20 +1,3 @@ -/* - * Copyright (C) 2020 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - package we; import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig; @@ -24,20 +7,16 @@ import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; -import org.springframework.context.ConfigurableApplicationContext; -/** - * @author lancer - * @author francis - */ -@SpringBootApplication(exclude = {ErrorWebFluxAutoConfiguration.class, RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class}) -// @EnableApolloConfig +@SpringBootApplication( + exclude = {ErrorWebFluxAutoConfiguration.class, RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class}, + scanBasePackages = {"we"} +) +@EnableApolloConfig @EnableDiscoveryClient public class FizzGatewayApplication { - public static ConfigurableApplicationContext appContext; - public static void main(String[] args) { - FizzGatewayApplication.appContext = SpringApplication.run(FizzGatewayApplication.class, args); + FizzAppContext.appContext = SpringApplication.run(FizzGatewayApplication.class, args); } } diff --git a/src/main/java/we/apollo/ApolloLog4j2ConfigurationFactory.java b/src/main/java/we/apollo/ApolloLog4j2ConfigurationFactory.java index f29889f..5c61fc9 100644 --- a/src/main/java/we/apollo/ApolloLog4j2ConfigurationFactory.java +++ b/src/main/java/we/apollo/ApolloLog4j2ConfigurationFactory.java @@ -27,8 +27,6 @@ import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; -import org.apache.logging.log4j.core.config.Order; -import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.properties.PropertiesConfigurationBuilder; import java.net.URI; diff --git a/src/main/java/we/config/AggrWebClientConfig.java b/src/main/java/we/config/AggrWebClientConfig.java index 6f628f7..f59742a 100644 --- a/src/main/java/we/config/AggrWebClientConfig.java +++ b/src/main/java/we/config/AggrWebClientConfig.java @@ -23,8 +23,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.function.client.WebClient; /** - * @author lancer + * @author hongqiaowei */ + @Configuration @ConfigurationProperties(prefix = AggrWebClientConfig.prefix) public class AggrWebClientConfig extends WebClientConfig { diff --git a/src/main/java/we/config/AppConfigProperties.java b/src/main/java/we/config/AppConfigProperties.java index f5346b6..5e19b1d 100644 --- a/src/main/java/we/config/AppConfigProperties.java +++ b/src/main/java/we/config/AppConfigProperties.java @@ -23,6 +23,7 @@ import org.springframework.context.annotation.Configuration; /** * @author unknown */ + @Configuration public class AppConfigProperties { diff --git a/src/main/java/we/config/ProxyWebClientConfig.java b/src/main/java/we/config/ProxyWebClientConfig.java index 6a4ee94..a5164c0 100644 --- a/src/main/java/we/config/ProxyWebClientConfig.java +++ b/src/main/java/we/config/ProxyWebClientConfig.java @@ -23,8 +23,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.function.client.WebClient; /** - * @author lancer + * @author hongqiaowei */ + @Configuration @ConfigurationProperties(prefix = ProxyWebClientConfig.prefix) public class ProxyWebClientConfig extends WebClientConfig { diff --git a/src/main/java/we/config/RedisReactiveConfig.java b/src/main/java/we/config/RedisReactiveConfig.java index a6279bc..b38424c 100644 --- a/src/main/java/we/config/RedisReactiveConfig.java +++ b/src/main/java/we/config/RedisReactiveConfig.java @@ -30,8 +30,9 @@ import org.springframework.data.redis.connection.lettuce.LettucePoolingClientCon import org.springframework.data.redis.core.ReactiveStringRedisTemplate; /** - * @author lancer + * @author hongqiaowei */ + public abstract class RedisReactiveConfig { protected static final Logger log = LoggerFactory.getLogger(RedisReactiveConfig.class); diff --git a/src/main/java/we/config/RedisReactiveProperties.java b/src/main/java/we/config/RedisReactiveProperties.java index bf40def..29cfef3 100644 --- a/src/main/java/we/config/RedisReactiveProperties.java +++ b/src/main/java/we/config/RedisReactiveProperties.java @@ -21,14 +21,15 @@ import we.util.Constants; import we.util.Utils; /** - * @author lancer + * @author hongqiaowei */ + public abstract class RedisReactiveProperties { - private String host = "127.0.0.1"; - private int port = 6379; + private String host = "127.0.0.1"; + private int port = 6379; private String password; - private int database = 0; + private int database = 0; public String getHost() { return host; diff --git a/src/main/java/we/config/SystemConfig.java b/src/main/java/we/config/SystemConfig.java index c2048d9..0d8bab6 100644 --- a/src/main/java/we/config/SystemConfig.java +++ b/src/main/java/we/config/SystemConfig.java @@ -20,11 +20,13 @@ package we.config; import com.ctrip.framework.apollo.model.ConfigChange; import com.ctrip.framework.apollo.model.ConfigChangeEvent; import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener; + import we.plugin.auth.GatewayGroup; import we.util.Constants; import we.util.JacksonUtils; import we.util.NetworkUtils; import we.util.WebUtils; + import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,8 +38,9 @@ import javax.management.RuntimeErrorException; import java.util.*; /** - * @author lancer + * @author hongqiaowei */ + @Configuration public class SystemConfig { @@ -51,19 +54,19 @@ public class SystemConfig { private Set logHeaderSet = new HashSet<>(); - @Value("${gateway-group:}") - private String gatewayGroup; - - private Map> server2gatewayGroupSetMap = new HashMap<>(); - - private Set currentServerGatewayGroupSet; + // @Value("${gateway-group:}") + // private String gatewayGroup; + // + // private Map> server2gatewayGroupSetMap = new HashMap<>(); + // + // private Set currentServerGatewayGroupSet; @Value("${spring.profiles.active}") private String profile; - public Set getCurrentServerGatewayGroupSet() { - return currentServerGatewayGroupSet; - } + // public Set getCurrentServerGatewayGroupSet() { + // return currentServerGatewayGroupSet; + // } public Set getLogHeaderSet() { return logHeaderSet; @@ -73,7 +76,7 @@ public class SystemConfig { public void afterPropertiesSet() { afterLogResponseBodySet(); afterLogHeadersSet(); - afterGatewayGroupSet(); + // afterGatewayGroupSet(); } private void afterLogResponseBodySet() { @@ -90,42 +93,42 @@ public class SystemConfig { log.info("log header list: " + logHeaderSet.toString()); } - private void afterGatewayGroupSet() { - server2gatewayGroupSetMap.clear(); - if (StringUtils.isNotBlank(gatewayGroup)) { - Arrays.stream(StringUtils.split(gatewayGroup, ';')).forEach( - gg -> { - Character group = Character.valueOf(gg.charAt(0)); - String servers = gg.substring(gg.indexOf(':') + 1); - Arrays.stream(StringUtils.split(servers, ',')).forEach( - s -> { - Set gs = server2gatewayGroupSetMap.get(s); - if (gs == null) { - gs = new HashSet<>(); - server2gatewayGroupSetMap.put(s, gs); - } - gs.add(group); - } - ); - } - ); - } - log.info("server 2 gateway group set map: " + JacksonUtils.writeValueAsString(server2gatewayGroupSetMap)); - String serverIp = NetworkUtils.getServerIp(); - currentServerGatewayGroupSet = server2gatewayGroupSetMap.get(serverIp); - if (currentServerGatewayGroupSet == null) { - if (Constants.Profiles.DEV.equals(profile) || Constants.Profiles.TEST.equals(profile)) { - currentServerGatewayGroupSet = new HashSet<>(); - currentServerGatewayGroupSet.add(GatewayGroup.C); - currentServerGatewayGroupSet.add(GatewayGroup.B); - currentServerGatewayGroupSet.add(GatewayGroup.T); - server2gatewayGroupSetMap.put(serverIp, currentServerGatewayGroupSet); - } else { - throw new RuntimeException("no gateway group config for " + serverIp); - } - } - log.info("current server: " + serverIp + ", belong to: " + currentServerGatewayGroupSet); - } + // private void afterGatewayGroupSet() { + // server2gatewayGroupSetMap.clear(); + // if (StringUtils.isNotBlank(gatewayGroup)) { + // Arrays.stream(StringUtils.split(gatewayGroup, ';')).forEach( + // gg -> { + // Character group = Character.valueOf(gg.charAt(0)); + // String servers = gg.substring(gg.indexOf(':') + 1); + // Arrays.stream(StringUtils.split(servers, ',')).forEach( + // s -> { + // Set gs = server2gatewayGroupSetMap.get(s); + // if (gs == null) { + // gs = new HashSet<>(); + // server2gatewayGroupSetMap.put(s, gs); + // } + // gs.add(group); + // } + // ); + // } + // ); + // } + // log.info("server 2 gateway group set map: " + JacksonUtils.writeValueAsString(server2gatewayGroupSetMap)); + // String serverIp = NetworkUtils.getServerIp(); + // currentServerGatewayGroupSet = server2gatewayGroupSetMap.get(serverIp); + // if (currentServerGatewayGroupSet == null) { + // if (Constants.Profiles.DEV.equals(profile) || Constants.Profiles.TEST.equals(profile)) { + // currentServerGatewayGroupSet = new HashSet<>(); + // currentServerGatewayGroupSet.add(GatewayGroup.C); + // currentServerGatewayGroupSet.add(GatewayGroup.B); + // currentServerGatewayGroupSet.add(GatewayGroup.T); + // server2gatewayGroupSetMap.put(serverIp, currentServerGatewayGroupSet); + // } else { + // throw new RuntimeException("no gateway group config for " + serverIp); + // } + // } + // log.info("current server: " + serverIp + ", belong to: " + currentServerGatewayGroupSet); + // } @ApolloConfigChangeListener private void configChangeListter(ConfigChangeEvent cce) { @@ -142,10 +145,10 @@ public class SystemConfig { } else if (p.equals("log.headers")) { logHeaders = nv; afterLogHeadersSet(); - } else if (p.equals("gateway-group")) { + } /*else if (p.equals("gateway-group")) { gatewayGroup = nv; afterGatewayGroupSet(); - } + }*/ } ); } diff --git a/src/main/java/we/config/WebClientConfig.java b/src/main/java/we/config/WebClientConfig.java index 6e3b84e..21596e0 100644 --- a/src/main/java/we/config/WebClientConfig.java +++ b/src/main/java/we/config/WebClientConfig.java @@ -39,31 +39,32 @@ import java.time.Duration; import java.util.concurrent.TimeUnit; /** - * @author lancer + * @author hongqiaowei */ + public abstract class WebClientConfig { protected static final Logger log = LoggerFactory.getLogger(WebClientConfig.class); private String name; - private int maxConnections = 2_000; + private int maxConnections = 2_000; - private Duration maxIdleTime = Duration.ofMillis(40_000); + private Duration maxIdleTime = Duration.ofMillis(40_000); private Duration pendingAcquireTimeout = Duration.ofMillis(6_000); - private long connReadTimeout = 20_000; + private long connReadTimeout = 20_000; - private long connWriteTimeout = 20_000; + private long connWriteTimeout = 20_000; - private int chConnTimeout = 20_000; + private int chConnTimeout = 20_000; - private boolean chTcpNodelay = true; + private boolean chTcpNodelay = true; - private boolean chSoKeepAlive = true; + private boolean chSoKeepAlive = true; - private boolean compress = false; + private boolean compress = false; public String getName() { return name; @@ -148,7 +149,9 @@ public abstract class WebClientConfig { private ConnectionProvider getConnectionProvider() { String cpName = name + "-cp"; ConnectionProvider cp = ConnectionProvider.builder(cpName).maxConnections(maxConnections) - .pendingAcquireTimeout(pendingAcquireTimeout).maxIdleTime(maxIdleTime).build(); + .pendingAcquireTimeout(pendingAcquireTimeout) + .maxIdleTime(maxIdleTime) + .build(); log.info(cpName + ' ' + cp); return cp; } diff --git a/src/main/java/we/config/WebFluxConfig.java b/src/main/java/we/config/WebFluxConfig.java index ba7c8af..52951af 100644 --- a/src/main/java/we/config/WebFluxConfig.java +++ b/src/main/java/we/config/WebFluxConfig.java @@ -40,8 +40,9 @@ import reactor.netty.resources.LoopResources; import java.time.Duration; /** - * @author lancer + * @author hongqiaowei */ + @Configuration @ConfigurationProperties(prefix = "server") @EnableConfigurationProperties(ServerProperties.class) @@ -124,9 +125,9 @@ public class WebFluxConfig { // .channel(NioServerSocketChannel.class) .option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT) // .option(ChannelOption.SO_BACKLOG, 8192) - .childOption(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT) + .childOption(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT) .childOption(ChannelOption.SO_KEEPALIVE, true) - .childOption(ChannelOption.TCP_NODELAY, true) + .childOption(ChannelOption.TCP_NODELAY, true) ) ) ); diff --git a/src/main/java/we/controller/ConfigController.java b/src/main/java/we/controller/ConfigController.java index b787340..fe0e39d 100644 --- a/src/main/java/we/controller/ConfigController.java +++ b/src/main/java/we/controller/ConfigController.java @@ -17,13 +17,13 @@ package we.controller; -import we.fizz.ConfigLoader; -import we.util.ScriptUtils; import org.apache.commons.io.FileUtils; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; +import we.fizz.ConfigLoader; +import we.util.ScriptUtils; import javax.annotation.Resource; import java.io.File; @@ -32,6 +32,7 @@ import java.nio.charset.StandardCharsets; /** * @author unknown */ + @RestController @RequestMapping(value = "/config") public class ConfigController { @@ -45,7 +46,7 @@ public class ConfigController { return Mono.just("ok"); } - // add by lancer + // add by hongqiaowei @PostMapping(value = "/fullUpdCommonJs", consumes = MediaType.TEXT_PLAIN_VALUE) public Mono fullUpdCommonJs(ServerWebExchange exchange, @RequestBody String js) { try { diff --git a/src/main/java/we/controller/HealthController.java b/src/main/java/we/controller/HealthController.java index f9e3207..8e1c3ef 100644 --- a/src/main/java/we/controller/HealthController.java +++ b/src/main/java/we/controller/HealthController.java @@ -18,50 +18,64 @@ package we.controller; import java.util.Date; +import java.util.HashMap; +import java.util.Map; -import we.plugin.auth.ApiConfigService; -import we.plugin.auth.AppService; -import we.util.JacksonUtils; +import com.alibaba.fastjson.JSON; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; +import we.plugin.auth.ApiConfigService; +import we.plugin.auth.AppService; +import we.plugin.auth.GatewayGroupService; +import we.util.JacksonUtils; import javax.annotation.Resource; /** * @author unknown */ + @RestController public class HealthController { + @Resource + private GatewayGroupService gatewayGroupService; + @Resource private AppService appService; @Resource private ApiConfigService apiConfigService; - @GetMapping("/time") - public Mono time(ServerWebExchange exchange) throws Exception{ - Date d = new Date(); - return Mono.just("Time: " + d.toString()); - } - - // add by lancer + // add by hongqiaowei @GetMapping("/sysgc") public Mono sysgc(ServerWebExchange exchange) throws Exception { System.gc(); return Mono.just("sysgc done"); } + @GetMapping("/gatewayGroups") + public Mono gatewayGroups(ServerWebExchange exchange) throws Exception { + return Mono.just(JacksonUtils.writeValueAsString(gatewayGroupService.gatewayGroupMap)); + } + + @GetMapping("/currentGatewayGroups") + public Mono currentGatewayGroups(ServerWebExchange exchange) throws Exception { + return Mono.just(JacksonUtils.writeValueAsString(gatewayGroupService.currentGatewayGroupSet)); + } + @GetMapping("/apps") public Mono apps(ServerWebExchange exchange) throws Exception { return Mono.just(JacksonUtils.writeValueAsString(appService.getAppMap())); } - @GetMapping("/apiConfigs") + @GetMapping("/serviceConfigs") public Mono apiConfigs(ServerWebExchange exchange) throws Exception { - return Mono.just(JacksonUtils.writeValueAsString(apiConfigService.getApp2gatewayGroupMap())); + return Mono.just(JacksonUtils.writeValueAsString(apiConfigService.serviceConfigMap)); } } diff --git a/src/main/java/we/controller/ManagerConfigController.java b/src/main/java/we/controller/ManagerConfigController.java index b3d83ca..92fa2f3 100644 --- a/src/main/java/we/controller/ManagerConfigController.java +++ b/src/main/java/we/controller/ManagerConfigController.java @@ -17,12 +17,6 @@ package we.controller; -import we.controller.req.BaseManagerConfigReq; -import we.controller.req.GetConfigStrReq; -import we.controller.req.GetConfigReq; -import we.controller.resp.ConfigStrResp; -import we.controller.resp.ConfigResp; -import we.fizz.ConfigLoader; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PostMapping; @@ -30,6 +24,12 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; +import we.controller.req.BaseManagerConfigReq; +import we.controller.req.GetConfigReq; +import we.controller.req.GetConfigStrReq; +import we.controller.resp.ConfigResp; +import we.controller.resp.ConfigStrResp; +import we.fizz.ConfigLoader; import javax.annotation.Resource; import javax.validation.Valid; diff --git a/src/main/java/we/controller/resp/ConfigResp.java b/src/main/java/we/controller/resp/ConfigResp.java index 49d5a84..d494175 100644 --- a/src/main/java/we/controller/resp/ConfigResp.java +++ b/src/main/java/we/controller/resp/ConfigResp.java @@ -17,12 +17,12 @@ package we.controller.resp; -import we.fizz.ConfigLoader; - import java.io.Serializable; import java.util.List; import java.util.Objects; +import we.fizz.ConfigLoader; + /** * 聚合配置响应实体类 * @author zhongjie diff --git a/src/main/java/we/filter/CorsFilterConfig.java b/src/main/java/we/filter/CorsFilterConfig.java index ebf4e2b..006839d 100644 --- a/src/main/java/we/filter/CorsFilterConfig.java +++ b/src/main/java/we/filter/CorsFilterConfig.java @@ -17,7 +17,6 @@ package we.filter; -import we.config.SystemConfig; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; @@ -27,11 +26,14 @@ import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.CorsWebFilter; import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource; +import we.config.SystemConfig; + import javax.annotation.Resource; /** - * @author lancer + * @author hongqiaowei */ + @Configuration public class CorsFilterConfig { diff --git a/src/main/java/we/filter/FilterExceptionHandlerConfig.java b/src/main/java/we/filter/FilterExceptionHandlerConfig.java index 1bdca11..b17bb1c 100644 --- a/src/main/java/we/filter/FilterExceptionHandlerConfig.java +++ b/src/main/java/we/filter/FilterExceptionHandlerConfig.java @@ -17,8 +17,6 @@ package we.filter; -import we.exception.StopAndResponseException; -import we.util.WebUtils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @@ -29,10 +27,13 @@ import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebExceptionHandler; import reactor.core.publisher.Mono; +import we.exception.StopAndResponseException; +import we.util.WebUtils; /** - * @author lancer + * @author hongqiaowei */ + @Configuration public class FilterExceptionHandlerConfig { diff --git a/src/main/java/we/filter/FilterResult.java b/src/main/java/we/filter/FilterResult.java index 67a0a75..eb6b5a9 100644 --- a/src/main/java/we/filter/FilterResult.java +++ b/src/main/java/we/filter/FilterResult.java @@ -20,8 +20,9 @@ package we.filter; import java.util.Map; /** - * @author lancer + * @author hongqiaowei */ + public class FilterResult { public String id; diff --git a/src/main/java/we/filter/FizzGatewayFilter.java b/src/main/java/we/filter/FizzGatewayFilter.java index cec27a2..27873f5 100644 --- a/src/main/java/we/filter/FizzGatewayFilter.java +++ b/src/main/java/we/filter/FizzGatewayFilter.java @@ -38,24 +38,24 @@ import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; import com.alibaba.fastjson.JSON; -import we.flume.clients.log4j2appender.LogService; + +import io.netty.buffer.UnpooledByteBufAllocator; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; import we.constants.CommonConstants; import we.fizz.AggregateResource; import we.fizz.AggregateResult; import we.fizz.ConfigLoader; import we.fizz.Pipeline; import we.fizz.input.Input; +import we.flume.clients.log4j2appender.LogService; import we.util.Constants; import we.util.MapUtil; import we.util.WebUtils; -import io.netty.buffer.UnpooledByteBufAllocator; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.core.scheduler.Schedulers; - /** - * @author lancer + * @author francis */ @Component @Order(2) diff --git a/src/main/java/we/filter/FizzLogFilter.java b/src/main/java/we/filter/FizzLogFilter.java index 6653ba5..3a1f054 100644 --- a/src/main/java/we/filter/FizzLogFilter.java +++ b/src/main/java/we/filter/FizzLogFilter.java @@ -17,8 +17,6 @@ package we.filter; -import we.flume.clients.log4j2appender.LogService; -import we.util.WebUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; @@ -27,10 +25,14 @@ import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; +import we.flume.clients.log4j2appender.LogService; +import we.util.ThreadContext; +import we.util.WebUtils; /** - * @author lancer + * @author hongqiaowei */ + @Component @Order(0) public class FizzLogFilter implements WebFilter { @@ -46,7 +48,7 @@ public class FizzLogFilter implements WebFilter { long startTime = System.currentTimeMillis(); return chain.filter(exchange).doAfterTerminate( () -> { - StringBuilder b = new StringBuilder(160); + StringBuilder b = ThreadContext.getStringBuilder(); WebUtils.request2stringBuilder(exchange, b); b.append(resp).append(exchange.getResponse().getStatusCode()) .append(in) .append(System.currentTimeMillis() - startTime); diff --git a/src/main/java/we/filter/PreFilter.java b/src/main/java/we/filter/PreFilter.java index 01d2615..1e2241e 100644 --- a/src/main/java/we/filter/PreFilter.java +++ b/src/main/java/we/filter/PreFilter.java @@ -17,15 +17,6 @@ package we.filter; -import we.config.SystemConfig; -import we.plugin.FixedPluginFilter; -import we.plugin.PluginConfig; -import we.plugin.PluginFilter; -import we.plugin.auth.*; -import we.plugin.stat.StatPluginFilter; -import we.util.Constants; -import we.util.ReactorUtils; -import we.util.WebUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,15 +28,24 @@ import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; +import we.plugin.FixedPluginFilter; +import we.plugin.PluginConfig; +import we.plugin.PluginFilter; +import we.plugin.auth.ApiConfig; +import we.plugin.auth.ApiConfigService; +import we.plugin.auth.AuthPluginFilter; +import we.plugin.stat.StatPluginFilter; +import we.util.ReactorUtils; +import we.util.WebUtils; -import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.*; import java.util.function.Function; /** - * @author lancer + * @author hongqiaowei */ + @Component(PreFilter.PRE_FILTER) @Order(1) public class PreFilter extends ProxyAggrFilter { @@ -62,25 +62,12 @@ public class PreFilter extends ProxyAggrFilter { @Value("${b-services:x}") private Set bServices = new HashSet<>(); - @Resource - private SystemConfig systemConfig; - @Resource(name = StatPluginFilter.STAT_PLUGIN_FILTER) private StatPluginFilter statPluginFilter; @Resource(name = AuthPluginFilter.AUTH_PLUGIN_FILTER) private AuthPluginFilter authPluginFilter; - private char currentGatewayGroup; - @PostConstruct - public void setCurrentGatewayGroup() { - for (Character gg : systemConfig.getCurrentServerGatewayGroupSet()) { - currentGatewayGroup = gg.charValue(); - log.info("current gateway group is " + currentGatewayGroup); - break; - } - } - @Override public Mono doFilter(ServerWebExchange exchange, WebFilterChain chain) { @@ -88,24 +75,11 @@ public class PreFilter extends ProxyAggrFilter { Map appendHdrs = new HashMap<>(6, 1.0f); Map eas = exchange.getAttributes(); eas.put(WebUtils.FILTER_CONTEXT, fc); eas.put(WebUtils.APPEND_HEADERS, appendHdrs); - eas.put(WebUtils.CGG, currentGatewayGroup); String app = WebUtils.getHeaderValue(exchange, WebUtils.APP_HEADER); - if (StringUtils.isBlank(app)) { - if (Constants.Profiles.DEV.equals(profile) || Constants.Profiles.TEST.equals(profile)) { - String service = WebUtils.getServiceId(exchange); - if (bServices.contains(service)) { - app = App.TO_B; - } else { - app = App.TO_C; - } - } else if (currentGatewayGroup == GatewayGroup.B) { - app = App.TO_B; - } else { - app = App.TO_C; - } + if (StringUtils.isNotBlank(app)) { + eas.put(WebUtils.APP_HEADER, app); } - eas.put(WebUtils.APP_HEADER, app); Mono vm = statPluginFilter.filter(exchange, null, null); return chain(exchange, vm, authPluginFilter).defaultIfEmpty(ReactorUtils.NULL) @@ -120,11 +94,7 @@ public class PreFilter extends ProxyAggrFilter { if (ac.pluginConfigs == null || ac.pluginConfigs.isEmpty()) { return m.flatMap(func(exchange, chain)); } else { - return m.flatMap( - e -> { - return executeManagedPluginFilters(exchange, ac.pluginConfigs); - } - ) + return m.flatMap(e -> {return executeManagedPluginFilters(exchange, ac.pluginConfigs);}) .defaultIfEmpty(ReactorUtils.NULL).flatMap(func(exchange, chain)); } } else if (authRes == ApiConfigService.Access.YES) { diff --git a/src/main/java/we/filter/ProxyAggrFilter.java b/src/main/java/we/filter/ProxyAggrFilter.java index a7a90c1..99529ca 100644 --- a/src/main/java/we/filter/ProxyAggrFilter.java +++ b/src/main/java/we/filter/ProxyAggrFilter.java @@ -17,15 +17,16 @@ package we.filter; -import we.util.WebUtils; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; +import we.util.WebUtils; /** - * @author lancer + * @author hongqiaowei */ + // TODO 类名调整 public abstract class ProxyAggrFilter implements WebFilter { diff --git a/src/main/java/we/filter/RouteFilter.java b/src/main/java/we/filter/RouteFilter.java index 7fe853e..1c8581f 100644 --- a/src/main/java/we/filter/RouteFilter.java +++ b/src/main/java/we/filter/RouteFilter.java @@ -17,11 +17,6 @@ package we.filter; -import we.flume.clients.log4j2appender.LogService; -import we.legacy.RespEntity; -import we.proxy.FizzWebClient; -import we.util.ThreadContext; -import we.util.WebUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.Ordered; @@ -36,14 +31,23 @@ import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; +import we.flume.clients.log4j2appender.LogService; +import we.legacy.RespEntity; +import we.plugin.auth.ApiConfig; +import we.plugin.auth.AuthPluginFilter; +import we.proxy.FizzWebClient; +import we.util.ThreadContext; +import we.util.WebUtils; import javax.annotation.Resource; import java.util.List; import java.util.Map; +import java.util.function.Function; /** - * @author lancer + * @author hongqiaowei */ + @Component @Order(Ordered.LOWEST_PRECEDENCE) public class RouteFilter extends ProxyAggrFilter { @@ -79,7 +83,6 @@ public class RouteFilter extends ProxyAggrFilter { private Mono doFilter0(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest clientReq = exchange.getRequest(); - String rid = clientReq.getId(); HttpHeaders hdrs = new HttpHeaders(); clientReq.getHeaders().forEach( (h, vs) -> { @@ -101,37 +104,65 @@ public class RouteFilter extends ProxyAggrFilter { ); } - return fizzWebClient.proxySend2service(rid, clientReq.getMethod(), WebUtils.getServiceId(exchange), WebUtils.getRelativeUri(exchange), hdrs, exchange.getRequest().getBody()).flatMap( - remoteResp -> { - ServerHttpResponse clientResp = exchange.getResponse(); - clientResp.setStatusCode(remoteResp.statusCode()); - HttpHeaders clientRespHeaders = clientResp.getHeaders(); - HttpHeaders remoteRespHeaders = remoteResp.headers().asHttpHeaders(); - remoteRespHeaders.entrySet().forEach( - h -> { - String k = h.getKey(); - if (clientRespHeaders.containsKey(k)) { - if (k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN) || k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS) - || k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS) || k.equals(HttpHeaders.ACCESS_CONTROL_MAX_AGE)) { - } else { - clientRespHeaders.put(k, h.getValue()); - } - } else { - clientRespHeaders.put(k, h.getValue()); - } - } - ); - if (log.isDebugEnabled()) { - StringBuilder b = ThreadContext.getStringBuilder(); - WebUtils.response2stringBuilder(rid, remoteResp, b); - log.debug(b.toString(), LogService.BIZ_ID, rid); - } - return clientResp.writeWith(remoteResp.body(BodyExtractors.toDataBuffers())) - .doOnError(throwable -> cleanup(remoteResp)).doOnCancel(() -> cleanup(remoteResp)); - } - ); + ApiConfig ac = null; + Object authRes = WebUtils.getFilterResultDataItem(exchange, AuthPluginFilter.AUTH_PLUGIN_FILTER, AuthPluginFilter.RESULT); + if (authRes instanceof ApiConfig) { + ac = (ApiConfig) authRes; + } + + String relativeUri = WebUtils.getRelativeUri(exchange); + if (ac == null || ac.proxyMode == ApiConfig.DIRECT_PROXY_MODE) { + return send(exchange, WebUtils.getServiceId(exchange), relativeUri, hdrs); + } else { + String realUri; + String backendUrl = ac.getNextBackendUrl(); + int acpLen = ac.path.length(); + if (acpLen == 1) { + realUri = backendUrl + relativeUri; + } else { + realUri = backendUrl + relativeUri.substring(acpLen); + } + relativeUri.substring(acpLen); + return fizzWebClient.send(clientReq.getId(), clientReq.getMethod(), realUri, hdrs, clientReq.getBody()).flatMap(genServerResponse(exchange)); + } } - + + private Mono send(ServerWebExchange exchange, String service, String relativeUri, HttpHeaders hdrs) { + ServerHttpRequest clientReq = exchange.getRequest(); + return fizzWebClient.proxySend2service(clientReq.getId(), clientReq.getMethod(), service, relativeUri, hdrs, clientReq.getBody()).flatMap(genServerResponse(exchange)); + } + + private Function> genServerResponse(ServerWebExchange exchange) { + return remoteResp -> { + ServerHttpResponse clientResp = exchange.getResponse(); + clientResp.setStatusCode(remoteResp.statusCode()); + HttpHeaders clientRespHeaders = clientResp.getHeaders(); + HttpHeaders remoteRespHeaders = remoteResp.headers().asHttpHeaders(); + remoteRespHeaders.entrySet().forEach( + h -> { + String k = h.getKey(); + if (clientRespHeaders.containsKey(k)) { + if (k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN) || k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS) + || k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS) || k.equals(HttpHeaders.ACCESS_CONTROL_MAX_AGE)) { + } else { + clientRespHeaders.put(k, h.getValue()); + } + } else { + clientRespHeaders.put(k, h.getValue()); + } + } + ); + if (log.isDebugEnabled()) { + StringBuilder b = ThreadContext.getStringBuilder(); + String rid = exchange.getRequest().getId(); + WebUtils.response2stringBuilder(rid, remoteResp, b); + log.debug(b.toString(), LogService.BIZ_ID, rid); + } + return clientResp.writeWith(remoteResp.body(BodyExtractors.toDataBuffers())) + .doOnError(throwable -> cleanup(remoteResp)).doOnCancel(() -> cleanup(remoteResp)); + }; + } + private void cleanup(ClientResponse clientResponse) { if (clientResponse != null) { clientResponse.bodyToMono(Void.class).subscribe(); diff --git a/src/main/java/we/fizz/ConfigLoader.java b/src/main/java/we/fizz/ConfigLoader.java index df7146f..e8a661c 100644 --- a/src/main/java/we/fizz/ConfigLoader.java +++ b/src/main/java/we/fizz/ConfigLoader.java @@ -19,10 +19,12 @@ package we.fizz; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; + import we.config.AppConfigProperties; import we.fizz.input.ClientInputConfig; import we.fizz.input.Input; import we.fizz.input.InputType; + import org.apache.commons.io.FileUtils; import org.noear.snack.ONode; import org.springframework.beans.factory.annotation.Value; @@ -32,6 +34,10 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import javax.annotation.Resource; + +import static we.listener.AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE; +import static we.util.Constants.Symbol.FORWARD_SLASH; + import java.io.File; import java.io.IOException; import java.io.Serializable; @@ -41,9 +47,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; - -import static we.listener.AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE; -import static we.util.Constants.Symbol.FORWARD_SLASH; /** * * @author francis @@ -56,7 +59,7 @@ public class ConfigLoader { * 聚合配置存放Hash的Key */ private static final String AGGREGATE_HASH_KEY = "fizz_aggregate_config"; - + private static Map aggregateResources = null; private static Map resourceKey2ConfigInfoMap = null; private static Map aggregateId2ResourceKeyMap = null; @@ -80,8 +83,13 @@ public class ConfigLoader { clientInputConfig.setHeaders(cfgNode.select("$.headers").toObject(Map.class)); clientInputConfig.setMethod(cfgNode.select("$.method").getString()); clientInputConfig.setPath(cfgNode.select("$.path").getString()); - if(cfgNode.select("$.debug") != null) { - clientInputConfig.setDebug(cfgNode.select("$.debug").getBoolean()); + if(clientInputConfig.getPath().startsWith(TEST_PATH_PREFIX)) { + // always enable debug for testing + clientInputConfig.setDebug(true); + }else { + if(cfgNode.select("$.debug") != null) { + clientInputConfig.setDebug(cfgNode.select("$.debug").getBoolean()); + } } clientInputConfig.setType(InputType.valueOf(cfgNode.select("$.type").getString())); clientInputConfig.setLangDef(cfgNode.select("$.langDef").toObject(Map.class)); diff --git a/src/main/java/we/fizz/Pipeline.java b/src/main/java/we/fizz/Pipeline.java index 9b5d8ba..87baf7c 100644 --- a/src/main/java/we/fizz/Pipeline.java +++ b/src/main/java/we/fizz/Pipeline.java @@ -25,11 +25,7 @@ import java.util.Map; import javax.script.ScriptException; -import we.fizz.input.ClientInputConfig; -import we.fizz.input.InputConfig; import we.schema.util.I18nUtils; -import we.util.JsonSchemaUtils; - import org.noear.snack.ONode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,14 +33,17 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import com.alibaba.fastjson.JSON; -import we.flume.clients.log4j2appender.LogService; -import we.fizz.input.Input; -import we.fizz.input.PathMapping; -import we.fizz.input.ScriptHelper; -import we.util.MapUtil; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import we.fizz.input.ClientInputConfig; +import we.fizz.input.Input; +import we.fizz.input.InputConfig; +import we.fizz.input.PathMapping; +import we.fizz.input.ScriptHelper; +import we.flume.clients.log4j2appender.LogService; +import we.util.JsonSchemaUtils; +import we.util.MapUtil; /** * diff --git a/src/main/java/we/fizz/Step.java b/src/main/java/we/fizz/Step.java index 9a44f41..93d0bd1 100644 --- a/src/main/java/we/fizz/Step.java +++ b/src/main/java/we/fizz/Step.java @@ -30,14 +30,14 @@ import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import com.alibaba.fastjson.JSON; + +import reactor.core.publisher.Mono; import we.fizz.input.Input; import we.fizz.input.InputConfig; import we.fizz.input.InputContext; import we.fizz.input.InputFactory; import we.fizz.input.InputType; -import reactor.core.publisher.Mono; - /** * * @author linwaiwai diff --git a/src/main/java/we/fizz/input/Input.java b/src/main/java/we/fizz/input/Input.java index 9cd571c..0904b68 100644 --- a/src/main/java/we/fizz/input/Input.java +++ b/src/main/java/we/fizz/input/Input.java @@ -19,11 +19,10 @@ package we.fizz.input; import java.util.HashMap; import java.util.Map; +import reactor.core.publisher.Mono; import we.fizz.StepContext; import we.fizz.StepResponse; -import reactor.core.publisher.Mono; - /** * * @author linwaiwai diff --git a/src/main/java/we/fizz/input/PathMapping.java b/src/main/java/we/fizz/input/PathMapping.java index 8449d3e..7b3f153 100644 --- a/src/main/java/we/fizz/input/PathMapping.java +++ b/src/main/java/we/fizz/input/PathMapping.java @@ -215,7 +215,8 @@ public class PathMapping { List list = Arrays.stream(arr).collect(Collectors.toList()); // 补齐 requests - if(list.size() >= 2 && !"requests".equals(list.get(1))) { + // fix-如果是从step*.result下获取数据不应该插入requests + if(list.size() >= 2 && !"requests".equals(list.get(1)) && !"result".equals(list.get(1))) { list.add(1,"requests"); } diff --git a/src/main/java/we/fizz/input/RequestInput.java b/src/main/java/we/fizz/input/RequestInput.java index e5ebe79..0494390 100644 --- a/src/main/java/we/fizz/input/RequestInput.java +++ b/src/main/java/we/fizz/input/RequestInput.java @@ -34,16 +34,16 @@ import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; import com.alibaba.fastjson.JSON; -import we.flume.clients.log4j2appender.LogService; -import we.FizzGatewayApplication; + +import reactor.core.publisher.Mono; +import we.FizzAppContext; import we.constants.CommonConstants; import we.fizz.StepContext; import we.fizz.StepResponse; +import we.flume.clients.log4j2appender.LogService; import we.proxy.FizzWebClient; import we.util.MapUtil; -import reactor.core.publisher.Mono; - /** * * @author linwaiwai @@ -222,7 +222,7 @@ public class RequestInput extends Input { String aggrPath = (String)inputContext.getStepContext().getInputReqAttr("path"); String aggrService = aggrPath.split("\\/")[2]; - FizzWebClient client = FizzGatewayApplication.appContext.getBean(FizzWebClient.class); + FizzWebClient client = FizzAppContext.appContext.getBean(FizzWebClient.class); return client.aggrSend(aggrService, aggrMethod, aggrPath, null, method, url, MapUtil.toHttpHeaders(headers), request.get("body"), (long)timeout); } diff --git a/src/main/java/we/fizz/input/ScriptHelper.java b/src/main/java/we/fizz/input/ScriptHelper.java index 15e42cb..a6644d9 100644 --- a/src/main/java/we/fizz/input/ScriptHelper.java +++ b/src/main/java/we/fizz/input/ScriptHelper.java @@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory; import com.alibaba.fastjson.JSON; import com.ctrip.framework.apollo.core.utils.StringUtils; + import we.constants.CommonConstants; import we.exception.StopAndResponseException; import we.fizz.StepContext; diff --git a/src/main/java/we/flume/clients/log4j2appender/LogService.java b/src/main/java/we/flume/clients/log4j2appender/LogService.java index 0aaf5cf..5ae538d 100644 --- a/src/main/java/we/flume/clients/log4j2appender/LogService.java +++ b/src/main/java/we/flume/clients/log4j2appender/LogService.java @@ -1,33 +1,31 @@ -/* - * Copyright (C) 2020 the original author or authors. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - package we.flume.clients.log4j2appender; -/** - * @author lancer - */ public enum LogService { - BIZ_ID, HANDLE_STGY; + BIZ_ID, HANDLE_STGY, APP; + + public static void cleanBizId() { + setBizId(null); + } + + public static Object getBizId() { + return ThreadContext.get(Constants.BIZ_ID); + } public static void setBizId(Object bizId) { + ThreadContext.set(Constants.BIZ_ID, bizId); } public static String toKF(String topic) { return topic; } + + public static String toESaKF(String topic) { + return Constants.AND + topic; + } + + public static class Constants { + static final String BIZ_ID = "bizId"; + static final char AND = '&'; + } } diff --git a/src/main/java/we/flume/clients/log4j2appender/ThreadContext.java b/src/main/java/we/flume/clients/log4j2appender/ThreadContext.java new file mode 100644 index 0000000..856d58d --- /dev/null +++ b/src/main/java/we/flume/clients/log4j2appender/ThreadContext.java @@ -0,0 +1,76 @@ +package we.flume.clients.log4j2appender; + +import java.text.SimpleDateFormat; +import java.util.HashMap; +import java.util.Map; + +/** for internal use */ +public abstract class ThreadContext { + + private static ThreadLocal> tl = new ThreadLocal<>(); + private static final int mapCap = 16; + private static final float mapLoadFactor = 1.0f; + + private static final String sb = "sb"; + private static final int sbCap = 256; + + public static StringBuilder getStringBuilder() { + return getStringBuilder(true); + } + + public static StringBuilder getStringBuilder(boolean clean) { + Map m = getMap(); + StringBuilder b = (StringBuilder) m.get(sb); + if (b == null) { + b = new StringBuilder(sbCap); + m.put(sb, b); + } else { + if (clean) { + b.delete(0, b.length()); + } + } + return b; + } + + public static SimpleDateFormat getSimpleDateFormat(String pattern) { + Map m = getMap(); + SimpleDateFormat sdf = (SimpleDateFormat) m.get(pattern); + if (sdf == null) { + sdf = new SimpleDateFormat(pattern); + m.put(pattern, sdf); + } + return sdf; + } + + public static Object get(String key, Class clz) { + Object obj = get(key); + if (obj == null) { + try { + obj = clz.newInstance(); + set(key, obj); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + return obj; + } + + private static Map getMap() { + Map m = tl.get(); + if (m == null) { + m = new HashMap<>(mapCap, mapLoadFactor); + tl.set(m); + } + return m; + } + + public static Object get(String key) { + return getMap().get(key); + } + + public static void set(String key, Object obj) { + getMap().put(key, obj); + } +} diff --git a/src/main/java/we/legacy/RespEntity.java b/src/main/java/we/legacy/RespEntity.java index b3a656d..4a81034 100644 --- a/src/main/java/we/legacy/RespEntity.java +++ b/src/main/java/we/legacy/RespEntity.java @@ -17,13 +17,15 @@ package we.legacy; -import we.util.Constants; -import we.util.ThreadContext; import org.springframework.lang.Nullable; +import we.util.Constants; +import we.util.ThreadContext; + /** - * @author lancer + * @author hongqiaowei */ + public class RespEntity { private static final String f0 = "{\"msgCode\":"; diff --git a/src/main/java/we/listener/AggregateChannelListener.java b/src/main/java/we/listener/AggregateChannelListener.java index 24374d9..77c3db7 100644 --- a/src/main/java/we/listener/AggregateChannelListener.java +++ b/src/main/java/we/listener/AggregateChannelListener.java @@ -19,7 +19,7 @@ package we.listener; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; -import we.fizz.ConfigLoader; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; @@ -31,14 +31,16 @@ import org.springframework.util.StringUtils; import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.core.scheduler.Schedulers; +import we.fizz.ConfigLoader; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; -import java.net.InetAddress; -import java.util.List; import static we.listener.AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_MESSAGE_LISTENER_CONTAINER; +import java.net.InetAddress; +import java.util.List; + /** * 聚合Channel监听器 * @author zhongjie diff --git a/src/main/java/we/listener/AggregateRedisConfig.java b/src/main/java/we/listener/AggregateRedisConfig.java index 252025d..86c7d31 100644 --- a/src/main/java/we/listener/AggregateRedisConfig.java +++ b/src/main/java/we/listener/AggregateRedisConfig.java @@ -17,8 +17,6 @@ package we.listener; -import we.config.RedisReactiveConfig; -import we.config.RedisReactiveProperties; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -27,6 +25,9 @@ import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; import org.springframework.data.redis.core.ReactiveStringRedisTemplate; import org.springframework.data.redis.listener.ReactiveRedisMessageListenerContainer; +import we.config.RedisReactiveConfig; +import we.config.RedisReactiveProperties; + /** * 聚合配置Redis配置 * @author zhongjie diff --git a/src/main/java/we/plugin/FixedPluginFilter.java b/src/main/java/we/plugin/FixedPluginFilter.java index d56c5ff..02ea426 100644 --- a/src/main/java/we/plugin/FixedPluginFilter.java +++ b/src/main/java/we/plugin/FixedPluginFilter.java @@ -14,16 +14,19 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.plugin; -import we.FizzGatewayApplication; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import we.FizzAppContext; +import we.util.ThreadContext; + import java.util.*; /** - * @author lancer + * @author hongqiaowei */ public abstract class FixedPluginFilter extends PluginFilter { @@ -56,7 +59,7 @@ public abstract class FixedPluginFilter extends PluginFilter { ); String fid = pf.getId(); fixedPluginFilterMap.put(fid, pf); - StringBuilder b = new StringBuilder(256); + StringBuilder b = ThreadContext.getStringBuilder(); b.append("add ").append(fid).append('\n'); b.append("fixed plugin filters: \n"); filters2sb(b); @@ -67,7 +70,7 @@ public abstract class FixedPluginFilter extends PluginFilter { if (fixedPluginFilterList == null) { synchronized (fixedPluginFilterMap) { if (fixedPluginFilterList == null) { - Map beansOfType = FizzGatewayApplication.appContext.getBeansOfType(FixedPluginFilter.class); + Map beansOfType = FizzAppContext.appContext.getBeansOfType(FixedPluginFilter.class); if (beansOfType == null || beansOfType.isEmpty()) { fixedPluginFilterList = Collections.EMPTY_LIST; } else { @@ -82,7 +85,7 @@ public abstract class FixedPluginFilter extends PluginFilter { fixedPluginFilterMap.put(f.getId(), f); } ); - StringBuilder b = new StringBuilder(256); + StringBuilder b = ThreadContext.getStringBuilder(); b.append("fixed plugin filters: \n"); filters2sb(b); log.info(b.toString()); diff --git a/src/main/java/we/plugin/PluginConfig.java b/src/main/java/we/plugin/PluginConfig.java index 1fcd1fa..1b8b1e8 100644 --- a/src/main/java/we/plugin/PluginConfig.java +++ b/src/main/java/we/plugin/PluginConfig.java @@ -14,17 +14,17 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.plugin; -import com.fasterxml.jackson.core.JsonProcessingException; -import we.util.JacksonUtils; import org.apache.commons.lang3.StringUtils; +import we.util.JacksonUtils; import java.util.Collections; import java.util.Map; /** - * @author lancer + * @author hongqiaowei */ public class PluginConfig { diff --git a/src/main/java/we/plugin/PluginFilter.java b/src/main/java/we/plugin/PluginFilter.java index 41edf4a..0de82b6 100644 --- a/src/main/java/we/plugin/PluginFilter.java +++ b/src/main/java/we/plugin/PluginFilter.java @@ -14,23 +14,24 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.plugin; -import we.flume.clients.log4j2appender.LogService; -import we.filter.FilterResult; -import we.legacy.RespEntity; -import we.util.WebUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; +import we.filter.FilterResult; +import we.flume.clients.log4j2appender.LogService; +import we.legacy.RespEntity; +import we.util.WebUtils; import java.util.Map; /** - * @author lancer + * @author hongqiaowei */ public abstract class PluginFilter { diff --git a/src/main/java/we/plugin/auth/ApiConfig.java b/src/main/java/we/plugin/auth/ApiConfig.java index 03ea86f..c8a15e4 100644 --- a/src/main/java/we/plugin/auth/ApiConfig.java +++ b/src/main/java/we/plugin/auth/ApiConfig.java @@ -14,66 +14,90 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.plugin.auth; +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpMethod; + import we.plugin.PluginConfig; import we.util.Constants; import we.util.JacksonUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.http.HttpMethod; -import java.util.List; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; /** - * @author lancer + * @author hongqiaowei */ public class ApiConfig { - public static final int DELETED = 1; + public static final int DELETED = 1; - public static final char ALLOW = 'a'; + public static final char ALLOW = 'a'; - public static final char FORBID = 'f'; + public static final char FORBID = 'f'; - public int id; // tb_api_auth.id + public static final byte DIRECT_PROXY_MODE = 1; - public int isDeleted = 0; // tb_api_auth.is_deleted + public static final byte PREFIX_REWRITE_PROXY_MODE = 2; - public char gatewayGroup; // tb_api_auth.gateway_group + // @JsonIgnore + public int id; // tb_api_auth.id + + // @JsonIgnore + public int isDeleted = 0; // tb_api_auth.is_deleted + + public Set gatewayGroups = new HashSet<>(6); public String service; - public HttpMethod method = HttpMethod.X; + public HttpMethod method = HttpMethod.X; - public String path = String.valueOf(Constants.Symbol.FORWARD_SLASH); + public String path = String.valueOf(Constants.Symbol.FORWARD_SLASH); - private String app; + public Set apps = new HashSet<>(6); - public char access = ALLOW; + public byte proxyMode = DIRECT_PROXY_MODE; + + private AtomicInteger counter = new AtomicInteger(-1); + + public List backendUrls; + + public char access = ALLOW; public List pluginConfigs; - public void setApp(String a) { - app = a; + public void setGatewayGroup(String ggs) { + if (StringUtils.isBlank(ggs)) { + gatewayGroups.add("*"); + } else { + Arrays.stream(StringUtils.split(ggs, ',')).forEach( + gg -> { + gatewayGroups.add(gg.trim()); + } + ); + } } - public String app() { - if (StringUtils.isBlank(app)) { - if (gatewayGroup == GatewayGroup.C) { - app = App.TO_C; - } else if (gatewayGroup == GatewayGroup.B) { - app = App.TO_B; - } else { - throw new RuntimeException(toString() + " no app", null, false, false) {}; - } + public void setApp(String as) { + if (StringUtils.isBlank(as)) { + apps.add("*"); + } else { + Arrays.stream(StringUtils.split(as, ',')).forEach( + a -> { + apps.add(a.trim()); + } + ); } - return app; } public void setPath(String p) { if (StringUtils.isNotBlank(p)) { - path = p; + path = p.trim(); } } @@ -84,6 +108,16 @@ public class ApiConfig { } } + @JsonIgnore + public String getNextBackendUrl() { + int idx = counter.incrementAndGet(); + if (idx < 0) { + counter.set(0); + idx = 0; + } + return backendUrls.get(idx % backendUrls.size()); + } + @Override public String toString() { return JacksonUtils.writeValueAsString(this); diff --git a/src/main/java/we/plugin/auth/ApiConfigService.java b/src/main/java/we/plugin/auth/ApiConfigService.java index 83c5dc9..84751f4 100644 --- a/src/main/java/we/plugin/auth/ApiConfigService.java +++ b/src/main/java/we/plugin/auth/ApiConfigService.java @@ -14,15 +14,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.plugin.auth; import com.ctrip.framework.apollo.model.ConfigChange; import com.ctrip.framework.apollo.model.ConfigChangeEvent; import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener; -import we.flume.clients.log4j2appender.LogService; -import we.config.SystemConfig; -import we.listener.AggregateRedisConfig; -import we.util.*; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,6 +33,9 @@ import org.springframework.stereotype.Service; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import we.flume.clients.log4j2appender.LogService; +import we.listener.AggregateRedisConfig; +import we.util.*; import javax.annotation.PostConstruct; import javax.annotation.Resource; @@ -43,7 +43,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; /** - * @author lancer + * @author hongqiaowei */ @Service @@ -61,9 +61,9 @@ public class ApiConfigService { private static final String secretKeyHeader = "fizz-secretkey"; - private Map app2gatewayGroupMap = new HashMap<>(32); + public Map serviceConfigMap = new HashMap<>(128); - private Map apiConfigMap = new HashMap<>(128); + private Map apiConfigMap = new HashMap<>(128); // TODO XXX @Value("${serviceWhiteList:x}") @@ -94,18 +94,24 @@ public class ApiConfigService { } } + @Value("${auth.compatible-wh:false}") + private boolean compatibleWh; + @Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE) private ReactiveStringRedisTemplate rt; @Resource - private SystemConfig systemConfig; + private AppService appService; @Resource - private AppService appService; + private GatewayGroupService gatewayGroupService; @Autowired(required = false) private CustomAuth customAuth; + @Value("${openServiceWhiteList:false}") + private boolean openServiceWhiteList = false; + @PostConstruct public void init() throws Throwable { @@ -127,7 +133,7 @@ public class ApiConfigService { try { ApiConfig ac = JacksonUtils.readValue(json, ApiConfig.class); apiConfigMap.put(ac.id, ac); - updateApp2gatewayGroupMap(ac); + updateServiceConfigMap(ac); return Flux.just(e); } catch (Throwable t) { throwable[0] = t; @@ -167,9 +173,9 @@ public class ApiConfigService { ApiConfig r = apiConfigMap.remove(ac.id); if (ac.isDeleted != ApiConfig.DELETED && r != null) { r.isDeleted = ApiConfig.DELETED; - updateApp2gatewayGroupMap(r); + updateServiceConfigMap(r); } - updateApp2gatewayGroupMap(ac); + updateServiceConfigMap(ac); if (ac.isDeleted != ApiConfig.DELETED) { apiConfigMap.put(ac.id, ac); } @@ -192,24 +198,21 @@ public class ApiConfigService { return Mono.just(ReactorUtils.EMPTY_THROWABLE); } - private void updateApp2gatewayGroupMap(ApiConfig ac) { - GatewayGroup gg = app2gatewayGroupMap.get(ac.app()); + private void updateServiceConfigMap(ApiConfig ac) { + ServiceConfig sc = serviceConfigMap.get(ac.service); if (ac.isDeleted == ApiConfig.DELETED) { - if (gg == null) { - log.info("no gateway group for " + ac.app()); + if (sc == null) { + log.info("no " + ac.service + " config to delete"); } else { - gg.remove(ac); - if (gg.getServiceConfigMap().isEmpty()) { - app2gatewayGroupMap.remove(ac.app()); - } + sc.remove(ac); } } else { - if (gg == null) { - gg = new GatewayGroup(ac.gatewayGroup); - app2gatewayGroupMap.put(ac.app(), gg); - gg.add(ac); + if (sc == null) { + sc = new ServiceConfig(ac.service); + serviceConfigMap.put(ac.service, sc); + sc.add(ac); } else { - gg.update(ac); + sc.update(ac); } } } @@ -218,13 +221,15 @@ public class ApiConfigService { YES (null), - CANT_ACCESS_CURRENT_GATEWAY_GROUP ("cant access current gateway group"), + NO_SERVICE_CONFIG ("no service config"), - NO_GATEWAY_GROUP_FOR_APP ("no gateway group for app"), + NO_API_CONFIG ("no api config"), - NO_APP_CONFIG_FOR_APP ("no app config for app"), + GATEWAY_GROUP_CANT_PROXY_API ("gateway group cant proxy api"), - ORIGIN_IP_NOT_IN_WHITE_LIST ("origin ip not in white list"), + APP_NOT_IN_API_LEGAL_APPS ("app not in api legal apps"), + + IP_NOT_IN_WHITE_LIST ("ip not in white list"), NO_TIMESTAMP_OR_SIGN ("no timestamp or sign"), @@ -236,10 +241,6 @@ public class ApiConfigService { SERVICE_NOT_OPEN ("service not open"), - NO_SERVICE_EXPOSE_TO_APP ("no service expose to app"), - - SERVICE_API_NOT_EXPOSE_TO_APP ("service api not expose to app"), - CANT_ACCESS_SERVICE_API ("cant access service api"); private String reason; @@ -254,7 +255,6 @@ public class ApiConfigService { } public Mono canAccess(ServerWebExchange exchange) { - ServerHttpRequest req = exchange.getRequest(); HttpHeaders hdrs = req.getHeaders(); LogService.setBizId(req.getId()); @@ -262,56 +262,85 @@ public class ApiConfigService { WebUtils.getServiceId(exchange), req.getMethod(), WebUtils.getReqPath(exchange)); } - private Mono canAccess(ServerWebExchange exchange, String app, String ip, String timestamp, String sign, String secretKey, - String service, HttpMethod method, String path) { + private Mono canAccess(ServerWebExchange exchange, String app, String ip, String timestamp, String sign, String secretKey, + String service, HttpMethod method, String path) { - GatewayGroup gg = app2gatewayGroupMap.get(app); boolean toCorBapp = App.TO_C.equals(app) || App.TO_B.equals(app); - - if (gg == null) { - if (toCorBapp) { return Mono.just(Access.YES); } else { return logWarnAndResult("no gateway group for " + app, Access.NO_GATEWAY_GROUP_FOR_APP); } + if (openServiceWhiteList) { + if (!whiteListSet.contains(service)) { // TODO XXX + return Mono.just(Access.SERVICE_NOT_OPEN); + } + } + ServiceConfig sc = serviceConfigMap.get(service); + if (sc == null) { + if (compatibleWh) { + return Mono.just(Access.YES); + } else { + return logWarnAndResult(service + Constants.Symbol.BLANK + Access.NO_SERVICE_CONFIG.getReason(), Access.NO_SERVICE_CONFIG); + } } else { - Set currentServerGatewayGroupSet = systemConfig.getCurrentServerGatewayGroupSet(); - if (currentServerGatewayGroupSet.contains(gg.id)) { - Mono am = Mono.just(Access.YES); - App a = appService.getApp(app); - if (a == null) { - if (!toCorBapp) { return logWarnAndResult("no app config for " + app, Access.NO_APP_CONFIG_FOR_APP); } - } else if (a.useWhiteList && !a.ips.contains(ip)) { - return logWarnAndResult(ip + " not in " + app + " white list", Access.ORIGIN_IP_NOT_IN_WHITE_LIST); - } else if (a.useAuth) { - if (a.authType == App.SIGN_AUTH) { - if (StringUtils.isBlank(timestamp) || StringUtils.isBlank(sign)) { return logWarnAndResult(app + " lack timestamp " + timestamp + " or sign " + sign, Access.NO_TIMESTAMP_OR_SIGN); } - else if (!validate(app, timestamp, a.secretkey, sign)) { return logWarnAndResult(app + " sign " + sign + " invalid", Access.SIGN_INVALID); } - } else if (customAuth == null) { - return logWarnAndResult(app + " no custom auth", Access.NO_CUSTOM_AUTH); - } else { - am = customAuth.auth(exchange, app, ip, timestamp, sign, secretKey, a); - } - } - return am.flatMap( - v -> { - LogService.setBizId(exchange.getRequest().getId()); - if (v == Access.CUSTOM_AUTH_REJECT || v != Access.YES) { return Mono.just(Access.CUSTOM_AUTH_REJECT); } - if (!whiteListSet.contains(service)) { return Mono.just(Access.SERVICE_NOT_OPEN); } // TODO XXX - ServiceConfig sc = gg.getServiceConfig(service); - if (sc == null) { - if (toCorBapp) { return Mono.just(Access.YES); } else { return logWarnAndResult("no service expose to " + app, Access.NO_SERVICE_EXPOSE_TO_APP); } - } else { - ApiConfig ac = sc.getApiConfig(method, path); - if (ac == null) { - if (toCorBapp) { return Mono.just(Access.YES); } else { return logWarnAndResult(service + ' ' + method.name() + ' ' + path + " not expose to " + app, Access.SERVICE_API_NOT_EXPOSE_TO_APP); } - } else if (ac.access == ApiConfig.ALLOW) { - return Mono.just(ac); - } else { - return logWarnAndResult(app + " cant access " + service + ' ' + method.name() + ' ' + path, Access.CANT_ACCESS_SERVICE_API); - } - } - } - ); - - } else { - return logWarnAndResult(app + " cant access " + currentServerGatewayGroupSet, Access.CANT_ACCESS_CURRENT_GATEWAY_GROUP); + String api = ThreadContext.getStringBuilder().append(service).append(Constants.Symbol.BLANK).append(method.name()).append(Constants.Symbol.BLANK + path).toString(); + ApiConfig ac0 = null; + for (String g : gatewayGroupService.currentGatewayGroupSet) { // compatible + ac0 = sc.getApiConfig(method, path, g, app); + if (ac0 != null) { + break; } + } + ApiConfig ac = ac0; + if (ac == null) { + if (compatibleWh) { + return Mono.just(Access.YES); + } else { + return logWarnAndResult(api + " no api config", Access.NO_API_CONFIG); + } + } else if (gatewayGroupService.currentGatewayGroupIn(ac.gatewayGroups)) { + if (ac.apps.contains(App.ALL_APP)) { + return allow(api, ac); + } else if (app != null && ac.apps.contains(app)) { + if (ac.access == ApiConfig.ALLOW) { + App a = appService.getApp(app); + if (a.useWhiteList && !a.allow(ip)) { + return logWarnAndResult(ip + " not in " + app + " white list", Access.IP_NOT_IN_WHITE_LIST); + } else if (a.useAuth) { + if (a.authType == App.SIGN_AUTH) { + if (StringUtils.isBlank(timestamp) || StringUtils.isBlank(sign)) { + return logWarnAndResult(app + " lack timestamp " + timestamp + " or sign " + sign, Access.NO_TIMESTAMP_OR_SIGN); + } else if (!validate(app, timestamp, a.secretkey, sign)) { + return logWarnAndResult(app + " sign " + sign + " invalid", Access.SIGN_INVALID); + } else { + return Mono.just(ac); + } + } else if (customAuth == null) { + return logWarnAndResult(app + " no custom auth", Access.NO_CUSTOM_AUTH); + } else { + return customAuth.auth(exchange, app, ip, timestamp, sign, secretKey, a).flatMap(v -> { + if (v == Access.YES) { + return Mono.just(ac); + } else { + return Mono.just(Access.CUSTOM_AUTH_REJECT); + } + }); + } + } else { + return Mono.just(ac); + } + } else { + return logWarnAndResult("cant access " + api, Access.CANT_ACCESS_SERVICE_API); + } + } else { + return logWarnAndResult(app + " not in " + api + " legal apps", Access.APP_NOT_IN_API_LEGAL_APPS); + } + } else { + return logWarnAndResult(gatewayGroupService.currentGatewayGroupSet + " cant proxy " + api, Access.GATEWAY_GROUP_CANT_PROXY_API); + } + } + } + + private static Mono allow(String api, ApiConfig ac) { + if (ac.access == ApiConfig.ALLOW) { + return Mono.just(ac); + } else { + return logWarnAndResult("cant access " + api, Access.CANT_ACCESS_SERVICE_API); } } @@ -321,12 +350,8 @@ public class ApiConfigService { } private static boolean validate(String app, String timestamp, String secretKey, String sign) { - StringBuilder b = new StringBuilder(128); + StringBuilder b = ThreadContext.getStringBuilder(); b.append(app).append(Constants.Symbol.UNDERLINE).append(timestamp).append(Constants.Symbol.UNDERLINE).append(secretKey); return sign.equals(DigestUtils.md532(b.toString())); } - - public Map getApp2gatewayGroupMap() { - return app2gatewayGroupMap; - } } diff --git a/src/main/java/we/plugin/auth/App.java b/src/main/java/we/plugin/auth/App.java index beaffc5..2e9e463 100644 --- a/src/main/java/we/plugin/auth/App.java +++ b/src/main/java/we/plugin/auth/App.java @@ -14,25 +14,24 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.plugin.auth; -import we.util.JacksonUtils; import org.apache.commons.lang3.StringUtils; -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; +import we.util.Constants; +import we.util.JacksonUtils; + +import java.util.*; import java.util.stream.Collectors; /** - * @author lancer + * @author hongqiaowei */ public class App { - public static final String TO_C = "2c"; - - public static final String TO_B = "2b"; + public static final String ALL_APP = "*"; public static final int DELETED = 1; @@ -56,7 +55,9 @@ public class App { public boolean useWhiteList = false; - public Set ips = Collections.emptySet(); + public String config; + + private Map ips = new HashMap<>(6); public void setUseAuth(int i) { if (i == 1) { @@ -72,10 +73,69 @@ public class App { public void setIps(String ips) { if (StringUtils.isNotBlank(ips)) { - this.ips = Arrays.stream(StringUtils.split(ips, ',')).collect(Collectors.toSet()); + Arrays.stream(StringUtils.split(ips, ',')).forEach( + ip -> { + ip = ip.trim(); + int i = ip.lastIndexOf('.'); + String subnet = ip.substring(0, i).trim(); + String addrSeg = ip.substring(i + 1).trim(); + if ("*".equals(addrSeg)) { + this.ips.put(subnet, new String[]{"2", "254"}); + } else if (addrSeg.indexOf('-') > 0) { + String[] a = StringUtils.split(addrSeg, '-'); + String beg = a[0].trim(); + String end = a[1].trim(); + this.ips.put(subnet, new String[]{beg, end}); + } else { + this.ips.put(subnet, new String[]{addrSeg, addrSeg}); + } + } + ); } } + public boolean allow(String ip) { + int originSubnetLen = ip.lastIndexOf(Constants.Symbol.DOT); + for (Map.Entry e : ips.entrySet()) { + String subnet = e.getKey(); + int subnetLen = subnet.length(); + byte i = 0; + if (subnetLen == originSubnetLen) { + for (; i < subnetLen; i++) { + if (subnet.charAt(i) != ip.charAt(i)) { + break; + } + } + if (i == subnetLen) { + int originAddrLen = ip.length() - originSubnetLen - 1; + String[] addrSeg = e.getValue(); + String addrSegBeg = addrSeg[0]; + String addrSegEnd = addrSeg[1]; + if (originAddrLen < addrSegBeg.length() || addrSegEnd.length() < originAddrLen) { + return false; + } else { + if (originAddrLen == addrSegBeg.length()) { + for (byte j = 0; j < addrSegBeg.length(); j++) { + if (ip.charAt(originSubnetLen + 1 + j) < addrSegBeg.charAt(j)) { + return false; + } + } + } + if (originAddrLen == addrSegEnd.length()) { + for (byte j = 0; j < addrSegEnd.length(); j++) { + if (addrSegEnd.charAt(j) < ip.charAt(originSubnetLen + 1 + j)) { + return false; + } + } + } + return true; + } + } + } + } + return false; + } + @Override public String toString() { return JacksonUtils.writeValueAsString(this); diff --git a/src/main/java/we/plugin/auth/AppService.java b/src/main/java/we/plugin/auth/AppService.java index 06d4be0..7ce09e1 100644 --- a/src/main/java/we/plugin/auth/AppService.java +++ b/src/main/java/we/plugin/auth/AppService.java @@ -14,19 +14,20 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.plugin.auth; -import we.flume.clients.log4j2appender.LogService; -import we.listener.AggregateRedisConfig; -import we.util.Constants; -import we.util.JacksonUtils; -import we.util.ReactorUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.ReactiveStringRedisTemplate; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import we.flume.clients.log4j2appender.LogService; +import we.listener.AggregateRedisConfig; +import we.util.Constants; +import we.util.JacksonUtils; +import we.util.ReactorUtils; import javax.annotation.PostConstruct; import javax.annotation.Resource; @@ -37,7 +38,7 @@ import java.util.Objects; import java.util.concurrent.TimeUnit; /** - * @author lancer + * @author hongqiaowei */ @Service diff --git a/src/main/java/we/plugin/auth/AuthPluginFilter.java b/src/main/java/we/plugin/auth/AuthPluginFilter.java index 8dad4b3..43c5aa3 100644 --- a/src/main/java/we/plugin/auth/AuthPluginFilter.java +++ b/src/main/java/we/plugin/auth/AuthPluginFilter.java @@ -14,23 +14,24 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.plugin.auth; -import we.flume.clients.log4j2appender.LogService; -import we.plugin.PluginFilter; -import we.util.WebUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; +import we.flume.clients.log4j2appender.LogService; +import we.plugin.PluginFilter; +import we.util.WebUtils; import javax.annotation.Resource; -import java.util.HashMap; +import java.util.Collections; import java.util.Map; /** - * @author lancer + * @author hongqiaowei */ @Component(AuthPluginFilter.AUTH_PLUGIN_FILTER) @@ -52,8 +53,7 @@ public class AuthPluginFilter extends PluginFilter { if (log.isDebugEnabled()) { log.debug("req auth: " + r, LogService.BIZ_ID, exchange.getRequest().getId()); } - Map data = new HashMap<>(1, 1.0f); - data.put(RESULT, r); + Map data = Collections.singletonMap(RESULT, r); return WebUtils.transmitSuccessFilterResultAndEmptyMono(exchange, AUTH_PLUGIN_FILTER, data); } ); diff --git a/src/main/java/we/plugin/auth/CustomAuth.java b/src/main/java/we/plugin/auth/CustomAuth.java index 9987724..59587a5 100644 --- a/src/main/java/we/plugin/auth/CustomAuth.java +++ b/src/main/java/we/plugin/auth/CustomAuth.java @@ -14,13 +14,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.plugin.auth; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** - * @author lancer + * @author hongqiaowei */ public interface CustomAuth { diff --git a/src/main/java/we/plugin/auth/GatewayGroup.java b/src/main/java/we/plugin/auth/GatewayGroup.java index a632e75..2f58cbe 100644 --- a/src/main/java/we/plugin/auth/GatewayGroup.java +++ b/src/main/java/we/plugin/auth/GatewayGroup.java @@ -14,70 +14,52 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.plugin.auth; -import com.fasterxml.jackson.annotation.JsonIgnore; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import we.util.JacksonUtils; -import java.util.HashMap; -import java.util.Map; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; /** - * @author lancer + * @author hongqiaowei */ public class GatewayGroup { private static final Logger log = LoggerFactory.getLogger(GatewayGroup.class); - public static final char C = 'c'; + public static final String DEFAULT = "default"; - public static final char B = 'b'; + public static final int DELETED = 1; - public static final char T = 't'; + public int id; - public char id; + public int isDeleted = 0; - private Map serviceConfigMap = new HashMap<>(128); + public String group; - public GatewayGroup(char id) { - this.id = id; - } + public String name; - public Map getServiceConfigMap() { - return serviceConfigMap; - } + public Set gateways = new HashSet<>(); - @JsonIgnore - public ServiceConfig getServiceConfig(String id) { - return serviceConfigMap.get(id); - } - - public void remove(ApiConfig ac) { - ServiceConfig sc = serviceConfigMap.get(ac.service); - if (sc == null) { - log.info("no service config for " + ac); - } else { - sc.remove(ac); - if (sc.apiConfigMap().isEmpty()) { - serviceConfigMap.remove(ac.service); - } + public void setGateways(String gateways) { + if (StringUtils.isNotBlank(gateways)) { + Arrays.stream(StringUtils.split(gateways, ',')).forEach( + ip -> { + this.gateways.add(ip.trim()); + } + ); } } - public void add(ApiConfig ac) { - ServiceConfig sc = new ServiceConfig(ac.service); - serviceConfigMap.put(ac.service, sc); - sc.add(ac); - } - - public void update(ApiConfig ac) { - ServiceConfig sc = serviceConfigMap.get(ac.service); - if (sc == null) { - add(ac); - } else { - sc.update(ac); - } + @Override + public String toString() { + return JacksonUtils.writeValueAsString(this); } } diff --git a/src/main/java/we/plugin/auth/GatewayGroup2appsToApiConfig.java b/src/main/java/we/plugin/auth/GatewayGroup2appsToApiConfig.java new file mode 100644 index 0000000..91ff728 --- /dev/null +++ b/src/main/java/we/plugin/auth/GatewayGroup2appsToApiConfig.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2020 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package we.plugin.auth; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import we.util.JacksonUtils; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author hongqiaowei + */ + +public class GatewayGroup2appsToApiConfig { + + private static final Logger log = LoggerFactory.getLogger(GatewayGroup2appsToApiConfig.class); + + private Map> configMap = new HashMap<>(6); + + public Map> getConfigMap() { + return configMap; + } + + public void setConfigMap(Map> configMap) { + this.configMap = configMap; + } + + public void add(ApiConfig ac) { + for (String gg : ac.gatewayGroups) { + Map app2apiConfigMap = configMap.get(gg); + if (app2apiConfigMap == null) { + app2apiConfigMap = new HashMap<>(); + configMap.put(gg, app2apiConfigMap); + } + for (String a : ac.apps) { + app2apiConfigMap.put(a, ac); + log.info(gg + " add " + a + " -> " + ac); + } + } + } + + public void remove(ApiConfig ac) { + for (String gg : ac.gatewayGroups) { + Map app2apiConfigMap = configMap.get(gg); + if (app2apiConfigMap != null) { + for (String a : ac.apps) { + ApiConfig r = app2apiConfigMap.remove(a); + log.info(gg + " remove " + a + " -> " + r); + } + } + } + } + + public void update(ApiConfig ac) { + for (String gg : ac.gatewayGroups) { + Map app2apiConfigMap = configMap.get(gg); + if (app2apiConfigMap == null) { + app2apiConfigMap = new HashMap<>(); + configMap.put(gg, app2apiConfigMap); + } + for (String a : ac.apps) { + ApiConfig old = app2apiConfigMap.put(a, ac); + log.info(gg + " update " + a + " -> " + old + " with " + ac); + } + } + } + + public ApiConfig get(String gatewayGroup, String app) { + Map app2apiConfigMap = configMap.get(gatewayGroup); + if (app2apiConfigMap == null) { + return null; + } else { + return app2apiConfigMap.get(app); + } + } + + public String toString() { + return JacksonUtils.writeValueAsString(this); + } +} diff --git a/src/main/java/we/plugin/auth/GatewayGroupService.java b/src/main/java/we/plugin/auth/GatewayGroupService.java new file mode 100644 index 0000000..a78c09d --- /dev/null +++ b/src/main/java/we/plugin/auth/GatewayGroupService.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2020 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package we.plugin.auth; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.redis.core.ReactiveStringRedisTemplate; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import we.flume.clients.log4j2appender.LogService; +import we.listener.AggregateRedisConfig; +import we.util.Constants; +import we.util.JacksonUtils; +import we.util.NetworkUtils; +import we.util.ReactorUtils; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * @author hongqiaowei + */ + +@Service +public class GatewayGroupService { + + private static final Logger log = LoggerFactory.getLogger(GatewayGroupService.class); + + private static final String fizzGatewayGroup = "fizz_gateway_group"; + + private static final String fizzGatewayGroupChannel = "fizz_gateway_group_channel"; + + public Map gatewayGroupMap = new HashMap<>(6); + + private Map oldGatewayGroupMap = new HashMap<>(6); + + public Set currentGatewayGroupSet = new HashSet<>(6); + + @Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE) + private ReactiveStringRedisTemplate rt; + + @PostConstruct + public void init() throws Throwable { + final Throwable[] throwable = new Throwable[1]; + Throwable error = Mono.just(Objects.requireNonNull(rt.opsForHash().entries(fizzGatewayGroup) + .defaultIfEmpty(new AbstractMap.SimpleEntry<>(ReactorUtils.OBJ, ReactorUtils.OBJ)).onErrorStop().doOnError(t -> { + log.info(null, t); + }) + .concatMap(e -> { + Object k = e.getKey(); + if (k == ReactorUtils.OBJ) { + return Flux.just(e); + } + Object v = e.getValue(); + log.info(k.toString() + Constants.Symbol.COLON + v.toString(), LogService.BIZ_ID, k.toString()); + String json = (String) v; + try { + GatewayGroup gg = JacksonUtils.readValue(json, GatewayGroup.class); + oldGatewayGroupMap.put(gg.id, gg); + updateGatewayGroupMap(gg); + return Flux.just(e); + } catch (Throwable t) { + throwable[0] = t; + log.info(json, t); + return Flux.error(t); + } + }).blockLast())).flatMap( + e -> { + if (throwable[0] != null) { + return Mono.error(throwable[0]); + } + return lsnGatewayGroupChange(); + } + ).block(); + if (error != ReactorUtils.EMPTY_THROWABLE) { + throw error; + } + } + + private Mono lsnGatewayGroupChange() { + final Throwable[] throwable = new Throwable[1]; + final boolean[] b = {false}; + rt.listenToChannel(fizzGatewayGroupChannel).doOnError(t -> { + throwable[0] = t; + b[0] = false; + log.error("lsn " + fizzGatewayGroupChannel, t); + }).doOnSubscribe( + s -> { + b[0] = true; + log.info("success to lsn on " + fizzGatewayGroupChannel); + } + ).doOnNext(msg -> { + String json = msg.getMessage(); + log.info(json, LogService.BIZ_ID, "gg" + System.currentTimeMillis()); + try { + GatewayGroup gg = JacksonUtils.readValue(json, GatewayGroup.class); + GatewayGroup r = oldGatewayGroupMap.remove(gg.id); + if (gg.isDeleted != GatewayGroup.DELETED && r != null) { + gatewayGroupMap.remove(r.group); + } + updateGatewayGroupMap(gg); + if (gg.isDeleted != GatewayGroup.DELETED) { + oldGatewayGroupMap.put(gg.id, gg); + } + } catch (Throwable t) { + log.info(json, t); + } + }).subscribe(); + Throwable t = throwable[0]; + while (!b[0]) { + if (t != null) { + return Mono.error(t); + } else { + try { + TimeUnit.SECONDS.sleep(2); + } catch (InterruptedException e) { + return Mono.error(e); + } + } + } + return Mono.just(ReactorUtils.EMPTY_THROWABLE); + } + + private void updateGatewayGroupMap(GatewayGroup gg) { + if (gg.isDeleted == GatewayGroup.DELETED) { + GatewayGroup r = gatewayGroupMap.remove(gg.group); + log.info("remove " + r); + } else { + GatewayGroup existGatewayGroup = gatewayGroupMap.get(gg.group); + gatewayGroupMap.put(gg.group, gg); + if (existGatewayGroup == null) { + log.info("add " + gg); + } else { + log.info("update " + existGatewayGroup + " with " + gg); + } + } + updateCurrentGatewayGroupSet(); + } + + private void updateCurrentGatewayGroupSet() { + String ip = NetworkUtils.getServerIp(); + currentGatewayGroupSet.clear(); + gatewayGroupMap.forEach( + (k, gg) -> { + if (gg.gateways.contains(ip)) { + currentGatewayGroupSet.add(gg.group); + } + } + ); + if (currentGatewayGroupSet.isEmpty()) { + currentGatewayGroupSet.add(GatewayGroup.DEFAULT); + } + } + + public boolean currentGatewayGroupIn(Set gatewayGroups) { + for (String cgg : currentGatewayGroupSet) { + if (gatewayGroups.contains(cgg)) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/we/plugin/auth/ServiceConfig.java b/src/main/java/we/plugin/auth/ServiceConfig.java index 6979b78..594a611 100644 --- a/src/main/java/we/plugin/auth/ServiceConfig.java +++ b/src/main/java/we/plugin/auth/ServiceConfig.java @@ -14,10 +14,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.plugin.auth; import com.fasterxml.jackson.annotation.JsonIgnore; + +import org.apache.commons.lang3.StringUtils; import we.util.Constants; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpMethod; @@ -27,99 +31,122 @@ import java.util.HashMap; import java.util.Map; /** - * @author lancer + * @author hongqiaowei */ public class ServiceConfig { private static final Logger log = LoggerFactory.getLogger(ServiceConfig.class); - private static final String forward_slash_str = String.valueOf(Constants.Symbol.FORWARD_SLASH); + public String id; - public String id; + @JsonIgnore + public Map apiConfigMap = new HashMap<>(32); - private Map apiConfigMap = new HashMap<>(32); - - private Map> path2methodToApiConfigMapMap = new HashMap<>(32); + public Map> path2methodToApiConfigMapMap = new HashMap<>(6); public ServiceConfig(String id) { this.id = id; } - public Map apiConfigMap() { - return apiConfigMap; - } - - public Map> getPath2methodToApiConfigMapMap() { - return path2methodToApiConfigMapMap; + public void add(ApiConfig ac) { + apiConfigMap.put(ac.id, ac); + EnumMap method2apiConfigMap = path2methodToApiConfigMapMap.get(ac.path); + if (method2apiConfigMap == null) { + method2apiConfigMap = new EnumMap<>(HttpMethod.class); + GatewayGroup2appsToApiConfig gatewayGroup2appsToApiConfig = new GatewayGroup2appsToApiConfig(); + gatewayGroup2appsToApiConfig.add(ac); + method2apiConfigMap.put(ac.method, gatewayGroup2appsToApiConfig); + path2methodToApiConfigMapMap.put(ac.path, method2apiConfigMap); + } else { + GatewayGroup2appsToApiConfig gatewayGroup2appsToApiConfig = method2apiConfigMap.get(ac.method); + if (gatewayGroup2appsToApiConfig == null) { + gatewayGroup2appsToApiConfig = new GatewayGroup2appsToApiConfig(); + method2apiConfigMap.put(ac.method, gatewayGroup2appsToApiConfig); + } + gatewayGroup2appsToApiConfig.add(ac); + } + log.info("add " + ac); } public void remove(ApiConfig ac) { ApiConfig remove = apiConfigMap.remove(ac.id); - log.info(remove + " is removed from api config map"); - Map method2apiConfigMap = path2methodToApiConfigMapMap.get(ac.path); - if (method2apiConfigMap != null) { - ApiConfig r = method2apiConfigMap.remove(ac.method); - log.info(r + " is removed from method 2 api config map"); - if (method2apiConfigMap.isEmpty()) { - path2methodToApiConfigMapMap.remove(ac.path); - } - } else { - log.info("no method 2 api config map for " + ac.path); - } - } - - public void add(ApiConfig ac) { - apiConfigMap.put(ac.id, ac); - EnumMap method2apiConfigMap = path2methodToApiConfigMapMap.get(ac.path); + Map method2apiConfigMap = path2methodToApiConfigMapMap.get(ac.path); if (method2apiConfigMap == null) { - method2apiConfigMap = new EnumMap<>(HttpMethod.class); - path2methodToApiConfigMapMap.put(ac.path, method2apiConfigMap); + log.info("no config to delete for " + ac.service + ' ' + ac.path); + } else { + GatewayGroup2appsToApiConfig gatewayGroup2appsToApiConfig = method2apiConfigMap.get(ac.method); + if (gatewayGroup2appsToApiConfig == null) { + log.info("no config to delete for " + ac.service + ' ' + ac.method + ' ' + ac.path); + } else { + log.info(id + " remove " + ac); + gatewayGroup2appsToApiConfig.remove(ac); + } } - method2apiConfigMap.put(ac.method, ac); - log.info(ac + " is added to api config map"); } public void update(ApiConfig ac) { ApiConfig prev = apiConfigMap.put(ac.id, ac); log.info(prev + " is updated by " + ac + " in api config map"); - EnumMap method2apiConfigMap = path2methodToApiConfigMapMap.get(ac.path); + EnumMap method2apiConfigMap = path2methodToApiConfigMapMap.get(ac.path); if (method2apiConfigMap == null) { method2apiConfigMap = new EnumMap<>(HttpMethod.class); + GatewayGroup2appsToApiConfig gatewayGroup2appsToApiConfig = new GatewayGroup2appsToApiConfig(); + gatewayGroup2appsToApiConfig.add(ac); + method2apiConfigMap.put(ac.method, gatewayGroup2appsToApiConfig); path2methodToApiConfigMapMap.put(ac.path, method2apiConfigMap); + } else { + GatewayGroup2appsToApiConfig gatewayGroup2appsToApiConfig = method2apiConfigMap.get(ac.method); + if (gatewayGroup2appsToApiConfig == null) { + gatewayGroup2appsToApiConfig = new GatewayGroup2appsToApiConfig(); + method2apiConfigMap.put(ac.method, gatewayGroup2appsToApiConfig); + gatewayGroup2appsToApiConfig.add(ac); + } else { + log.info(id + " update " + ac); + gatewayGroup2appsToApiConfig.update(ac); + } } - ApiConfig put = method2apiConfigMap.put(ac.method, ac); - log.info(put + " is updated by " + ac + " in method 2 api config map"); } @JsonIgnore - public ApiConfig getApiConfig(HttpMethod method, String path) { + public ApiConfig getApiConfig(HttpMethod method, String path, String gatewayGroup, String app) { + GatewayGroup2appsToApiConfig r = getApiConfig0(method, path); + if (r == null) { + return null; + } + if (StringUtils.isBlank(app)) { + app = App.ALL_APP; + } + return r.get(gatewayGroup, app); + } + + private GatewayGroup2appsToApiConfig getApiConfig0(HttpMethod method, String path) { while (true) { - EnumMap method2apiConfigMap = path2methodToApiConfigMapMap.get(path); + EnumMap method2apiConfigMap = path2methodToApiConfigMapMap.get(path); if (method2apiConfigMap == null) { int i = path.lastIndexOf(Constants.Symbol.FORWARD_SLASH); if (i == 0) { - method2apiConfigMap = path2methodToApiConfigMapMap.get(forward_slash_str); + method2apiConfigMap = path2methodToApiConfigMapMap.get(Constants.Symbol.FORWARD_SLASH_STR); if (method2apiConfigMap == null) { return null; } else { - return getApiConfig0(method, method2apiConfigMap); + return getApiConfig1(method, method2apiConfigMap); } } else { path = path.substring(0, i); } } else { - return getApiConfig0(method, method2apiConfigMap); + return getApiConfig1(method, method2apiConfigMap); } } } - private ApiConfig getApiConfig0(HttpMethod method, EnumMap method2apiConfigMap) { - ApiConfig ac = method2apiConfigMap.get(method); - if (ac == null) { + private GatewayGroup2appsToApiConfig getApiConfig1(HttpMethod method, EnumMap method2apiConfigMap) { + GatewayGroup2appsToApiConfig r = method2apiConfigMap.get(method); + if (r == null) { return method2apiConfigMap.get(HttpMethod.X); } else { - return ac; + return r; } } } diff --git a/src/main/java/we/plugin/stat/StatPluginFilter.java b/src/main/java/we/plugin/stat/StatPluginFilter.java index 24bca24..a314537 100644 --- a/src/main/java/we/plugin/stat/StatPluginFilter.java +++ b/src/main/java/we/plugin/stat/StatPluginFilter.java @@ -14,24 +14,32 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.plugin.stat; -import we.flume.clients.log4j2appender.LogService; -import we.plugin.PluginFilter; -import we.util.Constants; -import we.util.ThreadContext; -import we.util.WebUtils; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.ReactiveStringRedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; +import we.flume.clients.log4j2appender.LogService; +import we.listener.AggregateRedisConfig; +import we.plugin.PluginFilter; +import we.plugin.auth.GatewayGroupService; +import we.util.Constants; +import we.util.ThreadContext; +import we.util.WebUtils; +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.Iterator; import java.util.Map; /** - * @author lancer + * @author hongqiaowei */ @Component(StatPluginFilter.STAT_PLUGIN_FILTER) @@ -41,8 +49,6 @@ public class StatPluginFilter extends PluginFilter { public static final String STAT_PLUGIN_FILTER = "statPlugin"; - private static final String accessStat = "$accessStat"; - private static final String ip = "\"ip\":"; private static final String gatewayGroup = "\"gatewayGroup\":"; @@ -60,24 +66,40 @@ public class StatPluginFilter extends PluginFilter { @Value("${stat.open:false}") private boolean statOpen = false; - @Value("${stat.topic:fizz_access_stat}") + @Value("${stat.channel:fizz_access_stat}") + private String fizzAccessStatChannel; + + @Value("${stat.topic:}") private String fizzAccessStatTopic; + @Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE) + private ReactiveStringRedisTemplate rt; + + @Resource + private GatewayGroupService gatewayGroupService; + + private String currentGatewayGroups; + + @PostConstruct + public void init() { + Iterator it = gatewayGroupService.currentGatewayGroupSet.iterator(); + while (it.hasNext()) { + if (StringUtils.isBlank(currentGatewayGroups)) { + currentGatewayGroups = it.next(); + } else { + currentGatewayGroups = currentGatewayGroups + ',' + it.next(); + } + } + } + @Override public Mono doFilter(ServerWebExchange exchange, Map config, String fixedConfig) { if (statOpen) { - StringBuilder b = (StringBuilder) ThreadContext.get(accessStat); - if (b == null) { - b = new StringBuilder(128); - ThreadContext.set(accessStat, b); - } else { - b.delete(0, b.length()); - } - + StringBuilder b = ThreadContext.getStringBuilder(); b.append(Constants.Symbol.LEFT_BRACE); b.append(ip); toJsonStringValue(b, WebUtils.getOriginIp(exchange)); b.append(Constants.Symbol.COMMA); - b.append(gatewayGroup); toJsonStringValue(b, WebUtils.getCurrentGatewayGroup(exchange)); b.append(Constants.Symbol.COMMA); + b.append(gatewayGroup); toJsonStringValue(b, currentGatewayGroups); b.append(Constants.Symbol.COMMA); b.append(service); toJsonStringValue(b, WebUtils.getServiceId(exchange)); b.append(Constants.Symbol.COMMA); b.append(appid); toJsonStringValue(b, WebUtils.getAppId(exchange)); b.append(Constants.Symbol.COMMA); b.append(apiMethod); toJsonStringValue(b, exchange.getRequest().getMethodValue()); b.append(Constants.Symbol.COMMA); @@ -85,7 +107,11 @@ public class StatPluginFilter extends PluginFilter { b.append(reqTime) .append(System.currentTimeMillis()); b.append(Constants.Symbol.RIGHT_BRACE); - log.info(b.toString(), LogService.HANDLE_STGY, LogService.toKF(fizzAccessStatTopic)); + if (StringUtils.isBlank(fizzAccessStatTopic)) { + rt.convertAndSend(fizzAccessStatChannel, b.toString()); + } else { + log.info(b.toString(), LogService.HANDLE_STGY, LogService.toKF(fizzAccessStatTopic)); + } } return WebUtils.transmitSuccessFilterResultAndEmptyMono(exchange, STAT_PLUGIN_FILTER, null); diff --git a/src/main/java/we/proxy/CallBackendConfig.java b/src/main/java/we/proxy/CallBackendConfig.java index 7d61112..f7e60b2 100644 --- a/src/main/java/we/proxy/CallBackendConfig.java +++ b/src/main/java/we/proxy/CallBackendConfig.java @@ -14,10 +14,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.proxy; /** - * @author lancer + * @author hongqiaowei * 请求转发/调用后端接口时的负载均衡、流控、failover、超时等配置 */ diff --git a/src/main/java/we/proxy/FizzWebClient.java b/src/main/java/we/proxy/FizzWebClient.java index 348385e..d1be262 100644 --- a/src/main/java/we/proxy/FizzWebClient.java +++ b/src/main/java/we/proxy/FizzWebClient.java @@ -14,17 +14,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.proxy; import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.EurekaClient; import com.netflix.discovery.shared.Applications; -import we.flume.clients.log4j2appender.LogService; -import we.config.AggrWebClientConfig; -import we.config.ProxyWebClientConfig; -import we.util.Constants; -import we.util.ThreadContext; -import we.util.WebUtils; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -38,14 +34,22 @@ import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import we.config.AggrWebClientConfig; +import we.config.ProxyWebClientConfig; +import we.flume.clients.log4j2appender.LogService; +import we.util.Constants; +import we.util.ThreadContext; +import we.util.WebUtils; import javax.annotation.PostConstruct; import javax.annotation.Resource; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicLong; /** - * @author lancer + * @author hongqiaowei */ @Service @@ -95,18 +99,26 @@ public class FizzWebClient { return aggrResolveAddressSend(aggrService, aggrMethod, aggrPath, originReqIdOrBizId, method, uriOrSvc, headers, body, null); } - private Mono aggrResolveAddressSend(String aggrService, HttpMethod aggrMethod, String aggrPath, @Nullable String originReqIdOrBizId, - HttpMethod method, String uriOrSvc, @Nullable HttpHeaders headers, @Nullable Object body, @Nullable CallBackendConfig cbc) { + public Mono send(String reqId, HttpMethod method, String uriOrSvc, @Nullable HttpHeaders headers, @Nullable Object body) { + return send(reqId, method, uriOrSvc, headers, body, null); + } + public Mono send(String reqId, HttpMethod method, String uriOrSvc, HttpHeaders headers, Object body, CallBackendConfig cbc) { String s = extractServiceOrAddress(uriOrSvc); if (isService(s)) { String path = uriOrSvc.substring(uriOrSvc.indexOf(Constants.Symbol.FORWARD_SLASH, 10)); - return send2service(originReqIdOrBizId, method, s, path, headers, body, cbc); + return send2service(reqId, method, s, path, headers, body, cbc); } else { - return send2uri(originReqIdOrBizId, method, uriOrSvc, headers, body, cbc); + return send2uri(reqId, method, uriOrSvc, headers, body, cbc); } } + private Mono aggrResolveAddressSend(String aggrService, HttpMethod aggrMethod, String aggrPath, @Nullable String originReqIdOrBizId, + HttpMethod method, String uriOrSvc, @Nullable HttpHeaders headers, @Nullable Object body, @Nullable CallBackendConfig cbc) { + + return send(originReqIdOrBizId, method, uriOrSvc, headers, body, cbc); + } + public Mono proxySend2service(@Nullable String originReqIdOrBizId, HttpMethod method, String service, String relativeUri, @Nullable HttpHeaders headers, @Nullable Object body) { @@ -218,7 +230,23 @@ public class FizzWebClient { return b.append(Constants.Symbol.HTTP_PROTOCOL_PREFIX).append(inst.getIPAddr()).append(Constants.Symbol.COLON).append(inst.getPort()).append(path).toString(); } + + // private static List aggrMemberInsts = new ArrayList<>(); + // static { + // InstanceInfo i0 = InstanceInfo.Builder.newBuilder().setAppName("TRIP-MINI").setIPAddr("xxx.25.63.192").setPort(7094).build(); + // aggrMemberInsts.add(i0); + // } + // private static AtomicLong counter = new AtomicLong(0); + // private static final String aggrMember = "trip-mini"; + + private InstanceInfo roundRobinChoose1instFrom(String service) { + + // if (aggrMember.equals(service)) { + // int idx = (int) (counter.incrementAndGet() % aggrMemberInsts.size()); + // return aggrMemberInsts.get(idx); + // } + List insts = eurekaClient.getInstancesByVipAddress(service, false); if (insts == null || insts.isEmpty()) { throw new RuntimeException("eureka no " + service, null, false, false) {}; diff --git a/src/main/java/we/util/Constants.java b/src/main/java/we/util/Constants.java index 3152b26..b17404f 100644 --- a/src/main/java/we/util/Constants.java +++ b/src/main/java/we/util/Constants.java @@ -14,12 +14,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.util; import org.apache.commons.lang3.SystemUtils; /** - * @author lancer + * @author hongqiaowei */ public final class Constants { @@ -33,6 +34,7 @@ public final class Constants { public static final char BLANK = ' '; public static final char SPACE = BLANK; public static final char FORWARD_SLASH = '/'; + public static final String FORWARD_SLASH_STR = "/"; public static final char BACK_SLASH = '\\'; public static final char DOT = '.'; public static final char SEMICOLON = ';'; diff --git a/src/main/java/we/util/DateTimeUtils.java b/src/main/java/we/util/DateTimeUtils.java index 2b2a20d..511e5cc 100644 --- a/src/main/java/we/util/DateTimeUtils.java +++ b/src/main/java/we/util/DateTimeUtils.java @@ -14,9 +14,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package we.util; -import we.util.Constants.DatetimePattern; +package we.util; import java.time.*; import java.time.format.DateTimeFormatter; @@ -25,8 +24,10 @@ import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; +import we.util.Constants.DatetimePattern; + /** - * @author lancer + * @author hongqiaowei */ public abstract class DateTimeUtils { diff --git a/src/main/java/we/util/DigestUtils.java b/src/main/java/we/util/DigestUtils.java index 0f89972..ca4466d 100644 --- a/src/main/java/we/util/DigestUtils.java +++ b/src/main/java/we/util/DigestUtils.java @@ -22,7 +22,7 @@ import org.apache.commons.codec.binary.Hex; import java.security.MessageDigest; /** - * @author lancer + * @author hongqiaowei */ public abstract class DigestUtils extends org.apache.commons.codec.digest.DigestUtils { diff --git a/src/main/java/we/util/JacksonUtils.java b/src/main/java/we/util/JacksonUtils.java index c4dce6d..0b186bf 100644 --- a/src/main/java/we/util/JacksonUtils.java +++ b/src/main/java/we/util/JacksonUtils.java @@ -14,6 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.util; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -23,6 +24,7 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; + import we.plugin.auth.ApiConfig; import we.util.Constants.DatetimePattern; @@ -33,7 +35,7 @@ import java.time.format.DateTimeFormatter; import java.util.Date; /** - * @author lancer + * @author hongqiaowei */ public abstract class JacksonUtils { @@ -42,19 +44,19 @@ public abstract class JacksonUtils { static { JsonFactory f = new JsonFactory(); - f.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); + f.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); m = new ObjectMapper(f); m.setSerializationInclusion(Include.NON_EMPTY); - m.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true); - m.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true); - m.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, true); - m.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, true); // FIXME - m.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, true); - m.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - m.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); + m.configure( SerializationFeature. WRITE_ENUMS_USING_TO_STRING, true); + m.configure( DeserializationFeature. READ_ENUMS_USING_TO_STRING, true); + m.configure( DeserializationFeature. FAIL_ON_NUMBERS_FOR_ENUMS, true); + m.configure( SerializationFeature. WRITE_EMPTY_JSON_ARRAYS, true); // FIXME + m.configure( SerializationFeature. WRITE_NULL_MAP_VALUES, true); + m.configure( DeserializationFeature. FAIL_ON_UNKNOWN_PROPERTIES, false); + m.configure( JsonParser.Feature. ALLOW_UNQUOTED_CONTROL_CHARS, true); SimpleModule m0 = new SimpleModule(); m0.addDeserializer(Date.class, new DateDeseralizer()); diff --git a/src/main/java/we/util/NetworkUtils.java b/src/main/java/we/util/NetworkUtils.java index 5d8d503..579a35c 100644 --- a/src/main/java/we/util/NetworkUtils.java +++ b/src/main/java/we/util/NetworkUtils.java @@ -14,6 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.util; import org.slf4j.Logger; @@ -27,7 +28,7 @@ import java.security.SecureRandom; import java.util.Enumeration; /** - * @author lancer + * @author hongqiaowei */ public class NetworkUtils { @@ -75,7 +76,7 @@ public class NetworkUtils { public static int getServerId() { if (serverId == -1) { try { - StringBuilder b = new StringBuilder(); + StringBuilder b = ThreadContext.getStringBuilder(); Enumeration nis = NetworkInterface.getNetworkInterfaces(); while (nis.hasMoreElements()) { NetworkInterface ni = nis.nextElement(); diff --git a/src/main/java/we/util/ReactorUtils.java b/src/main/java/we/util/ReactorUtils.java index 58f5700..d8f73ee 100644 --- a/src/main/java/we/util/ReactorUtils.java +++ b/src/main/java/we/util/ReactorUtils.java @@ -14,12 +14,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.util; import reactor.core.publisher.Mono; /** - * @author lancer + * @author hongqiaowei */ public interface ReactorUtils { diff --git a/src/main/java/we/util/Script.java b/src/main/java/we/util/Script.java index ceede2f..fd1e791 100644 --- a/src/main/java/we/util/Script.java +++ b/src/main/java/we/util/Script.java @@ -14,10 +14,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.util; /** - * @author lancer + * @author hongqiaowei */ public class Script { diff --git a/src/main/java/we/util/ScriptUtils.java b/src/main/java/we/util/ScriptUtils.java index b00afd7..ba0c76a 100644 --- a/src/main/java/we/util/ScriptUtils.java +++ b/src/main/java/we/util/ScriptUtils.java @@ -14,9 +14,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.util; -import com.fasterxml.jackson.core.JsonProcessingException; import org.apache.commons.lang3.StringUtils; import javax.script.*; @@ -26,7 +26,7 @@ import java.util.HashMap; import java.util.Map; /** - * @author lancer + * @author hongqiaowei */ public abstract class ScriptUtils { diff --git a/src/main/java/we/util/ThreadContext.java b/src/main/java/we/util/ThreadContext.java index ffb53ec..f654f47 100644 --- a/src/main/java/we/util/ThreadContext.java +++ b/src/main/java/we/util/ThreadContext.java @@ -14,6 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.util; import java.text.SimpleDateFormat; @@ -21,7 +22,7 @@ import java.util.HashMap; import java.util.Map; /** - * @author lancer + * @author hongqiaowei */ public abstract class ThreadContext { @@ -29,7 +30,7 @@ public abstract class ThreadContext { private static ThreadLocal> tl = new ThreadLocal<>(); private static final int mapCap = 32; - private static final String sb = "_sb"; + private static final String sb = "$sb"; private static final int sbCap = 256; /** use me carefully! */ @@ -39,31 +40,29 @@ public abstract class ThreadContext { /** use me carefully! */ public static StringBuilder getStringBuilder(boolean clean) { - // Map m = getMap(); - // StringBuilder b = (StringBuilder) m.get(sb); - // if (b == null) { - // b = new StringBuilder(sbCap); - // m.put(sb, b); - // } else { - // if (clean) { - // b.delete(0, b.length()); - // } - // } - // return b; - return new StringBuilder(64); + Map m = getMap(); + StringBuilder b = (StringBuilder) m.get(sb); + if (b == null) { + b = new StringBuilder(sbCap); + m.put(sb, b); + } else { + if (clean) { + b.delete(0, b.length()); + } + } + return b; } public static StringBuilder getStringBuilder(String key) { - // StringBuilder b = (StringBuilder) get(key); - // if (b == null) { - // b = new StringBuilder(sbCap); - // Map m = getMap(); - // m.put(key, b); - // } else { - // b.delete(0, b.length()); - // } - // return b; - return getStringBuilder(true); + StringBuilder b = (StringBuilder) get(key); + if (b == null) { + b = new StringBuilder(sbCap); + Map m = getMap(); + m.put(key, b); + } else { + b.delete(0, b.length()); + } + return b; } /** for legacy code. */ diff --git a/src/main/java/we/util/Utils.java b/src/main/java/we/util/Utils.java index 71d7438..709d643 100644 --- a/src/main/java/we/util/Utils.java +++ b/src/main/java/we/util/Utils.java @@ -14,6 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.util; import org.apache.commons.lang3.StringUtils; @@ -23,7 +24,7 @@ import java.time.LocalDateTime; import java.time.LocalTime; /** - * @author lancer + * @author hongqiaowei */ public abstract class Utils { diff --git a/src/main/java/we/util/WebUtils.java b/src/main/java/we/util/WebUtils.java index f09b2f7..2e5525d 100644 --- a/src/main/java/we/util/WebUtils.java +++ b/src/main/java/we/util/WebUtils.java @@ -14,11 +14,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package we.util; -import we.flume.clients.log4j2appender.LogService; -import we.filter.FilterResult; -import we.legacy.RespEntity; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,11 +30,14 @@ import org.springframework.lang.Nullable; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; +import we.filter.FilterResult; +import we.flume.clients.log4j2appender.LogService; +import we.legacy.RespEntity; import java.util.*; /** - * @author lancer + * @author hongqiaowei */ public abstract class WebUtils { @@ -57,7 +58,7 @@ public abstract class WebUtils { private static final String SERVICE_ID = "serviceId"; - private static final String xForwardedFor = "X_FORWARDED_FOR"; + private static final String xForwardedFor = "X-FORWARDED-FOR"; private static final String unknown = "unknown"; @@ -73,8 +74,6 @@ public abstract class WebUtils { private static final String originIp = "originIp"; - public static final String CGG = "cgg"; - public static String getHeaderValue(ServerWebExchange exchange, String header) { return exchange.getRequest().getHeaders().getFirst(header); } @@ -87,10 +86,6 @@ public abstract class WebUtils { return exchange.getAttribute(APP_HEADER); } - public static Character getCurrentGatewayGroup(ServerWebExchange exchange) { - return exchange.getAttribute(CGG); - } - public static String getServiceId(ServerWebExchange exchange) { String svc = exchange.getAttribute(SERVICE_ID); if (svc == null) { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 53abe69..eaa6ac7 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -22,8 +22,6 @@ aggregate.redis.database: 10 proxy-webclient.name: proxy aggr-webclient.name: aggr -serviceWhiteList: aservice,bservice,trip-search-common-foundation,trip-mini - fizz-web-client.timeout: 20000 log.headers: COOKIE,FIZZ-APPID,FIZZ-SECRETKEY,FIZZ-SIGN,FIZZ-TS,FIZZ-RSV