gpt4 book ai didi

java - 带有 Spring Data REST 的不同 REST API 的多个调度程序 servlet 的 Spring Boot (JAR)

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:09:22 25 4
gpt4 key购买 nike

我有一个项目使用 Spring Boot 生成一个可执行 JAR,该 JAR 公开了一个带有 Spring Data REST 的 REST API。它还与 Spring Security OAuth 集成。那很好用。我的问题如下,

我想为 REST API 使用不同的模块,仅当具有 JPA 存储库的相应 JAR 在类路径中(它已被定义为依赖项)时,我才想启用这些模块。

问题是我希望它们彼此独立。我希望能够在具有不同映射的不同调度程序 servlet 下为它们提供服务,这样我就可以为每个指定不同的 baseUri,并为资源发现设置不同的根 URL。

我会尽量让它更清楚:

  • API 模块 A:

    • 一个 JAR,例如包含资源 X 和 Y 的 XRespository 和 YRespository。
    • 调度程序 servlet A。
    • Servlet 映射:/api/moduleA/
    • Spring Data REST 的基本 URI:/api/moduleA/
    • 如果我检查 URL/api/moduleA/,我应该会发现资源 X 和 Y。
  • API 模块 B:

    • 一个 JAR,例如包含资源 P 和 Q 的 PRespository 和 QRespository。
    • 调度程序 servlet B。
    • Servlet 映射:/api/moduleB/
    • Spring Data REST 的基本 URI:/api/moduleB/
    • 如果我检查 URL/api/moduleB/,我应该会发现资源 P 和 Q。
  • 更多模块...

除此之外,我还可以拥有另一个调度程序 servlet,其中包含/oauth/* 端点以及其他自定义 Controller ,并且安全配置必须对所有 (/*) 正常工作

我知道我可以通过 ServletRegistrationBean 定义更多的调度程序 servlet,但我不知道如何附加到每个不同的 spring 数据 rest 配置。

我也一直在尝试通过在每个子上下文中定义每个调度程序 servlet 的配置、每个 RepositoryRestMvcConfiguration 和每个 @EnableJpaRepositories 注释定义要扫描的不同包来使用 SpringApplicationBuilder 对分层应用程序上下文执行此操作。无论如何,我什至无法加载上下文,因为它们不是作为 WebApplicationContext 创建的,因此失败,因为没有可用的 ServletContext。

有什么帮助/建议吗?提前致谢。

最佳答案

我刚才找到了解决方案,但我忘了在这里分享,所以感谢 Jan 提醒我。

我通过使用具有不同配置 (RepositoryRestMvcConfiguration) 的新 Web 应用程序上下文和一个公共(public)父级(即 Spring Boot 应用程序的根应用程序上下文)创建和注册多个调度程序 servlet 来解决此问题。为了根据类路径中包含的不同 jar 自动启用 API 模块,我或多或少地模拟了 Spring Boot 所做的事情。

该项目分为几个 gradle 模块。像这样:

  • 项目服务器
  • 项目-api-自动配置
  • 项目模块-a-api
  • 项目模块-b-api
  • ...
  • 项目模块-n-api

project-server 模块是主要模块。它声明了对 project-api-autoconfigure 的依赖,同时排除了 project-api-autoconfigureproject-module-? -api 模块

project-server.gradle 中:

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

project-api-autoconfigure 依赖于所有 API 模块,因此依赖项在 project-api-autoconfigure.gradle 上看起来像这样:

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

project-api-autoconfigure 是我为每个 API 模块创建具有自己的 Web 应用程序上下文的调度程序 servlet bean 的地方,但此配置取决于位于内部的每个 API 模块的配置类每个 API 模块 jar。

我创建了一个抽象类,每个自动配置类都继承自该类:

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;
}

}

现在,您的 ApiModuleAConfigurationApiModuleBConfiguration... 配置类将位于每个 api 模块 project-module-a-api 上, 项目模块-b-api...

它们可以是RepositoryRestMvcConfiguration,也可以从它扩展,也可以是导入 Spring Data REST 配置的任何其他配置类。

最后但同样重要的是,我在主模块 project-server 中创建了不同的 gradle 脚本,以根据传递给 gradle 的属性加载以模拟 Maven 配置文件。每个脚本都将需要包含的 api 模块声明为依赖项。它看起来像这样:

- project-server
/profiles/
profile-X.gradle
profile-Y.gradle
profile-Z.gradle

例如,profile-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 模块。

配置文件以这种方式从 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"
}

差不多就这些了。我希望它能帮助你简。

干杯。

关于java - 带有 Spring Data REST 的不同 REST API 的多个调度程序 servlet 的 Spring Boot (JAR),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27319051/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com