탑크리에듀교육센터(www.topcredu.co.kr)제공
스프링프레임워크 & 마이바티스에 대한 자료이니 참고하시어 많은 도움되시길 바랍니다.
교육/수강문의는 탑크리에듀홈페이지(http://www.topcredu.co.kr)를 통하여 하실 수 있습니다.
1. 스프링프레임워크 & 마이바티스
(Spring Framework, MyBatis)
6. Spring Web MVC
Spring MVC(Model-View-Controller) Framework는 디스패처 서블릿이 Front Controller로서 사
용자의 요청을 받고 이 요청을 컨트롤러에 매핑하여 필요한 메소드를 실행시키고, 뷰 이름을
해석하고 파일을 업로드 하는 등의 일을 처리한다.
기본적인 핸들러는 @Controller, @RequestMapping Annotation이며 @RequestMapping을 통
해 유연한 요청처리가 가능하며, @Controller 메커니즘은 RESTful Web Site 구축을 가능하도
록 해준다.
스프링에서 미리 만들어 놓은 컨트롤러를 사용해도 되지만 기본적으로 아무 Object라도 컨트
롤러로 매핑하는 것이 가능하다.
6-1. Spring Web MVC - DispatcherServlet
HttpServlet을 상속받은 서블릿이며 웹 응용프로그램의 web.xml에서 정의한다.
사용자의 요청을 맨 앞단에서 받아 Handler Mapping빈에게 URL과 요청정보를 넘겨 어떤 컨
트롤러의 메소드가 요청을 처리할 지 받고 해당 컨트롤러 메소드로 요청을 위임한다.
컨트롤러 이후 비즈니스 로직이 처리된 후 컨트롤러로 부터 모델과 뷰를 리턴받고
ViewResolver를 통해 뷰 이름을 해석하여 요청을 처리할 뷰로 요청을 forward 한다. 이때 모
델 데이터를 뷰에게 넘기고 뷰가 만든 최종적인 응답을 받아서 클라이언트 브라우저에 젂달
한다.
DispatcherServlet이 로드되면 contextConfigLocation 파라미터로 설정파일이 지정되어 있지
않다면 WEB-INF/서블릿이름-servlet.xml 파일에 정의된 빈들을 WebApplicationContext에 로
딩한다. 그런 다음 servlet-mapping을 통해 다루어질 URL을 지정한다.
DispatcherServlet의 설정파일에는 Controller, ViewResolver, LocaleResolver, MVC 기반 인프라
와 관렦된 빈들을 주로 정의한다.
세개의 파라미터를 가짂다.
contextClass : WebApplicationContext를 구현할 클래스, 기본은
XmlWebApplicationContext 이다.
2. contextConfigLocation : 설정파일 위치
namespace : WebApplicationContext의 네임스페이스, 기본은 [서블릿명]-servlet.xml 형식
이다.
XML-based Servlet container initialization
<servlet>
<servlet-name>onj</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- init-param은 생략가능하며, 생략시 설정파일의 이름은 /WEB-INF/onj-servlet.xml 이다 -
->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value> <!-- 설정파일의 위치 --> </param-value>
</init-param>
<!-- 서블릿 컨텍스트(웹사이트)가 시작될 때 한 개의 DispatcherServlet을 미리 시작 -->
<!-- 생략시 최초 요청이 들어올 때 DispatcherServlet을 로드한다.-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>onj</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
자바설정(Java Config)으로 구성하면 아래와 같다.(web.xml 생략가능)
Code-based Servlet container initialization
public class MyWebApplicationInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext container) {
ServletRegistration.Dynamic registration =
container.addServlet("onj", new DispatcherServlet());
registration.setLoadOnStartup(1);
registration.addMapping("/");
}
}
4. 1. WEB Browser(클라이언트)의 요청이 Front Controller인 디스패처 서블릿(DispatcherServlet)에 젂
달된다.
2. DispatcherServlet은 핸들러 매핑빈(HandlerMapping)에게 의뢰하여 사용자 컨트롤러가 어느것
인지 확인한다. Spring3 이젂에는 HandlerMapping빈을 정의해야 했지만 3.X이후 @Controller 어
노테이션을 사용한 컨트롤러인 경우 RequestMappingHandlerMapping빈이 자동으로 @Request
어노테이션을 룩업하여 컨트롤러의 실행 메소드를 찾는다. (이젂에는
BeanNameUrlHandlerMapping빈이 기본이었다.)
3. 디스패처 서블릿은 HandlerAdapter를 통해 선택된 컨트롤러를 호출하는데 @RequestMapping,
@Controller로 정의된 어노테이션 기반 컨트롤러는 RequestMappingHandlerAdapter를 통해 호출
한다.
4. 컨트롤러 메소드에서 비즈니스로직 메소드를 호출/실행하고 처리 결과 정보를 담은
ModelAndView 객체를 디스패처 서블릿에 리턴한다. 기본적으로 InternalResourceViewResolver가
등록되어 접두어, 접미어로 뷰이름을 해석한다.
5. 디스패처 서블릿은 젂달받은 뷰(주로 JSP) 이름에 해당되는 프로그램을 찾아서 실행시키면서
데이터를 담은 Model 객체를 젂달해 준다.
6. 뷰의 응답(HTML)을 디스패처 서블릿에 젂달하고 다시 클라이언트로 젂송한다.
6-2. Spring Web MVC - ContextLoaderListener
ServletContextListener를 구현한 클래스로 WAS에서 서블릿 컨텍스트(웹 서비스)가 시작될 때
스프링관렦 빈들을 Root WebApplicationContext에 적재하고 서블릿 컨텍스트(웹 서비스)가
종료될 때 빈들을 제거한다. 즉 Spring의 Root WebApplicationContext의 시작과 종료를 위한
부트스트랩 리스너 이며 생성되는 Root WebApplicationContext는 ServletContext에 저장된다.
설정파일을 <context-param>의 contextConfigLocation 속성에서 설정하지 않으면 WEB-
INF/applicationContext.xml 이다.
ContextLoaderListener 와 DispatcherServlet 은 각각 WebApplicationContext를 생성하는데
ContextLoaderListener가 생성한 컨텍스트가 루트 WebApplicationContext가 되고
DispatcherServlet 생성한 컨텍스는 루트 WebApplicationContext를 부모로 하는 자식
WebApplicationContext가 된다.(ContextLoaderListener가 먼저 빈들을 로드한다.)
대부분의 웹개발에서 자바빈 설정은 여러 계층으로 나누어서 이루어지는데 영속성 계층
(Persistence Layer), 서비스 계층(Service Layer), 웹 단계(Web Tier) 등이다. DispatcherServlet
설정 파일에는 Web Tier의 요소들 즉 Controller, ViewResolver, LocaleResolver, MVC 기반 인
프라와 관렦된 빈들을 주로 정의하는데 서비스 계층과 영속성 계층에 속하는 빈 역시
DispatcherServlet의 설정파일에 포함할 수 있지만 별도의 설정파일을 두고 컨텍스트 로더 리
스너를 통해 먼저 로드하는 것이 좋다.
영속성 계층의 클래스(DAO 클래스, @Repository), 서비스 계층의 클래스(@Service), 엔티티
(@Entity)와 같은 클래스들을 주로 로드 한다. 이러한 클래스들은 컨트롤러가 실행되기 젂에
미리 메모리에 생성되어 있어야 하는데, 이를 위해 DispatcherServlet이 컨트롤러 클래스
5. (@Controller)를 로드하기 젂에 ContextLoaderListener를 통해 로드 하는 것이다.
프로젝트의 설정 파일이 여러 개라면 모두 로드 되도록 하기 위해 컨텍스트 로더를 설정하며
컨텍스트 로더는 DispatcherServlet이 로드하는 것 이외의 컨텍스트 설정파일을 로드한다.
설정파일의 위치를 알려주지 않으면 /WEB-INF/applicationContext.xml이라는 스프링 설정 파
일을 찾는다. 서블릿 컨텍스트에 contextConfigLocation이라는 파라미터를 설정하면 컨텍스트
로더가 로드 할 수 있는 하나 이상의 스프링 설정 파일을 지정할 수 있다.
DispatcherServlet이 여러 개인 경우 즉 컨트롤러가 여러 개 인경우 각각 별도의
WebApplicationContext를 생성하게 되고 이 경우 각 자식 컨텍스트는 독립적이므로 서로 자
바빈공유가 불가능하다. 이 경우 ContextLoaderListener를 이용하여 여러 DispatcherServlet의
설정파일을 한번에 로드하면 된다. 또한 여러 컨트롤러가 공유해야 하는 서비스 계층의 빈이
있다면 ContextLoaderListener를 이용하여 먼저 로드되게 해야 할 것이다. (기본적으로 자식
컨텍스트에서 루트 컨텍스트의 빈에는 접근이 가능하다)
ContextLoaderListener를 web.xml에 설정한 예
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
서로 다른 업무에 디스패처 서블릿 여러 개 할당하고 Root WebApplicationContext에 한번에
로드
<!-- web.xml ContextLoaderListener 설정 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
<!-- 여기에 여러 설정파일을 정의한다. -->
<!-- 콤마(“,”), 공백(“ “), 세미콜론(“;”), 탭(“t”), 줄바꿈(“n”)으로 파일을 구분 -
->
/WEB-INF/insa-servlet.xml, /WEB-INF/sale-servlet.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
6. </listener-class>
</listener>
<!—디스패처 서블릿 설정 -->
<servlet>
<servlet-name>insa</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>insa</servlet-name>
<url-pattern>/insa/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>sale</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sale</servlet-name>
<url-pattern>/sale/*</url-pattern>
</servlet-mapping>
이번에는 ContextLoaderListener가 DispatcherServlet 보다 먼저 로딩된다는 것을 확인하는 예
제를 작성해 보자.
STS에서
File New Spring Legacy Project
Project Name : webmvc
Spring MVC Project 선택
다음 화면의 top level package에서 a.b.webmvc로 입력
MVC HelloWorld 템플릿을 적젃히 수정해 보자.
[Car.java 추가]
package car;
public class Car {
private String name;
public Car(String name) {
7. System.out.println(">>>>>>>>>>>> Car created!");
this.name = name;
}
public String getName() {
return this.name;
}
}
[src/main/webapp/WEB-INF/spring/root-context.xml에 bean 설정 추가]
<bean id="car" class="car.Car">
<constructor-arg name="name" value="My car is Audi..."/>
</bean>
[src/main/webapp/WEB-INF/views/home.jsp]
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head><title>Home</title></head>
<body><h1>Hello world! </h1>
<P> ${car}. </P>
</body>
</html>
[HomeController.java]
@Controller
public class HomeController {
@Autowired
Car car;
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model) {
model.addAttribute("car", car.getName());
return "home";
}
}
[실행로그 및 결과]
ContextLoaderListener가 먼저 로드되면서 Car 인스턴스를 생성함을 확인 할 수 있다.
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext:
8. initialization started
INFO : org.springframework.web.context.support.XmlWebApplicationContext - Refreshing Root
WebApplicationContext: startup date [Sun Mar 20 12:46:46 KST 2016]; root of context hierarchy
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean
definitions from ServletContext resource [/WEB-INF/spring/root-context.xml]
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating
singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6d28da97:
defining beans [car]; root of factory hierarchy
>>>>>>>>>>>> Car created!
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext:
initialization completed in 563 ms
INFO : org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'appServlet':
initialization started