Spring IoC Container 연동
Servlet Application 에 Spring 연동하기
- 서블릿에서 스프링이 제공하는 IoC 컨테이너 활용하는 방법
- 스프링이 제공하는 서블릿 구현체 DispatcherServlet 사용하기
IoC 컨테이너 활용하는 예제
- 의존성 추가
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
- web.xml 수정 기존 listener 제거후 아래 추가
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
- AppConfig 생성
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class AppConfig {
}
- HelloService 생성
import org.springframework.stereotype.Service;
@Service
public class HelloService {
public String getName() {
return "TheWing";
}
}
- HelloServlet 생성
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ApplicationContext context = (ApplicationContext) getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
HelloService helloService = context.getBean(HelloService.class);
System.out.println("doGet");
resp.getWriter().println("<html>");
resp.getWriter().println("<head>");
resp.getWriter().println("</head>");
resp.getWriter().println("<body>");
resp.getWriter().println("<h1>Hello, " + helloService.getName() + "</h1>");
resp.getWriter().println("</body>");
resp.getWriter().println("</html>");
}
private Object getName() {
return getServletContext().getAttribute("name");
}
@Override
public void destroy() {
System.out.println("destroy");
}
@Override
public void init() throws ServletException {
System.out.println("init");
}
}
- 위에
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
는ApplicationContext
를 담고 있는 것이다 - 결과
- 결과는 동일하다
ContextLoaderListener
- 서블릿 리스너 구현체
- ApplicationContext를 만들어 준다
- ApplicationContext를 서블릿 컨텍스트 라이프사이클에 따라 등록하고 소멸시켜준다
- 서블릿에서 IoC 컨테이너를 ServletContext를 통해 꺼내 사용할 수 있다.
Serlvet의 단점
- 하나하나 아래와 같이 URL 요청하나 할 때마다 하나의 서블릿을 지정해줘야해서 번거로움이 있다
- 여러개 공통된 서블릿을 처리할때 filter로 처리할 수는 있긴하다
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>kr.thewing.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
DispatcherServlet
- 스프링 MVC의 핵심이다
- 스프링이 분배를 해주고 Front Controller 역할을 해주는 서블릿을 구현해놓았다
Front Controller
- 모든 요청을 받아서 해당 요청을 처리할 핸들러에게 분배를 한다
- http://www.corej2eepatterns.com/FrontController.htm
DispatcherServlet
- Servlet Context에 등록 되어있는 ApplicationContext를
Root WebApplicationContext
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>kr.thewing.HelloServlet</servlet-class>
</servlet>
- 이것이 Root WebApplicationContext이다
- Root WebApplicationContext를 디스패처서블릿이 상속받는 애플리케이션 컨텍스트를 하나 더 만든다
- 상속 관계를 만드는 이유는 ContextLoaderListener는 다른 서블릿이 공유해서 사용이 가능하다. 디스패처 서블릿이 만든 애플리케이션 컨텍스트는 그 안에서만 한정되어 있다.
혹시라도 여러개의 서블릿을 만들 경우에 커버하기위해 상속구조를 만들었다. - RootWebApplicationContext는 웹과 관련된 빈들은 등록되지 않는다
결론
- DispatcherServlet이 Servlet WebApplicationContext와 Root WebApplicationContext를 감싼다.
- 스프링 MVC의 핵심이다
- Servlet WebApplicationContext는 Web과 관련된 빈을 등록한다. Controller, ViewResolver, HandlerMapping
- Root WebApplicationContext는 Web과 관련된 빈은 등록하지 않는다. Services, Repositories
Reference
- 해당 포스팅은 백기선님의 인프런 - Spring Web MVC 강의를 보고 정리한 내용입니다.
'Spring > Spring MVC' 카테고리의 다른 글
[Spring] HTTP 요청 맵핑 - 미디어 타입 (0) | 2020.11.15 |
---|---|
[Spring] HTTP 요청 맵핑 - URI 패턴 맵핑 (0) | 2020.11.15 |
[Spring] HTTP 요청 맵핑 - 요청 메소드 (0) | 2020.11.15 |
[Spring] Servlet listener, filter (0) | 2020.11.06 |
[Spring] Servlet 서블릿 (0) | 2020.11.06 |