2014-12-05 63 views
6

我有一個使用Spring啓動生成一個可執行的JAR暴露與Spring數據REST一個REST API的項目。它也與Spring Security OAuth集成。這工作正常。我的問題如下,春季啓動(JAR)與多個調度的servlet不同的REST API的使用Spring數據REST

我想爲REST API使用不同的模塊,只有當JPA存儲庫中的對應JAR位於類路徑(它已被定義爲依賴關係)時纔會啓用它。

的事情是我想他們是相互獨立的。我希望能夠爲他們服務,下有不同的映射不同的調度的servlet,所以我可以指定每一個不同的baseUri和擁有的資源會發現不同的根的URL。

I'm要去嘗試,使之更加清楚:

  • 模塊API的一個:

    • 含有例如XRespository和YRespository資源X和Y JAR
    • 調度程序小服務程序A.
    • 小服務程序映射:/ api/moduleA/
    • Spring Data REST的基本URI:/ api/moduleA/
    • 如果我檢查URL/API/moduleA/I應當發現資源X和Y
  • 模塊API的B:

    • 含有例如PRespository和QRespository資源JAR P和Q
    • 分派器的servlet B.
    • servlet映射:/ API/moduleB/
    • 基本URI彈簧數據REST:/ API/moduleB/
    • 如果我檢查URL/API/moduleB /我應該探索資源P和Q
  • 多個模塊...

除此之外,我可以有另調度的servlet在哪裏(/ *)

我知道我可以通過ServletRegistrationBean定義更多的調度程序servlet,但我不知道如何附加到每一個不同的spri ng數據休息配置。

從來就也一直試圖通過在每個孩子的上下文定義每個調度的servlet,每個RepositoryRestMvcConfiguration配置並在各@EnableJpaRepositories註釋定義不同的包進行掃描與SpringApplicationBuilder分層應用上下文來做到這一點。無論如何,我甚至無法加載上下文,因爲它們不是作爲WebApplicationContext而創建的,因此沒有ServletContext可用。

任何幫助/建議嗎?提前致謝。

+0

由於您正在使用spring引導,爲什麼不在每個tomcat和上下文(完全獨立)中部署每個spring data rest應用程序?也許你需要設置一個CORS來防止跨域。我無法看到這種方法的任何問題。 – 2014-12-07 01:29:54

+0

我會對此感興趣。如果你找到了解決方案,請分享 – 2015-02-12 09:40:11

回答

6

前段時間我找到了解決方案,但是我忘記了在這裏分享,所以謝謝Jan提醒我。

我通過創建和註冊用具有不同構造(RepositoryRestMvcConfiguration)和一個公共的父這是Spring啓動應用程序的根應用上下文新的web應用程序上下文幾個調度員的servlet解決它。要根據類路徑中包含的不同jar來自動啓用API模塊,我模擬了Spring Boot或多或少做了什麼。

該項目分爲幾個gradle模塊。事情是這樣的:

  • 項目服務器
  • 項目-API自動配置
  • 項目模塊-A-API
  • 項目模塊-B-API
  • ...
  • project-module-n-api

該模塊項目服務器是th主要的一個。它聲明對project-api-autoconfigure的依賴關係,同時它排除project-api-autoconfigure項目模塊-pi-api模塊的傳遞依賴關係。

項目server.gradle

dependencies { 
    compile (project(':project-api-autoconfigure')) { 
     exclude module: 'project-module-a-api' 
     exclude module: 'project-module-b-api' 
     ... 
    } 
    ... 
} 

項目-API自動配置取決於所有API模塊,因此依賴將是這樣的項目-API autoconfigure.gradle

dependencies { 
    compile project(':project-module-a-api') 
    compile project(':project-module-b-api') 
    ... 
} 

項目-API自動配置是我創建d ispatcher servlet bean爲每個API模塊提供自己的Web應用程序上下文,但是此配置取決於每個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; 
    } 

} 

而現在,你ApiModuleAConfiguration,ApiModuleBConfiguration ...配置類將在每個API模塊上project-module-a-api,project-module-b-api ...

它們可以是RepositoryRestMvcConfiguration或者它們可以從它擴展或者它們可以是導入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模塊。

配置文件是從項目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" 
} 

而這一切,或多或少。我希望它可以幫助你1月

乾杯。

+0

感謝分享丹尼爾...你有任何改變你有一個完整的工作在github上的考試?順便說一下,你是否設法在同一個服務器/進程上運行所有的API模塊? – dimi 2015-04-09 18:11:35

+0

@dimi,對不起,我沒有任何公開回購。如果我找到時間,我可以做到,但基本上我之前解釋過。除此之外,所有API模塊都運行在同一個嵌入式servlet容器上。 – 2015-04-13 09:51:24

+0

Daniel沒問題。僅供參考,我根據您的示例在[github](https://github.com/dbalaouras/multibaserest)上上傳了一個PoC(謝謝)。似乎工作正常,並且API託管在兩個基本URL(** localhost:8080/private/**和** localhost:8080/public/**)下,但它也託管在根路徑下:** localhost :8080 /本地主機/ **。如果你知道如何解決這個問題,大聲喊叫。 TA。 – dimi 2015-04-16 00:15:34