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
설정 파일 생성 (@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
하나의 컨트롤러만을 사용하여
해당 컨트롤러가 요청을 받아
각각의 핸들러들에게 분배(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
'Spring > Spring MVC' 카테고리의 다른 글
(SERVLET) DispatcherServlet의 내부 살펴보기 (0) | 2020.01.17 |
---|---|
(SERVLET) 스프링 MVC 연동 (0) | 2020.01.12 |
(SERVLET) 서블릿 리스너와 서블릿 필터 (0) | 2020.01.11 |
(SERVLET) 서블릿 애플리케이션 개발 (0) | 2020.01.11 |
(SERVLET) Servlet 개요 (0) | 2020.01.11 |