## # 概述

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

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

## # gateway开发

        实现
        public abstract class PluginFilter {
            public abstract Mono<Void> doFilter(ServerWebExchange exchange, Map<String, Object> config, String fixedConfig);
        }
        即定义了一个插件。

        比如
        @Component(TestPluginFilter.TEST_PLUGIN_FILTER)
        public class TestPluginFilter extends PluginFilter {

            private static final Logger log = LoggerFactory.getLogger(TestPluginFilter.class);

            public  static final String TEST_PLUGIN_FILTER = "testPlugin";

            @Override
            public Mono<Void> doFilter(ServerWebExchange exchange, Map<String, Object> config, String fixedConfig) {
                String rid = exchange.getRequest().getId();
                Boolean logReqId = (Boolean) config.get("logReqId"); // 是否记录请求id日志，可通过manager配置
                if (logReqId == null || logReqId) {
                    log.info(exchange.getRequest().getURI().toString() + " 的请求id: " + rid);
                }
                Boolean appendFizzRsv = (Boolean) config.get("appendFizzRsv");
                if (appendFizzRsv == null || appendFizzRsv) {
                    WebUtils.appendHeader(exchange, "FIZZ-RSV", rid);
                }
                return WebUtils.transmitSuccessFilterResultAndEmptyMono(exchange, TEST_PLUGIN_FILTER, null); // 保存插件执行结果，并返回
            }
        }
        这个插件，插件必须是一个spring的Component（或子注解），且要有id，这个插件的id是testPlugin，它实现了两个功能，记录请求id日志，转发请求时添加FIZZ-RSV请求头，并且功能是可打开或关闭的。

        另外可通过：
        WebUtils.getPrevFilterResult(exchange); 获取上一个插件的执行结果，
        WebUtils.getFilterResult(exchange, "plugin.id"); 获取已执行的任意一个插件的执行结果。

## # manager配置

1、定义插件

        在插件表中，定义上面的插件：
        INSERT INTO `tb_plugin` (`eng_name`, `chn_name`, `config`, `order`)
        VALUES
        (
        'testPlugin',
        '测试插件',
        '[{\"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}]}]',
        250
        );

        eng_name为插件的id，chn_name为插件中文名，order为插件的执行顺序，也是插件在界面上的显示顺序。

        config：
        [
            {
                "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
                    }
                ]
            }
        ]
        前端据此生成插件的配置表单，具体参前端说明。

2、应用插件

如对

接口应用插件：

上面配置的"打印请求id日志"、"添加fizzRsv请求头"，对应

    public Mono<Void> doFilter(ServerWebExchange exchange, Map<String, Object> config, String fixedConfig)

中config的logReqId和appendFizzRsv key。