복붙노트

[SPRING] 스프링 루트 애플리케이션 컨텍스트와 서블릿 컨텍스트 혼동

SPRING

스프링 루트 애플리케이션 컨텍스트와 서블릿 컨텍스트 혼동

내 webapp을 액세스 가능하게 만들기 위해 서블릿 컨텍스트에 @Controller라는 주석이 달린 클래스를 등록해야한다는 것을 알고있다. 일반적으로, 나는 다음과 같은 방법으로 그것을한다 :

@Configuration
@EnableWebMvc
@ComponentScan({"foo.bar.controller"})
public class WebConfig extends WebMvcConfigurerAdapter {
    //other stuff like ViewResolvers, MessageResolvers, MessageConverters, etc.
}

다른 모든 구성 클래스를 루트 응용 프로그램 컨텍스트에 추가했습니다. 다음은 디스패처 초기화 프로그램의 일반적인 모습입니다.

public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RootConfig.class, ServiceConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

하지만 웹 소켓을 사용하기 시작하면 점점 더 흥미로워지고 있습니다. 웹 소켓을 작동 시키려면 WebSocket Config.class를 서블릿 컨텍스트에 넣어야합니다. WebSocketConfig의 예가 아래와 같습니다.

@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/chat").withSockJS();
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration channelRegistration) {
        channelRegistration.taskExecutor().corePoolSize(4).maxPoolSize(8);
    }

    @Override
    public void configureClientOutboundChannel(ChannelRegistration channelRegistration) {
        channelRegistration.taskExecutor().corePoolSize(4).maxPoolSize(8);
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/queue", "/topic");
        registry.setApplicationDestinationPrefixes("/app");
    }

}

또한 주제에 대한 메시지를 보낼 서비스를 만들었습니다.

@Service
public class TimeServiceWsImpl implements TimeServiceWs {

    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    @Override
    public void sentCurrentTime() {
        long currentTime = System.currentTimeMillis();
        String destination = "/topic/chatty";
        logger.info("sending current time to websocket /topic/time : " + currentTime);
        this.messagingTemplate.convertAndSend(destination, currentTime);
    }
}

다른 서비스 (autowire)에서이 서비스를 사용해야합니다. 이제 교착 상태에 빠졌습니다.

내가 뭘해야되는거야? 루트 컨텍스트 내부에 있어야하는 것은 무엇입니까? 서블릿 컨텍스트 내부에 있어야하는 것은 무엇입니까? 그리고이 문맥의 차이점을 다시 한번 분명히 해 주시겠습니까?

추가 정보가 필요하면 알려주십시오.

해결법

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

    1.대부분의 Spring MVC 애플리케이션은 모든 서비스 계층 / DAO 계층 Bean을 포함하는 하나의 루트 컨텍스트와 각 서블릿의 컨트롤러를 포함하는 애플리케이션의 스프링 디스패처 서블릿 당 하나의 서블릿 컨텍스트를 포함합니다.

    대부분의 Spring MVC 애플리케이션은 모든 서비스 계층 / DAO 계층 Bean을 포함하는 하나의 루트 컨텍스트와 각 서블릿의 컨트롤러를 포함하는 애플리케이션의 스프링 디스패처 서블릿 당 하나의 서블릿 컨텍스트를 포함합니다.

    하나의 애플리케이션에 URL / 쇼핑 / * 및 URL / reporting / *에 대한 하나의 서블릿 디스패처가있을 수 있다는 아이디어가 있습니다. 각 서블릿 디스패처는 각각 컨트롤러 세트를 가지고 있습니다.

    하나의 서블릿 디스패처의 컨트롤러는 서로 격리되어 있습니다. 즉, 스프링 콩이기는하지만 서로 주입 할 수 없습니다.

    루트 컨텍스트의 서비스 레이어와 DAO 빈은 모든 서블릿 컨텍스트에서 볼 수 있으므로 서비스 레이어 빈은 모든 컨트롤러에 삽입 될 수 있지만 다른 방법으로는 삽입 될 수 없습니다.

    루트 컨텍스트는 컨트롤러 서블릿 컨텍스트 / 컨텍스트의 부모라고합니다.

    그것은 모두 서로에게서 콩 그룹을 분리하여 아무런 관련없는 의존성이 없도록 보장하는 메커니즘을 의미합니다.

    이것을 감안할 때 질문을 통해 :

  2. ==============================

    2.WebSocket 관련 설정은 DispatcherServlet 설정에 속합니다. 모든 HTTP 핸드 셰이크가 처리기 매핑을 통해 DispatcherServlet에 의해 처리 된 후.

    WebSocket 관련 설정은 DispatcherServlet 설정에 속합니다. 모든 HTTP 핸드 셰이크가 처리기 매핑을 통해 DispatcherServlet에 의해 처리 된 후.

    웹 애플리케이션에 단 하나의 DispatcherServlet 만있는 배치 시나리오에서 단일 Spring 컨텍스트를 사용할 수 있어야한다. AbstractAnnotationConfigDispatcherServletInitializer (SPR-11357 참고)에 버그가 있었지만 예를 들어 Spring Security를 ​​사용하면 설정을 루트 컨텍스트로 통합하는 것이 더 효과적입니다. DispatcherServlet 컨텍스트로 통합하는 것도 가능해야하지만 예외가 있다고 썼다. 예외 세부 사항을 제공 할 수 있습니까?

    또한 root 및 DispatcherServlet 컨텍스트를 모두 가질 수있는 옵션입니다. 이 경우 WebSocket 구성은 DispatcherServlet 컨텍스트에 있고 SimpMessagingTemplate을 루트 컨텍스트의 Bean에 삽입 할 수 없습니다. 각각의 DispatcherServlet (또는 다른 서블릿)과 함께 갈 하나의 SimpMessagingTemplate이 있기 때문에 실제로 의미가 있습니다. 필요한 것은 웹 레이어 구성 요소이며, SimpMessagingTemplate과 함께 주입 될 수있는 Service Layer Bean (예 : TimeServiceWs 위의 예제)을 감싸는 얇은 래퍼 일 수 있습니다. 이 웹 레이어 구성 요소는 본질적으로 브리지 역할을합니다.

  3. from https://stackoverflow.com/questions/21319450/spring-root-application-context-and-servlet-context-confusion by cc-by-sa and MIT license