diff --git a/pom.xml b/pom.xml index c715765c02f61c6d1161020fce158564bba6115c..0970aa19b590cfb7a29c6397b463736fc7a26190 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ com.gitee.starblues spring-brick-parent pom - 3.0.2 + 3.0.3 spring-brick-common diff --git a/spring-brick-bootstrap/pom.xml b/spring-brick-bootstrap/pom.xml index 730adc0fc110be1b5e129d048858d46bf3b76dfb..cf32d07c87bc0dc4ffc13fbc594c07a843896f0b 100644 --- a/spring-brick-bootstrap/pom.xml +++ b/spring-brick-bootstrap/pom.xml @@ -7,7 +7,7 @@ spring-brick-parent com.gitee.starblues - 3.0.2 + 3.0.3 spring-brick-bootstrap diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/AutowiredTypeDefinerConfig.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/AutowiredTypeDefinerConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..2481c0b13d52707841487cbd9432874bbeac31ea --- /dev/null +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/AutowiredTypeDefinerConfig.java @@ -0,0 +1,58 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.bootstrap; + +import com.gitee.starblues.bootstrap.annotation.AutowiredType; +import com.gitee.starblues.bootstrap.realize.AutowiredTypeDefiner; +import com.gitee.starblues.utils.ObjectUtils; + +import java.util.*; + +/** + * 配置 ClassDefiner + * + * @author starBlues + * @since 3.0.3 + * @version 3.0.3 + */ +public class AutowiredTypeDefinerConfig { + + private final Set classDefiners; + + public AutowiredTypeDefinerConfig(){ + this.classDefiners = new HashSet<>(); + } + + Set getClassDefiners(){ + return classDefiners; + } + + public AutowiredTypeDefinerConfig add(AutowiredType.Type type, String... classNamePatterns){ + if(type != null && classNamePatterns != null && classNamePatterns.length > 0){ + classDefiners.add(AutowiredTypeDefiner.ClassDefiner.config(type, classNamePatterns)); + } + return this; + } + + public AutowiredTypeDefinerConfig add(AutowiredType.Type type, Class... classes){ + if(type != null && classes != null && classes.length > 0){ + classDefiners.add(AutowiredTypeDefiner.ClassDefiner.config(type, classes)); + } + return this; + } + +} diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/AutowiredTypeResolver.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/AutowiredTypeResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..cdbf3454fd4b0eb504eeccb16840c68075005ae1 --- /dev/null +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/AutowiredTypeResolver.java @@ -0,0 +1,73 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.bootstrap; + +import com.gitee.starblues.bootstrap.annotation.AutowiredType; +import com.gitee.starblues.bootstrap.processor.ProcessorContext; +import com.gitee.starblues.bootstrap.realize.AutowiredTypeDefiner; +import com.gitee.starblues.utils.ObjectUtils; +import com.gitee.starblues.utils.UrlUtils; +import org.springframework.beans.factory.config.DependencyDescriptor; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; + +import java.util.Collections; +import java.util.Set; + +/** + * @author starBlues + * @since 3.0.3 + * @version 3.0.3 + */ +public class AutowiredTypeResolver { + + private final Set classDefiners; + private final PathMatcher pathMatcher = new AntPathMatcher(); + + + public AutowiredTypeResolver(ProcessorContext processorContext) { + AutowiredTypeDefiner autowiredTypeDefiner = processorContext.getSpringPluginBootstrap().autowiredTypeDefiner(); + if(autowiredTypeDefiner != null){ + AutowiredTypeDefinerConfig definerConfig = new AutowiredTypeDefinerConfig(); + autowiredTypeDefiner.config(definerConfig); + classDefiners = definerConfig.getClassDefiners(); + } else { + classDefiners = Collections.emptySet(); + } + } + + public AutowiredType.Type resolve(DependencyDescriptor descriptor){ + String name = descriptor.getDependencyType().getName(); + String classNamePath = UrlUtils.formatMatchUrl(name); + for (AutowiredTypeDefiner.ClassDefiner classDefiner : classDefiners) { + Set classNamePatterns = classDefiner.getClassNamePatterns(); + for (String classNamePattern : classNamePatterns) { + if(pathMatcher.match(classNamePattern, classNamePath)){ + return classDefiner.getAutowiredType(); + } + } + } + AutowiredType autowiredType = descriptor.getAnnotation(AutowiredType.class); + if(autowiredType != null){ + return autowiredType.value(); + } else { + return AutowiredType.Type.PLUGIN; + } + } + + +} diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ConfigureMainPluginEnvironment.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ConfigureMainPluginEnvironment.java index c2e0080564535f9d08d943077d88ce6882844b22..912f2546cda5c555de6622fedaf650c596209b32 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ConfigureMainPluginEnvironment.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ConfigureMainPluginEnvironment.java @@ -39,6 +39,7 @@ import java.util.*; * 插件环境配置 * @author starBlues * @version 3.0.0 + * @since 3.0.0 */ class ConfigureMainPluginEnvironment { diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ConfigurePluginEnvironment.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ConfigurePluginEnvironment.java index c159c6e9b470648b34f8885e72c18d9f2c539328..67ba59416d5028bf0648ee32f14b546f416fd5e6 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ConfigurePluginEnvironment.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ConfigurePluginEnvironment.java @@ -23,6 +23,7 @@ import com.gitee.starblues.utils.Assert; import com.gitee.starblues.utils.FilesUtils; import com.gitee.starblues.utils.ObjectUtils; import com.gitee.starblues.utils.PluginFileUtils; +import org.springframework.context.support.LiveBeansView; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/EmptyMainApplicationContext.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/EmptyMainApplicationContext.java index 0321276c98ebb22c5e19fe62a551f7e2ff7018af..7608046cae2e2f9f2d41522922e8c80dcb2d4026 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/EmptyMainApplicationContext.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/EmptyMainApplicationContext.java @@ -18,6 +18,9 @@ package com.gitee.starblues.bootstrap; import com.gitee.starblues.spring.MainApplicationContext; import com.gitee.starblues.spring.SpringBeanFactory; +import com.gitee.starblues.spring.environment.EmptyEnvironmentProvider; +import com.gitee.starblues.spring.environment.EnvironmentProvider; + import java.util.Collections; import java.util.Map; import java.util.Set; @@ -25,7 +28,7 @@ import java.util.Set; /** * 空的MainApplicationContext实现 * @author starBlues - * @version 3.0.1 + * @version 3.0.3 */ public class EmptyMainApplicationContext implements MainApplicationContext { @@ -46,4 +49,19 @@ public class EmptyMainApplicationContext implements MainApplicationContext { return Collections.emptyMap(); } + @Override + public EnvironmentProvider getEnvironmentProvider() { + return new EmptyEnvironmentProvider(); + } + + @Override + public Object resolveDependency(String requestingBeanName, Class dependencyType) { + return null; + } + + @Override + public boolean isWebEnvironment() { + return false; + } + } diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginApplicationContext.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginApplicationContext.java index 2ed37d010bff52beae6cdfe2b5745d590b5a3e35..b6c9cb144c2c80fdad11572076ff3854c6235e9c 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginApplicationContext.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginApplicationContext.java @@ -20,12 +20,14 @@ import com.gitee.starblues.bootstrap.processor.ProcessorContext; import com.gitee.starblues.core.descriptor.PluginDescriptor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.boot.web.context.WebServerApplicationContext; +import org.springframework.boot.web.server.WebServer; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * 插件ApplicationContext实现 * @author starBlues - * @version 3.0.0 + * @version 3.0.3 */ public class PluginApplicationContext extends AnnotationConfigApplicationContext { @@ -57,4 +59,5 @@ public class PluginApplicationContext extends AnnotationConfigApplicationContext public void close() { super.close(); } + } diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginContextHolder.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginContextHolder.java new file mode 100644 index 0000000000000000000000000000000000000000..253c89496778d88012cf4cead27aa891c9267d5d --- /dev/null +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginContextHolder.java @@ -0,0 +1,121 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.bootstrap; + +import com.gitee.starblues.bootstrap.processor.ProcessorContext; +import com.gitee.starblues.core.descriptor.InsidePluginDescriptor; +import com.gitee.starblues.integration.IntegrationConfiguration; +import com.gitee.starblues.spring.SpringBeanFactory; +import com.gitee.starblues.spring.environment.EnvironmentProvider; + +/** + * 提供插件上下文的工具类 + * + * @author starBlues + * @version 3.0.3 + */ +public abstract class PluginContextHolder { + + private static volatile Boolean INITIALIZED = false; + + private static ProcessorContext processorContext; + + private static ClassLoader pluginClassLoader; + private static InsidePluginDescriptor pluginDescriptor; + + private static IntegrationConfiguration configuration; + private static Boolean mainIsWebEnv; + private static SpringBeanFactory mainSpringBeanFactory; + + + private PluginContextHolder(){} + + static void initialize(ProcessorContext processorContext){ + if(INITIALIZED){ + return; + } + PluginContextHolder.processorContext = processorContext; + + PluginContextHolder.pluginClassLoader = processorContext.getClassLoader(); + PluginContextHolder.pluginDescriptor = processorContext.getPluginDescriptor(); + PluginContextHolder.configuration = processorContext.getConfiguration(); + PluginContextHolder.mainIsWebEnv = processorContext.getMainApplicationContext().isWebEnvironment(); + PluginContextHolder.mainSpringBeanFactory = processorContext.getMainBeanFactory(); + INITIALIZED = true; + } + + /** + * 获取主程序环境中配置文件内容提供者 + * @return EnvironmentProvider + */ + public static EnvironmentProvider getEnvironmentProvider(){ + check(); + return processorContext.getMainApplicationContext().getEnvironmentProvider(); + } + + /** + * 获取主程序针对本框架的配置内容 + * @return IntegrationConfiguration + */ + public static IntegrationConfiguration getConfiguration() { + check(); + return configuration; + } + + /** + * 获取主程序的 SpringBeanFactory . 通过它可获取主程序中的Bean + * @return SpringBeanFactory + */ + public static SpringBeanFactory getMainSpringBeanFactory() { + check(); + return mainSpringBeanFactory; + } + + /** + * 判断主程序是否为web环境 + * @return Boolean + */ + public static Boolean getMainIsWebEnv() { + check(); + return mainIsWebEnv; + } + + /** + * 获取插件的 classloader + * @return ClassLoader + */ + public static ClassLoader getPluginClassLoader() { + check(); + return pluginClassLoader; + } + + /** + * 获取插件信息 + * @return InsidePluginDescriptor + */ + public static InsidePluginDescriptor getPluginDescriptor() { + check(); + return pluginDescriptor; + } + + private static void check(){ + if(!INITIALIZED){ + throw new IllegalStateException("PluginContextHolder 未初始化"); + } + } + +} diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginDisableAutoConfiguration.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginDisableAutoConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..7c69c391c44890ee45e68ad11c41df9d666c38af --- /dev/null +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginDisableAutoConfiguration.java @@ -0,0 +1,72 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.bootstrap; + +import com.gitee.starblues.utils.ObjectUtils; +import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter; +import org.springframework.boot.autoconfigure.AutoConfigurationMetadata; + +import java.util.ArrayList; +import java.util.List; + +/** + * 插件禁用的 AutoConfiguration + * + * @author starBlues + * @version 3.0.3 + */ +public class PluginDisableAutoConfiguration implements AutoConfigurationImportFilter { + + private static final List DISABLE_FUZZY_CLASSES = new ArrayList<>(); + + public PluginDisableAutoConfiguration(){ + addDisableFuzzyClasses(); + } + + private void addDisableFuzzyClasses() { + DISABLE_FUZZY_CLASSES.add("org.springframework.boot.autoconfigure.http"); + DISABLE_FUZZY_CLASSES.add("org.springframework.boot.autoconfigure.web"); + DISABLE_FUZZY_CLASSES.add("org.springframework.boot.autoconfigure.websocket"); + DISABLE_FUZZY_CLASSES.add("org.springframework.boot.autoconfigure.jackson"); + DISABLE_FUZZY_CLASSES.add("org.springframework.boot.autoconfigure.webservices"); + } + + public static boolean isDisabled(String className){ + if(ObjectUtils.isEmpty(className)){ + return false; + } + for (String disableFuzzyClass : DISABLE_FUZZY_CLASSES) { + if (className.contains(disableFuzzyClass)) { + return true; + } + } + return false; + } + + @Override + public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) { + boolean[] match = new boolean[autoConfigurationClasses.length]; + for (int i = 0; i < autoConfigurationClasses.length; i++) { + String autoConfigurationClass = autoConfigurationClasses[i]; + if(autoConfigurationClass == null || "".equals(autoConfigurationClass)){ + continue; + } + match[i] = !isDisabled(autoConfigurationClass); + } + return match; + } +} diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginListableBeanFactory.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginListableBeanFactory.java index fda812953dfe96df79455ce6c412c62db5e3777f..76e8f7f9917a145fb89fb57aab44c20a46d11ebc 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginListableBeanFactory.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginListableBeanFactory.java @@ -16,62 +16,95 @@ package com.gitee.starblues.bootstrap; +import com.gitee.starblues.bootstrap.annotation.AutowiredType; +import com.gitee.starblues.bootstrap.processor.ProcessorContext; import com.gitee.starblues.bootstrap.utils.DestroyUtils; import com.gitee.starblues.spring.MainApplicationContext; import com.gitee.starblues.spring.SpringBeanFactory; -import com.gitee.starblues.utils.ObjectUtils; import com.gitee.starblues.utils.ReflectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.TypeConverter; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.DependencyDescriptor; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.lang.Nullable; -import java.util.Set; +import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * 插件BeanFactory实现 * @author starBlues - * @version 3.0.0 + * @since 3.0.3 + * @version 3.0.3 */ public class PluginListableBeanFactory extends DefaultListableBeanFactory { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private static final Logger LOG = LoggerFactory.getLogger(PluginListableBeanFactory.class); private final MainApplicationContext applicationContext; + private final AutowiredTypeResolver autowiredTypeResolver; - public PluginListableBeanFactory(MainApplicationContext applicationContext) { - this.applicationContext = applicationContext; + public PluginListableBeanFactory(ProcessorContext processorContext) { + this.applicationContext = processorContext.getMainApplicationContext(); + this.autowiredTypeResolver = new AutowiredTypeResolver(processorContext); } + @SuppressWarnings("unchecked") @Override public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { - - try { - return super.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); - } catch (BeansException e){ - return resolveDependencyFromMain(descriptor); + AutowiredType.Type autowiredType = getAutowiredType(descriptor); + Class dependencyType = descriptor.getDependencyType(); + if (dependencyType == ObjectFactory.class || dependencyType == ObjectProvider.class) { + Object dependencyObj = super.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, + typeConverter); + ObjectProvider provider = (ObjectProvider) dependencyObj; + return new PluginObjectProviderWrapper(provider, requestingBeanName, descriptor, autowiredType); } - } - private Object resolveDependencyFromMain(DependencyDescriptor descriptor){ - String dependencyName = descriptor.getDependencyName(); - SpringBeanFactory springBeanFactory = applicationContext.getSpringBeanFactory(); - if(!ObjectUtils.isEmpty(dependencyName) && springBeanFactory.containsBean(dependencyName)){ - return springBeanFactory.getBean(dependencyName); - } else { + if(autowiredType == AutowiredType.Type.MAIN){ + Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor); + if(dependencyObj != null){ + return dependencyObj; + } + throw new NoSuchBeanDefinitionException(descriptor.getDependencyType()); + } else if(autowiredType == AutowiredType.Type.PLUGIN){ + return super.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); + } else if(autowiredType == AutowiredType.Type.PLUGIN_MAIN){ try { - return springBeanFactory.getBean(descriptor.getDependencyType()); - } catch (Exception e){ - throw new NoSuchBeanDefinitionException(descriptor.getDependencyType()); + return super.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, + typeConverter); + } catch (BeansException e){ + if(e instanceof NoSuchBeanDefinitionException){ + Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor); + if(dependencyObj != null){ + return dependencyObj; + } + } + throw e; + } + } else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){ + Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor); + if(dependencyObj instanceof ObjectProvider){ + ObjectProvider provider = (ObjectProvider) dependencyObj; + return new PluginObjectProviderWrapper(provider, requestingBeanName, descriptor, autowiredType); } + if(dependencyObj != null){ + return dependencyObj; + } + return super.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, + typeConverter); } + throw new NoSuchBeanDefinitionException(descriptor.getDependencyType()); } @Override @@ -84,6 +117,26 @@ public class PluginListableBeanFactory extends DefaultListableBeanFactory { destroyAll(); } + @Override + public ObjectProvider getBeanProvider(Class requiredType, boolean allowEagerInit) { + return super.getBeanProvider(requiredType, allowEagerInit); + } + + protected AutowiredType.Type getAutowiredType(DependencyDescriptor descriptor){ + return autowiredTypeResolver.resolve(descriptor); + } + + protected Object resolveDependencyFromMain(String requestingBeanName, DependencyDescriptor descriptor){ + Object dependencyObj = null; + try { + dependencyObj = applicationContext.resolveDependency(requestingBeanName, + descriptor.getDependencyType()); + } catch (Exception e){ + return null; + } + return dependencyObj; + } + private void destroyAll(){ ReflectionUtils.findField(this.getClass(), field -> { field.setAccessible(true); @@ -97,4 +150,207 @@ public class PluginListableBeanFactory extends DefaultListableBeanFactory { }); } + + private class PluginObjectProviderWrapper implements ObjectProvider { + + private final ObjectProvider pluginObjectProvider; + + private final String requestingBeanName; + private final DependencyDescriptor descriptor; + private final AutowiredType.Type autowiredType; + + private PluginObjectProviderWrapper(ObjectProvider pluginObjectProvider, + String requestingBeanName, + DependencyDescriptor descriptor, + AutowiredType.Type autowiredType) { + this.pluginObjectProvider = pluginObjectProvider; + this.requestingBeanName = requestingBeanName; + this.descriptor = new NestedDependencyDescriptor(descriptor); + this.autowiredType = autowiredType; + } + + @Override + public Object getObject() throws BeansException { + if(autowiredType == AutowiredType.Type.PLUGIN) { + return pluginObjectProvider.getObject(); + } else if(autowiredType == AutowiredType.Type.MAIN){ + Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor); + if(dependencyObj != null){ + return dependencyObj; + } + } else if(autowiredType == AutowiredType.Type.PLUGIN_MAIN) { + try { + return pluginObjectProvider.getObject(); + } catch (Exception e) { + Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor); + if (dependencyObj != null) { + return dependencyObj; + } + throw e; + } + } else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){ + Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor); + if(dependencyObj != null){ + return dependencyObj; + } + return pluginObjectProvider.getObject(); + } + throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType()); + } + + @Override + public Object getObject(final Object... args) throws BeansException { + if(autowiredType == AutowiredType.Type.PLUGIN){ + return pluginObjectProvider.getObject(args); + } else if(autowiredType == AutowiredType.Type.MAIN){ + Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor); + if(dependencyObj != null){ + return dependencyObj; + } + } else if(autowiredType == AutowiredType.Type.PLUGIN_MAIN){ + try { + return pluginObjectProvider.getObject(); + } catch (Exception e){ + try { + return applicationContext.getSpringBeanFactory().getBean(requestingBeanName, args); + } catch (Exception e2){ + // 忽略 + } + throw e; + } + } else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){ + Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor); + if(dependencyObj != null){ + return dependencyObj; + } + return pluginObjectProvider.getObject(args); + } + throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType()); + } + + @Override + @Nullable + public Object getIfAvailable() throws BeansException { + if(autowiredType == AutowiredType.Type.PLUGIN){ + return pluginObjectProvider.getIfAvailable(); + } else if(autowiredType == AutowiredType.Type.MAIN){ + return resolveDependencyFromMain(requestingBeanName, descriptor); + } else if(autowiredType == AutowiredType.Type.PLUGIN_MAIN){ + Object dependencyObj = pluginObjectProvider.getIfAvailable(); + if(dependencyObj == null){ + dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor); + } + return dependencyObj; + } else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){ + Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor); + if(dependencyObj != null){ + return dependencyObj; + } + return pluginObjectProvider.getIfAvailable(); + } + return null; + } + + @Override + public void ifAvailable(Consumer dependencyConsumer) throws BeansException { + Object ifAvailable = getIfAvailable(); + if(ifAvailable != null){ + dependencyConsumer.accept(ifAvailable); + } + } + + @Override + @Nullable + public Object getIfUnique() throws BeansException { + if(autowiredType == AutowiredType.Type.PLUGIN){ + return pluginObjectProvider.getIfUnique(); + } else if(autowiredType == AutowiredType.Type.MAIN){ + return resolveDependencyFromMain(requestingBeanName, descriptor); + } else if(autowiredType == AutowiredType.Type.PLUGIN_MAIN){ + Object dependencyObj = pluginObjectProvider.getIfUnique(); + if(dependencyObj == null){ + dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor); + } + return dependencyObj; + } else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){ + Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor); + if(dependencyObj != null){ + return dependencyObj; + } + return pluginObjectProvider.getIfUnique(); + } + return null; + } + + @Override + public void ifUnique(Consumer dependencyConsumer) throws BeansException { + Object ifUnique = getIfUnique(); + if(ifUnique != null){ + dependencyConsumer.accept(ifUnique); + } + } + + @Override + public Stream stream() { + if(autowiredType == AutowiredType.Type.PLUGIN){ + return pluginObjectProvider.stream(); + } else if(autowiredType == AutowiredType.Type.MAIN){ + return getStreamOfMain().stream(); + } else if (autowiredType == AutowiredType.Type.PLUGIN_MAIN){ + Stream stream = pluginObjectProvider.stream(); + List collect = stream.collect(Collectors.toList()); + if(!collect.isEmpty()){ + return collect.stream(); + } + return getStreamOfMain().stream(); + } else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){ + Set collection = getStreamOfMain(); + if(!collection.isEmpty()){ + return collection.stream(); + } + return pluginObjectProvider.stream(); + } + return Stream.empty(); + } + + @Override + public Stream orderedStream() { + if(autowiredType == AutowiredType.Type.PLUGIN){ + return pluginObjectProvider.orderedStream(); + } else if(autowiredType == AutowiredType.Type.MAIN){ + return getStreamOfMain().stream().sorted(); + } else if(autowiredType == AutowiredType.Type.PLUGIN_MAIN){ + Stream stream = pluginObjectProvider.stream(); + List collect = stream.collect(Collectors.toList()); + if(!collect.isEmpty()){ + return collect.stream(); + } + return getStreamOfMain().stream().sorted(); + } else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){ + Set collection = getStreamOfMain(); + if(!collection.isEmpty()){ + return collection.stream().sorted(); + } + return pluginObjectProvider.stream(); + } + return Stream.empty(); + } + + @SuppressWarnings("unchecked") + private Set getStreamOfMain(){ + SpringBeanFactory springBeanFactory = applicationContext.getSpringBeanFactory(); + Map beansOfType = springBeanFactory.getBeansOfType(descriptor.getDependencyType()); + return new HashSet<>(beansOfType.values()); + } + } + + + private static class NestedDependencyDescriptor extends DependencyDescriptor { + + public NestedDependencyDescriptor(DependencyDescriptor original) { + super(original); + increaseNestingLevel(); + } + } + } diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginSpringApplication.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginSpringApplication.java index 59a700261526741a46a6065cbf5bcf4ebe4cd30b..d923a1b0399f207ec8a7519fd8ea587c46dab0d2 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginSpringApplication.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginSpringApplication.java @@ -34,11 +34,11 @@ import org.springframework.core.io.ResourceLoader; /** * 插件SpringApplication实现 * @author starBlues - * @version 3.0.0 + * @version 3.0.3 */ public class PluginSpringApplication extends SpringApplication { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final Logger logger = LoggerFactory.getLogger(PluginSpringApplication.class); private final ProcessorContext.RunMode runMode; @@ -59,7 +59,7 @@ public class PluginSpringApplication extends SpringApplication { this.pluginProcessor = pluginProcessor; this.processorContext = processorContext; this.resourceLoader = processorContext.getResourceLoader(); - this.beanFactory = new PluginListableBeanFactory(processorContext.getMainApplicationContext()); + this.beanFactory = new PluginListableBeanFactory(processorContext); this.configurePluginEnvironment = new ConfigurePluginEnvironment(processorContext); this.applicationContext = getApplicationContext(); setDefaultPluginConfig(); @@ -68,6 +68,9 @@ public class PluginSpringApplication extends SpringApplication { protected GenericApplicationContext getApplicationContext(){ if(runMode == ProcessorContext.RunMode.ONESELF){ return (GenericApplicationContext) super.createApplicationContext(); + } + if(processorContext.getMainApplicationContext().isWebEnvironment()){ + return new PluginWebApplicationContext(beanFactory, processorContext); } else { return new PluginApplicationContext(beanFactory, processorContext); } @@ -99,6 +102,7 @@ public class PluginSpringApplication extends SpringApplication { public ConfigurableApplicationContext run(String... args) { try { processorContext.setApplicationContext(this.applicationContext); + PluginContextHolder.initialize(processorContext); pluginProcessor.initialize(processorContext); return super.run(args); } catch (Exception e) { diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginWebApplicationContext.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginWebApplicationContext.java new file mode 100644 index 0000000000000000000000000000000000000000..9539cb34c409ed7d05c6821a774d89946d98d194 --- /dev/null +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/PluginWebApplicationContext.java @@ -0,0 +1,94 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.bootstrap; + +import com.gitee.starblues.bootstrap.listener.PluginApplicationWebEventListener; +import com.gitee.starblues.bootstrap.processor.ProcessorContext; +import com.gitee.starblues.spring.environment.EnvironmentProvider; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.boot.web.context.WebServerApplicationContext; +import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.WebServerException; + +/** + * 主程序为 web 类型时创建的插件 ApplicationContext + * + * @author starBlues + * @version 3.0.3 + */ +public class PluginWebApplicationContext extends PluginApplicationContext implements WebServerApplicationContext { + + private final WebServer webServer; + private final String serverNamespace; + + public PluginWebApplicationContext(DefaultListableBeanFactory beanFactory, ProcessorContext processorContext) { + super(beanFactory, processorContext); + this.webServer = new PluginSimulationWebServer(processorContext); + this.serverNamespace = processorContext.getPluginDescriptor().getPluginId(); + addApplicationListener(new PluginApplicationWebEventListener(this)); + } + + @Override + public WebServer getWebServer() { + return webServer; + } + + @Override + public String getServerNamespace() { + return serverNamespace; + } + + + public static class PluginSimulationWebServer implements WebServer { + + private final int port; + + public PluginSimulationWebServer(ProcessorContext processorContext) { + EnvironmentProvider provider = processorContext.getMainApplicationContext().getEnvironmentProvider(); + Integer port = provider.getInteger("server.port"); + if(port == null){ + this.port = -1; + } else { + this.port = port; + } + } + + @Override + public void start() throws WebServerException { + throw new InvalidWebServerException(); + } + + @Override + public void stop() throws WebServerException { + throw new InvalidWebServerException(); + } + + @Override + public int getPort() { + return port; + } + + } + + public static class InvalidWebServerException extends WebServerException{ + + public InvalidWebServerException() { + super("Invalid operation", null); + } + } + +} diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ResolveHttpMessageConvertersConfiguration.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ResolveHttpMessageConvertersConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..5490027bf90da627fad94aae1ad6825628dd687e --- /dev/null +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/ResolveHttpMessageConvertersConfiguration.java @@ -0,0 +1,41 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.bootstrap; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.http.HttpMessageConverters; +import org.springframework.context.annotation.Bean; +import org.springframework.http.converter.HttpMessageConverter; + +import java.util.stream.Collectors; + +/** + * resolve config HttpMessageConverters bean + * + * @author starBlues + * @version 3.0.3 + */ +public class ResolveHttpMessageConvertersConfiguration { + + @Bean + @ConditionalOnMissingBean + public HttpMessageConverters messageConverters(ObjectProvider> converters) { + return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList())); + } + +} diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/SpringPluginBootstrap.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/SpringPluginBootstrap.java index b54de8b32a9287fa8f8fda930b130ff5e066d585..14d882af9c0bc7a1e033835b6b2548e3b3838a89 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/SpringPluginBootstrap.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/SpringPluginBootstrap.java @@ -20,6 +20,7 @@ import com.gitee.starblues.bootstrap.processor.ComposeSpringPluginProcessor; import com.gitee.starblues.bootstrap.processor.DefaultProcessorContext; import com.gitee.starblues.bootstrap.processor.ProcessorContext; import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor; +import com.gitee.starblues.bootstrap.realize.AutowiredTypeDefiner; import com.gitee.starblues.core.launcher.plugin.PluginInteractive; import com.gitee.starblues.spring.SpringPluginHook; @@ -29,7 +30,8 @@ import java.util.List; /** * 插件引导抽象类。插件入口需集成本抽象类 * @author starBlues - * @version 3.0.0 + * @since 3.0.0 + * @version 3.0.3 */ public abstract class SpringPluginBootstrap { @@ -96,4 +98,14 @@ public abstract class SpringPluginBootstrap { */ protected void addCustomSpringPluginProcessor(){} + /** + * 设置 AutowiredTypeDefiner + * @return AutowiredTypeDefiner + * @since 3.0.3 + */ + protected AutowiredTypeDefiner autowiredTypeDefiner(){ + return null; + } + + } diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/annotation/AutowiredType.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/annotation/AutowiredType.java new file mode 100644 index 0000000000000000000000000000000000000000..1d9d583747e0a54d9936edecd2a1e43f8d56832f --- /dev/null +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/annotation/AutowiredType.java @@ -0,0 +1,47 @@ +package com.gitee.starblues.bootstrap.annotation; + + +import java.lang.annotation.*; + +/** + * 注入类型 + * + * @author starBlues + * @version 3.0.3 + */ +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface AutowiredType { + + /** + * 插件Bean注入类型 + * @return Type + */ + Type value() default Type.PLUGIN; + + + enum Type{ + /** + * Bean 注入类型: 仅插件(默认) + */ + PLUGIN, + + /** + * Bean 注入类型: 仅主程序 + */ + MAIN, + + /** + * Bean 注入类型: 先插件后主程序 + */ + PLUGIN_MAIN, + + /** + * Bean 注入类型: 先主程序后插件 + */ + MAIN_PLUGIN + } + + +} diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/listener/PluginApplicationWebEventListener.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/listener/PluginApplicationWebEventListener.java new file mode 100644 index 0000000000000000000000000000000000000000..68654012d851656a095ff6246eb8d0f137d215b0 --- /dev/null +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/listener/PluginApplicationWebEventListener.java @@ -0,0 +1,82 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.bootstrap.listener; + +import com.gitee.starblues.bootstrap.PluginWebApplicationContext; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.boot.web.context.WebServerApplicationContext; +import org.springframework.boot.web.context.WebServerInitializedEvent; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.core.ResolvableType; + +/** + * 插件监听器扩展 + * + * @author starBlues + * @version 3.0.3 + */ +public class PluginApplicationWebEventListener implements ApplicationListener { + + + private final PluginWebApplicationContext applicationContext; + + public PluginApplicationWebEventListener(PluginWebApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + @Override + public void onApplicationEvent(ApplicationEvent event) { + if (event instanceof ApplicationReadyEvent) { + callWebServerInitializedEvent(); + } + } + + @SuppressWarnings("all") + protected void callWebServerInitializedEvent(){ + String[] beanNamesForType = applicationContext.getBeanNamesForType(ResolvableType.forClassWithGenerics( + ApplicationListener.class, WebServerInitializedEvent.class + )); + PluginWebServerInitializedEvent pluginWebServerInitializedEvent = + new PluginWebServerInitializedEvent(applicationContext); + for (String beanName : beanNamesForType) { + try { + ApplicationListener applicationListener = + (ApplicationListener) applicationContext.getBean(beanName); + applicationListener.onApplicationEvent(pluginWebServerInitializedEvent); + } catch (Exception e){ + e.printStackTrace(); + } + } + } + + public static class PluginWebServerInitializedEvent extends WebServerInitializedEvent{ + + private final PluginWebApplicationContext pluginWebApplicationContext; + + protected PluginWebServerInitializedEvent(PluginWebApplicationContext pluginWebApplicationContext) { + super(pluginWebApplicationContext.getWebServer()); + this.pluginWebApplicationContext = pluginWebApplicationContext; + } + + @Override + public WebServerApplicationContext getApplicationContext() { + return pluginWebApplicationContext; + } + } + +} diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/ComposeSpringPluginProcessor.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/ComposeSpringPluginProcessor.java index 05d48476a050b42a822b4235f3971118812427c9..63e7911341c4a2154db9d88ba65842c04a5d4015 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/ComposeSpringPluginProcessor.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/ComposeSpringPluginProcessor.java @@ -38,7 +38,7 @@ import java.util.stream.Collectors; /** * 组合的处理器 * @author starBlues - * @version 3.0.0 + * @version 3.0.3 */ public class ComposeSpringPluginProcessor implements SpringPluginProcessor { @@ -160,6 +160,10 @@ public class ComposeSpringPluginProcessor implements SpringPluginProcessor { * @param processors 处理者容器集合 */ protected void addDefaultWebEnvProcessors(ProcessorContext context, List processors){ + if(!context.getMainApplicationContext().isWebEnvironment()){ + // 主程序不是web类型, 则不进行注册 + return; + } SpringPluginBootstrap springPluginBootstrap = context.getSpringPluginBootstrap(); DisablePluginWeb disablePluginWeb = AnnotationUtils.findAnnotation(springPluginBootstrap.getClass(), DisablePluginWeb.class); diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/DefaultProcessorContext.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/DefaultProcessorContext.java index d9d85e090eb25c0a030e640999f5ca7725d55996..d0801cc961327e0ac7d1c5ca04f81a5a9cce6375 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/DefaultProcessorContext.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/DefaultProcessorContext.java @@ -25,10 +25,14 @@ import com.gitee.starblues.spring.MainApplicationContext; import com.gitee.starblues.spring.SpringBeanFactory; import com.gitee.starblues.spring.WebConfig; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.StandardEnvironment; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.ResourceLoader; import org.springframework.util.ClassUtils; +import java.util.Map; + /** * 默认的处理者上下文 * @author starBlues @@ -131,8 +135,8 @@ public class DefaultProcessorContext extends CacheRegistryInfo implements Proces this.applicationContext = applicationContext; } - protected ClassLoader getPluginClassLoader(){ return ClassUtils.getDefaultClassLoader(); } + } diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/FrameDefineBeanProcessor.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/FrameDefineBeanProcessor.java index 56fcb6af01916a9de51eaf1c8c57d56230c3229a..ddbb7b8fafdb53c4fff23c623e33252e9fe665e9 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/FrameDefineBeanProcessor.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/FrameDefineBeanProcessor.java @@ -17,9 +17,6 @@ package com.gitee.starblues.bootstrap.processor; -import com.gitee.starblues.bootstrap.realize.DefaultMainEnvironmentProvider; -import com.gitee.starblues.bootstrap.realize.EmptyMainEnvironmentProvider; -import com.gitee.starblues.bootstrap.realize.MainEnvironmentProvider; import com.gitee.starblues.core.descriptor.InsidePluginDescriptor; import com.gitee.starblues.integration.AutoIntegrationConfiguration; import com.gitee.starblues.integration.ExtendPointConfiguration; @@ -40,16 +37,6 @@ public class FrameDefineBeanProcessor implements SpringPluginProcessor { ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory(); beanFactory.registerSingleton("pluginDescriptor", pluginDescriptor.toPluginDescriptor()); beanFactory.registerSingleton("mainApplicationContext", context.getMainApplicationContext()); - - MainEnvironmentProvider mainEnvironmentProvider = null; - if(context.runMode() == ProcessorContext.RunMode.ONESELF){ - beanFactory.registerSingleton("integrationConfiguration", new AutoIntegrationConfiguration()); - applicationContext.registerBean(ExtendPointConfiguration.class); - mainEnvironmentProvider = new EmptyMainEnvironmentProvider(); - } else { - mainEnvironmentProvider = new DefaultMainEnvironmentProvider(context.getMainApplicationContext()); - } - beanFactory.registerSingleton("mainEnvironmentProvider", mainEnvironmentProvider); } @Override diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/ProcessorContext.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/ProcessorContext.java index db4c125427aa79507918a11895fa75cf05606bd0..42cec5b55f5ed4a9e55a0ae6f1f09e1cf8140d77 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/ProcessorContext.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/ProcessorContext.java @@ -26,6 +26,7 @@ import com.gitee.starblues.spring.MainApplicationContext; import com.gitee.starblues.spring.SpringBeanFactory; import com.gitee.starblues.spring.WebConfig; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.io.ResourceLoader; /** diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/web/PluginControllerProcessor.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/web/PluginControllerProcessor.java index a097e6464080e15ad68257d52722886cb44d5068..3840ab5a18aa3ac08b84ff2b4bfbabe2ac7f4f87 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/web/PluginControllerProcessor.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/processor/web/PluginControllerProcessor.java @@ -24,26 +24,33 @@ import com.gitee.starblues.bootstrap.utils.DestroyUtils; import com.gitee.starblues.integration.IntegrationConfiguration; import com.gitee.starblues.spring.SpringBeanFactory; import com.gitee.starblues.utils.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.mvc.condition.RequestCondition; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; /** * 插件Controller处理者 * @author starBlues - * @version 3.0.0 + * @version 3.0.3 */ public class PluginControllerProcessor implements SpringPluginProcessor { @@ -53,7 +60,6 @@ public class PluginControllerProcessor implements SpringPluginProcessor { private RequestMappingHandlerMapping requestMappingHandlerMapping; - private Method getMappingForMethod; private RequestMappingHandlerAdapter handlerAdapter; private final AtomicBoolean canRegistered = new AtomicBoolean(false); @@ -65,13 +71,6 @@ public class PluginControllerProcessor implements SpringPluginProcessor { this.requestMappingHandlerMapping = mainBeanFactory.getBean(RequestMappingHandlerMapping.class); this.handlerAdapter = SpringBeanCustomUtils.getExistBean(processorContext.getMainApplicationContext(), RequestMappingHandlerAdapter.class); - this.getMappingForMethod = ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, - "getMappingForMethod", Method.class, Class.class); - if(getMappingForMethod == null){ - LOG.warn("RequestMappingHandlerMapping 类中没有发现 方法, 无法注册插件接口. " + - "请检查当前环境是否为 web 环境"); - } - this.getMappingForMethod.setAccessible(true); canRegistered.set(true); } @@ -82,8 +81,8 @@ public class PluginControllerProcessor implements SpringPluginProcessor { return; } GenericApplicationContext applicationContext = processorContext.getApplicationContext(); - applicationContext.registerBean("changeRestPathPostProcessor", - ChangeRestPathPostProcessor.class, ()-> new ChangeRestPathPostProcessor(processorContext)); + applicationContext.registerBean("pluginControllerPostProcessor", + ControllerPostProcessor.class, ()-> new ControllerPostProcessor(processorContext)); } @Override @@ -91,12 +90,6 @@ public class PluginControllerProcessor implements SpringPluginProcessor { if(!canRegistered.get()){ return; } - IntegrationConfiguration configuration = processorContext.getConfiguration(); - if(ObjectUtils.isEmpty(configuration.pluginRestPathPrefix()) - && !configuration.enablePluginIdRestPathPrefix()){ - // 如果 pluginRestPathPrefix 为空, 并且没有启用插件id作为插件前缀, 则不进行修改插件controller地址前缀 - return; - } String pluginId = processorContext.getPluginDescriptor().getPluginId(); List controllerWrappers = processorContext.getRegistryInfo(PROCESS_CONTROLLERS); if(ObjectUtils.isEmpty(controllerWrappers)){ @@ -105,21 +98,30 @@ public class PluginControllerProcessor implements SpringPluginProcessor { GenericApplicationContext applicationContext = processorContext.getApplicationContext(); Iterator iterator = controllerWrappers.iterator(); + String pathPrefix = PluginConfigUtils.getPluginRestPrefix(processorContext.getConfiguration(), pluginId); + PluginRequestMappingHandlerMapping pluginHandlerMapping = new PluginRequestMappingHandlerMapping(pathPrefix); + while (iterator.hasNext()){ ControllerWrapper controllerWrapper = iterator.next(); if(!applicationContext.containsBean(controllerWrapper.getBeanName())){ iterator.remove(); } Object controllerBean = applicationContext.getBean(controllerWrapper.getBeanName()); - Set requestMappingInfos = registry(applicationContext, controllerBean.getClass()); - if(requestMappingInfos.isEmpty()){ - iterator.remove(); - } else { - for (RequestMappingInfo requestMappingInfo : requestMappingInfos) { - LOG.info("插件[{}]注册接口: {}", pluginId, requestMappingInfo.toString()); - } - controllerWrapper.setRequestMappingInfos(requestMappingInfos); + pluginHandlerMapping.registerHandler(controllerBean); + List registerMappingInfo = pluginHandlerMapping.getAndClear(); + + Set requestMappingInfoSet = new HashSet<>(registerMappingInfo.size()); + for (RegisterMappingInfo mappingInfo : registerMappingInfo) { + RequestMappingInfo requestMappingInfo = mappingInfo.getRequestMappingInfo(); + requestMappingHandlerMapping.registerMapping( + requestMappingInfo, + mappingInfo.getHandler(), + mappingInfo.getMethod() + ); + LOG.info("插件[{}]注册接口: {}", pluginId, requestMappingInfo); + requestMappingInfoSet.add(requestMappingInfo); } + controllerWrapper.setRequestMappingInfo(requestMappingInfoSet); } } @@ -140,36 +142,14 @@ public class PluginControllerProcessor implements SpringPluginProcessor { return ProcessorContext.RunMode.PLUGIN; } - - private Set registry(GenericApplicationContext pluginApplicationContext, Class aClass) - throws ProcessorException { - Object object = pluginApplicationContext.getBean(aClass); - - Method[] methods = aClass.getDeclaredMethods(); - Set requestMappingInfos = new HashSet<>(); - for (Method method : methods) { - if (isHaveRequestMapping(method)) { - try { - RequestMappingInfo requestMappingInfo = (RequestMappingInfo) - getMappingForMethod.invoke(requestMappingHandlerMapping, method, aClass); - requestMappingHandlerMapping.registerMapping(requestMappingInfo, object, method); - requestMappingInfos.add(requestMappingInfo); - } catch (Exception e){ - throw new ProcessorException(e.getMessage()); - } - } - } - return requestMappingInfos; - } - /** * 卸载具体的Controller操作 * @param controllerBeanWrapper controllerBean包装 */ private void unregister(ControllerWrapper controllerBeanWrapper) { - Set requestMappingInfos = controllerBeanWrapper.getRequestMappingInfos(); - if(requestMappingInfos != null && !requestMappingInfos.isEmpty()){ - for (RequestMappingInfo requestMappingInfo : requestMappingInfos) { + Set requestMappingInfoSet = controllerBeanWrapper.getRequestMappingInfo(); + if(requestMappingInfoSet != null && !requestMappingInfoSet.isEmpty()){ + for (RequestMappingInfo requestMappingInfo : requestMappingInfoSet) { requestMappingHandlerMapping.unregisterMapping(requestMappingInfo); } } @@ -181,26 +161,17 @@ public class PluginControllerProcessor implements SpringPluginProcessor { } } - /** - * 方法上是否存在 @RequestMapping 注解 - * @param method method - * @return boolean - */ - private boolean isHaveRequestMapping(Method method){ - return AnnotationUtils.findAnnotation(method, RequestMapping.class) != null; - } - - private static class ChangeRestPathPostProcessor implements BeanPostProcessor { + private static class ControllerPostProcessor implements BeanPostProcessor { - private final static Logger LOG = LoggerFactory.getLogger(ChangeRestPathPostProcessor.class); - private final static String COMMON_ERROR = "无法统一处理该Controller请求路径前缀"; + private final static Logger LOG = LoggerFactory.getLogger(ControllerPostProcessor.class); private final ProcessorContext processorContext; - private ChangeRestPathPostProcessor(ProcessorContext processorContext) { + private ControllerPostProcessor(ProcessorContext processorContext) { this.processorContext = processorContext; } + @SuppressWarnings("unchecked") @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { Class aClass = bean.getClass(); @@ -209,64 +180,26 @@ public class PluginControllerProcessor implements SpringPluginProcessor { Controller.class, RestController.class }); if(requestMapping != null && isController){ - changePathForClass(beanName, aClass, requestMapping); + addControllerWrapper(beanName, aClass); } return bean; } - private void changePathForClass(String beanName, Class aClass, RequestMapping requestMapping){ - String pluginId = processorContext.getPluginDescriptor().getPluginId(); - IntegrationConfiguration configuration = processorContext.getConfiguration(); - String pathPrefix = PluginConfigUtils.getPluginRestPrefix(configuration, pluginId); - - if(ObjectUtils.isEmpty(pathPrefix)){ - LOG.error("插件 [{}] Controller类 [{}] 未发现 path 配置, {}", - pluginId, aClass.getSimpleName(), COMMON_ERROR); - return; - } - Set definePaths = new HashSet<>(); - definePaths.addAll(Arrays.asList(requestMapping.path())); - definePaths.addAll(Arrays.asList(requestMapping.value())); - try { - Map memberValues = ClassUtils.getAnnotationsUpdater(requestMapping); - if(memberValues == null){ - LOG.error("插件 [{}] Controller 类 [{}] 无法反射获取注解属性, {}", - pluginId, aClass.getSimpleName(), COMMON_ERROR); - return; - } - String[] newPath = new String[definePaths.size()]; - int i = 0; - for (String definePath : definePaths) { - // 解决插件启用、禁用后, 路径前缀重复的问题。 - if(definePath.contains(pathPrefix)){ - newPath[i++] = definePath; - } else { - newPath[i++] = UrlUtils.restJoiningPath(pathPrefix, definePath); - } - } - if(newPath.length == 0){ - newPath = new String[]{ pathPrefix }; - } - memberValues.put("path", newPath); - memberValues.put("value", newPath); - - List controllerWrappers = processorContext.getRegistryInfo(PROCESS_CONTROLLERS); - if(controllerWrappers == null){ - controllerWrappers = new ArrayList<>(); - processorContext.addRegistryInfo(PROCESS_CONTROLLERS, controllerWrappers); - } - ControllerWrapper controllerWrapper = new ControllerWrapper(); - controllerWrapper.setPathPrefix(newPath); - controllerWrapper.setBeanName(beanName); - controllerWrapper.setBeanClass(aClass); - controllerWrappers.add(controllerWrapper); - } catch (Exception e) { - LOG.error("插件 [{}] Controller 类[{}] 注册异常. {}", pluginId, aClass.getName(), e.getMessage(), e); + private void addControllerWrapper(String beanName, Class aClass){ + List controllerWrappers = processorContext.getRegistryInfo(PROCESS_CONTROLLERS); + if(controllerWrappers == null){ + controllerWrappers = new ArrayList<>(); + processorContext.addRegistryInfo(PROCESS_CONTROLLERS, controllerWrappers); } + ControllerWrapper controllerWrapper = new ControllerWrapper(); + controllerWrapper.setBeanName(beanName); + controllerWrapper.setBeanClass(aClass); + controllerWrappers.add(controllerWrapper); } - } + } + @Data static class ControllerWrapper{ /** @@ -274,11 +207,6 @@ public class PluginControllerProcessor implements SpringPluginProcessor { */ private String beanName; - /** - * controller 路径前缀 - */ - private String[] pathPrefix; - /** * controller bean 类型 */ @@ -287,39 +215,50 @@ public class PluginControllerProcessor implements SpringPluginProcessor { /** * controller 的 RequestMappingInfo 集合 */ - private Set requestMappingInfos; + private Set requestMappingInfo; + } - public Class getBeanClass() { - return beanClass; - } - public void setBeanClass(Class beanClass) { - this.beanClass = beanClass; - } + private static class PluginRequestMappingHandlerMapping extends RequestMappingHandlerMapping { - public String getBeanName() { - return beanName; - } + private final List registerMappingInfo = new ArrayList<>(); - public void setBeanName(String beanName) { - this.beanName = beanName; + public PluginRequestMappingHandlerMapping(){ + this(null); } - public String[] getPathPrefix() { - return pathPrefix; + public PluginRequestMappingHandlerMapping(String pathPrefix){ + if(!ObjectUtils.isEmpty(pathPrefix)){ + Map>> prefixes = new HashMap<>(); + prefixes.put(pathPrefix, c->true); + setPathPrefixes(prefixes); + } } - public void setPathPrefix(String[] pathPrefix) { - this.pathPrefix = pathPrefix; + public void registerHandler(Object handler){ + detectHandlerMethods(handler); } - public Set getRequestMappingInfos() { - return requestMappingInfos; + @Override + protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) { + super.registerHandlerMethod(handler, method, mapping); + registerMappingInfo.add(new RegisterMappingInfo(handler, method, mapping)); } - public void setRequestMappingInfos(Set requestMappingInfos) { - this.requestMappingInfos = requestMappingInfos; + public List getAndClear(){ + List registerMappingInfo = new ArrayList<>(this.registerMappingInfo); + this.registerMappingInfo.clear(); + return registerMappingInfo; } + + } + + @AllArgsConstructor + @Getter + private static class RegisterMappingInfo{ + private final Object handler; + private final Method method; + private final RequestMappingInfo requestMappingInfo; } } diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/AutowiredTypeDefiner.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/AutowiredTypeDefiner.java new file mode 100644 index 0000000000000000000000000000000000000000..a81d519d1c3ebc35aee7cf8eb08fa7a6f295908c --- /dev/null +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/AutowiredTypeDefiner.java @@ -0,0 +1,95 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.bootstrap.realize; + +import com.gitee.starblues.bootstrap.AutowiredTypeDefinerConfig; +import com.gitee.starblues.bootstrap.annotation.AutowiredType; +import com.gitee.starblues.utils.UrlUtils; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +import java.util.HashSet; +import java.util.Set; + +/** + * autowiredType 批量定义接口 + * + * @author starBlues + * @since 3.0.3 + * @version 3.0.3 + */ +public interface AutowiredTypeDefiner { + + /** + * 定义 ClassDefiner + * @param config 往config中进行配置 ClassDefiner + */ + void config(AutowiredTypeDefinerConfig config); + + + @Getter + @EqualsAndHashCode + class ClassDefiner{ + /** + * 注入类型 + */ + private final AutowiredType.Type autowiredType; + + /** + * 类名称匹配 + */ + private final Set classNamePatterns; + + private ClassDefiner(AutowiredType.Type autowiredType, Set classNamePatterns){ + this.autowiredType = autowiredType; + this.classNamePatterns = classNamePatterns; + } + + public static ClassDefiner config(AutowiredType.Type autowiredType, Class... classes){ + if(autowiredType == null){ + throw new IllegalArgumentException("autowiredType 参数不能为空"); + } + int length = classes.length; + if(length == 0){ + throw new IllegalArgumentException("classes 参数不能为空"); + } + Set classNamePatterns = new HashSet<>(length); + for (Class aClass : classes) { + classNamePatterns.add(UrlUtils.formatMatchUrl(aClass.getName())); + } + return new ClassDefiner(autowiredType, classNamePatterns); + } + + public static ClassDefiner config(AutowiredType.Type autowiredType, String... classNamePatterns){ + if(autowiredType == null){ + throw new IllegalArgumentException("autowiredType 参数不能为空"); + } + int length = classNamePatterns.length; + if(length == 0){ + throw new IllegalArgumentException("classNamePatterns 参数不能为空"); + } + Set classNamePatternsSet = new HashSet<>(length); + for (String classNamePattern : classNamePatterns) { + classNamePatternsSet.add(UrlUtils.formatMatchUrl(classNamePattern)); + } + return new ClassDefiner(autowiredType, classNamePatternsSet); + } + + } + + +} diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/PluginCloseListener.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/PluginCloseListener.java index dfdfd66132e1526abcd3d4048c2db539bccb9b5f..7942eae37c9c9f42b603a55986275809fabe734f 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/PluginCloseListener.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/PluginCloseListener.java @@ -21,6 +21,7 @@ import com.gitee.starblues.core.descriptor.PluginDescriptor; /** * 插件被停止监听者。用于自定义关闭资源 * @author starBlues + * @since 3.0.0 * @version 3.0.0 */ public interface PluginCloseListener { diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/StopValidator.java b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/StopValidator.java index be1d74dbc0046d706f3630287e366d653c820366..54e58a0c927eef7fb39c09043dbd3dd9a0c366f6 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/StopValidator.java +++ b/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/StopValidator.java @@ -19,7 +19,8 @@ package com.gitee.starblues.bootstrap.realize; /** * 插件停止校验器. 自主实现判断是否可卸载 * @author starBlues - * @version 3.0.0 + * @since 3.0.0 + * @version 3.0.3 */ public interface StopValidator { @@ -27,6 +28,7 @@ public interface StopValidator { /** * 校验是否可停止/卸载。如果校验器抛出异常. 默认插件不可停止/卸载 * @return 校验结果 + * @since 3.0.0 */ Result verify(); @@ -52,6 +54,34 @@ public interface StopValidator { this.message = message; } + /** + * 可卸载 + * @return Result + * @since 3.0.3 + */ + public static Result ok(){ + return new Result(true); + } + + /** + * 禁止停止 + * @return Result + * @since 3.0.3 + */ + public static Result forbid(){ + return forbid(null); + } + + /** + * 禁止停止 + * @param message 禁止停止信息 + * @return Result + * @since 3.0.3 + */ + public static Result forbid(String message){ + return new Result(false, message); + } + public boolean isVerify() { return verify; } diff --git a/spring-brick-bootstrap/src/main/resources/META-INF/spring.factories b/spring-brick-bootstrap/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000000000000000000000000000000000000..9d17993ae52e8e794acca3335cebd416a6291d14 --- /dev/null +++ b/spring-brick-bootstrap/src/main/resources/META-INF/spring.factories @@ -0,0 +1,7 @@ +# Auto Configuration Import Filters +org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ +com.gitee.starblues.bootstrap.PluginDisableAutoConfiguration + +# Auto Configure +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +com.gitee.starblues.bootstrap.ResolveHttpMessageConvertersConfiguration \ No newline at end of file diff --git a/spring-brick-common/pom.xml b/spring-brick-common/pom.xml index f5213b9e0b5e85bb6ac23dba4d71ae5ac0fbea1a..98f6c3650c6305b1494d167822473b5179668c2c 100644 --- a/spring-brick-common/pom.xml +++ b/spring-brick-common/pom.xml @@ -7,7 +7,7 @@ spring-brick-parent com.gitee.starblues - 3.0.2 + 3.0.3 spring-brick-common diff --git a/spring-brick-common/src/main/java/com/gitee/starblues/utils/MapValueGetter.java b/spring-brick-common/src/main/java/com/gitee/starblues/utils/MapValueGetter.java index 191198e03a3c660833f162307f0c72950b610e26..813844c0f545a7f876e789298e61f2abb813921f 100644 --- a/spring-brick-common/src/main/java/com/gitee/starblues/utils/MapValueGetter.java +++ b/spring-brick-common/src/main/java/com/gitee/starblues/utils/MapValueGetter.java @@ -8,27 +8,31 @@ import java.util.function.Function; * map 值获取者工具类 * * @author starBlues - * @version 3.0.1 + * @version 3.0.3 */ public class MapValueGetter { - private final Map map; + private final Map source; - public MapValueGetter(Map map) { - if(map == null){ - this.map = Collections.emptyMap(); + public MapValueGetter(Map source) { + if(source == null){ + this.source = Collections.emptyMap(); } else { - this.map = map; + this.source = source; } } + public Map getSource(){ + return source; + } + /** * 获取object * @param key map key * @return value */ public Object getObject(String key) { - return map.get(key); + return source.get(key); } @@ -38,7 +42,7 @@ public class MapValueGetter { * @return String value */ public String getString(String key) { - return getValue(key, String::valueOf); + return getValue(key, ObjectValueUtils::getString); } /** @@ -47,12 +51,7 @@ public class MapValueGetter { * @return Integer value */ public Integer getInteger(String key) { - return getValue(key, value -> { - if(value instanceof Integer){ - return (Integer) value; - } - return Integer.parseInt(String.valueOf(value)); - }); + return getValue(key, ObjectValueUtils::getInteger); } /** @@ -61,12 +60,7 @@ public class MapValueGetter { * @return Long value */ public Long getLong(String key) { - return getValue(key, value -> { - if(value instanceof Long){ - return (Long) value; - } - return Long.parseLong(String.valueOf(value)); - }); + return getValue(key, ObjectValueUtils::getLong); } /** @@ -75,12 +69,7 @@ public class MapValueGetter { * @return Double value */ public Double getDouble(String key) { - return getValue(key, value -> { - if(value instanceof Double){ - return (Double) value; - } - return Double.parseDouble(String.valueOf(value)); - }); + return getValue(key, ObjectValueUtils::getDouble); } /** @@ -89,12 +78,7 @@ public class MapValueGetter { * @return Float value */ public Float getFloat(String key) { - return getValue(key, value -> { - if(value instanceof Float){ - return (Float) value; - } - return Float.parseFloat(String.valueOf(value)); - }); + return getValue(key, ObjectValueUtils::getFloat); } /** @@ -103,12 +87,7 @@ public class MapValueGetter { * @return Boolean value */ public Boolean getBoolean(String key) { - return getValue(key, value -> { - if(value instanceof Boolean){ - return (Boolean) value; - } - return Boolean.parseBoolean(String.valueOf(value)); - }); + return getValue(key, ObjectValueUtils::getBoolean); } /** diff --git a/spring-brick-common/src/main/java/com/gitee/starblues/utils/ObjectValueUtils.java b/spring-brick-common/src/main/java/com/gitee/starblues/utils/ObjectValueUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..9f3472511754ebe47ac0d794be30f84833a4de0e --- /dev/null +++ b/spring-brick-common/src/main/java/com/gitee/starblues/utils/ObjectValueUtils.java @@ -0,0 +1,90 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.utils; + +/** + * object value convert utils + * + * @author starBlues + * @version 3.0.3 + */ +public abstract class ObjectValueUtils { + + private ObjectValueUtils(){ + } + + public static String getString(Object value){ + if(value == null){ + return null; + } + if(value instanceof CharSequence){ + return ((CharSequence) value).toString(); + } + return String.valueOf(value); + } + + public static Integer getInteger(Object value){ + if(value == null){ + return null; + } + if(value instanceof Integer){ + return (Integer) value; + } + return Integer.parseInt(String.valueOf(value)); + } + + public static Long getLong(Object value){ + if(value == null){ + return null; + } + if(value instanceof Long){ + return (Long) value; + } + return Long.parseLong(String.valueOf(value)); + } + + public static Double getDouble(Object value) { + if(value == null){ + return null; + } + if(value instanceof Double){ + return (Double) value; + } + return Double.parseDouble(String.valueOf(value)); + } + + public static Float getFloat(Object value) { + if(value == null){ + return null; + } + if(value instanceof Float){ + return (Float) value; + } + return Float.parseFloat(String.valueOf(value)); + } + + public static Boolean getBoolean(Object value) { + if(value == null){ + return null; + } + if(value instanceof Boolean){ + return (Boolean) value; + } + return Boolean.parseBoolean(String.valueOf(value)); + } + +} diff --git a/spring-brick-common/src/main/java/com/gitee/starblues/utils/UrlUtils.java b/spring-brick-common/src/main/java/com/gitee/starblues/utils/UrlUtils.java index 90b80dbc4dbd3a069e095ec4aca0477ee11a266a..e4c7bdd42b90cf4aa1b4637db663d5620f661112 100644 --- a/spring-brick-common/src/main/java/com/gitee/starblues/utils/UrlUtils.java +++ b/spring-brick-common/src/main/java/com/gitee/starblues/utils/UrlUtils.java @@ -20,13 +20,17 @@ package com.gitee.starblues.utils; * http url util * * @author starBlues - * @version 3.0.0 + * @since 3.0.0 + * @version 3.0.3 */ public class UrlUtils { private UrlUtils(){} - public static final String SPLIT = "/"; + public static final String PATH_SEPARATOR = "/"; + + public final static String SEPARATOR_DOT = "."; + public final static String SEPARATOR_BACKSLASH = "\\"; /** * rest接口拼接路径 @@ -34,13 +38,14 @@ public class UrlUtils { * @param path1 路径1 * @param path2 路径2 * @return 拼接的路径 + * @since 3.0.0 */ public static String restJoiningPath(String path1, String path2){ if(path1 != null && path2 != null){ - if(path1.endsWith(SPLIT) && path2.startsWith(SPLIT)){ + if(path1.endsWith(PATH_SEPARATOR) && path2.startsWith(PATH_SEPARATOR)){ return path1 + path2.substring(1); - } else if(!path1.endsWith(SPLIT) && !path2.startsWith(SPLIT)){ - return path1 + SPLIT + path2; + } else if(!path1.endsWith(PATH_SEPARATOR) && !path2.startsWith(PATH_SEPARATOR)){ + return path1 + PATH_SEPARATOR + path2; } else { return path1 + path2; } @@ -59,6 +64,7 @@ public class UrlUtils { * * @param paths 拼接的路径 * @return 拼接的路径 + * @since 3.0.0 */ public static String joiningUrlPath(String ...paths){ if(paths == null || paths.length == 0){ @@ -71,13 +77,13 @@ public class UrlUtils { if(ObjectUtils.isEmpty(path)) { continue; } - if((i < length - 1) && path.endsWith(SPLIT)){ - path = path.substring(path.lastIndexOf(SPLIT)); + if((i < length - 1) && path.endsWith(PATH_SEPARATOR)){ + path = path.substring(path.lastIndexOf(PATH_SEPARATOR)); } - if(path.startsWith(SPLIT)){ + if(path.startsWith(PATH_SEPARATOR)){ stringBuilder.append(path); } else { - stringBuilder.append(SPLIT).append(path); + stringBuilder.append(PATH_SEPARATOR).append(path); } } @@ -88,12 +94,13 @@ public class UrlUtils { * 格式化 url * @param url 原始url * @return 格式化后的url + * @since 3.0.0 */ public static String format(String url){ if(ObjectUtils.isEmpty(url)){ return url; } - String[] split = url.split(SPLIT); + String[] split = url.split(PATH_SEPARATOR); StringBuilder stringBuilder = new StringBuilder(); int length = split.length; for (int i = 0; i < length; i++) { @@ -102,7 +109,7 @@ public class UrlUtils { continue; } if(i < length - 1){ - stringBuilder.append(str).append(SPLIT); + stringBuilder.append(str).append(PATH_SEPARATOR); } else { stringBuilder.append(str); } @@ -110,4 +117,23 @@ public class UrlUtils { return stringBuilder.toString(); } + /** + * 格式化匹配url时的格式 + * @param url url + * @return 格式化后 + * @since 3.0.3 + */ + public static String formatMatchUrl(String url){ + if(url.contains(SEPARATOR_DOT)){ + url = url.replace(SEPARATOR_DOT, PATH_SEPARATOR); + } + if(url.contains(SEPARATOR_BACKSLASH)){ + url = url.replace(SEPARATOR_BACKSLASH, PATH_SEPARATOR); + } + if(url.startsWith(PATH_SEPARATOR)){ + url = url.substring(url.indexOf(PATH_SEPARATOR) + 1); + } + return url; + } + } diff --git a/spring-brick-loader/pom.xml b/spring-brick-loader/pom.xml index 2df42130e1ba20beabfa221ab97c4c903d945313..2b61cd0496b8caaf31f9447d8a11986ca39c1b99 100644 --- a/spring-brick-loader/pom.xml +++ b/spring-brick-loader/pom.xml @@ -5,7 +5,7 @@ spring-brick-parent com.gitee.starblues - 3.0.2 + 3.0.3 4.0.0 diff --git a/spring-brick-maven-packager/pom.xml b/spring-brick-maven-packager/pom.xml index 10d4c6b7621bbea7e018886b9389165abda98a05..cb70eb68bc05abbc3b5e69b7dd200b962edfc58e 100644 --- a/spring-brick-maven-packager/pom.xml +++ b/spring-brick-maven-packager/pom.xml @@ -7,7 +7,7 @@ spring-brick-parent com.gitee.starblues - 3.0.2 + 3.0.3 spring-brick-maven-packager diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/AbstractDependencyFilterMojo.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/AbstractDependencyFilterMojo.java index 42e0e14658cb59a5baa57a439cdc78572813f02d..19505ea54d8096d971639df0c3c82253d747e5ad 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/AbstractDependencyFilterMojo.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/AbstractDependencyFilterMojo.java @@ -95,6 +95,12 @@ public abstract class AbstractDependencyFilterMojo extends AbstractMojo { excludes.add(Exclude.get("org.springframework.boot", "spring-boot-starter-json")); excludes.add(Exclude.get("org.springframework", "spring-webmvc")); excludes.add(Exclude.get("org.springframework", "spring-web")); + + // jackson + excludes.add(Exclude.get("com.fasterxml.jackson.core", "jackson-core")); + excludes.add(Exclude.get("com.fasterxml.jackson.core", "jackson-databind")); + excludes.add(Exclude.get("com.fasterxml.jackson.core", "jackson-annotations")); + excludes.add(Exclude.get("com.fasterxml.jackson.module", "jackson-module-parameter-names")); } } diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/AbstractPackagerMojo.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/AbstractPackagerMojo.java index b24c52523d6a5463f6ec4ca63203420ed9d077d3..bfd403724e3464b84b24ed343bc37dab2760b1c9 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/AbstractPackagerMojo.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/AbstractPackagerMojo.java @@ -48,6 +48,9 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo{ @Parameter(property = "spring-brick-packager.skip", defaultValue = "false") private boolean skip; + @Parameter + private String classifier; + @Parameter(property = "spring-brick-packager.pluginInfo") private PluginInfo pluginInfo; diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/BasicRepackager.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/BasicRepackager.java index bb1f79012dfec24951f3ea77c9c2bd8c19fa2ce6..7eee475675a2519616449b45a8083110dc9c0a92 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/BasicRepackager.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/BasicRepackager.java @@ -17,6 +17,7 @@ package com.gitee.starblues.plugin.pack; import com.gitee.starblues.common.*; +import com.gitee.starblues.plugin.pack.utils.CommonUtils; import com.gitee.starblues.utils.FilesUtils; import com.gitee.starblues.utils.ObjectUtils; import lombok.Getter; @@ -32,6 +33,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.*; import java.util.jar.Attributes; import java.util.jar.Manifest; @@ -119,7 +121,7 @@ public class BasicRepackager implements Repackager{ protected String createRootDir() throws MojoFailureException { String rootDirPath = getBasicRootDir(); File rootDir = new File(rootDirPath); - rootDir.deleteOnExit(); + CommonUtils.deleteFile(rootDir); if(rootDir.mkdir()){ return rootDirPath; } @@ -237,7 +239,7 @@ public class BasicRepackager implements Repackager{ protected String writePluginMetaInfo(Properties properties) throws Exception { File pluginMetaFile = createPluginMetaFile(); try (OutputStreamWriter writer = new OutputStreamWriter( - new FileOutputStream(pluginMetaFile), StandardCharsets.UTF_8)){ + Files.newOutputStream(pluginMetaFile.toPath()), StandardCharsets.UTF_8)){ properties.store(writer, Constant.PLUGIN_METE_COMMENTS); return pluginMetaFile.getPath(); } diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/Constant.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/Constant.java index a08d41bc78b9ac8b07b2c6c74e22b7ec1a76cb5c..b66fe5d1dedabcf8db9547b459b9ef5279c06055 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/Constant.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/Constant.java @@ -31,6 +31,8 @@ public class Constant { public static final String SCOPE_SYSTEM = "system"; public static final String SCOPE_TEST = "test"; + public static final String MAVEN_POM_TYPE = "pom"; + public static final String MAVEN_MAIN_TYPE = "main"; public static final String MODE_MAIN = "main"; @@ -51,7 +53,7 @@ public class Constant { if(Constant.isSystemScope(artifact.getScope())){ return includeSystemScope == null || !includeSystemScope; } - return false; + return Constant.filterPomTypeArtifact(artifact); } public static boolean filterMainTypeArtifact(Artifact artifact){ @@ -59,6 +61,10 @@ public class Constant { return MAVEN_MAIN_TYPE.equalsIgnoreCase(artifact.getType()); } + public static boolean filterPomTypeArtifact(Artifact artifact){ + return MAVEN_POM_TYPE.equalsIgnoreCase(artifact.getType()); + } + public static boolean scopeFilter(String scope){ return SCOPE_PROVIDED.equalsIgnoreCase(scope) || SCOPE_TEST.equalsIgnoreCase(scope); diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/RepackageMojo.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/RepackageMojo.java index 0e6dbb7abc21448318d68870cf524987756ebfa5..1aa220a665745354bfd8355c5c1449356f6e1ece 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/RepackageMojo.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/RepackageMojo.java @@ -34,7 +34,6 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/DevConfig.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/DevConfig.java index 20ed1b65d3642a0bf0c666f72f6bf7454e1f5da1..9070a6eb3116748360fe06f741cac5a85127977e 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/DevConfig.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/DevConfig.java @@ -34,4 +34,9 @@ public class DevConfig { */ private List moduleDependencies; + /** + * 本地jar依赖文件定义 + */ + private List localJars; + } diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/DevRepackager.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/DevRepackager.java index 9e436c24dad17ca38a6a4e0fefd3669ee971a0fb..6540b3f7daffb010f8dff037c70c6460943beed3 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/DevRepackager.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/dev/DevRepackager.java @@ -44,11 +44,19 @@ public class DevRepackager extends BasicRepackager { @Override protected Set getDependenciesIndexSet() throws Exception { - moduleDependencies = getModuleDependencies(repackageMojo.getDevConfig()); + DevConfig devConfig = repackageMojo.getDevConfig(); + if(devConfig == null){ + return super.getDependenciesIndexSet(); + } + moduleDependencies = getModuleDependencies(devConfig); Set dependenciesIndexSet = super.getDependenciesIndexSet(); for (Dependency dependency : moduleDependencies.values()) { dependenciesIndexSet.add(dependency.getClassesPath()); } + List localJars = devConfig.getLocalJars(); + if(!ObjectUtils.isEmpty(localJars)){ + dependenciesIndexSet.addAll(localJars); + } return dependenciesIndexSet; } diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/main/JarOuterPackager.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/main/JarOuterPackager.java index 3e24c97d77bbffed6a2202e95c3f6bed2ae07c1a..de5a493c8a6b258a0bb1acb3755afffc283f5d84 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/main/JarOuterPackager.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/main/JarOuterPackager.java @@ -31,6 +31,7 @@ import java.util.HashSet; import java.util.Set; import java.util.jar.Attributes; import java.util.jar.Manifest; +import java.util.stream.Stream; import static com.gitee.starblues.common.ManifestKey.*; @@ -68,9 +69,7 @@ public class JarOuterPackager extends JarNestPackager { String fileName = mainConfig.getFileName(); String rootDirPath = FilesUtils.joiningFilePath(outputDirectory, fileName); File rootFile = new File(rootDirPath); - if(rootFile.exists()){ - rootFile.deleteOnExit(); - } + CommonUtils.deleteFile(rootFile); if(rootFile.mkdirs()){ return rootDirPath; } else { @@ -86,11 +85,7 @@ public class JarOuterPackager extends JarNestPackager { attributes.putValue(START_CLASS, mainConfig.getMainClass()); attributes.putValue(MAIN_CLASS, MAIN_CLASS_VALUE); attributes.putValue(MAIN_PACKAGE_TYPE, PackageType.MAIN_PACKAGE_TYPE_JAR_OUTER); - String libDir = PackageStructure.LIB_NAME; - if(!ObjectUtils.isEmpty(mainConfig.getLibDir())){ - libDir = mainConfig.getLibDir(); - } - attributes.putValue(MAIN_LIB_DIR, libDir); + attributes.putValue(MAIN_LIB_DIR, getLibPath()); attributes.putValue(MAIN_LIB_INDEXES, getLibIndexes()); return manifest; } @@ -119,12 +114,25 @@ public class JarOuterPackager extends JarNestPackager { packageJar.copyZipToPackage(artifact.getFile()); } else { File artifactFile = artifact.getFile(); - String targetFilePath = FilesUtils.joiningFilePath( - mainConfig.getOutputDirectory(), PackageStructure.LIB_NAME, artifactFile.getName()); + String libPath = getLibPath(); + if(FilesUtils.isRelativePath(libPath)){ + libPath = FilesUtils.resolveRelativePath(mainConfig.getOutputDirectory(), getLibPath()); + } else { + libPath = FilesUtils.joiningFilePath(mainConfig.getOutputDirectory(), libPath); + } + String targetFilePath = FilesUtils.joiningFilePath(libPath, artifactFile.getName()); FileUtils.copyFile(artifactFile, new File(targetFilePath)); dependencyIndexNames.add(artifactFile.getName()); } } } + private String getLibPath(){ + String libDir = PackageStructure.LIB_NAME; + if(!ObjectUtils.isEmpty(mainConfig.getLibDir())){ + libDir = mainConfig.getLibDir(); + } + return libDir; + } + } diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/DirProdRepackager.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/DirProdRepackager.java index 5a3bd8ec2d0588c12a07bd1938b18869d4121062..bd819f686206019d3ed04f1ea2f31226ca0b203f 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/DirProdRepackager.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/DirProdRepackager.java @@ -68,18 +68,7 @@ public class DirProdRepackager extends DevRepackager { String fileName = prodConfig.getFileName(); String dirPath = FilesUtils.joiningFilePath(prodConfig.getOutputDirectory(), fileName); File dirFile = new File(dirPath); - if(dirFile.exists() && dirFile.isFile()){ - int i = 0; - while (true){ - dirFile = new File(dirPath + "_" + i); - if(dirFile.exists() && dirFile.isFile()){ - i = i + 1; - continue; - } - break; - } - } - dirFile.deleteOnExit(); + CommonUtils.deleteFile(dirFile); if(!dirFile.mkdirs()){ throw new MojoFailureException("Create package dir failure: " + dirFile.getPath()); } diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ProdRepackager.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ProdRepackager.java index 9db3b18386ec7bdf91e7b22fa4c0ecc255b23a27..0ff7d34e7f8e6d00a1f74f264769b6f65e4a01ea 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ProdRepackager.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ProdRepackager.java @@ -17,7 +17,6 @@ package com.gitee.starblues.plugin.pack.prod; import com.gitee.starblues.common.PackageType; -import com.gitee.starblues.plugin.pack.Constant; import com.gitee.starblues.plugin.pack.PluginInfo; import com.gitee.starblues.plugin.pack.RepackageMojo; import com.gitee.starblues.plugin.pack.Repackager; diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ZipProdRepackager.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ZipProdRepackager.java index dacd996be1cd34ce27de958b9d667cba793f112e..303fd54ad009a6e8211ca4128b123607fcf894d9 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ZipProdRepackager.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/prod/ZipProdRepackager.java @@ -25,6 +25,7 @@ import com.gitee.starblues.plugin.pack.RepackageMojo; import com.gitee.starblues.plugin.pack.dev.Dependency; import com.gitee.starblues.plugin.pack.dev.DevConfig; import com.gitee.starblues.plugin.pack.dev.DevRepackager; +import com.gitee.starblues.plugin.pack.utils.CommonUtils; import com.gitee.starblues.plugin.pack.utils.PackageZip; import com.gitee.starblues.utils.FilesUtils; import com.gitee.starblues.utils.ObjectUtils; diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/CommonUtils.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/CommonUtils.java index 87b282e2dbfa8d26b2eebb6c07048ffb41623d39..09ac0a0c30ee2d2b4340cfe5f0539e52e16a09f3 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/CommonUtils.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/CommonUtils.java @@ -17,8 +17,11 @@ package com.gitee.starblues.plugin.pack.utils; import com.gitee.starblues.plugin.pack.filter.Exclude; +import org.apache.commons.io.FileUtils; import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.MojoFailureException; +import java.io.File; import java.util.Objects; /** @@ -48,4 +51,23 @@ public class CommonUtils { return Objects.equals(artifact.getGroupId(), PLUGIN_FRAMEWORK_GROUP_ID) && Objects.equals(artifact.getArtifactId(), PLUGIN_FRAMEWORK_LOADER_ARTIFACT_ID); } + + public static void deleteFile(File rootFile) throws MojoFailureException { + try { + if(rootFile == null){ + return; + } + if(!rootFile.exists()){ + return; + } + if(rootFile.isFile()){ + FileUtils.delete(rootFile); + } else { + FileUtils.deleteDirectory(rootFile); + } + } catch (Exception e){ + e.printStackTrace(); + throw new MojoFailureException("Delete file '" + rootFile.getPath() + "' failure. " + e.getMessage()); + } + } } diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/PackageJar.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/PackageJar.java index d82a8f387ef9e87823e4518244dcd9b45e96a713..cf3012241a5e28a0afe33925f3826ecdfed1400f 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/PackageJar.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/PackageJar.java @@ -23,6 +23,7 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import java.io.File; import java.io.FileOutputStream; +import java.nio.file.Files; /** * jar 打包工具 @@ -45,7 +46,7 @@ public class PackageJar extends PackageZip{ @Override protected ArchiveOutputStream getOutputStream(File packFile) throws Exception { - return new JarArchiveOutputStream(new FileOutputStream(packFile)); + return new JarArchiveOutputStream(Files.newOutputStream(packFile.toPath())); } @Override diff --git a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/PackageZip.java b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/PackageZip.java index 7867941ff37cd64c8adc15c83d26e2879b13ac7a..f7aa974c010845db067e1736af06516456f5fdf6 100644 --- a/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/PackageZip.java +++ b/spring-brick-maven-packager/src/main/java/com/gitee/starblues/plugin/pack/utils/PackageZip.java @@ -28,6 +28,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import java.io.*; +import java.nio.file.Files; import java.util.Enumeration; import java.util.jar.Manifest; import java.util.zip.CRC32; @@ -73,18 +74,7 @@ public class PackageZip implements Closeable{ protected File getPackageFile(String rootPath) throws Exception { String fileSuffix = getPackageFileSuffix(); File file = new File(rootPath + "." + fileSuffix); - - if(file.exists()){ - int i = 0; - while (true){ - file = new File(rootPath + "_" + i + "." + fileSuffix); - if(file.exists()){ - i = i + 1; - continue; - } - break; - } - } + CommonUtils.deleteFile(file); if(file.createNewFile()){ return file; } @@ -96,7 +86,7 @@ public class PackageZip implements Closeable{ } protected ArchiveOutputStream getOutputStream(File packFile) throws Exception { - return new ZipArchiveOutputStream(new FileOutputStream(packFile)); + return new ZipArchiveOutputStream(Files.newOutputStream(packFile.toPath())); } public void copyDirToPackage(File rootDir, String packageDir) throws Exception { diff --git a/spring-brick-maven-packager/src/main/resources/META-INF/maven/com.gitee.starblues.springboot-plugin-maven-packager/plugin-help.xml b/spring-brick-maven-packager/src/main/resources/META-INF/maven/com.gitee.starblues.springboot-plugin-maven-packager/plugin-help.xml index ebe06e796278073f4d6a73fc560a66a0b5b8e87d..ddfb1ce44fb119f21f5ada61509aea1ebc8ee3ae 100644 --- a/spring-brick-maven-packager/src/main/resources/META-INF/maven/com.gitee.starblues.springboot-plugin-maven-packager/plugin-help.xml +++ b/spring-brick-maven-packager/src/main/resources/META-INF/maven/com.gitee.starblues.springboot-plugin-maven-packager/plugin-help.xml @@ -1,21 +1,17 @@ - - Spring Boot Plugin Maven Packager com.gitee.starblues spring-brick-maven-packager - 3.0.2 + 3.0.3 spring-brick-packager false true repackage - Repackage existing JAR and WAR archives so that they can be executed from the command - line using {@literal java -jar}. With <code>layout=NONE</code> can also be used simply - to package a JAR with nested dependencies (and no main class, so not executable). + 重新打包 compile+runtime false true @@ -28,54 +24,49 @@ java per-lookup once-per-session - 1.0.0 + 3.0.0 compile+runtime true project org.apache.maven.project.MavenProject - 1.0.0 + 3.0.0 true false - The Maven project. + 当前项目 outputDirectory java.io.File - 1.0.0 + 3.0.0 true true - Directory containing the generated archive. + 打包输出目录地址 includes java.util.List - 1.2.0 + 3.0.0 false true - Collection of artifact definitions to include. The {@link Include} element defines - mandatory {@code groupId} and {@code artifactId} properties and an optional - mandatory {@code groupId} and {@code artifactId} properties and an optional - {@code classifier} property. + 包含依赖定义 excludes java.util.List - 1.1.0 + 3.0.0 false true - Collection of artifact definitions to exclude. The {@link Exclude} element defines - mandatory {@code groupId} and {@code artifactId} properties and an optional - {@code classifier} property. + 排除依赖定义 skip boolean - 1.2.0 + 3.0.0 false true - Skip the execution. + 跳过执行 mode diff --git a/spring-brick-maven-packager/src/main/resources/META-INF/maven/plugin.xml b/spring-brick-maven-packager/src/main/resources/META-INF/maven/plugin.xml index ebe06e796278073f4d6a73fc560a66a0b5b8e87d..ddfb1ce44fb119f21f5ada61509aea1ebc8ee3ae 100644 --- a/spring-brick-maven-packager/src/main/resources/META-INF/maven/plugin.xml +++ b/spring-brick-maven-packager/src/main/resources/META-INF/maven/plugin.xml @@ -1,21 +1,17 @@ - - Spring Boot Plugin Maven Packager com.gitee.starblues spring-brick-maven-packager - 3.0.2 + 3.0.3 spring-brick-packager false true repackage - Repackage existing JAR and WAR archives so that they can be executed from the command - line using {@literal java -jar}. With <code>layout=NONE</code> can also be used simply - to package a JAR with nested dependencies (and no main class, so not executable). + 重新打包 compile+runtime false true @@ -28,54 +24,49 @@ java per-lookup once-per-session - 1.0.0 + 3.0.0 compile+runtime true project org.apache.maven.project.MavenProject - 1.0.0 + 3.0.0 true false - The Maven project. + 当前项目 outputDirectory java.io.File - 1.0.0 + 3.0.0 true true - Directory containing the generated archive. + 打包输出目录地址 includes java.util.List - 1.2.0 + 3.0.0 false true - Collection of artifact definitions to include. The {@link Include} element defines - mandatory {@code groupId} and {@code artifactId} properties and an optional - mandatory {@code groupId} and {@code artifactId} properties and an optional - {@code classifier} property. + 包含依赖定义 excludes java.util.List - 1.1.0 + 3.0.0 false true - Collection of artifact definitions to exclude. The {@link Exclude} element defines - mandatory {@code groupId} and {@code artifactId} properties and an optional - {@code classifier} property. + 排除依赖定义 skip boolean - 1.2.0 + 3.0.0 false true - Skip the execution. + 跳过执行 mode diff --git a/spring-brick/pom.xml b/spring-brick/pom.xml index e0c702dbc4442e60d3613bd95a2087a2253f29a9..c92fc860fbfdbaf16ba242fc7d719a342c6b1dfb 100644 --- a/spring-brick/pom.xml +++ b/spring-brick/pom.xml @@ -7,7 +7,7 @@ spring-brick-parent com.gitee.starblues - 3.0.2 + 3.0.3 spring-brick diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/DefaultPluginManager.java b/spring-brick/src/main/java/com/gitee/starblues/core/DefaultPluginManager.java index f5824ac4c37b8126917951ecccb0ddf6f9543f0c..ac678a21772abae3f55ade7d69391468b536b782 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/DefaultPluginManager.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/DefaultPluginManager.java @@ -49,11 +49,11 @@ import java.util.stream.Collectors; /** * 抽象的插件管理者 * @author starBlues - * @version 3.0.2 + * @version 3.0.3 */ public class DefaultPluginManager implements PluginManager{ - private final Logger log = LoggerFactory.getLogger(this.getClass()); + private final Logger log = LoggerFactory.getLogger(DefaultPluginManager.class); private final RealizeProvider provider; private final IntegrationConfiguration configuration; diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/PluginLauncherManager.java b/spring-brick/src/main/java/com/gitee/starblues/core/PluginLauncherManager.java index d9b9b907fd185d58c7784b2a7bc0e3db50ead2e8..a7b4f05400e5712246701c4293ffd87bde2f59d9 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/PluginLauncherManager.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/PluginLauncherManager.java @@ -20,6 +20,7 @@ import com.gitee.starblues.core.checker.PluginLauncherChecker; import com.gitee.starblues.core.descriptor.InsidePluginDescriptor; import com.gitee.starblues.core.descriptor.PluginDescriptor; import com.gitee.starblues.core.exception.PluginException; +import com.gitee.starblues.core.exception.PluginProhibitStopException; import com.gitee.starblues.core.launcher.plugin.DefaultPluginInteractive; import com.gitee.starblues.core.launcher.plugin.PluginInteractive; import com.gitee.starblues.core.launcher.plugin.PluginLauncher; @@ -43,7 +44,8 @@ import java.util.concurrent.ConcurrentHashMap; /** * 可引导启动的插件管理者 * @author starBlues - * @version 3.0.1 + * @since 3.0.0 + * @version 3.0.3 */ public class PluginLauncherManager extends DefaultPluginManager{ @@ -123,6 +125,10 @@ public class PluginLauncherManager extends DefaultPluginManager{ registryInfo.remove(pluginId); super.stop(pluginInsideInfo); } catch (Exception e){ + if(e instanceof PluginProhibitStopException){ + // 禁止停止时, 不设置插件状态 + throw e; + } pluginInsideInfo.setPluginState(PluginState.STOPPED_FAILURE); throw e; } diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/checker/DefaultPluginLauncherChecker.java b/spring-brick/src/main/java/com/gitee/starblues/core/checker/DefaultPluginLauncherChecker.java index 052b74a898356e5a611e61442d2093d435a27ac4..f2590e56d616902bd10be7748857c3f4a409c039 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/checker/DefaultPluginLauncherChecker.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/checker/DefaultPluginLauncherChecker.java @@ -77,6 +77,9 @@ public class DefaultPluginLauncherChecker implements PluginLauncherChecker { return; } String requires = pluginInfo.getPluginDescriptor().getRequires(); + if(ObjectUtils.isEmpty(requires)){ + return; + } boolean exactVersion = configuration.exactVersion(); int compareVersion = realizeProvider.getVersionInspector().compareTo(requires, version); PluginDescriptor descriptor = pluginInfo.getPluginDescriptor(); @@ -92,8 +95,4 @@ public class DefaultPluginLauncherChecker implements PluginLauncherChecker { } } - - - - } diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/CacheMainResourceMatcher.java b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/CacheMainResourceMatcher.java index 58ed42aadbfc044440a043c45130994db14816fa..84c2a4f3114566c2f3e3a33e71addfc207e591f8 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/CacheMainResourceMatcher.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/CacheMainResourceMatcher.java @@ -23,10 +23,13 @@ import java.util.concurrent.ConcurrentHashMap; /** * 可缓存的 ResourceMatcher * @author starBlues - * @version 3.0.0 + * @since 3.0.0 + * @version 3.0.3 */ public class CacheMainResourceMatcher extends DefaultMainResourceMatcher implements AutoCloseable { + public static final String TYPE = "CacheMainResourceMatcher"; + private final Map resourceUrlMatchCache = new ConcurrentHashMap<>(); public CacheMainResourceMatcher(MainResourcePatternDefiner mainResourcePatternDefiner) { @@ -34,7 +37,7 @@ public class CacheMainResourceMatcher extends DefaultMainResourceMatcher impleme } @Override - public boolean match(String resourceUrl) { + public Boolean match(String resourceUrl) { Boolean match = resourceUrlMatchCache.get(resourceUrl); if(match == null){ match = super.match(resourceUrl); diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/ComposeMainResourceMatcher.java b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/ComposeMainResourceMatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..c993535f446a09dc989a1dd7529bdc444eb8ea41 --- /dev/null +++ b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/ComposeMainResourceMatcher.java @@ -0,0 +1,62 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.core.classloader; + +import com.gitee.starblues.utils.ObjectUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 组合的 MainResourcePatternDefiner + * + * @author starBlues + * @version 3.0.3 + */ +public class ComposeMainResourceMatcher implements MainResourceMatcher{ + + private final List resourceMatchers; + + public ComposeMainResourceMatcher(){ + this(null); + } + + public ComposeMainResourceMatcher(List resourceMatchers) { + if(ObjectUtils.isEmpty(resourceMatchers)){ + this.resourceMatchers = new ArrayList<>(); + } else { + this.resourceMatchers = resourceMatchers; + } + } + + public void addMainResourceMatcher(MainResourceMatcher mainResourceMatcher){ + if(mainResourceMatcher == null){ + return; + } + resourceMatchers.add(mainResourceMatcher); + } + + @Override + public Boolean match(String resourceUrl) { + for (MainResourceMatcher resourceMatcher : resourceMatchers) { + if(resourceMatcher.match(resourceUrl)){ + return Boolean.TRUE; + } + } + return Boolean.FALSE; + } +} diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/DefaultMainResourceMatcher.java b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/DefaultMainResourceMatcher.java index 29c95de46d55e68278f66866cde19b895916789d..1dc02c3e090c1f41dac844985ff74beea94b2b3b 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/DefaultMainResourceMatcher.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/DefaultMainResourceMatcher.java @@ -17,6 +17,7 @@ package com.gitee.starblues.core.classloader; import com.gitee.starblues.utils.ObjectUtils; +import com.gitee.starblues.utils.UrlUtils; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; @@ -26,7 +27,8 @@ import java.util.Set; /** * 默认的主程序资源匹配者 * @author starBlues - * @version 3.0.0 + * @since 3.0.0 + * @version 3.0.3 */ public class DefaultMainResourceMatcher implements MainResourceMatcher{ @@ -42,44 +44,38 @@ public class DefaultMainResourceMatcher implements MainResourceMatcher{ } @Override - public boolean match(String resourceUrl) { + public Boolean match(String resourceUrl) { return match(includePatterns, resourceUrl); } - private boolean match(Collection patterns, String url){ + private Boolean match(Collection patterns, String url){ if(ObjectUtils.isEmpty(patterns) || ObjectUtils.isEmpty(url)){ - return false; + return Boolean.FALSE; } - url = formatUrl(url); + url = UrlUtils.formatMatchUrl(url); for (String pattern : patterns) { boolean match = pathMatcher.match(pattern, url); if(match){ return !excludeMatch(excludePatterns, url); } } - return false; + return Boolean.FALSE; } - private boolean excludeMatch(Collection patterns, String url){ + private Boolean excludeMatch(Collection patterns, String url){ if(ObjectUtils.isEmpty(patterns) || ObjectUtils.isEmpty(url)){ - return false; + return Boolean.FALSE; } - url = formatUrl(url); + url = UrlUtils.formatMatchUrl(url); for (String pattern : patterns) { boolean match = pathMatcher.match(pattern, url); if(match){ - return true; + return Boolean.TRUE; } } - return false; + return Boolean.FALSE; } - private String formatUrl(String url){ - url = url.replace("\\", AntPathMatcher.DEFAULT_PATH_SEPARATOR); - if(url.startsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR)){ - url = url.substring(url.indexOf(AntPathMatcher.DEFAULT_PATH_SEPARATOR) + 1); - } - return url; - } + } diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/MainResourceMatcher.java b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/MainResourceMatcher.java index 5977f35f51c2f3daf933c2a20ee6d46ab8d1fd7f..9b94955686905aa9d88c9c6b1e22d7d1a45e65fc 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/MainResourceMatcher.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/MainResourceMatcher.java @@ -19,7 +19,7 @@ package com.gitee.starblues.core.classloader; /** * 主程序资源匹配者 * @author starBlues - * @version 3.0.0 + * @version 3.0.3 */ public interface MainResourceMatcher { @@ -28,6 +28,6 @@ public interface MainResourceMatcher { * @param resourceUrl 主程序资源url * @return true 匹配成功, false 匹配失败 */ - boolean match(String resourceUrl); + Boolean match(String resourceUrl); } diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/MainResourcePatternDefiner.java b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/MainResourcePatternDefiner.java index 5759573f88aaf28dd30cc5d5ff4bbea8d61892b0..1a56fe38f1e925f7858b7f5b0f4d963db9bc532f 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/MainResourcePatternDefiner.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/MainResourcePatternDefiner.java @@ -37,6 +37,4 @@ public interface MainResourcePatternDefiner { */ Set getExcludePatterns(); - - } diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/PluginClassLoader.java b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/PluginClassLoader.java index 31f624fcd1a738d948c8dec19bb174150c1aa99d..c94681e52f554388066a8ab85c9b1c5187871778 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/PluginClassLoader.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/PluginClassLoader.java @@ -38,27 +38,24 @@ import java.util.Set; /** * 插件 classLoader * @author starBlues - * @version 3.0.0 + * @version 3.0.3 */ @Slf4j public class PluginClassLoader extends GenericClassLoader { private final GenericClassLoader parentClassLoader; - private MainResourceMatcher mainResourceMatcher; + private final MainResourceMatcher mainResourceMatcher; - public PluginClassLoader(String name, GenericClassLoader parentClassLoader, MainResourcePatternDefiner patternDefiner, - ResourceLoaderFactory resourceLoaderFactory) { + public PluginClassLoader(String name, GenericClassLoader parentClassLoader, + ResourceLoaderFactory resourceLoaderFactory, + MainResourceMatcher mainResourceMatcher) { super(name, parentClassLoader, resourceLoaderFactory); this.parentClassLoader = parentClassLoader; - if(patternDefiner != null){ - setMainResourceMatcher(new CacheMainResourceMatcher(patternDefiner)); - } else { - setMainResourceMatcher(new ProhibitMainResourceMatcher()); - } + this.mainResourceMatcher = mainResourceMatcher; } - public void setMainResourceMatcher(MainResourceMatcher mainResourceMatcher){ - this.mainResourceMatcher = Assert.isNotNull(mainResourceMatcher, "参数 mainResourceMatcher 不能为空"); + public MainResourceMatcher getMainResourceMatcher() { + return mainResourceMatcher; } public void addResource(InsidePluginDescriptor descriptor) throws Exception { diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/ProhibitMainResourceMatcher.java b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/ProhibitMainResourceMatcher.java index 296dacf2d0a58c9cdbdd903f12d4f32eafdde26d..cba6d62277f62f9a292c84a6cc3a6438b98bbfa7 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/classloader/ProhibitMainResourceMatcher.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/classloader/ProhibitMainResourceMatcher.java @@ -19,12 +19,12 @@ package com.gitee.starblues.core.classloader; /** * 禁止匹配所有主程序资源 * @author starBlues - * @version 3.0.0 + * @version 3.0.3 */ public class ProhibitMainResourceMatcher implements MainResourceMatcher{ @Override - public boolean match(String resourceUrl) { + public Boolean match(String resourceUrl) { return false; } diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/DefaultMainResourcePatternDefiner.java b/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/DefaultMainResourcePatternDefiner.java new file mode 100644 index 0000000000000000000000000000000000000000..ac6014e6e25c5b0d81e4def7af6859a5836cdfeb --- /dev/null +++ b/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/DefaultMainResourcePatternDefiner.java @@ -0,0 +1,153 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.core.launcher.plugin; + +import com.gitee.starblues.core.classloader.MainResourcePatternDefiner; +import com.gitee.starblues.core.launcher.JavaMainResourcePatternDefiner; +import com.gitee.starblues.utils.ObjectUtils; +import com.gitee.starblues.utils.SpringBeanUtils; +import org.springframework.context.ApplicationContext; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * 主程序资源匹配定义 + * + * @author starBlues + * @version 3.0.3 + */ +public class DefaultMainResourcePatternDefiner extends JavaMainResourcePatternDefiner { + + private static final String FRAMEWORK = "com/gitee/starblues/**"; + + public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; + + private final String mainPackage; + private final ApplicationContext applicationContext; + + public DefaultMainResourcePatternDefiner(String mainPackage, ApplicationContext applicationContext) { + this.mainPackage = mainPackage; + this.applicationContext = applicationContext; + } + + @Override + public Set getIncludePatterns() { + Set includeResourcePatterns = super.getIncludePatterns(); + // add mainPackage + includeResourcePatterns.add(ObjectUtils.changePackageToMatch(mainPackage)); + // add framework + includeResourcePatterns.add(FRAMEWORK); + addWebIncludeResourcePatterns(includeResourcePatterns); + addApiDoc(includeResourcePatterns); + addDbDriver(includeResourcePatterns); + + addIdea(includeResourcePatterns); + + // add extension + List extensionPatternDefiners = getExtensionPatternDefiners(); + for (MainResourcePatternDefiner extensionPatternDefiner : extensionPatternDefiners) { + Set includePatterns = extensionPatternDefiner.getIncludePatterns(); + if(!ObjectUtils.isEmpty(includePatterns)){ + includeResourcePatterns.addAll(includePatterns); + } + } + + return includeResourcePatterns; + } + + @Override + public Set getExcludePatterns() { + Set excludeResourcePatterns = new HashSet<>(); + excludeResourcePatterns.add(FACTORIES_RESOURCE_LOCATION); + + // add extension + List extensionPatternDefiners = getExtensionPatternDefiners(); + for (MainResourcePatternDefiner extensionPatternDefiner : extensionPatternDefiners) { + Set excludePatterns = extensionPatternDefiner.getExcludePatterns(); + if(!ObjectUtils.isEmpty(excludePatterns)){ + excludeResourcePatterns.addAll(excludePatterns); + } + } + return excludeResourcePatterns; + } + + protected void addWebIncludeResourcePatterns(Set patterns) { + patterns.add("org/springframework/web/**"); + patterns.add("org/springframework/http/**"); + patterns.add("org/springframework/remoting/**"); + patterns.add("org/springframework/ui/**"); + + patterns.add("org/springframework/boot/autoconfigure/http/**"); + patterns.add("org/springframework/boot/autoconfigure/web/**"); + patterns.add("org/springframework/boot/autoconfigure/websocket/**"); + patterns.add("org/springframework/boot/autoconfigure/webservices/**"); + patterns.add("org/springframework/boot/autoconfigure/jackson/**"); + + patterns.add("com/fasterxml/jackson/**"); + } + + protected void addApiDoc(Set patterns) { + patterns.add("springfox/documentation/**"); + patterns.add("io/swagger/**"); + patterns.add("org/springdoc/**"); + } + + protected void addDbDriver(Set patterns) { + // mysql + patterns.add("com/mysql/**"); + // oracle + patterns.add("oracle/jdbc/**"); + // sqlserver + patterns.add("com/microsoft/jdbc/sqlserver/**"); + // DB2 + patterns.add("com/ibm/db2/jdbc/**"); + // DB2/AS400 + patterns.add("com/ibm/as400/**"); + // Informix + patterns.add("com/informix/jdbc/**"); + // Hypersonic + patterns.add("org/hsql/**"); + // MS SQL + patterns.add("com/microsoft/jdbc/**"); + // Postgres + patterns.add("org/postgresql/**"); + // Sybase + patterns.add("com/sybase/jdbc2/**"); + // Weblogic + patterns.add("weblogic/jdbc/**"); + // h2 + patterns.add("jdbc/h2/**"); + } + + private void addIdea(Set includeResourcePatterns) { + // idea debug agent + includeResourcePatterns.add("com/intellij/rt/debugger/agent/**"); + } + + + /** + * 获取扩展的 MainResourcePatternDefiner + * + * @return List + */ + private List getExtensionPatternDefiners() { + return SpringBeanUtils.getBeans(applicationContext, MainResourcePatternDefiner.class); + } + +} diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/PluginLauncher.java b/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/PluginLauncher.java index 9878c3d685cb7a238ebd73d066b1c5a6e7a611b9..8ff0e503409bb1e1cb1bbd559ee63533322d0ccc 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/PluginLauncher.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/PluginLauncher.java @@ -16,24 +16,28 @@ package com.gitee.starblues.core.launcher.plugin; +import com.gitee.starblues.core.classloader.*; import com.gitee.starblues.core.descriptor.InsidePluginDescriptor; -import com.gitee.starblues.core.classloader.PluginClassLoader; import com.gitee.starblues.core.launcher.plugin.involved.PluginLaunchInvolved; import com.gitee.starblues.loader.classloader.GenericClassLoader; import com.gitee.starblues.loader.classloader.resource.loader.DefaultResourceLoaderFactory; import com.gitee.starblues.loader.classloader.resource.loader.ResourceLoaderFactory; import com.gitee.starblues.loader.launcher.AbstractLauncher; import com.gitee.starblues.loader.launcher.LauncherContext; +import com.gitee.starblues.spring.MainApplicationContext; import com.gitee.starblues.spring.SpringPluginHook; import com.gitee.starblues.utils.MsgUtils; +import com.gitee.starblues.utils.SpringBeanCustomUtils; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.WeakHashMap; /** * 插件启动引导类 * @author starBlues - * @version 3.0.1 + * @version 3.0.3 */ public class PluginLauncher extends AbstractLauncher { @@ -41,7 +45,7 @@ public class PluginLauncher extends AbstractLauncher { protected final PluginInteractive pluginInteractive; protected final InsidePluginDescriptor pluginDescriptor; - protected final PluginMainResourcePatternDefiner mainResourcePatternDefiner; + protected final MainResourceMatcher mainResourceMatcher; protected final PluginLaunchInvolved pluginLaunchInvolved; @@ -49,10 +53,24 @@ public class PluginLauncher extends AbstractLauncher { PluginLaunchInvolved pluginLaunchInvolved) { this.pluginInteractive = pluginInteractive; this.pluginDescriptor = pluginInteractive.getPluginDescriptor(); - this.mainResourcePatternDefiner = new PluginMainResourcePatternDefiner(pluginInteractive); + this.mainResourceMatcher = getMainResourceMatcher(pluginInteractive); this.pluginLaunchInvolved = pluginLaunchInvolved; } + protected MainResourceMatcher getMainResourceMatcher(PluginInteractive pluginInteractive){ + MainApplicationContext mainApplicationContext = pluginInteractive.getMainApplicationContext(); + // 获取主程序定义的资源匹配 + List mainResourceMatchers = + SpringBeanCustomUtils.getBeans(mainApplicationContext, MainResourceMatcher.class); + + List resourceMatchers = new ArrayList<>(mainResourceMatchers); + // 新增插件定义的资源匹配 + resourceMatchers.add(new DefaultMainResourceMatcher( + new PluginMainResourcePatternDefiner(pluginInteractive) + )); + return new ComposeMainResourceMatcher(resourceMatchers); + } + @Override protected ClassLoader createClassLoader(String... args) throws Exception { PluginClassLoader pluginClassLoader = getPluginClassLoader(); @@ -68,8 +86,7 @@ public class PluginLauncher extends AbstractLauncher { return classLoader; } PluginClassLoader pluginClassLoader = new PluginClassLoader( - pluginId, getParentClassLoader(), mainResourcePatternDefiner, - getResourceLoaderFactory() + pluginId, getParentClassLoader(), getResourceLoaderFactory(), mainResourceMatcher ); CLASS_LOADER_CACHE.put(key, pluginClassLoader); return pluginClassLoader; diff --git a/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/PluginMainResourcePatternDefiner.java b/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/PluginMainResourcePatternDefiner.java index 8772b542c3e8cd3d90184f6b84d07c1d4508e9f3..f32c6b0381f90e03a9e9949825b06fe9eb79c98b 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/PluginMainResourcePatternDefiner.java +++ b/spring-brick/src/main/java/com/gitee/starblues/core/launcher/plugin/PluginMainResourcePatternDefiner.java @@ -16,12 +16,9 @@ package com.gitee.starblues.core.launcher.plugin; +import com.gitee.starblues.core.classloader.MainResourcePatternDefiner; import com.gitee.starblues.core.descriptor.InsidePluginDescriptor; -import com.gitee.starblues.core.launcher.JavaMainResourcePatternDefiner; -import com.gitee.starblues.spring.MainApplicationContext; -import com.gitee.starblues.utils.Assert; import com.gitee.starblues.utils.ObjectUtils; -import com.gitee.starblues.utils.SpringBeanCustomUtils; import java.util.HashSet; import java.util.Set; @@ -29,129 +26,37 @@ import java.util.Set; /** * 定义插件从主程序加载资源的匹配 * @author starBlues - * @version 3.0.0 + * @version 3.0.3 */ -public class PluginMainResourcePatternDefiner extends JavaMainResourcePatternDefiner { +public class PluginMainResourcePatternDefiner implements MainResourcePatternDefiner { - private static final String FRAMEWORK = "com/gitee/starblues/**"; - - public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; - - private final String mainPackage; private final InsidePluginDescriptor descriptor; - private final BasicMainResourcePatternDefiner basicPatternDefiner; public PluginMainResourcePatternDefiner(PluginInteractive pluginInteractive) { - mainPackage = pluginInteractive.getConfiguration().mainPackage(); this.descriptor = pluginInteractive.getPluginDescriptor(); - basicPatternDefiner = getPatternDefiner(pluginInteractive); } @Override public Set getIncludePatterns() { - Set includeResourcePatterns = super.getIncludePatterns(); - Set includePatterns = basicPatternDefiner.getIncludePatterns(); - if(!ObjectUtils.isEmpty(includePatterns)){ - includeResourcePatterns.addAll(includePatterns); - } else { - includeResourcePatterns.add(ObjectUtils.changePackageToMatch(mainPackage)); - } - includeResourcePatterns.add(FRAMEWORK); - addWebIncludeResourcePatterns(includeResourcePatterns); - addApiDoc(includeResourcePatterns); - addDbDriver(includeResourcePatterns); - + Set includeResourcePatterns = new HashSet<>(); // 配置插件自定义从主程序加载的资源匹配 Set includeMainResourcePatterns = descriptor.getIncludeMainResourcePatterns(); - if(ObjectUtils.isEmpty(includeMainResourcePatterns)){ - return includeResourcePatterns; - } - - for (String includeMainResourcePattern : includeMainResourcePatterns) { - if(ObjectUtils.isEmpty(includeMainResourcePattern)){ - continue; - } - includeResourcePatterns.add(includeMainResourcePattern); + if(!ObjectUtils.isEmpty(includeMainResourcePatterns)){ + includeResourcePatterns.addAll(includeMainResourcePatterns); } return includeResourcePatterns; } - - @Override public Set getExcludePatterns() { Set excludeResourcePatterns = new HashSet<>(); - Set excludePatterns = basicPatternDefiner.getExcludePatterns(); - if(!ObjectUtils.isEmpty(excludePatterns)){ - excludeResourcePatterns.addAll(excludePatterns); - } Set excludeMainResourcePatterns = descriptor.getExcludeMainResourcePatterns(); if(!ObjectUtils.isEmpty(excludeMainResourcePatterns)){ excludeResourcePatterns.addAll(excludeMainResourcePatterns); } - excludeResourcePatterns.add(FACTORIES_RESOURCE_LOCATION); return excludeResourcePatterns; } - protected void addWebIncludeResourcePatterns(Set patterns){ - patterns.add("org/springframework/web/**"); - patterns.add("org/springframework/http/**"); - patterns.add("org/springframework/remoting/**"); - patterns.add("org/springframework/ui/**"); - - patterns.add("com/fasterxml/jackson/**"); - - } - - protected void addApiDoc(Set patterns){ - patterns.add("springfox/documentation/**"); - patterns.add("io/swagger/**"); - patterns.add("org/springdoc/**"); - } - - protected void addDbDriver(Set patterns){ - // mysql - patterns.add("com/mysql/**"); - // oracle - patterns.add("oracle/jdbc/**"); - // sqlserver - patterns.add("com/microsoft/jdbc/sqlserver/**"); - // DB2 - patterns.add("com/ibm/db2/jdbc/**"); - // DB2/AS400 - patterns.add("com/ibm/as400/**"); - // Informix - patterns.add("com/informix/jdbc/**"); - // Hypersonic - patterns.add("org/hsql/**"); - // MS SQL - patterns.add("com/microsoft/jdbc/**"); - // Postgres - patterns.add("org/postgresql/**"); - // Sybase - patterns.add("com/sybase/jdbc2/**"); - // Weblogic - patterns.add("weblogic/jdbc/**"); - // h2 - patterns.add("jdbc/h2/**"); - } - - /** - * 获取基本的 MainResourcePatternDefiner - * @param pluginInteractive PluginInteractive - * @return BasicMainResourcePatternDefiner - */ - private BasicMainResourcePatternDefiner getPatternDefiner(PluginInteractive pluginInteractive){ - final MainApplicationContext mainApplicationContext = pluginInteractive.getMainApplicationContext(); - BasicMainResourcePatternDefiner definer = SpringBeanCustomUtils.getExistBean( - mainApplicationContext, BasicMainResourcePatternDefiner.class); - if(definer == null){ - return new BasicMainResourcePatternDefiner(mainPackage); - } else { - return definer; - } - } - } diff --git a/spring-brick/src/main/java/com/gitee/starblues/integration/AutoIntegrationConfiguration.java b/spring-brick/src/main/java/com/gitee/starblues/integration/AutoIntegrationConfiguration.java index 5134ad9517a376a4639b877a1a99a3c9d0819ddc..39e3af8d19f5c50d0ac994b1d7969c0aba1e8a84 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/integration/AutoIntegrationConfiguration.java +++ b/spring-brick/src/main/java/com/gitee/starblues/integration/AutoIntegrationConfiguration.java @@ -32,7 +32,7 @@ import java.util.Set; /** * 自动集成的配置 * @author starBlues - * @version 3.0.1 + * @version 3.0.3 */ @EqualsAndHashCode(callSuper = true) @Component @@ -92,7 +92,7 @@ public class AutoIntegrationConfiguration extends DefaultIntegrationConfiguratio * pluginRestPathPrefix: 为pluginRestPathPrefix的配置值 * pluginId: 为插件id */ - @Value("${pluginRestPathPrefix:true}") + @Value("${enablePluginIdRestPathPrefix:true}") private Boolean enablePluginIdRestPathPrefix; /** diff --git a/spring-brick/src/main/java/com/gitee/starblues/integration/DefaultIntegrationConfiguration.java b/spring-brick/src/main/java/com/gitee/starblues/integration/DefaultIntegrationConfiguration.java index 42a855792e7b7d0737256789ef52cdabfc264e83..b99e55e558570910fed25ffe1c8bf1363b9841ac 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/integration/DefaultIntegrationConfiguration.java +++ b/spring-brick/src/main/java/com/gitee/starblues/integration/DefaultIntegrationConfiguration.java @@ -16,6 +16,7 @@ package com.gitee.starblues.integration; +import com.gitee.starblues.common.Constants; import com.gitee.starblues.integration.decrypt.DecryptConfiguration; import com.gitee.starblues.utils.Assert; @@ -83,7 +84,7 @@ public abstract class DefaultIntegrationConfiguration implements IntegrationConf @Override public String version() { - return "0.0.0"; + return Constants.ALLOW_VERSION; } @Override diff --git a/spring-brick/src/main/java/com/gitee/starblues/integration/ExtendPointConfiguration.java b/spring-brick/src/main/java/com/gitee/starblues/integration/ExtendPointConfiguration.java index cd7944e6adcc59835e530ff73441088b3a669978..79f43b55d80bb4cdfd758404576d175402c7536f 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/integration/ExtendPointConfiguration.java +++ b/spring-brick/src/main/java/com/gitee/starblues/integration/ExtendPointConfiguration.java @@ -18,15 +18,19 @@ package com.gitee.starblues.integration; import com.gitee.starblues.core.DefaultRealizeProvider; import com.gitee.starblues.core.RealizeProvider;; +import com.gitee.starblues.core.classloader.CacheMainResourceMatcher; +import com.gitee.starblues.core.classloader.MainResourceMatcher; import com.gitee.starblues.core.descriptor.decrypt.DefaultPluginDescriptorDecrypt; import com.gitee.starblues.core.descriptor.decrypt.PluginDescriptorDecrypt; import com.gitee.starblues.core.launcher.plugin.BasicMainResourcePatternDefiner; +import com.gitee.starblues.core.launcher.plugin.DefaultMainResourcePatternDefiner; import com.gitee.starblues.integration.operator.DefaultPluginOperator; import com.gitee.starblues.integration.operator.PluginOperator; import com.gitee.starblues.integration.operator.PluginOperatorWrapper; import com.gitee.starblues.integration.user.DefaultPluginUser; import com.gitee.starblues.integration.user.PluginUser; import com.gitee.starblues.spring.extract.ExtractFactory; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.*; import org.springframework.context.annotation.Bean; import org.springframework.context.support.GenericApplicationContext; @@ -34,7 +38,7 @@ import org.springframework.context.support.GenericApplicationContext; /** * 系统Bean配置 * @author starBlues - * @version 3.0.1 + * @version 3.0.3 */ public class ExtendPointConfiguration { @@ -78,9 +82,11 @@ public class ExtendPointConfiguration { } @Bean - @ConditionalOnMissingBean - public BasicMainResourcePatternDefiner mainResourcePatternDefiner(){ - return new BasicMainResourcePatternDefiner(configuration.mainPackage()); + public MainResourceMatcher mainResourceMatcher(){ + return new CacheMainResourceMatcher(new DefaultMainResourcePatternDefiner( + configuration.mainPackage(), + applicationContext + )); } @Bean diff --git a/spring-brick/src/main/java/com/gitee/starblues/integration/ExtendPointWebConfiguration.java b/spring-brick/src/main/java/com/gitee/starblues/integration/ExtendPointWebConfiguration.java index e1e197d57fcb14aba5bb0cbabf9f0607d70ab25c..9c198e3793606b04624cba07dff84ccddc9ef354 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/integration/ExtendPointWebConfiguration.java +++ b/spring-brick/src/main/java/com/gitee/starblues/integration/ExtendPointWebConfiguration.java @@ -17,6 +17,7 @@ package com.gitee.starblues.integration; import com.gitee.starblues.integration.listener.SwaggerListener; +import com.gitee.starblues.spring.ResolvePluginThreadClassLoader; import com.gitee.starblues.spring.web.PluginStaticResourceConfig; import com.gitee.starblues.spring.web.PluginStaticResourceWebMvcConfigurer; import com.gitee.starblues.spring.web.thymeleaf.PluginThymeleafInvolved; @@ -27,6 +28,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.resource.ResourceResolver; import org.thymeleaf.spring5.SpringTemplateEngine; import org.thymeleaf.templatemode.TemplateMode; @@ -90,4 +92,9 @@ public class ExtendPointWebConfiguration { } + @Bean + public WebMvcConfigurer webMvcConfigurer(){ + return new ResolvePluginThreadClassLoader(); + } + } diff --git a/spring-brick/src/main/java/com/gitee/starblues/integration/listener/DefaultPluginListenerFactory.java b/spring-brick/src/main/java/com/gitee/starblues/integration/listener/DefaultPluginListenerFactory.java index 070659afdfccaebd7b538cb934a5915d47a74d26..bce94ea8b3c3aa4e7958eb8c3d0f0240f7988048 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/integration/listener/DefaultPluginListenerFactory.java +++ b/spring-brick/src/main/java/com/gitee/starblues/integration/listener/DefaultPluginListenerFactory.java @@ -27,7 +27,8 @@ import java.util.List; /** * 默认的插件工厂 * @author starBlues - * @version 3.0.0 + * @since 3.0.0 + * @version 3.0.3 */ public class DefaultPluginListenerFactory implements PluginListenerFactory{ @@ -35,7 +36,6 @@ public class DefaultPluginListenerFactory implements PluginListenerFactory{ public DefaultPluginListenerFactory(ApplicationContext applicationContext){ listeners = new ArrayList<>(); - addPluginListener(new SwaggerListener(applicationContext)); addExtendPluginListener(applicationContext); } diff --git a/spring-brick/src/main/java/com/gitee/starblues/integration/listener/SwaggerListener.java b/spring-brick/src/main/java/com/gitee/starblues/integration/listener/SwaggerListener.java index a8b40099c9b34228ddea661e97e8b6cf739db612..a75d6fbadfa07cd2fee27ba68cf37c2899310357 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/integration/listener/SwaggerListener.java +++ b/spring-brick/src/main/java/com/gitee/starblues/integration/listener/SwaggerListener.java @@ -17,43 +17,121 @@ package com.gitee.starblues.integration.listener; import com.gitee.starblues.core.PluginInfo; +import com.gitee.starblues.core.descriptor.PluginDescriptor; +import com.gitee.starblues.loader.utils.ObjectUtils; +import com.gitee.starblues.utils.MsgUtils; import com.gitee.starblues.utils.SpringBeanUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; +import org.springframework.plugin.core.PluginRegistry; +import org.springframework.plugin.core.PluginRegistrySupport; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.service.Parameter; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.DocumentationPlugin; +import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + /** * Swagger 监听事件 * @author starBlues - * @version 3.0.0 + * @since 3.0.0 + * @version 3.0.3 */ public class SwaggerListener implements PluginListener{ private final Logger log = LoggerFactory.getLogger(this.getClass()); private final ApplicationContext mainApplicationContext; + private static List parameterList = new ArrayList<>(); + + /** + * 设置全局头部/参数 + * ParameterBuilder tokenPar = new ParameterBuilder(); + * tokenPar.name("参数名称") + * .description("参数描述") + * .modelRef(new ModelRef("参数数据类型")) + * .parameterType("header或者query等") + * .required(false); + * Parameter param = tokenPar.build(); + * @param parameters parameters + */ + public static void setParameters(List parameters){ + parameterList = parameters; + } + public SwaggerListener(ApplicationContext mainApplicationContext) { this.mainApplicationContext = mainApplicationContext; } @Override public void startSuccess(PluginInfo pluginInfo) { - if(pluginInfo.isFollowSystem()){ - return; + PluginDescriptor descriptor = pluginInfo.getPluginDescriptor(); + Docket docket = this.createDocket(descriptor); + String groupName = docket.getGroupName(); + PluginRegistry pluginRegistry = this.getPluginRegistry(); + List plugins = pluginRegistry.getPlugins(); + List newPlugins = new ArrayList<>(); + for(DocumentationPlugin plugin : plugins){ + if(plugin.getGroupName().equals(groupName)){ + continue; + } + newPlugins.add(plugin); + } + newPlugins.add(docket); + try { + Field field = PluginRegistrySupport.class.getDeclaredField("plugins"); + field.setAccessible(true); + field.set(pluginRegistry, newPlugins); + // 如果第一次启动且为跟随系统启动的插件,减少刷新 + if(!pluginInfo.isFollowSystem() || pluginInfo.getStopTime() != null){ + this.refresh(); + } + log.debug("插件[{}]注册到 Swagger 成功", pluginInfo.getPluginId()); + } catch (NoSuchFieldException | IllegalAccessException e) { + log.error("插件[{}]注册到 Swagger 失败,错误为:{}", pluginInfo.getPluginId(),e.getMessage()); } - refresh(); } @Override public void stopSuccess(PluginInfo pluginInfo) { - refresh(); + PluginDescriptor descriptor = pluginInfo.getPluginDescriptor(); + String groupName = getGroupName(descriptor); + + PluginRegistry pluginRegistry = this.getPluginRegistry(); + List plugins = pluginRegistry.getPlugins(); + List newPlugins = new ArrayList<>(); + for(DocumentationPlugin plugin : plugins){ + if(groupName.equalsIgnoreCase(plugin.getGroupName())){ + continue; + } + newPlugins.add(plugin); + } + try{ + Field field = PluginRegistrySupport.class.getDeclaredField("plugins"); + field.setAccessible(true); + field.set(pluginRegistry, newPlugins); + + this.refresh(); + log.debug("插件[{}]从 Swagger 移除成功", MsgUtils.getPluginUnique(descriptor)); + } + catch (NoSuchFieldException | IllegalAccessException e) { + log.error("插件[{}]从 Swagger 移除失败,错误为:{}", MsgUtils.getPluginUnique(descriptor), e.getMessage()); + } } void refresh(){ try { - DocumentationPluginsBootstrapper documentationPluginsBootstrapper = SpringBeanUtils.getExistBean(mainApplicationContext, - DocumentationPluginsBootstrapper.class); + DocumentationPluginsBootstrapper documentationPluginsBootstrapper = this.getDocumentationPluginsBootstrapper(); if(documentationPluginsBootstrapper != null){ documentationPluginsBootstrapper.stop(); documentationPluginsBootstrapper.start(); @@ -62,8 +140,67 @@ public class SwaggerListener implements PluginListener{ } } catch (Exception e){ // ignore - log.warn("refresh swagger failure"); + log.warn("refresh swagger failure. {}", e.getMessage()); } } + /** + * 获取文档 Bootstrapper + * @return DocumentationPluginsBootstrapper + */ + private DocumentationPluginsBootstrapper getDocumentationPluginsBootstrapper(){ + return SpringBeanUtils.getExistBean(mainApplicationContext, DocumentationPluginsBootstrapper.class); + } + + /** + * 获取文档PluginRegistry + * @return PluginRegistry + */ + private PluginRegistry getPluginRegistry(){ + return SpringBeanUtils.getExistBean(mainApplicationContext,"documentationPluginRegistry"); + } + + /** + * 创建swagger分组对象 + * + * @param descriptor 插件信息 + * @return Docket + */ + private Docket createDocket(PluginDescriptor descriptor) { + String description = descriptor.getDescription(); + if (ObjectUtils.isEmpty(description)) { + description = descriptor.getPluginId(); + } + + String provider = descriptor.getProvider(); + String pluginBootstrapClass = descriptor.getPluginBootstrapClass(); + String pluginClass = pluginBootstrapClass.substring(0, pluginBootstrapClass.lastIndexOf(".")); + Contact contact = new Contact(provider, "", ""); + ApiInfo apiInfo = new ApiInfoBuilder() + .title(getGroupName(descriptor)) + .description(description) + .contact(contact) + .version(descriptor.getPluginVersion()) + .build(); + + Docket docket = (new Docket(DocumentationType.SWAGGER_2)) + .apiInfo(apiInfo).select() + .apis(RequestHandlerSelectors.basePackage(pluginClass)) + .paths(PathSelectors.any()).build() + .groupName(getGroupName(descriptor)); + + if(parameterList != null && !parameterList.isEmpty()){ + return docket.globalOperationParameters(parameterList); + } + return docket; + } + + /** + * 获取组名称 + * @param descriptor 插件信息 + * @return 分组信息 + */ + private String getGroupName(PluginDescriptor descriptor){ + return descriptor.getPluginId() +"@" + descriptor.getPluginVersion(); + } } diff --git a/spring-brick/src/main/java/com/gitee/starblues/integration/user/DefaultPluginUser.java b/spring-brick/src/main/java/com/gitee/starblues/integration/user/DefaultPluginUser.java index d63c7053293e7ecb19796d31dd123b10b31754af..a4a1389c20c3a34842a1d4d158dfab9dfe61b872 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/integration/user/DefaultPluginUser.java +++ b/spring-brick/src/main/java/com/gitee/starblues/integration/user/DefaultPluginUser.java @@ -25,6 +25,7 @@ import com.gitee.starblues.utils.SpringBeanCustomUtils; import org.springframework.context.support.GenericApplicationContext; import java.lang.annotation.Annotation; +import java.lang.reflect.Modifier; import java.util.*; /** @@ -148,7 +149,8 @@ public class DefaultPluginUser implements PluginUser{ * @param clazz clazz */ private void checkInterface(Class clazz) { - if (clazz.isInterface()) { + int modifiers = clazz.getModifiers(); + if (Modifier.isInterface(modifiers)|| Modifier.isAbstract(clazz.getModifiers())) { return; } throw new PluginException("[" + clazz.getName() + "]不是一个接口"); diff --git a/spring-brick/src/main/java/com/gitee/starblues/spring/MainApplicationContext.java b/spring-brick/src/main/java/com/gitee/starblues/spring/MainApplicationContext.java index d7017a0c1d8cca17583fd3dd862e6c18fae45dd3..b143ef55b6387454eabb5e143d605dacd86eddb5 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/spring/MainApplicationContext.java +++ b/spring-brick/src/main/java/com/gitee/starblues/spring/MainApplicationContext.java @@ -16,6 +16,8 @@ package com.gitee.starblues.spring; +import com.gitee.starblues.spring.environment.EnvironmentProvider; + import java.util.Map; /** @@ -32,4 +34,28 @@ public interface MainApplicationContext extends ApplicationContext { */ Map> getConfigurableEnvironment(); + + /** + * 得到主程序配置的 Provider + * @return EnvironmentProvider + */ + EnvironmentProvider getEnvironmentProvider(); + + + /** + * 从主程序获取依赖 + * + * @param requestingBeanName 依赖Bean名称 + * @param dependencyType 依赖类型 + * @return boolean + */ + Object resolveDependency(String requestingBeanName, Class dependencyType); + + /** + * 是否为web环境 + * @return boolean + */ + boolean isWebEnvironment(); + + } diff --git a/spring-brick/src/main/java/com/gitee/starblues/spring/MainApplicationContextProxy.java b/spring-brick/src/main/java/com/gitee/starblues/spring/MainApplicationContextProxy.java index b77d4a3b610a8cc4a2f2c9aa528699b0aa2f2db3..4c5b61bb2845a310b424f0dab2bd7f4d03690ec1 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/spring/MainApplicationContextProxy.java +++ b/spring-brick/src/main/java/com/gitee/starblues/spring/MainApplicationContextProxy.java @@ -16,6 +16,11 @@ package com.gitee.starblues.spring; +import com.gitee.starblues.spring.environment.EnvironmentProvider; +import com.gitee.starblues.spring.environment.MainSpringBootEnvironmentProvider; +import com.gitee.starblues.utils.ObjectUtils; +import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; +import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.EnumerablePropertySource; @@ -34,15 +39,19 @@ import java.util.Map; public class MainApplicationContextProxy extends ApplicationContextProxy implements MainApplicationContext{ private final GenericApplicationContext applicationContext; + private final boolean isWebEnvironment; public MainApplicationContextProxy(GenericApplicationContext applicationContext) { super(applicationContext.getBeanFactory()); this.applicationContext = applicationContext; + this.isWebEnvironment = getIsWebEnvironment(applicationContext); } - public MainApplicationContextProxy(GenericApplicationContext applicationContext, AutoCloseable autoCloseable) { + public MainApplicationContextProxy(GenericApplicationContext applicationContext, + AutoCloseable autoCloseable) { super(applicationContext.getBeanFactory(), autoCloseable); this.applicationContext = applicationContext; + this.isWebEnvironment = getIsWebEnvironment(applicationContext); } @Override @@ -67,4 +76,28 @@ public class MainApplicationContextProxy extends ApplicationContextProxy impleme return environmentMap; } + @Override + public EnvironmentProvider getEnvironmentProvider() { + return new MainSpringBootEnvironmentProvider(applicationContext.getEnvironment()); + } + + @Override + public Object resolveDependency(String requestingBeanName, Class dependencyType) { + try { + return applicationContext.getBean(dependencyType); + } catch (Exception e){ + return null; + } + } + + @Override + public boolean isWebEnvironment() { + return isWebEnvironment; + } + + private boolean getIsWebEnvironment(GenericApplicationContext applicationContext){ + return applicationContext instanceof AnnotationConfigServletWebServerApplicationContext + || applicationContext instanceof AnnotationConfigReactiveWebServerApplicationContext; + } + } diff --git a/spring-brick/src/main/java/com/gitee/starblues/spring/ResolvePluginThreadClassLoader.java b/spring-brick/src/main/java/com/gitee/starblues/spring/ResolvePluginThreadClassLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..f2191e979eb299e02512579b140d724fb94bbe41 --- /dev/null +++ b/spring-brick/src/main/java/com/gitee/starblues/spring/ResolvePluginThreadClassLoader.java @@ -0,0 +1,71 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.spring; + +import com.gitee.starblues.loader.classloader.GenericClassLoader; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 解决插件线程中的ClassLoader + * + * @author starBlues + * @version 3.0.3 + */ +public class ResolvePluginThreadClassLoader implements WebMvcConfigurer { + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new ResolveHandlerInterceptor()).addPathPatterns("/**"); + } + + private static class ResolveHandlerInterceptor implements HandlerInterceptor { + + private final ThreadLocal oldClassLoader = new ThreadLocal<>(); + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if(handler instanceof HandlerMethod){ + HandlerMethod handlerMethod = (HandlerMethod) handler; + ClassLoader classLoader = handlerMethod.getBeanType().getClassLoader(); + if(classLoader instanceof GenericClassLoader){ + oldClassLoader.set(Thread.currentThread().getContextClassLoader()); + Thread.currentThread().setContextClassLoader(classLoader); + } + } + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + try { + ClassLoader classLoader = oldClassLoader.get(); + if(classLoader != null){ + Thread.currentThread().setContextClassLoader(classLoader); + } + } finally { + oldClassLoader.remove(); + } + } + } + +} diff --git a/spring-brick/src/main/java/com/gitee/starblues/spring/SpringBeanFactory.java b/spring-brick/src/main/java/com/gitee/starblues/spring/SpringBeanFactory.java index 8830eed81e85d88f54c787733e25aa814f7a1a8c..545728f1059c6cbed658b04aed8c874d46d27cee 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/spring/SpringBeanFactory.java +++ b/spring-brick/src/main/java/com/gitee/starblues/spring/SpringBeanFactory.java @@ -21,7 +21,9 @@ import org.springframework.beans.factory.ListableBeanFactory; /** * spring bean factory 封装接口 * @author starBlues + * @since 3.0.0 * @version 3.0.0 */ public interface SpringBeanFactory extends ListableBeanFactory { + } diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/EmptyMainEnvironmentProvider.java b/spring-brick/src/main/java/com/gitee/starblues/spring/environment/EmptyEnvironmentProvider.java similarity index 75% rename from spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/EmptyMainEnvironmentProvider.java rename to spring-brick/src/main/java/com/gitee/starblues/spring/environment/EmptyEnvironmentProvider.java index 8180226fff2cf9e92bb7b7ba1e5fd56c0ca417c0..69ca692d1c4d327f9d42bcdf4cbba9f9c4f65922 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/EmptyMainEnvironmentProvider.java +++ b/spring-brick/src/main/java/com/gitee/starblues/spring/environment/EmptyEnvironmentProvider.java @@ -14,18 +14,19 @@ * limitations under the License. */ -package com.gitee.starblues.bootstrap.realize; +package com.gitee.starblues.spring.environment; -import java.util.Collections; -import java.util.Map; +import java.util.function.BiConsumer; /** - * 主程序配置信息提供者空值实现 + * 空的配置信息提供者 * * @author starBlues - * @version 3.0.0 + * @version 3.0.3 */ -public class EmptyMainEnvironmentProvider implements MainEnvironmentProvider{ +public class EmptyEnvironmentProvider implements EnvironmentProvider{ + + @Override public Object getValue(String name) { return null; @@ -62,7 +63,12 @@ public class EmptyMainEnvironmentProvider implements MainEnvironmentProvider{ } @Override - public Map> getAll() { - return Collections.emptyMap(); + public EnvironmentProvider getByPrefix(String prefix) { + return new EmptyEnvironmentProvider(); + } + + @Override + public void forEach(BiConsumer action) { + } } diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/MainEnvironmentProvider.java b/spring-brick/src/main/java/com/gitee/starblues/spring/environment/EnvironmentProvider.java similarity index 80% rename from spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/MainEnvironmentProvider.java rename to spring-brick/src/main/java/com/gitee/starblues/spring/environment/EnvironmentProvider.java index ea68a164bec6f04e3b4c5e32c73b51c1f778c8b6..a4e1facb83aa4f4340098a90b66e4d9b5c90abc8 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/MainEnvironmentProvider.java +++ b/spring-brick/src/main/java/com/gitee/starblues/spring/environment/EnvironmentProvider.java @@ -14,17 +14,17 @@ * limitations under the License. */ -package com.gitee.starblues.bootstrap.realize; +package com.gitee.starblues.spring.environment; -import java.util.Map; +import java.util.function.BiConsumer; /** - * 主程序配置信息提供者 + * 配置信息提供者接口 * * @author starBlues - * @version 3.0.0 + * @version 3.0.3 */ -public interface MainEnvironmentProvider { +public interface EnvironmentProvider { /** * 根据名称获取配置值 @@ -75,10 +75,18 @@ public interface MainEnvironmentProvider { */ Boolean getBoolean(String name); + /** + * 根据前缀名称批量获取配置值 + * @param prefix 前缀 + * @return 环境 + */ + EnvironmentProvider getByPrefix(String prefix); + /** * 获取所有配置集合 - * @return Map + * @param action 每个条目执行的操作 */ - Map> getAll(); + void forEach(BiConsumer action); + } diff --git a/spring-brick/src/main/java/com/gitee/starblues/spring/environment/MainSpringBootEnvironmentProvider.java b/spring-brick/src/main/java/com/gitee/starblues/spring/environment/MainSpringBootEnvironmentProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..84106b311e1410101e580cb9460a4cc1130fcae4 --- /dev/null +++ b/spring-brick/src/main/java/com/gitee/starblues/spring/environment/MainSpringBootEnvironmentProvider.java @@ -0,0 +1,108 @@ +/** + * Copyright [2019-2022] [starBlues] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitee.starblues.spring.environment; + +import com.gitee.starblues.utils.ObjectUtils; +import com.gitee.starblues.utils.ObjectValueUtils; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.BiConsumer; + +/** + * 主程序配置信息提供者实现 + * + * @author starBlues + * @version 3.0.3 + */ +public class MainSpringBootEnvironmentProvider implements EnvironmentProvider { + + private final ConfigurableEnvironment environment; + + public MainSpringBootEnvironmentProvider(ConfigurableEnvironment environment) { + this.environment = environment; + } + + @Override + public Object getValue(String name) { + MutablePropertySources propertySources = environment.getPropertySources(); + for (PropertySource propertySource : propertySources) { + Object property = propertySource.getProperty(name); + if (property != null) { + return property; + } + } + return null; + } + + @Override + public String getString(String name) { + return ObjectValueUtils.getString(getValue(name)); + } + + @Override + public Integer getInteger(String name) { + return ObjectValueUtils.getInteger(getValue(name)); + } + + @Override + public Long getLong(String name) { + return ObjectValueUtils.getLong(getValue(name)); + } + + @Override + public Double getDouble(String name) { + return ObjectValueUtils.getDouble(getValue(name)); + } + + @Override + public Float getFloat(String name) { + return ObjectValueUtils.getFloat(getValue(name)); + } + + @Override + public Boolean getBoolean(String name) { + return ObjectValueUtils.getBoolean(getValue(name)); + } + + @Override + public EnvironmentProvider getByPrefix(String prefix) { + if(ObjectUtils.isEmpty(prefix)){ + return new EmptyEnvironmentProvider(); + } + Map collect = new LinkedHashMap<>(); + MutablePropertySources propertySources = environment.getPropertySources(); + for (PropertySource propertySource : propertySources) { + String name = propertySource.getName(); + if(name.startsWith(prefix)){ + collect.put(MapEnvironmentProvider.resolveKey(prefix, name), propertySource.getSource()); + } + } + return new MapEnvironmentProvider(collect); + } + + @Override + public void forEach(BiConsumer action) { + MutablePropertySources propertySources = environment.getPropertySources(); + for (PropertySource propertySource : propertySources) { + action.accept(propertySource.getName(), propertySource.getSource()); + } + } +} diff --git a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/DefaultMainEnvironmentProvider.java b/spring-brick/src/main/java/com/gitee/starblues/spring/environment/MapEnvironmentProvider.java similarity index 36% rename from spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/DefaultMainEnvironmentProvider.java rename to spring-brick/src/main/java/com/gitee/starblues/spring/environment/MapEnvironmentProvider.java index f71a363c300da964609be23baf3ff280501803e7..6a25cb14b55eba3eeafdd791377eacab9c3ec777 100644 --- a/spring-brick-bootstrap/src/main/java/com/gitee/starblues/bootstrap/realize/DefaultMainEnvironmentProvider.java +++ b/spring-brick/src/main/java/com/gitee/starblues/spring/environment/MapEnvironmentProvider.java @@ -14,94 +14,106 @@ * limitations under the License. */ -package com.gitee.starblues.bootstrap.realize; +package com.gitee.starblues.spring.environment; -import com.gitee.starblues.loader.utils.ObjectUtils; -import com.gitee.starblues.spring.MainApplicationContext; -import com.gitee.starblues.utils.MapValueGetter; +import com.gitee.starblues.utils.ObjectUtils; +import com.gitee.starblues.utils.ObjectValueUtils; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.Map; -import java.util.function.Function; +import java.util.function.BiConsumer; /** - * 主程序配置信息提供者默认实现 + * map类型的配置信息提供者 * * @author starBlues - * @version 3.0.0 + * @version 3.0.3 */ -public class DefaultMainEnvironmentProvider implements MainEnvironmentProvider{ +public class MapEnvironmentProvider implements EnvironmentProvider{ - private final MainApplicationContext mainApplicationContext; + private final String prefix; + private final Map source; - public DefaultMainEnvironmentProvider(MainApplicationContext mainApplicationContext) { - this.mainApplicationContext = mainApplicationContext; + public MapEnvironmentProvider(Map source){ + this(null, source); } - @Override - public Object getValue(String name) { - Map> configurableEnvironment = mainApplicationContext.getConfigurableEnvironment(); - if(ObjectUtils.isEmpty(configurableEnvironment)){ - return null; + public MapEnvironmentProvider(String prefix, Map source) { + if(prefix == null){ + this.prefix = ""; + } else { + this.prefix = prefix; } - for (Map.Entry> entry : configurableEnvironment.entrySet()) { - Map value = entry.getValue(); - Object o = value.get(name); - if(o != null){ - return o; - } + if(ObjectUtils.isEmpty(source)){ + this.source = Collections.emptyMap(); + } else { + this.source = source; + } + } + + public static String resolveKey(String prefix, String name){ + String key = name.replace(prefix, ""); + int i = key.indexOf("."); + if(i > -1){ + key = key.substring(i + 1); } - return null; + return key; + } + + @Override + public Object getValue(String name) { + String key = prefix + name; + return source.get(key); } @Override public String getString(String name) { - return getMapValueGetter(name).getString(name); + return ObjectValueUtils.getString(getValue(name)); } @Override public Integer getInteger(String name) { - return getMapValueGetter(name).getInteger(name); + return ObjectValueUtils.getInteger(getValue(name)); } @Override public Long getLong(String name) { - return getMapValueGetter(name).getLong(name); + return ObjectValueUtils.getLong(getValue(name)); } @Override public Double getDouble(String name) { - return getMapValueGetter(name).getDouble(name); + return ObjectValueUtils.getDouble(getValue(name)); } @Override public Float getFloat(String name) { - return getMapValueGetter(name).getFloat(name); + return ObjectValueUtils.getFloat(getValue(name)); } @Override public Boolean getBoolean(String name) { - return getMapValueGetter(name).getBoolean(name); + return ObjectValueUtils.getBoolean(getValue(name)); } @Override - public Map> getAll() { - return mainApplicationContext.getConfigurableEnvironment(); - } - - private MapValueGetter getMapValueGetter(String name) { - Map> configurableEnvironment = mainApplicationContext.getConfigurableEnvironment(); - if(ObjectUtils.isEmpty(configurableEnvironment)){ - return new MapValueGetter(Collections.emptyMap()); + public EnvironmentProvider getByPrefix(String prefix) { + if(ObjectUtils.isEmpty(prefix)){ + return new EmptyEnvironmentProvider(); } - for (Map.Entry> entry : configurableEnvironment.entrySet()) { - Map value = entry.getValue(); - if(value.containsKey(name)){ - return new MapValueGetter(value); + Map collect = new LinkedHashMap<>(); + source.forEach((k,v)->{ + if(k.startsWith(prefix)){ + collect.put(resolveKey(prefix, k), v); } - } - return new MapValueGetter(Collections.emptyMap()); + }); + return new MapEnvironmentProvider(collect); } + @Override + public void forEach(BiConsumer action) { + source.forEach(action); + } } diff --git a/spring-brick/src/main/java/com/gitee/starblues/spring/web/PluginStaticResourceResolver.java b/spring-brick/src/main/java/com/gitee/starblues/spring/web/PluginStaticResourceResolver.java index b923cde29c9bc2ba05aeda8d1210235ebb671045..3a2d192d20ef505ed637d20932f6d4839892c66e 100644 --- a/spring-brick/src/main/java/com/gitee/starblues/spring/web/PluginStaticResourceResolver.java +++ b/spring-brick/src/main/java/com/gitee/starblues/spring/web/PluginStaticResourceResolver.java @@ -106,8 +106,18 @@ public class PluginStaticResourceResolver extends AbstractResourceResolver { // 存在后缀 return null; } - partialPath = UrlUtils.joiningUrlPath(partialPath, indexPageName); - return findResource(pluginResource, partialPath); + + // 查找第一级节点,找不到则读取根index.html + if(partialPath.contains(UrlUtils.PATH_SEPARATOR)){ + partialPath = partialPath.substring(0, partialPath.indexOf(UrlUtils.PATH_SEPARATOR)); + } + // 第一级节点 + resource = findResource(pluginResource, UrlUtils.joiningUrlPath(partialPath, indexPageName)); + if(resource != null){ + return resource; + } + // 根节点 + return findResource(pluginResource, UrlUtils.joiningUrlPath(UrlUtils.PATH_SEPARATOR, indexPageName)); } } @@ -144,7 +154,11 @@ public class PluginStaticResourceResolver extends AbstractResourceResolver { PluginResource resource = new PluginResource(classPath + partialPath, pluginResource.getPluginDescriptor()); resource.setClassLoader(pluginClassLoader); if(resource.exists()){ - return resource; + // 确保资源为文件 + File file = resource.getFile(); + if(file != null && file.isFile()){ + return resource; + } } } catch (Exception e){ logger.debug("Get static resources of classpath '{}' error.", classPath, e); diff --git a/update.md b/update.md index f2ee7f572cab55d8b8c99fdee742d857ab76c4b7..6bbe377578eb573664e693f3fa5193b7283d6946 100644 --- a/update.md +++ b/update.md @@ -1,7 +1,20 @@ -1. 新增 `xx-outer、dir` 打包类型的插件可自定义依赖目录 -2. 新增`includeSystemScope`、`type=main` 打包属性 -3. 修复插件拦截器无法拦截不存在的url -4. 修复主程序在 `jar-outer` 打包模式后无法启动问题 -5. 修复插件首次安装时异常 -6. fix https://gitee.com/starblues/springboot-plugin-framework-parent/issues/I53K4G -7. fix https://gitee.com/starblues/springboot-plugin-framework-parent/issues/I53T9W \ No newline at end of file +1. 【新增[#I58CDB]([#I58CDB](https://gitee.com/starblues/springboot-plugin-framework-parent/issues/I58CDB))】 插件可触发`WebServerInitializedEvent`类型的事件 +2. 【新增】插件`dev`模式打包, 新增`localJars`配置(配置本地`jar`依赖文件) +3. 【新增】插件新增`@AutowiredType`注解, 可指定依赖注入类型 +4. 【新增】支持插件`Controller`可不配置地址前缀(配置后会影响插件拦截器和静态资源访问) +5. 【新增】新增`PluginContextHolder`, 使用方式见文档: [PluginContextHolder使用说明](https://www.yuque.com/starblues/spring-brick-3.0.0/un3cic) +6. 【优化】优化静态资源文件加载问题 +7. 【优化】优化插件在某些版本的`idea`中缺失`debug`包, 导致无法`debug` +8. 【优化】优化从主程序依赖加载`Class`资源模块 +9. 【优化】优化插件中注入异常提示 +10. 【优化】优化`Swagger`相关功能 +11. 【修复】`enablePluginIdRestPathPrefix`不生效问题 +12. 【修复】插件无法注入`ObjectProvider`、`ObjectFactory`类型为主程序的`Bean` +13. 【修复[#I58CDB](https://gitee.com/starblues/springboot-plugin-framework-parent/issues/I58CDB)】 插件`Controller`使用`Aop`后, 获取不到参数 +14. 【修复[#I58GCI](https://gitee.com/starblues/springboot-plugin-framework-parent/issues/I58GCI)】 主程序打包参数`libDir`不生效问题 +15. 【修复】修复主程序配置`version`, 插件未配置`requires`导致出现版本校验失败的问题 +16. 【修复】修复`StopValidator`禁止插件停止时, 插件状态变为`STOPPED_FAILURE`问题 +17. 【修复】解决`jdk17`反射问题, 导致无法注册插件`Controller`问题 + + +- 注意: 本次升级后, 从主程序注入的`Bean`, 需设置注入类型, 详见文档: [插件中注入主程序Bean说明](https://www.yuque.com/starblues/spring-brick-3.0.0/vot8gg) \ No newline at end of file