Certification/Spring(2V0-72.22, SCP)

Spring WEB MVC 프로세스 - Home.jsp 동작순서

엘호리스 2018. 8. 5. 15:17

Spring WEB MVC 프로세스


  • Client가 서버에 어떤 요청(Request)을 한다.
  • Spring 내장된 클래스인 DispatcherServlet이 모든 요청을 가로챈다.
  • (web.xml 파일에 설정 되있는 url-pattern에 '/' 값이 그 역할을 한다.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- 서블릿의 환경설정 -->
<servlet>
    <servlet-name>appServlet</servlet-name>
    <!--  DispatcherServlet이 최초 관문(or 짐검다리) 같은 역할을 한다(내장된 서블릿 클래스) -->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <!--  servlet-context.xml 파일에서 설정을 읽어들여 객체를 생성한다 -->
        <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <!--  시작할때 첫번째 우선순위로 지정  -->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <!--  url 패턴을 /로 정하면서 DispatcherServlet이 모든 요청을 가로채게 된다  -->
    <url-pattern>/</url-pattern>
</servlet-mapping>
cs


1. DispatcherServlet은 HandlerMapping에게 해당 url에 맞는 컨트롤러가 있는지 물어본다.

해당 url 패턴에 맞는 컨트롤러에 가라고 DispatcherServlet 에게 알려준다.


2. DispatcherServlet은 해당 컨트롤러에게 가서 url 패턴에 맞는 메서드를 실행할 것을 요청한다.

3. 컨트롤러는 해당 메서드를 실행, Service에게 요청을 위임, DAO를 통해 VO객체를 반환 받는다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Controller //스프링에서 관리하는 컨트롤러 빈으로 등록
public class MemberController {
//MemberService 인스턴스를 주입시킴
    @Inject
    MemberService memberService;
    
    @RequestMapping("member/list.do"//url mapping
    public String memberList(Model model) {
        List<MemberDTO> list=memberService.memberList();
        model.addAttribute("list", list);
        //   WEB-INF/views/member/member_list.jsp로 포워딩
        return "member/member_list";
    }
}
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
//현재 클래스를 스프링에서 관리하는 service bean으로 설정
@Service
public class MemberServiceImpl implements MemberService {
 
    //dao 인스턴스를 주입시킴(스프링이 생명주기를 관리하게 함)
    @Inject
    MemberDAO memberDao;
    
    @Override
    public List<MemberDTO> memberList() {
        return memberDao.memberList();
    }
}
cs


4. 컨트롤러에서 반환받은 view 이름을 ViewResolver를 통해 접근 가능한 url로 변환 받는다.

1
2
3
4
5
<!-- 뷰 리졸버 : 뷰(jsp 페이지)의 접두어,접미어 설정 -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/views/" />
    <beans:property name="suffix" value=".jsp" />
</beans:bean>
cs


5. ViewResolver를 통해 받은 view에 랜더링을 지시, 랜더링 된 view를 클라이언트에게 응답(Response)한다.



스프링 MVC 주요 구성 요소

  • DispatcherServlet : 클라이언트의 요청을 받는다. 컨트롤러에게 요청을 전달하고 컨트롤러가 반환한 결과값을 View에 전달
  • HandlerMapping : 클라이언트의 요청 URL을 어떤 컨트롤러가 처리할지 결정한다
  • HandlerAdapter : DispatcherServlet의 처리 요청을 변환해서 컨트롤러에게 전달, 컨트롤러의 응답 결과를 DispatcherServlet이 요구하는 형식으로 변환한다. 웹 브라우저 캐시 등의 설정도 담당. =변환기 역할
  • Controller : 클라이언트의 요청을 처리한 뒤 결과를 리턴한다. 응답 결과에서 보여줄 데이터를 모델에 담아 전달하기도 한다.
  • ModelAndView : 컨트롤러가 처리한 결과 정보 및 뷰 선택에 필요한 정보를 담는다.
  • ViewResolver : 컨트롤러 처리 결과를 보여줄 뷰를 결정한다. prefix + 뷰이름 + suffix
  • View : 컨트롤러 처리 결과 화면을 생성. JSP나 Velocity 템플릿 파일 등을 이용해서 클라이언트에 응답 결과를 전송



Home.jsp 동작 순서


프로젝트 클릭하고 Server 가동하게 되면 최초 URL은 http://localhost:8080/spring01/ 이런식으로 요청하게 된다.

web.xml 파일에 설정된 filter 태그를 통해 필터링을 하게 되고 DispatcherServlet이 요청을 가로채게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">
    <!-- 스프링의 환경설정 파일 로딩 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!-- 위에서 아래로... 제일 먼저 root-context.xml 파일을 로딩한다 -->
        <param-value>/WEB-INF/spring/root-context.xml</param-value>
    </context-param>
    <listener><!-- 위 Context 설정하는데 필요한 리스너 -->
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- 서블릿의 환경설정 -->
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <!--  DispatcherServlet이 최초 관문(or 짐검다리) 같은 역할을 한다(내장된 서블릿 클래스) -->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!--  servlet-context.xml 파일에서 설정을 읽어들여 객체를 생성한다 -->
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <!--  시작할때 첫번째 우선순위로 지정  -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <!--  url 패턴을 /로 정하면서 DispatcherServlet이 모든 요청을 가로채게 된다  -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
    <!-- 한글 처리를 위한 인코딩 필터 -->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
cs


root-servlet.xml 파일에는 별 다른 설정이 없는 상태이므로 넘어가고

servlet-context.xml 파일 설정에서 <annotation-driven />으로 인해 HandlerMapping 객체와 HandlerAdapter 객체가 생성된다.

이 두객체가 생성되어 어노테이션을 통해 매핑할 수 있는 상태가 된다.

이어 ViewResolver 객체도 생성한다. 이것은 이후에 컨트롤러에서 뷰 이름을 받아 접근 경로로 변환해주는 역할을 한다.

<context:component-scan>을 통해 컨트롤러 클래스들을 자바 빈 객체로 로드한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    
    <!-- Enables the Spring MVC @Controller programming model -->
    <!-- 어노테이션 사용 -->
    <annotation-driven />
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <!-- js, css, img 등 파일을 넣고 필요할 때 꺼내 쓸수 있게 매핑 해둔다. (안하면 DispatcherServlet이 걸림돌이 된다) -->
    <resources mapping="/resources/**" location="/resources/" />
    
    <!-- location="리소스의 실제 경로" mapping="리소스의 가상 url" 가상 url로 매핑 -->    
    <resources location="/WEB-INF/views/include/" mapping="/include/**" />
    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <!-- 뷰 리졸버 : 뷰(jsp 페이지)의 접두어,접미어 설정 -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>
    <!-- 스프링에서 관리하는 bean의 기본 디렉토리 -->
    <!-- 컴포넌트 스캔 : 해당 패키지 아래에 있는 컴포넌트들을 검색해 빈 객채로 등록 해준다 -->
    <context:component-scan base-package="com.example.spring01" />
    
</beans:beans>
cs


앞서 말했다 싶이 최초 URL은 http://localhost:8080/spring01/ 으로 요청하게 된다.
맨 뒤 '/' 가 HomeController 클래스의
@RequestMapping(value = "/", method="RequestMethod.GET)
에 따라 메서드가 실행되면서 'home'이란 문자열을 반환하게 된다.
반환된 'home'은 ViewResolver를 통해 prefix + 'home' + suffix
/WEB-INF/views/home.jsp 로 가게 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.example.spring01;
 
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
 
/**
 * Handles requests for the application home page.
 */
@Controller //현재 클래스를 스프링에서 관리하는 컨트롤러로 등록
public class HomeController {
    
    private static final Logger logger 
        = LoggerFactory.getLogger(HomeController.class);
    
    /**
     * Simply selects the home view to render by returning its name.
     */
    // annotation-driven이 @RequestMapping을 사용할 수 있게 해준다.
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);
        
        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
        
        String formattedDate = dateFormat.format(date);
        
        model.addAttribute("serverTime", formattedDate );
        // /WEB-INF/views/home.jsp로 포워딩
        return "home";
    }
 
}
cs



패키지 익스플로러로 보고 흐름 인지할 것