이론
ContextLoaderListener와 DispatcherServlet의 관계
Tomcat Server는 WebApp을 시작할 때 ServletContextListener를 구현한 ContextLoaderListener를 클래스를 실행한다. ContextLoaderListener는 ApplicationContext를 구현한 IoC Container를 포함하고 있다. 그리고 이 IoC 컨테이너는 app-context.xml
와 같은 bean 설정 파일을 읽고 해당하는 객체들을 찾아 생성하여 관리한다.
DispatcherServlet도 마찬가지로 개별적인 IoC Container를 포함한다. 이 IoC 컨테이너는 app-servlet.xml
과 같은 bean 설정 파일에 따라 해당하는 객체들을 찾아 생성하여 관리한다. 이때, DispatcherServlet은 ContextLoaderListener의 IoC Container를 사용할 수 있다.
ContextLoaderListener와 DispatcherServlet의 IoC Container에서 관리하는 객체
ContextLoaderListner가 포함하고 있는 IoC Container에서는 Service, DAO, 트랜잭션 관련 객체(SqlSessionFactory
등)가 들어있어야 한다. 이 객체들은 각각의 DispatcherServlet들이 공통으로 사용하는 의존 객체이기 때문이다. 각각의 DispatcherServlet의 IoC Container에는 Controller 객체가 들어 있다.
문제
현재 관리자 기능이 일반 페이지에 함께 섞여 있다. 일반 페이지(/app/*
)와 관리자 페이지(/admin/*
)로 분리한다.
해결방법
이를 위해서는 다른 구성을 가진 별도의 Dispatcher Context가 필요하다. /app/*
요청을 처리하는 DispatcherServlet 외에 /admin/*
요청을 처리하는 DispatcherServlet을 추가하여야 한다.
ContextLoaderListener 생성 및 등록
기존에는 app-servlet.xml
에서 Service, DAO, 트랜잭션 관련 객체가 들어 있는 패키지를 지정하였다. 그러나 이제는 DispatcherServlet이 두 개이기 때문에 이 두 개의 DispatcherServlet이 공유하는 독립적인 전용 ContextloaderListener를 추가하고, 여기에서 admin DispatcherServlet과 app DispatcherServlet이 공유하는 Service, DAO, 트랜잭션 관련 객체를 생성하고 관리하도록 분리하였다.
WEB-INF/config/app-context.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<context:component-scan base-package="com.devil">
<context:exclude-filter type="regex" expression="com.devil.web.*"/>
</context:component-scan>
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations"
value="classpath*:com/devil/mapper/*Mapper.xml" />
<property name="typeAliasesPackage" value="com.devil.domain"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<context:property-placeholder location="classpath:com/devil/conf/jdbc.properties"/>
<mybatis:scan base-package="com.devil.dao" />
WEB-INF/web.xml
1
2
3
4
5
6
7
8
9
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- ContextLoaderListener가 사용할 IoC 컨테이너 설정 파일 정보 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/app-context.xml</param-value>
</context-param>