본문 바로가기

Spring/Spring MVC

(SERVLET) 스프링 IoC 컨테이너 연동

pom.xml 추가

(스프링 부트는 버전을 명시하지 않아도 되지만 현재는 그렇지 않기에 버전 명시하는 것이 필수이다.)

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.1.3.RELEASE</version>
</dependency>


리스너 변경 (스프링이 지원해주는 리스너로 변경)

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
  • ContextLoaderListener : ApplicationContext(Spring IOC Container)를 서블릿 Application의 Lifecycle에 맞추어서 바인딩해주는 역할
  • ApplicationContext를 ServletContext에 등록
  • Servlet 종료 시점에 ApplicationContext 제거

https://jwdeveloper.tistory.com/74?category=823920

 

(SPRING) IoC 컨테이너 - ApplicationContext와다양한 빈 설정 방법

org.springframework.bootspring-boot-starter-web spring-boot-starter-web를 추가할 경우 대부분의 기본적인 의존성들이 들어온다...

jwdeveloper.tistory.com


설정 파일 생성 (@Configuration , @ComponentScan)

@Configuration
@ComponentScan
public class AppConfig {

}

HelloService.class Bean 등록

@Service
public class HelloService {

    public String getName() {
        return "junwoo";
    }
}

Listener의 contextClass 설정(ACWA) - Bean을 생성

<context-param>
   <param-name>contextClass</param-name>
   <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>

설정 파일의 위치 지정

<context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>me.choi.AppConfig</param-value>
</context-param>
더보기

 

Class ContextLoader

application-context을 위한 초기화 작업을 진행한다. (이는 ContextLoaderListener에 의해 호출된다.)

Create a new ContextLoader that will create a web application context based on the "contextClass" and "contextConfigLocation" servlet context-params. See class-level documentation for details on default values for each.

 

This constructor is typically used when declaring the ContextLoaderListener subclass as a <listener> within web.xml, as a no-arg constructor is required.
The created application context will be registered into the ServletContext under the attribute name WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE and subclasses are free to call the closeWebApplicationContext(javax.servlet.ServletContext) method on container shutdown to close the application context.

"contextClass"및 "contextConfigLocation"서블릿 콘텍스트 매개 변수를 기반으로 웹 애플리케이션 콘텍스트를 작성하는 새 "ContextLoader"를 작성하십시오.

이 생성자는 일반적으로 인수가 없는 생성자가 필요하므로 ContextLoaderListener 서브 클래스를 web.xml 내부에서 선언할 때 사용됩니다.

작성된 애플리케이션 콘텍스트는 속성 이름 

WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE로 ServletContext에 등록되며 서브 클래스는 컨테이너 종료 시 closeWebApplicationContext (javax.servlet.ServletContext) 메서드를 호출하여 애플리케이션 콘텍스트를 닫을 수 있습니다.

 

하 해석이 힘드네 영어공부 좀 해야겠다...


Servlet에서 Bean 불러오기

ApplicationContext context = (ApplicationContext) getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
HelloService bean = context.getBean(HelloService.class);

아까 분명히 나는 Listener를 org.springframework.web.context.ContextLoaderListener로 변경하였기에

이제는 MyListener는 동작하지 않는다.

 

위에서 불러온 Bean에 해당하는 getName()을 호출하면

 

 

HelloService의 return 값 "junwoo"가 전시될 것이다.

 

 

 

resp.getWriter().println("<html>");
resp.getWriter().println("<head>");
resp.getWriter().println("<body>");
resp.getWriter().println("<h1>Hello," + bean.getName() + "</h1>");
resp.getWriter().println("</body>");
resp.getWriter().println("</head>");
resp.getWriter().println("</html>");

실행결과



이제까지 했던 방법은 Spring IOC Container를 이용하는 방법이었다.

 

여기서 문제는 url 하나당 servlet 하나라는 문제가 발생한다.

<filter>
<filter-name> myfilter </filter-name>
<filter-class> me.choi.MyFilter </filter-class>
</filter>
<filter-mapping>
<filter-name> myfilter </filter-name>
<servlet-name> hello </servlet-name>
</filter-mapping>

공통적으로 처리해야 하는 servlet은 어떻게 처리할까?

http://www.corej2eepatterns.com/FrontController.htm

 

Core J2EE Patterns

 

www.corej2eepatterns.com

 

 

하나의 컨트롤러만을 사용하여

해당 컨트롤러가 요청을 받아 

각각의 핸들러들에게 분배(dispatch)해주는 디자인 패턴

 

 

 

 

근데 이미 Spring은 위의 FrontController를 구현해놓았다.

이것이 바로 DispatcherServlet이다.

 

그림에서 Root WebApplicationContext는 

우리가 등록한 서블릿에 해당한다.

<filter>
<filter-name>myfilter</filter-name>
<filter-class>me.choi.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myfilter</filter-name>
<servlet-name>hello</servlet-name>
</filter-mapping>

DispatcherServlet은 해당 Root WebApplicationContext를 상속받는 

Application Context를 하나 더 만든다.

 

 

굳이 이러한 상속관계를 만드는 이유는 무엇일까?

상속관계로 만든다면 부모에 해당하는 Root WebApplicationContext는 다른 자원(servlet)들이 공유할 수 있게 된다.

반면에 DispatcherServlet이 만든 Root WebApplicationContext를 상속받는 Application Context는 자기만 사용할 수 있도록 즉 

DispatcherServlet Scope 안에서만 사용이 가능하다.

 

여기서 주의해서 볼 점은 Root WebApplicationContext에는 web과 관련된 자원들은 존재하지 않는다.

왜냐면 Service와 Repository는 다른 Servlet들이 공유할 수 있는 자원이기 때문이다.


코드 참조 

https://github.com/mike6321/Spring/tree/master/SpringMVC/java-servlet-demo

 

mike6321/Spring

Contribute to mike6321/Spring development by creating an account on GitHub.

github.com