ContextLoaderListener 여부?


122

표준 스프링 웹 애플리케이션 (Roo 또는 "Spring MVC 프로젝트"템플릿으로 생성)은 ContextLoaderListenerDispatcherServlet. 왜를 사용 DispatcherServlet하여 전체 구성을로드하는 데 사용하지 않습니까?

ContextLoaderListener를 사용하여 웹과 관련이없는 항목을로드해야하고 DispatcherServlet을 사용하여 웹 관련 항목 (컨트롤러, ...)을로드해야한다는 것을 이해합니다. 결과적으로 부모와 자식 컨텍스트의 두 가지 컨텍스트가 생성됩니다.

배경:

나는 몇 년 동안이 표준적인 방식으로 그것을하고 있었다.

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Handles Spring requests -->
<servlet>
    <servlet-name>roo</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/spring/webmvc-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

이로 인해 두 컨텍스트 및 둘 사이의 종속성에 문제가 발생하는 경우가 많습니다. 과거에는 항상 해결책을 찾을 수 있었고 이것이 소프트웨어 구조 / 아키텍처를 항상 더 좋게 만든다는 강한 느낌을 받았습니다. 하지만 지금 은 두 가지 상황 모두에서 문제에 직면 해 있습니다 .

-그러나 이것은이 두 가지 컨텍스트 패턴을 다시 생각하게 만들고 스스로에게 묻고 있습니다. 왜이 문제를 겪어야하는지, 왜 모든 스프링 구성 파일을 하나로로드하지 않고 완전히 DispatcherServlet제거 해야합니까 ContextLoaderListener? (여전히 다른 구성 파일을 가지지 만 컨텍스트는 하나뿐입니다.)

제거하지 않을 이유가 ContextLoaderListener있습니까?


"이로 인해 종종 두 컨텍스트 및 둘 간의 종속성에 문제가 발생했습니다." 이것은 의존성 주입 프레임 워크가 스스로하는 것보다 우리의 삶을 더 어렵게 만드는 방법을 보여주는 훌륭한 예입니다.
Andy

1
@Andy-이 관점에 대해 약간의 공감이 있지만, 두 가지 컨텍스트 (보안 필터와 서블릿간에 객체 공유, 트랜잭션을 자동으로 관리하여보기 후에 닫힘)가 필요한 사용 사례를 알아 차릴 수 없습니다. 리디렉션을 완료 한 경우) 프레임 워크의 도움 없이는 달성하기가 매우 어렵습니다. 이는 주로 서블릿 API가 종속성 주입과 함께 작동하도록 설계되지 않았기 때문이며, 직접 시도하면 적극적으로 작동합니다.
Periata Breatta 2016 년

@PeriataBreatta 알겠습니다! 글쎄요, 다르게 설계 되었다면 Spring MVC에 대한 더 나은 대안이있을 것이라고 생각하십니까? 어쨌든 사람들은 Servlet API에 대한 완전한 대안을 설계 할 수 있었지만 ...
Andy

@PeriataBreatta 내가 약 1 년 동안 HTTP 요청을 라우팅하기 위해 Express를 사용해 온 JS 세계에서는 "종속성 주입"에 대한 언급이 거의없고 Spring 프레임 워크와 닮은 것은 전혀 없다는 점에 주목하는 것이 흥미 롭다.
Andy

답변:


86

귀하의 경우에는 ContextLoaderListener및 을 유지할 이유가 없습니다 applicationContext.xml. 앱이 서블릿의 컨텍스트에서만 잘 작동한다면 그게 더 간단합니다.

예, 일반적으로 권장되는 패턴은 웹 앱 수준의 컨텍스트에서 웹이 아닌 항목을 유지하는 것이지만 약한 규칙에 지나지 않습니다.

웹앱 수준 컨텍스트를 사용하는 유일한 이유는 다음과 같습니다.

  • DispatcherServlet서비스를 공유해야하는 여러 대가 있는 경우
  • Spring 유선 서비스에 액세스해야하는 레거시 / 비 Spring 서블릿이있는 경우
  • 당신은 서블릿 필터가있는 경우 그 웹 애플리케이션 레벨의 컨텍스트에 후크 (예를 들어 스프링 시큐리티의 DelegatingFilterProxy, OpenEntityManagerInViewFilter등)

이들 중 어느 것도 귀하에게 적용되지 않으므로 추가 복잡성은 부적절합니다.

