From a25a9d196960983fc86e9f0ce8fbf614a976000e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=8D=8E?= Date: Wed, 8 Dec 2021 19:09:40 +0800 Subject: [PATCH] =?UTF-8?q?plugin=E5=B0=81=E8=A3=85=E5=A2=9E=E5=BC=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fizz-plugin/plugin-core.md | 160 ++++++++++++++++++ .../config/WeFizzPluginAutoConfiguration.java | 26 +++ .../core/filter/AbstractFizzPlugin.java | 144 ++++++++++++++++ .../core/filter/config/ConfigUtils.java | 39 +++++ .../core/filter/config/ContentParser.java | 18 ++ .../plugin/core/filter/config/FizzConfig.java | 21 +++ .../core/filter/config/parser/JsonParser.java | 90 ++++++++++ .../core/spring/FizzPluginAliasProcessor.java | 51 ++++++ .../util/FizzPluginAppContextUtils.java | 34 ++++ .../java/we/plugin/myplugin/MyPluginPlus.java | 76 +++++++++ .../main/resources/META-INF/spring.factories | 3 + .../filter/config/parser/JsonParserTest.java | 83 +++++++++ 12 files changed, 745 insertions(+) create mode 100755 fizz-plugin/plugin-core.md create mode 100644 fizz-plugin/src/main/java/we/plugin/core/config/WeFizzPluginAutoConfiguration.java create mode 100644 fizz-plugin/src/main/java/we/plugin/core/filter/AbstractFizzPlugin.java create mode 100644 fizz-plugin/src/main/java/we/plugin/core/filter/config/ConfigUtils.java create mode 100644 fizz-plugin/src/main/java/we/plugin/core/filter/config/ContentParser.java create mode 100644 fizz-plugin/src/main/java/we/plugin/core/filter/config/FizzConfig.java create mode 100644 fizz-plugin/src/main/java/we/plugin/core/filter/config/parser/JsonParser.java create mode 100644 fizz-plugin/src/main/java/we/plugin/core/spring/FizzPluginAliasProcessor.java create mode 100644 fizz-plugin/src/main/java/we/plugin/core/spring/util/FizzPluginAppContextUtils.java create mode 100644 fizz-plugin/src/main/java/we/plugin/myplugin/MyPluginPlus.java create mode 100644 fizz-plugin/src/main/resources/META-INF/spring.factories create mode 100644 fizz-plugin/src/test/java/we/plugin/core/filter/config/parser/JsonParserTest.java diff --git a/fizz-plugin/plugin-core.md b/fizz-plugin/plugin-core.md new file mode 100755 index 0000000..880b301 --- /dev/null +++ b/fizz-plugin/plugin-core.md @@ -0,0 +1,160 @@ +--- +home: false +title: plugin core +--- + +## 主要封装说明 + +- 1、引入核心包后,不影响以前编写的插件,只是提供更加便捷的开发方式; +- 2、插件名字编写规范。在保留原有编写方式的前提下,强制实现 pluginName() 方法,对开发更加友好,减少失误; +- 3、配置获取更加容易。配置主要有3个:路由配置、插件全局配置、插件在路由里的个性配置。现在都可以直接获取相应的配置实体对象,而不是默认提供的 Map 或者 String ; + +## 使用说明 + +核心包是用于开发插件的基础包。主要是简化操作,方便开发,使开发人员更专注于业务代码对编写。 + +**1、编写2个配置实体类:插件在路由里的个性配置、插件全局配置,并添加注解 @FizzConfig** + +> @FizzConfig 参数说明: +> +> contentParser :配置内容解析器。选填,默认是 json 解析器 JsonParser 。也可以自定义解析器,只需实现 we.plugin.core.filter.config.ContentParser 接口 + +注意:默认解析器 JsonParser 的 parseRouterCfg 方法只对第一层的 json string 做了增强,但这也足够用了。如(注意 varJson 是个 json 字符串,并不是 json 对象): +```groovy +void parseRouterCfg() { + String varJson = "{\n" + + " \"var1\": \"var1\",\n" + + " \"var2\": \"var2\",\n" + + " \"var3\": \"var3\"\n" + + "}"; +// String varJson = ""; +// String varJson = null; + Map config = Maps.newHashMap(); + config.put("codeSource", "this is code source"); + config.put("var", varJson); + RouterConfig routerConfig = parser.parseRouterCfg(config, RouterConfig.class); + System.out.println(routerConfig); + } +``` + +示例: + +```java + @Data + @FizzConfig + public class PluginConfig { + private String id; + private Var var; + } + + @Data + @FizzConfig + public class RouterConfig { + private String codeSource; + private Var var; + } + + @Data + public class Var { + private String var1; + private Integer var2; + private Long var3; + } +``` + +**3、编写插件逻辑** +继承 we.plugin.core.filter.AbstractFizzPlugin ,并实现 pluginName 和 doFilter 方法 + +> pluginName 方法:获取插件名称。无参,返回插件名称,要与网关后台配置的插件名称一致 +> +> doFilter 方法:插件主要逻辑方法。入参是 ServerWebExchange,出参是 Mono + +直接调用父类方法获取各种配置: +> routerConfig:获取路由级别插件配置 +> +> pluginConfig:获取插件级别插件配置 +> +> originRouterCfg:获取原始路由级别插件配置 +> +> originPluginCfg:获取原始插件级别插件配置 +> +> apiConfig:获取路由配置 + +示例: + +```java +package we.fizz.plugin.example.plugin; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; +import we.plugin.core.filter.AbstractFizzPlugin; +import we.plugin.core.filter.config.FizzConfig; +import we.plugin.auth.ApiConfig; +import we.util.WebUtils; + +import java.util.Map; + +import static we.fizz.plugin.example.plugin.ExamplePlugin.PluginConfig; +import static we.fizz.plugin.example.plugin.ExamplePlugin.RouterConfig; + +@Slf4j +@Component +public class ExamplePlugin extends AbstractFizzPlugin { + + /** + * 插件名称 + */ + @Override + public String pluginName() { + return "examplePlugin"; + } + + /** + * filter逻辑 + */ + @Override + public Mono doFilter(ServerWebExchange exchange) { + RouterConfig routerConfig = routerConfig(exchange); + PluginConfig pluginConfig = pluginConfig(exchange); + Map originRouterCfg = originRouterCfg(exchange); + String originPluginCfg = originPluginCfg(exchange); + ApiConfig apiConfig = apiConfig(exchange); + if (log.isTraceEnabled()) { + log.trace("routerConfig : {}", routerConfig); + log.trace("pluginConfig : {}", pluginConfig); + log.trace("originRouterCfg : {}", originRouterCfg); + log.trace("originPluginCfg : {}", originPluginCfg); + log.trace("apiConfig : {}", apiConfig); + } + return WebUtils.buildDirectResponse(exchange, HttpStatus.OK, null, "success"); + } + + @Data + @FizzConfig + public static class PluginConfig { + private String id; + private Var var; + } + + @Data + public static class Var { + private String var1; + private String var2; + private String var3; + } + + @Data + @FizzConfig + public static class RouterConfig { + private String codeSource; + private Var var; + } +} + +``` + + diff --git a/fizz-plugin/src/main/java/we/plugin/core/config/WeFizzPluginAutoConfiguration.java b/fizz-plugin/src/main/java/we/plugin/core/config/WeFizzPluginAutoConfiguration.java new file mode 100644 index 0000000..f9a2585 --- /dev/null +++ b/fizz-plugin/src/main/java/we/plugin/core/config/WeFizzPluginAutoConfiguration.java @@ -0,0 +1,26 @@ +package we.plugin.core.config; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import we.plugin.core.filter.config.parser.JsonParser; +import we.plugin.core.spring.FizzPluginAliasProcessor; + +/** + * @author huanghua + */ +@Configuration +@ComponentScan({"we.config", "we.fizz", "we.plugin", "we.filter", "we.proxy", "we.stats"/*, "we.plugin.core"*/}) +public class WeFizzPluginAutoConfiguration { + + @Bean + public FizzPluginAliasProcessor fizzPluginAliasProcess(ApplicationContext context) { + return new FizzPluginAliasProcessor(context); + } + + @Bean + public JsonParser jsonParser() { + return new JsonParser(); + } +} diff --git a/fizz-plugin/src/main/java/we/plugin/core/filter/AbstractFizzPlugin.java b/fizz-plugin/src/main/java/we/plugin/core/filter/AbstractFizzPlugin.java new file mode 100644 index 0000000..851fc4f --- /dev/null +++ b/fizz-plugin/src/main/java/we/plugin/core/filter/AbstractFizzPlugin.java @@ -0,0 +1,144 @@ +package we.plugin.core.filter; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; +import we.plugin.FizzPluginFilter; +import we.plugin.PluginConfig; +import we.plugin.auth.ApiConfig; +import we.plugin.auth.ApiConfigService; +import we.plugin.core.filter.config.ContentParser; +import we.plugin.core.filter.config.FizzConfig; +import we.plugin.core.filter.config.parser.JsonParser; +import we.plugin.core.spring.util.FizzPluginAppContextUtils; +import we.util.WebUtils; + +import javax.annotation.Resource; +import java.lang.reflect.ParameterizedType; +import java.util.Map; +import java.util.function.Function; + +/** + * @author huanghua + */ +@Slf4j +@SuppressWarnings("unchecked") +public abstract class AbstractFizzPlugin implements FizzPluginFilter { + // api 配置 + public final Function nameExApiCfg = in -> "fizz.pl.api.cfg"; + // 路由上的插件配置(原始) + public final Function nameExRtCfg = in -> "fizz.pl.rt.cfg." + pluginName(); + // 插件级别配置(原始) + public final Function nameExPlCfg = in -> "fizz.pl.pl.cfg." + pluginName(); + // 路由上的插件配置(解析后) + public final Function nameExRtCfgParsed = in -> "fizz.pl.rt.cfg.parsed." + pluginName(); + // 插件级别配置(解析后) + public final Function nameExPlCfgParsed = in -> "fizz.pl.pl.cfg.parsed." + pluginName(); + @Resource + private ApiConfigService apiConfigService; + + @Override + public Mono filter(ServerWebExchange exchange, Map config) { + if (log.isTraceEnabled()) { + log.trace("{} doFilter execute...", this.pluginName()); + } + initConfig(exchange, config); + return this.doFilter(exchange); + } + + /** + * 获取路由级别插件配置 + */ + public RouterCfg routerConfig(ServerWebExchange exchange) { + if (originRouterCfg(exchange) == null) { + return null; + } + RouterCfg routerCfgInAttr = exchange.getAttribute(nameExRtCfgParsed.apply(pluginName())); + if (routerCfgInAttr != null) { + return routerCfgInAttr; + } + Class cfgClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()) + .getActualTypeArguments()[0]; + FizzConfig fizzConfig = AnnotationUtils.findAnnotation(cfgClass, FizzConfig.class); + Class cfgParser = fizzConfig == null ? JsonParser.class : fizzConfig.contentParser(); + RouterCfg routerCfg = FizzPluginAppContextUtils.getBean(cfgParser).parseRouterCfg(originRouterCfg(exchange), cfgClass); + putAttr2exchange(exchange, nameExRtCfgParsed.apply(pluginName()), routerCfg); + return routerCfg; + } + + /** + * 获取插件级别插件配置 + */ + public PluginCfg pluginConfig(ServerWebExchange exchange) { + if (originPluginCfg(exchange) == null) { + return null; + } + PluginCfg pluginCfgInAttr = exchange.getAttribute(nameExPlCfgParsed.apply(pluginName())); + if (pluginCfgInAttr != null) { + return pluginCfgInAttr; + } + Class cfgClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()) + .getActualTypeArguments()[1]; + FizzConfig fizzConfig = AnnotationUtils.findAnnotation(cfgClass, FizzConfig.class); + Class cfgParser = fizzConfig == null ? JsonParser.class : fizzConfig.contentParser(); + PluginCfg pluginCfg = FizzPluginAppContextUtils.getBean(cfgParser).parsePluginCfg(originPluginCfg(exchange), cfgClass); + putAttr2exchange(exchange, nameExPlCfgParsed.apply(pluginName()), pluginCfg); + return pluginCfg; + } + + /** + * 获取原始路由级别插件配置 + */ + public T originRouterCfg(ServerWebExchange exchange) { + return exchange.getAttribute(nameExRtCfg.apply(pluginName())); + } + + /** + * 获取原始插件级别插件配置 + */ + public T originPluginCfg(ServerWebExchange exchange) { + return exchange.getAttribute(nameExPlCfg.apply(pluginName())); + } + + /** + * 获取路由配置 + */ + public ApiConfig apiConfig(ServerWebExchange exchange) { + return exchange.getAttribute(nameExApiCfg.apply(pluginName())); + } + + protected void putAttr2exchange(ServerWebExchange exchange, String key, Object val) { + if (exchange == null || key == null || val == null) { + return; + } + exchange.getAttributes().put(key, val); + } + + private void initConfig(ServerWebExchange exchange, Map config) { + ServerHttpRequest req = exchange.getRequest(); + ApiConfig apiConfig = apiConfigService.getApiConfig(WebUtils.getAppId(exchange), + WebUtils.getClientService(exchange), req.getMethod(), WebUtils.getClientReqPath(exchange)); + String fixedConfig = (String) config.get(PluginConfig.CUSTOM_CONFIG); + if (log.isTraceEnabled()) { + log.trace("api config : {}", apiConfig); + log.trace("router config : {}", config); + log.trace("plugin config : {}", fixedConfig); + } + putAttr2exchange(exchange, nameExApiCfg.apply(pluginName()), apiConfig); + putAttr2exchange(exchange, nameExRtCfg.apply(pluginName()), config); + putAttr2exchange(exchange, nameExPlCfg.apply(pluginName()), fixedConfig); + } + + /** + * 插件名称 + */ + public abstract String pluginName(); + + /** + * filter逻辑 + */ + public abstract Mono doFilter(ServerWebExchange exchange); + +} diff --git a/fizz-plugin/src/main/java/we/plugin/core/filter/config/ConfigUtils.java b/fizz-plugin/src/main/java/we/plugin/core/filter/config/ConfigUtils.java new file mode 100644 index 0000000..6b44215 --- /dev/null +++ b/fizz-plugin/src/main/java/we/plugin/core/filter/config/ConfigUtils.java @@ -0,0 +1,39 @@ +package we.plugin.core.filter.config; + +import com.google.common.base.CharMatcher; +import com.google.common.base.Splitter; +import com.google.common.collect.Sets; +import org.apache.commons.lang3.StringUtils; + +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author huanghua + */ +public abstract class ConfigUtils { + public static final String DEFAULT_CHAR_MATCHER_ANY_OF = ",\n"; + + public static Set string2set(String strVal, String charMatcherAnyOf) { + Set finalSet = Sets.newHashSet(); + if (StringUtils.isBlank(strVal)) { + return finalSet; + } + charMatcherAnyOf = StringUtils.isBlank(charMatcherAnyOf) ? DEFAULT_CHAR_MATCHER_ANY_OF : charMatcherAnyOf; + Set set = Sets.newHashSet( + Splitter.on(CharMatcher.anyOf(charMatcherAnyOf)).trimResults().split(strVal)); + set = set.stream().filter(StringUtils::isNotBlank).collect(Collectors.toSet()); + for (String s : set) { + if (StringUtils.isBlank(s)) { + continue; + } + finalSet.add(StringUtils.trimToEmpty(s)); + } + return finalSet; + } + + public static Set string2set(String strVal) { + return string2set(strVal, DEFAULT_CHAR_MATCHER_ANY_OF); + } + +} diff --git a/fizz-plugin/src/main/java/we/plugin/core/filter/config/ContentParser.java b/fizz-plugin/src/main/java/we/plugin/core/filter/config/ContentParser.java new file mode 100644 index 0000000..f99c4af --- /dev/null +++ b/fizz-plugin/src/main/java/we/plugin/core/filter/config/ContentParser.java @@ -0,0 +1,18 @@ +package we.plugin.core.filter.config; + +import java.util.Map; + +/** + * @author huanghua + */ +public interface ContentParser { + + default T parseRouterCfg(Map config, Class toValueType) { + throw new RuntimeException(); + } + + default T parsePluginCfg(String source, Class toValueType) { + throw new RuntimeException(); + } + +} diff --git a/fizz-plugin/src/main/java/we/plugin/core/filter/config/FizzConfig.java b/fizz-plugin/src/main/java/we/plugin/core/filter/config/FizzConfig.java new file mode 100644 index 0000000..557fc20 --- /dev/null +++ b/fizz-plugin/src/main/java/we/plugin/core/filter/config/FizzConfig.java @@ -0,0 +1,21 @@ +package we.plugin.core.filter.config; + +import we.plugin.core.filter.config.parser.JsonParser; + +import java.lang.annotation.*; + +import static java.lang.annotation.ElementType.TYPE; + +/** + * @author huanghua + */ +@Target(TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface FizzConfig { + /** + * 配置内容解析器 + */ + Class contentParser() default JsonParser.class; +} diff --git a/fizz-plugin/src/main/java/we/plugin/core/filter/config/parser/JsonParser.java b/fizz-plugin/src/main/java/we/plugin/core/filter/config/parser/JsonParser.java new file mode 100644 index 0000000..71c587d --- /dev/null +++ b/fizz-plugin/src/main/java/we/plugin/core/filter/config/parser/JsonParser.java @@ -0,0 +1,90 @@ +package we.plugin.core.filter.config.parser; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import lombok.extern.slf4j.Slf4j; +import we.plugin.core.filter.config.ContentParser; + +import javax.annotation.Resource; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author huanghua + */ +@Slf4j +public class JsonParser implements ContentParser { + private static final Set> IGNORE_CONVERT_CLASS = Sets.newHashSet( + String.class + , Long.class + , Integer.class + , Double.class + , Short.class + , CharSequence.class + , Character.class + , BigDecimal.class + , Boolean.class + ); + private static final Map, List> FIELD_CACHE = Maps.newHashMap(); + @Resource + private ObjectMapper objectMapper; + + @Override + public T parseRouterCfg(Map config, Class toValueType) { + ObjectNode jsonNode = objectMapper.convertValue(config, ObjectNode.class); + convertConfig(jsonNode, toValueType); + return objectMapper.convertValue(jsonNode, toValueType); + } + + @Override + public T parsePluginCfg(String source, Class toValueType) { + try { + return objectMapper.readValue(source, toValueType); + } catch (JsonProcessingException e) { + log.warn(e.getMessage(), e); + throw new RuntimeException(e.getMessage(), e); + } + } + + private void convertConfig(ObjectNode jsonNode, Class toValueType) { + List cacheFields = fields(toValueType); + for (Field field : cacheFields) { + String fn = field.getName(); + if (jsonNode.has(fn) && !IGNORE_CONVERT_CLASS.contains(field.getType())) { + List fs = fields(field.getType()); + if (fs.size() > 0) { + JsonNode node = jsonNode.get(fn); + JsonNode readTree = null; + try { + readTree = objectMapper.readTree(node.asText()); + } catch (JsonProcessingException e) { + // ignore + } + if (readTree != null) { + jsonNode.put(fn, readTree); + } + } + } + } + } + + private List fields(Class toValueType) { + List cacheFields = FIELD_CACHE.get(toValueType); + if (cacheFields == null) { + // returns all members including private members but not inherited members. + Field[] fields = toValueType.getDeclaredFields(); + cacheFields = Lists.newArrayList(fields); + FIELD_CACHE.put(toValueType, cacheFields); + } + return cacheFields; + } + +} diff --git a/fizz-plugin/src/main/java/we/plugin/core/spring/FizzPluginAliasProcessor.java b/fizz-plugin/src/main/java/we/plugin/core/spring/FizzPluginAliasProcessor.java new file mode 100644 index 0000000..5756e0f --- /dev/null +++ b/fizz-plugin/src/main/java/we/plugin/core/spring/FizzPluginAliasProcessor.java @@ -0,0 +1,51 @@ +package we.plugin.core.spring; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.util.CollectionUtils; +import we.plugin.core.filter.AbstractFizzPlugin; + +import javax.annotation.PostConstruct; +import java.util.Map; + +/** + * @author huanghua + */ +@Slf4j +public class FizzPluginAliasProcessor { + private ApplicationContext applicationContext; + + public FizzPluginAliasProcessor(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + @PostConstruct + public void postProcessPluginAlias() { + Map serviceBeanMap = applicationContext.getBeansOfType(AbstractFizzPlugin.class); + if (CollectionUtils.isEmpty(serviceBeanMap)) { + log.debug("not found fizz plugin. skip!"); + return; + } + if (!(applicationContext instanceof GenericApplicationContext)) { + log.error("ApplicationContext is not instance of GenericApplicationContext. skip!"); + return; + } + serviceBeanMap.forEach((s, o) -> registerAlias( + ((GenericApplicationContext) applicationContext).getBeanFactory(), s, o)); + } + + private void registerAlias(ConfigurableListableBeanFactory beanFactory, + String beanName, AbstractFizzPlugin fizzPlugin) { + log.debug("register bean : {}", fizzPlugin.getClass().getName()); + BeanDefinition bd = beanFactory.getBeanDefinition(beanName); + if (bd instanceof AbstractBeanDefinition) { + AbstractBeanDefinition abd = (AbstractBeanDefinition) bd; + abd.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_AUTODETECT); + } + beanFactory.registerAlias(beanName, fizzPlugin.pluginName()); + } +} diff --git a/fizz-plugin/src/main/java/we/plugin/core/spring/util/FizzPluginAppContextUtils.java b/fizz-plugin/src/main/java/we/plugin/core/spring/util/FizzPluginAppContextUtils.java new file mode 100644 index 0000000..92e1084 --- /dev/null +++ b/fizz-plugin/src/main/java/we/plugin/core/spring/util/FizzPluginAppContextUtils.java @@ -0,0 +1,34 @@ +package we.plugin.core.spring.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @author huanghua + * @deprecated and use {@link we.Fizz} instead + */ +@Component +public class FizzPluginAppContextUtils implements ApplicationContextAware { + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext appContext) throws BeansException { + applicationContext = appContext; + } + + public static T getBean(Class requiredType) throws BeansException { + return FizzPluginAppContextUtils.getApplicationContext().getBean(requiredType); + } + + public static ApplicationContext getApplicationContext() { + if (applicationContext == null) { + String msg = "The applicationContext is not yet available. " + + "Please ensure that the spring applicationContext is completely created before calling this method!"; + throw new IllegalStateException(msg); + } + + return applicationContext; + } +} diff --git a/fizz-plugin/src/main/java/we/plugin/myplugin/MyPluginPlus.java b/fizz-plugin/src/main/java/we/plugin/myplugin/MyPluginPlus.java new file mode 100644 index 0000000..3f6976e --- /dev/null +++ b/fizz-plugin/src/main/java/we/plugin/myplugin/MyPluginPlus.java @@ -0,0 +1,76 @@ +package we.plugin.myplugin; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; +import we.plugin.auth.ApiConfig; +import we.plugin.core.filter.AbstractFizzPlugin; +import we.plugin.core.filter.config.FizzConfig; +import we.util.WebUtils; + +import java.util.Map; + +@Slf4j +@Component +public class MyPluginPlus extends AbstractFizzPlugin { + + /** + * 插件名称 + */ + @Override + public String pluginName() { + return "myPluginPlus"; + } + + /** + * filter逻辑 + */ + @Override + public Mono doFilter(ServerWebExchange exchange) { + RouterConfig routerConfig = routerConfig(exchange); + PluginConfig pluginConfig = pluginConfig(exchange); + Map originRouterCfg = originRouterCfg(exchange); + String originPluginCfg = originPluginCfg(exchange); + ApiConfig apiConfig = apiConfig(exchange); + if (log.isTraceEnabled()) { + log.trace("routerConfig : {}", routerConfig); + log.trace("pluginConfig : {}", pluginConfig); + log.trace("originRouterCfg : {}", originRouterCfg); + log.trace("originPluginCfg : {}", originPluginCfg); + log.trace("apiConfig : {}", apiConfig); + } + return WebUtils.buildDirectResponse(exchange, HttpStatus.OK, null, "success"); + } + + @Data + @FizzConfig + public static class PluginConfig { + private String id; + private PluginItem pluginItem; + } + + @Data + public static class PluginItem { + private String p1; + private String p2; + private String p3; + } + + @Data + @FizzConfig + public static class RouterConfig { + private String codeSource; + private RouterItem routerItem; + } + + @Data + public static class RouterItem { + private String r1; + private String r2; + private String r3; + } + +} diff --git a/fizz-plugin/src/main/resources/META-INF/spring.factories b/fizz-plugin/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..4421ac1 --- /dev/null +++ b/fizz-plugin/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +# Auto Configure +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + we.plugin.core.config.WeFizzPluginAutoConfiguration \ No newline at end of file diff --git a/fizz-plugin/src/test/java/we/plugin/core/filter/config/parser/JsonParserTest.java b/fizz-plugin/src/test/java/we/plugin/core/filter/config/parser/JsonParserTest.java new file mode 100644 index 0000000..271f275 --- /dev/null +++ b/fizz-plugin/src/test/java/we/plugin/core/filter/config/parser/JsonParserTest.java @@ -0,0 +1,83 @@ +package we.plugin.core.filter.config.parser; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Maps; +import lombok.Data; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import we.plugin.core.filter.config.FizzConfig; + +import java.lang.reflect.Field; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class JsonParserTest { + + private static JsonParser parser = new JsonParser(); + + @BeforeAll + public static void init() throws NoSuchFieldException, IllegalAccessException { + Class clazz = parser.getClass(); + Field field = clazz.getDeclaredField("objectMapper"); + field.setAccessible(true); + field.set(parser, new ObjectMapper()); + } + + @Test + void parseRouterCfg() { + String varJson = "{\n" + + " \"var1\": \"var1\",\n" + + " \"var2\": \"var2\",\n" + + " \"var3\": \"var3\"\n" + + "}"; +// String varJson = ""; +// String varJson = null; + Map config = Maps.newHashMap(); + config.put("codeSource", "this is code source"); + config.put("var", varJson); + RouterConfig routerConfig = parser.parseRouterCfg(config, RouterConfig.class); + assertNotNull(routerConfig, "未解析出routerConfig"); + assertNotNull( routerConfig.getVar(), "未解析出routerConfig.var"); + assertEquals("var1", routerConfig.getVar().getVar1(), "routerConfig.var.var1不匹配"); + + } + + @Test + void parsePluginCfg() { + String json = "{\n" + + " \"id\": \"123\",\n" + + " \"var\": {\n" + + " \"var1\": \"var1\",\n" + + " \"var2\": \"var2\",\n" + + " \"var3\": \"var3\"\n" + + " }\n" + + "}"; + PluginConfig config = parser.parsePluginCfg(json, PluginConfig.class); + assertNotNull(config, "未解析出config"); + assertEquals("123", config.getId(), "id不匹配"); + } + + @Data + @FizzConfig + public static class PluginConfig { + private String id; + private Var var; + } + + @Data + public static class Var { + private String var1; + private String var2; + private String var3; + } + + @Data + @FizzConfig + public static class RouterConfig { + private String codeSource; + private Var var; + } + +} \ No newline at end of file