2013-08-20 2 views
3

스프링 구성을 이해하려고합니다. 나는 두 기사를 읽기 : "응용 프로그램 컨텍스트"와 "웹 응용 프로그램 컨텍스트"스프링의 최적 구성 3.2.3

  1. http://www.onjava.com/pub/a/onjava/2006/03/22/advanced-spring-configuration.html?page=1
  2. http://syntx.io/difference-between-loading-context-via-dispatcherservlet-and-contextloaderlistener/

다음은이 개 설정 파일을 가지고하는 것이 좋습니다.

/WEB-INF/applicationContext.xml을을 사용하면 다음을 할 수 있습니다 : 당신이 이제까지 스프링 MVC 프레임 워크를 사용하여 웹 응용 프로그램을 개발하기 위해 노력하는 경우

, 당신은 사용해야 두 개의 구성 파일이 있다는 것을 알고 빈을 구성하거나 을 사용하여 응용 프로그램의 컨텍스트를 표시하십시오. 이 곳에서 비즈니스 로직 빈, 리소스 및 웹 계층과 직접 관련이없는 다른 모든 콩 을 정의하는 곳입니다.

/WEB-INF/[servlet-name]-servlet.xml은 웹 계층에게 볼 리졸버, 컨트롤러, 유효성 검사기, 그리고 당신은 MVC 프레임 워크에 필요한 다른 모든 콩을 구성하는 데 사용됩니다. [servlet-name]은 web.xml 배치 서술자에 정의 된 Spring의 디스패처 서블릿 이름 을 참조합니다.

<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 


    <!-- Application Context --> 
    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 

    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/applicationContext.xml, 
      /WEB-INF/spring-security.xml</param-value> 
    </context-param> 


    <!-- Spring MVC --> 
    <servlet> 
     <servlet-name>mvc-dispatcher</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
     <init-param> 
      <param-name>contextConfigLocation</param-name> 
      <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

    <servlet-mapping> 
     <servlet-name>mvc-dispatcher</servlet-name> 
     <url-pattern>/</url-pattern> 
    </servlet-mapping> 


    <!-- Spring Security --> 
    <filter> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <filter-class> 
      org.springframework.web.filter.DelegatingFilterProxy 
     </filter-class> 
    </filter> 

    <filter-mapping> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 
    <!-- Fin Spring Security --> 

</web-app> 

이 내 applicationContext.xml이다 :

이에 따르면, 나는 다음과 같이 내 web.xml을 쓰기

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:jee="http://www.springframework.org/schema/jee" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd 
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd"> 


    <!-- Look in tom cats context --> 
    <jee:jndi-lookup id="myDataSource" jndi-name="java:comp/env/jdbc/rhcimax"/> 

    <!-- Hibernate Session Factory --> 
    <bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="myDataSource"/> 
    <property name="packagesToScan"> 
     <array> 
     <value>com.blah.baseProject</value> 
     </array> 
    </property> 
    <property name="hibernateProperties"> 
     <value> 
     hibernate.dialect=org.hibernate.dialect.MySQLDialect 
     </value> 
    </property> 
    </bean> 

    <!-- Hibernate Transaction Manager --> 
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="mySessionFactory"/> 
    </bean> 

    <!-- Activates annotation based transaction management --> 
    <tx:annotation-driven transaction-manager="transactionManager"/> 

</beans> 

그리고 이것은 내 MVC-디스패처 - 서블릿이다. xml :

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> 

    <!-- Enable @Controller annotation support --> 
    <mvc:annotation-driven /> 

    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> 
    <mvc:resources mapping="/resources/**" location="/resources/" /> 

    <!-- Map simple view name such as "test" into /WEB-INF/views/test.jsp --> 
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <property name="prefix" value="/view/" /> 
    <property name="suffix" value=".jsp" /> 
    </bean> 

    <!-- Scan classpath for annotations (eg: @Service, @Repository etc) --> 
    <context:component-scan base-package="com.blah.baseProject"/> 


</beans> 

이 구성이 거의 불분명한지 알고 싶습니다. rect. 이 구성의 실행은하지만 난이 예외가 있기 때문에 applicationContext.xml가 호출되지 것을 느낄 :

org.hibernate.HibernateException: No Session found for current thread 

내 의도가 봄에 좋은 관행을 유지하고 올바른 구성을 배우는 것입니다.

는 "중간 계층 사이에 명확한 분리를 유지하는 것이 좋습니다 등 (보통의 ApplicationContext에 정의되어있다)와 같은 관련 구성 요소를 웹 - 비즈니스 로직 구성 요소와 데이터 액세스 클래스 을 같은 서비스 컨트롤러 및보기 확인자 (즉, 은 Dispatcher 서블릿 당 WebApplicationContext에 정의되어 있습니다.) 내 경험에

답변

5

당신은 당신의 web.xml에 컨텍스트 PARAM을 변경할 수 있습니다 : 대신 주석 기반 구성을 사용하는 DispatcherServlet를 구성하는 경우, 그것은 여분의 노력없이 기본적으로 비어 있습니다

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

그리고 문맥을 또한

enter image description here

을 뿌리를 가져 오지 않고 상황에 맞는 파일의 수를 만들어 t는 다중 모듈 프로젝트가 있고 각 모듈에 구성 파일을 넣을 때 매우 유용합니다. 이름을 applicationContext-.xml로 지정하면 자동으로 스캔됩니다.

mvc-dispatcher-servlet.xml에서 인터셉터 (로켈, 테마 인터셉터 및 본인),보기 확인자, 리소스, 예외 핸들러, 템플릿 엔진 구성 및 기타 관련된 구성 요소를 선언하는 것이 좋습니다. 볼 수 있습니다.

