我不久前找到了解决方案,但我忘了在这里分享,所以感谢 Jan 提醒我。
我通过使用具有不同配置的新 Web 应用程序上下文创建和注册多个调度程序 servlet 来解决这个问题(存储库RestMvcConfiguration)和一个公共父级,它是 Spring Boot 应用程序的根应用程序上下文。为了根据类路径中包含的不同 jar 自动启用 API 模块,我或多或少模拟了 Spring Boot 的功能。
该项目分为几个 gradle 模块。像这样的东西:
- 项目服务器
- 项目-api-自动配置
- 项目模块 a-api
- 项目模块 b-api
- ...
- 项目模块 n-api
该模块项目服务器是主要的。它声明了对项目-api-自动配置,同时它排除了传递依赖项目-api-自动配置 on 项目模块-?-api 模块.
Inside 项目服务器.gradle:
dependencies {
compile (project(':project-api-autoconfigure')) {
exclude module: 'project-module-a-api'
exclude module: 'project-module-b-api'
...
}
...
}
项目-api-自动配置依赖于所有 API 模块,因此依赖关系将如下所示项目-api-自动配置.gradle:
dependencies {
compile project(':project-module-a-api')
compile project(':project-module-b-api')
...
}
项目-api-自动配置是我为每个 API 模块创建具有自己的 Web 应用程序上下文的调度程序 servlet bean 的地方,但此配置以位于每个 API 模块 jar 内的每个 API 模块的配置类为条件。
我创建了每个自动配置类继承的抽象类:
public abstract class AbstractApiModuleAutoConfiguration<T> {
@Autowired
protected ApplicationContext applicationContext;
@Autowired
protected ServerProperties server;
@Autowired(required = false)
protected MultipartConfigElement multipartConfig;
@Value("${project.rest.base-api-path}")
protected String baseApiPath;
protected DispatcherServlet createApiModuleDispatcherServlet() {
AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
webContext.setParent(applicationContext);
webContext.register(getApiModuleConfigurationClass());
return new DispatcherServlet(webContext);
}
protected ServletRegistrationBean createApiModuleDispatcherServletRegistration(DispatcherServlet apiModuleDispatcherServlet) {
ServletRegistrationBean registration = new ServletRegistrationBean(
apiModuleDispatcherServlet,
this.server.getServletMapping() + baseApiPath + "/" + getApiModulePath() + "/*");
registration.setName(getApiModuleDispatcherServletBeanName());
if (this.multipartConfig != null) {
registration.setMultipartConfig(this.multipartConfig);
}
return registration;
}
protected abstract String getApiModuleDispatcherServletBeanName();
protected abstract String getApiModulePath();
protected abstract Class<T> getApiModuleConfigurationClass();
}
现在,模块 A 的自动配置类将如下所示:
@Configuration
@ConditionalOnClass(ApiModuleAConfiguration.class)
@ConditionalOnProperty(prefix = "project.moduleA.", value = "enabled")
public class ApiModuleAAutoConfiguration extends AbstractApiModuleAutoConfiguration<ApiModuleAConfiguration> {
public static final String API_MODULE_A_DISPATCHER_SERVLET_BEAN_NAME = "apiModuleADispatcherServlet";
public static final String API_MODULE_A_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "apiModuleADispatcherServletRegistration";
@Value("${project.moduleA.path}")
private String apiModuleAPath;
@Bean(name = API_MODULE_A_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet apiModuleADispatcherServlet() {
return createApiModuleDispatcherServlet();
}
@Bean(name = API_MODULE_A_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
public ServletRegistrationBean apiModuleADispatcherServletRegistration() {
return createApiModuleDispatcherServletRegistration(apiModuleADispatcherServlet());
}
@Override
protected String getApiModuleDispatcherServletBeanName() {
return API_MODULE_A_DISPATCHER_SERVLET_BEAN_NAME;
}
@Override
protected String getApiModulePath() {
return apiModuleAPath;
}
@Override
protected Class<ApiModuleAConfiguration> getApiModuleConfigurationClass() {
return ApiModuleAConfiguration.class;
}
}
而现在,你的ApiModuleA配置, ApiModuleB配置...配置类将位于每个 api 模块上项目模块 a-api, 项目模块 b-api...
他们可以存储库RestMvcConfiguration或者它们可以从中扩展,或者它们可以是导入 Spring Data REST 配置的任何其他配置类。
最后但并非最不重要的一点是,我在主模块中创建了不同的 gradle 脚本项目服务器根据传递给 gradle 的属性进行加载以模拟 Maven 配置文件。每个脚本都将需要包含的 api 模块声明为依赖项。它看起来像这样:
- project-server
/profiles/
profile-X.gradle
profile-Y.gradle
profile-Z.gradle
例如,轮廓-X启用 API 模块 A 和 B:
dependencies {
compile project(':project-module-a-api')
compile project(':project-module-b-api')
}
processResources {
from 'src/main/resources/profiles/profile-X'
include 'profile-x.properties'
into 'build/resources/main'
}
其他配置文件可以启用不同的 API 模块。
配置文件以这种方式从项目服务器.gradle:
loadProfile()
processResources {
include '**/*'
exclude 'profiles'
}
dependencies {
compile (project(':project-api-autoconfigure')) {
exclude module: 'project-module-a-api'
exclude module: 'project-module-b-api'
...
}
...
}
...
def loadProfile() {
def profile = hasProperty('profile') ? "${profile}" : "dev"
println "Profile: " + profile
apply from: "profiles/" + profile + ".gradle"
}
或多或少就是这样。我希望它对你有帮助。
Cheers.