등의 예약 된 작업, JMS 연결, 같은 서블릿의 컨텍스트에 백그라운드 작업을 추가 할 때 추가하는 것을 잊지 경우 그냥 조심 <load-on-startup>당신에 web.xml, 다음이 작업은 서블릿의 첫 번째 액세스 할 때까지 시작되지 않습니다.


2
리스너는 Context Loader 리스너 (IllegalStateException, No WebApplicationContext found, Triggered by MultipartFilter, CharacterEncodingFilter, Spring Security DelegatingFilterProxy and OpenEntityManagerInViewFilter)에 의해 생성되는 Context가 필요하다는 점은 어떻습니까? 다른 방법으로 수행하는 것이 좋은 생각입니까 (ContextLoaderListener로 모든 것을로드하고 DispatcherServlet을 구성없이 그대로 둡니다)?
Ralph

@Ralph : 좋은 캐치, 그 사용 사례를 목록에 추가했습니다. DispatcherServlet구성없이 떠나는 경우-그렇게했다면 웹 인터페이스가 없을 것입니다. 모든 MVC 항목은 거기에 들어가야합니다.
skaffman

2
@skaffman DelegatingFilterProxy와 함께 스프링 보안을 사용할 때 왜 두 가지 컨텍스트를 사용해야합니까? 제 경우에는 스프링 보안 빈과 기본 스프링 컨텍스트가 일부 빈을 공유합니다. 따라서 그들은 또한 동일한 컨텍스트를 공유해야합니다. 아니면 스프링 보안 빈이 기본 스프링 컨텍스트에서 벗어나야합니까?
Matthias M

10

다른 방법으로도 애플리케이션 컨텍스트를 구성 할 수 있습니다. 예를 들어 OpenEntityManagerInViewFilter가 작동 하도록하기 위해 . 설정 의 ContextLoaderListener 다음은 당신의 DispatcherServlet을 함께 구성 :

<servlet>
    <servlet-name>spring-mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value></param-value>
    </init-param>
</servlet>

contextConfigLocation 매개 변수 값이 비어 있는지 확인하십시오 .


1
그러나이 구성의 장점은 무엇입니까? "다른 방법"이란 무엇을 의미합니까?
Ralph

"skaffman"의 솔루션은 웹 애플리케이션 컨텍스트 (서블릿) 만 구성했습니다. 그러나 이러한 접근 방식을 사용하면 솔루션 자체에 자세히 설명 된대로 문제가 발생합니다. "웹앱 수준 컨텍스트를 사용하는 유일한 이유는 다음과 같습니다."... "웹앱 수준 컨텍스트에 연결되는 서블릿 필터가있는 경우 (예 : Spring Security의 DelegatingFilterProxy, OpenEntityManagerInViewFilter 등) "하나의 애플리케이션 컨텍스트 XML 파일 만 사용하려면 내 솔루션 (ContextLoaderListener를 통해 XML 지정)이 더 바람직하다고 생각합니다.
Gunnar Hillert

컨텍스트 리스너가 생성 한 컨텍스트에서 MVC 웹 컨트롤러를 사용할 수 있습니까?
Ralph

1
예. 컨텍스트 리스너가 지정한 context.xml 파일에 컨트롤러를 설정하기 만하면됩니다. 작동 방식은 DispatcherServlet이 단순히 "상위 애플리케이션 컨텍스트"(컨텍스트 리스너)에 결합하는 것입니다. "contextConfigLocation"값을 비워두면 컨텍스트 리스너가 지정한 context.xml 파일이 독점적으로 사용됩니다.
Gunnar Hillert

1
귀하의 맥락에서 <mvc : annotation-driven />을 놓친 것 같습니다. @GunnarHillert 솔루션이 저에게 효과적입니다.
milbr

10

Spring-MVC 애플리케이션에서 내가 한 일을 공유하고 싶습니다.

  1. we-mvc-config.xml나는 @Controller로 주석 단지 클래스를 추가 :

    <context:component-scan base-package="com.shunra.vcat">
        <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>
  2. applicationContext.xml파일 나는 모든 나머지를 추가 :

    <context:component-scan base-package="com.shunra.vcat">
        <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>

예, 이것은 유용한 패턴입니다. 또 다른 유용한 패턴은 필터 나 리스너에 의해 특별히 필요한 것 (예 : 스프링 보안을 사용하는 데 필요한 정의)과 함께 응용 프로그램 컨텍스트 (OpenSessionInViewFilter 또는 이와 유사한 경우에 필요할 수 있음)에 데이터베이스 처리 빈을 넣는 것입니다.
Periata Breatta 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.