복붙노트

[SPRING] Spring Data REST를 사용하여 다양한 REST API에 대한 다중 디스패처 서블릿이있는 JAR (Spring Boot)

SPRING

Spring Data REST를 사용하여 다양한 REST API에 대한 다중 디스패처 서블릿이있는 JAR (Spring Boot)

Spring Data REST가있는 REST API를 제공하는 실행 가능한 JAR을 생성하기 위해 Spring Boot를 사용하는 프로젝트가있다. 또한 Spring Security OAuth와 통합되어 있습니다. 그건 잘 작동합니다. 내 문제는 다음과 같습니다.

JPA 저장소가있는 해당 JAR이 클래스 경로 (종속성으로 정의 됨)에있는 경우에만 사용 가능하게하려는 REST API에 대해 다른 모듈을 갖기를 원합니다.

것은 그들이 서로에게서 독립적이되기를 바란다. 서로 다른 매핑을 사용하여 다른 디스패처 서블릿에서 이들을 제공 할 수 있기를 원하며 각각에 대해 서로 다른 baseUri를 지정하고 리소스 검색에 대해 서로 다른 루트 URL을 지정할 수 있습니다.

나는 그것을 더 명백하게하려고 노력할 것이다 :

그 외에도 다른 사용자 지정 컨트롤러와 함께 / oauth / * 끝점을 보유하는 다른 디스패처 서블릿을 가질 수 있으며 보안 구성이 모든 (/ *)

나는 ServletRegistrationBean을 통해 더 많은 디스패처 서블릿을 정의 할 수 있다는 것을 알고 있지만 각기 다른 스프링 데이터 나머지 구성을 연결하는 방법을 모르겠다.

또한 각 하위 컨텍스트에서 각 Dispatcher 서블릿, 각 RepositoryRestMvcConfiguration을 정의하고 스캔 할 여러 패키지를 정의하는 각 @EnableJpaRepositories 주석을 갖는 SpringApplicationBuilder를 사용하여 계층 적 응용 프로그램 컨텍스트로이 작업을 수행하려고했습니다. 어쨌든 WebApplicationContext가 생성되지 않기 때문에 컨텍스트를로드 할 수 없습니다. 사용할 수있는 ServletContext가 없으므로 실패합니다.

어떤 도움 / 제안? 미리 감사드립니다.

해결법

  1. ==============================

    1.얼마 전 해결책을 찾았지만 여기서 공유하는 것을 잊어 버렸습니다. 그래서 저에게 상기시켜 줘서 고맙습니다.

    얼마 전 해결책을 찾았지만 여기서 공유하는 것을 잊어 버렸습니다. 그래서 저에게 상기시켜 줘서 고맙습니다.

    필자는 여러 가지 디스패처 서블릿을 다른 설정 (RepositoryRestMvcConfiguration)을 가진 새로운 웹 애플리케이션 컨텍스트와 스프링 부트 애플리케이션의 루트 애플리케이션 컨텍스트 인 공통 부모를 생성하고 등록함으로써이를 해결했다. classpath에 포함 된 다른 jar에 따라 자동으로 API 모듈을 사용하려면 Spring Boot가 수행하는 작업을 에뮬레이트했습니다.

    이 프로젝트는 여러 gradle 모듈로 나뉩니다. 이 같은:

    모듈 프로젝트 - 서버가 주요한 것입니다. 프로젝트 -pi-autoconfigure에 대한 의존성을 선언 함과 동시에 프로젝트 -pi-autifigure의 프로젝트 종속적 인 의존성을 프로젝트 모듈 -i-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 모듈에 대한 자체 웹 응용 프로그램 컨텍스트로 디스패처 서블릿 빈을 만드는 곳이지만이 구성은 각 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;
        }
    
    }
    

    이제 Api ModuleConfiguration, API 모듈 구성 ... 구성 클래스가 각 api 모듈 project-module-a-api, project-module-b-api ...에 있습니다.

    RepositoryRestMvcConfiguration 일 수도 있고 확장 할 수도 있고 Spring 데이터 REST 구성을 가져 오는 다른 모든 구성 클래스 일 수도 있습니다.

    마지막으로 중요한 것은 메인 모듈 프로젝트 - 서버 내부에 다른 그라데이션 스크립트를 작성하여 Maven 프로파일을 에뮬레이트하기 위해 gradle에 전달 된 속성을 기반으로로드되도록했습니다. 각 스크립트는 포함될 필요가있는 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"
    }
    

    그리고 그 정도면 충분합니다. 1 월에 도움이되기를 바랍니다.

    건배.

  2. from https://stackoverflow.com/questions/27319051/spring-boot-jar-with-multiple-dispatcher-servlets-for-different-rest-apis-with by cc-by-sa and MIT license