Saya menemukan solusinya beberapa waktu lalu tetapi saya lupa membagikannya di sini, jadi terima kasih Jan telah mengingatkan saya akan hal itu.
Saya menyelesaikannya dengan membuat dan mendaftarkan beberapa servlet operator dengan konteks aplikasi web baru dengan konfigurasi berbeda (RepositoryRestMvcConfiguration) dan induk umum yang merupakan konteks aplikasi root dari aplikasi Spring Boot. Untuk mengaktifkan modul API secara otomatis bergantung pada toples berbeda yang disertakan di classpath, saya meniru kurang lebih apa yang dilakukan Spring Boot.
Proyek ini dibagi dalam beberapa modul gradle. Sesuatu seperti ini:
- server proyek
- proyek-api-konfigurasi otomatis
- proyek-modul-a-api
- proyek-modul-b-api
- ...
- proyek-modul-n-api
Modul project-server adalah modul utama. Ia mendeklarasikan ketergantungan pada project-api-autoconfigure, dan pada saat yang sama mengecualikan ketergantungan transitif dari project-api-autoconfigure pada project-module-? -modul api.
Di dalam project-server.gradle:
dependencies {
compile (project(':project-api-autoconfigure')) {
exclude module: 'project-module-a-api'
exclude module: 'project-module-b-api'
...
}
...
}
project-api-autoconfigure bergantung pada semua modul API, sehingga dependensinya akan terlihat seperti ini di project-api-autoconfigure.gradle:
dependencies {
compile project(':project-module-a-api')
compile project(':project-module-b-api')
...
}
project-api-autoconfigure adalah tempat saya membuat kacang servlet operator dengan konteks aplikasi webnya sendiri untuk setiap modul API, tetapi konfigurasi ini bergantung pada kelas konfigurasi setiap modul API yang ada di dalam setiap modul API stoples.
Saya membuat dan mengabstraksi kelas yang darinya setiap kelas konfigurasi otomatis mewarisi:
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();
}
Jadi sekarang, kelas konfigurasi otomatis untuk modul A akan terlihat seperti ini:
@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;
}
}
Dan sekarang, kelas konfigurasi ApiModuleAConfiguration, ApiModuleBConfiguration... Anda akan ada di setiap modul api project-module-a-api, proyek-modul-b-api...
Mereka dapat berupa RepositoryRestMvcConfiguration atau dapat diperluas darinya atau dapat berupa kelas konfigurasi lain yang mengimpor konfigurasi Spring Data REST.
Dan yang tak kalah pentingnya, saya membuat skrip gradle berbeda di dalam modul utama project-server untuk dimuat berdasarkan properti yang diteruskan ke gradle untuk meniru profil Maven. Setiap skrip mendeklarasikan modul api yang perlu disertakan sebagai dependensi. Ini terlihat seperti ini:
- project-server
/profiles/
profile-X.gradle
profile-Y.gradle
profile-Z.gradle
dan misalnya, profile-X mengaktifkan modul API A dan 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'
}
Profil lain dapat mengaktifkan modul API yang berbeda.
Profil dimuat dengan cara ini dari project-server.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"
}
Dan itu kurang lebihnya. Saya harap ini membantu Anda Jan.
Bersulang.
person
Daniel Francisco Sabugal
schedule
13.02.2015