또한 단지 서블릿 구성에서 컨트롤러 구성 요소 검사를 선언하는 데 유용합니다 :

MVC-디스패처-servlet.xml에 :

<context:component-scan base-package="by.company.app" use-default-filters="false"> 
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/> 
</context:component-scan> 

스캔 @Controller 제외의 ApplicationContext에서 :

applicationContext.xml :

<context:component-scan base-package="by.company.app"> 
    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/> 
</context:component-scan> 

중복 빈 정의를 별도 ApplicationContexts 내의

예를 피하기 위해 (네임 스페이스 선언은 생략)

applicationContext.xml :

<beans>  
    <context:property-placeholder location="classpath*:META-INF/spring/a-*.properties" /> 

    <task:annotation-driven/> 

    <context:spring-configured/> 

    <context:component-scan base-package="by.company.app"> 
     <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/> 
    </context:component-scan> 
</beans> 

애플리케이션 컨텍스트 - db.xml가

<beans> 
    <bean id="dataSource" 
     class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="url" value="jdbc:mysql://${database.host}:${database.port}/${database.db-path}" /> 
     <property name="driverClassName" value="${database.driverClassName}" /> 
     <property name="username" value="${database.username}" /> 
     <property name="password" value="${database.password}" /> 
    </bean> 

    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory"/> 
    </bean> 

    <tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/> 

    <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"> 
     <property name="persistenceUnitName" value="persistenceUnit"/> 
     <property name="dataSource" ref="dataSource"/> 
     <property name="jpaVendorAdapter"> 
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> 
     </property> 
     <property name="jpaProperties"> 
      <props> 
       <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
       <prop key="hibernate.max_fetch_depth">3</prop> 
       <prop key="hibernate.jdbc.fetch_size">50</prop> 
       <prop key="hibernate.jdbc.batch_size">10</prop> 
       <prop key="hibernate.show_sql">false</prop> 
       <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop> 
       <prop key="hibernate.connection.charSet">UTF-8</prop> 
       <!-- <prop key="hibernate.hbm2ddl.auto">update</prop> --> 
      </props> 
     </property> 
    </bean> 

    <jpa:repositories base-package="by.company.app" /> 

</beans> 
+0

그는 대단히 감사합니다 !! 내가 언급 한 것처럼 서블릿 구성에서 컨트롤러에 대해서만 구성 요소 스캔을 선언했습니다. 이제는 모든 것이 잘 작동합니다 !! 나는 예외를 얻지 않는다 :). 마지막으로 한 가지 : application-context.xml과 application-context-db.xml을 공유 할 수 있습니까? – kiduxa

+0

완료. 업데이트 된 답변보기 – yname

2

는만큼 당신이 웹 애플리케이션 confiiguration에서 별도의 핵심 구성에 어떤 특별한 이유가없는 한, 가장 좋은 방법은 빈 DispatcherServlet의 컨텍스트를 유지하고 (루트 애플리케이션 컨텍스트에 applicationContext.xml 모든 것을 넣어하는 것입니다 , 등).그래서 당신은 특히, 여러 가지 문제를 피할 수 있습니다 이렇게함으로써

: 같은 <tx:annotation-driven> 같은

  • 포스트 프로세서 (즉 문제의) 당 컨텍스트 기반에서 선언해야합니다. 당신이 서블릿의 컨텍스트에는 콩이 없다면, 당신은 당신이 관리에 대해 걱정하는 경우 중복 된 bean 정의

에 심각한 문제가 발생할 수 있습니다 모두 상황에서 동일한 패키지에 대한 <context:component-scan> 선언이이 선언

  • 를 복제 할 필요가 없습니다 단일 모 놀리 식 컨텍스트의 경우, 이미 수행 한 것처럼 여러 파일로 분할 할 수 있습니다.

    DispatcherServlet이 XML 파일 (기본적으로 구성되어 있음)에서 컨텍스트 구성을 읽는 경우 유효한 루트 요소가있는 XML 파일을 만들어야합니다. 그러나, 약간의 트릭이있다 :

    <servlet> 
        <servlet-name>mvc-dispatcher</servlet-name> 
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
        <init-param> 
         <param-name>contextClass</param-name> 
         <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> 
        </init-param> 
        <load-on-startup>1</load-on-startup> 
    </servlet> 
    
  • +0

    "최선의 방법은 서블릿의 컨텍스트를 비우고 모든 것을 루트 컨텍스트에 넣으려면 mvc-dispatcher-servlet.xml ("WebApplicationContext")을 비워 두어야합니다.""WebApplicationContext "는 응용 프로그램 컨텍스트의 하위 컨텍스트이므로" "가정합니다." – kiduxa

    +4

    불필요한 우려가 혼합되기 때문에 귀하의 접근 방식에 동의하지 않습니다. MVC (프리젠 테이션 계층)와 관련된 모든 것이 디스패처 서블릿 config에 정의되며 (둘 이상의 디스패처 서블릿을 가질 수 있음) 코어 도메인과 관련된 모든 것이 루트 웹 응용 프로그램 컨텍스트에 포함됩니다 모든 발송자 전용 컨텍스트의 상위). –

    +1

    @CostiCiudatu : 귀하의 요지를 이해 합니다만, "레이어 원칙이 아닌 기능별 패키지"를 따르는 것을 선호합니다. 단일 컨텍스트를 기능별 부품으로 나누는 것은 컨피규레이션을 레이어 별 컨텍스트로 나누는 것보다 더 중요하다고 생각합니다. – axtavt