본문 바로가기
Spring/스프링 MVC

[스프링 MVC 1편] 5 - (1) 스프링 MVC

by Poorm 푸름 2023. 11. 16.

 *  스프링 입문 = window, 스프링 MVC 1편 = Mac 으로 진행합니다

 *  진도 : 섹션5 - (1) ~ (3)

 *          : 자바 클래스명,         : 코드,         : 단축키

 

 

1. 스프링 MVC 전체 구조


 1) 직접 만든 프레임워크(= 섹션 4) 스프링 MVC 비교

  • FrontController → DispatcherServlet
  • handlerMappingMap HandlerMapping
  • MyHandlerAdapter HandlerAdapter
  • ModelView ModelAndView
  • viewResolver ViewResolver
  • MyView View


 2) DispatcherServlet
구조 

 

  • 스프링 MVC의 프론트 컨트롤러 = 디스패처 서블릿(DispatcherServlet)

  • DispacherServlet 도 부모 클래스에서 HttpServlet 을 상속 받아서 사용하고, 서블릿으로 동작
    (DispatcherServlet FrameworkServlet HttpServletBean HttpServlet)

  • 서블릿이 호출되면 HttpServlet 이 제공하는 serivce() 호출 (핵심 코드 DispacherServlet.doDispatch 참고)

 

더보기
// 1. 핸들러 조회
mappedHandler = getHandler(processedRequest); 
if (mappedHandler == null) {
        noHandlerFound(processedRequest, response);
return; }

//2.핸들러 어댑터 조회-핸들러를 처리할 수 있는 어댑터
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// 3. 핸들러 어댑터 실행 -> 4. 핸들러 어댑터를 통해 핸들러 실행 -> 5. ModelAndView 반환 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

//6. 뷰 리졸버를 통해서 뷰 찾기,7.View 반환
    view = resolveViewName(viewName, mv.getModelInternal(), locale, request);

// 8. 뷰 렌더링
    view.render(mv.getModelInternal(), request, response);
  }

 

3) 동작 순서

 

  1. 핸들러 조회: 핸들러 매핑을 통해 요청 URL에 매핑된 핸들러(컨트롤러)를 조회한다.
  2. 핸들러 어댑터 조회: 핸들러를 실행할 수 있는 핸들러 어댑터를 조회한다.
  3. 핸들러 어댑터 실행: 핸들러 어댑터를 실행한다.
  4. 핸들러 실행: 핸들러 어댑터가 실제 핸들러를 실행한다.
  5. ModelAndView 반환: 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView로 변환해서 반환한다.
  6. viewResolver 호출: 뷰 리졸버를 찾고 실행한다.
  7. View반환: 뷰 리졸버는 뷰의 논리 이름을 물리 이름으로바꾸고, 렌더링 역할을 담당하는 뷰객체를 반환한다.
  8. 뷰렌더링: 뷰를 통해서 뷰를 렌더링한다.

 

2.  핸들러 매핑과 핸들러 어댑터

 

<OldController>

 
 
  • 스프링 빈의 이름으로 핸들러를 찾을 수 있는 핸들러 매핑이 필요하다.
  • @Component("/springmvc/old-controller") = 빈의 이름으로 URL을 매핑

더보기
@Component("/springmvc/old-controller")
public class OldController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("OldController");
        return null;
    }
}

 

 

  1. 핸들러 매핑으로 핸들러 조회
       
    • HandlerMapping 순서대로 실행해서 핸들러 찾기

    • 빈 이름으로 핸들러 찾는 BeanNameUrlHandlerMapping 실행

  2. 핸들러 어댑터 조회

    • HandlerAdaptersupports() 순서대로 실행해서 핸들러 찾기

    • SimpleControllerHandlerAdapter가 Controller 인터페이스를 지원하므로 대상이 된다

  3. 핸들러 어댑터 실행

    • 디스패처 서블릿이 조회한 SimpleControllerHandlerAdapter를 실행 + 핸들러 정보 넘기기

    • SimpleControllerHandlerAdapter는 핸들러인 OldController를 내부에서 실행하고 결과 반환

 

 

<HttpRequestHandler>

 

  • 서블릿과 가장 유사한 핸들러
더보기
public class MyHttpRequestHandler implements HttpRequestHandler {
    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("MyHttpRequestHandler");
    }
}
 
  1. 핸들러 매핑으로 핸들러 조회
       
    • HandlerMapping 순서대로 실행해서 핸들러 찾기

    • 빈 이름으로 핸들러 찾는 BeanNameUrlHandlerMapping 실행에 성공하고 핸들러인 MyHttpRequestHandler 반환

  2. 핸들러 어댑터 조회

    • HandlerAdapter supports() 순서대로 실행해서 핸들러 찾기

    • HttpRequestHandlerAdapterHttpRequestHandler 인터페이스를 지원하므로 대상이 된다

  3. 핸들러 어댑터 실행

    • 디스패처 서블릿이 조회한HttpRequestHandlerAdapter 를 실행 + 핸들러 정보 넘기기

    • HttpRequestHandlerAdapter는 핸들러인 MyHttpRequestHandler를 내부에서 실행하고 결과 반환

 

< OldController - View >

 

  • OldController 실행하면 화면이 아무것도 뜨지 않는다  View 설정 필요
  • application.properties 에 코드 추가
더보기

[ src - java - hello .servlet - web -springmvc - old - OldController]

 

@Component("/springmvc/old-controller")
public class OldController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("OldController");
        return new ModelAndView("new-form");
    }
}

 

 

뷰 리졸버 호출 [ src - main - resources - application.properties ]

 

spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp

 

 

  1. 핸들러 어댑터 호출
       
    • 핸들러 어댑터를 통해 "new-form" (뷰 논리이름) 획득

  2. ViewResolver 호출

    • "new-form"이라는 뷰 이름으로 viewResolver 순서대로 호출

    • 빈 이름으로 찾는 BeanNameViewResolver로 등록된 뷰 찾기

    • 없다면 InternalResourceViewResolver로 호출하고 InternalResourceView 를 반환

  3. 뷰 InternalResourceView

    • InternalResourceView는 JSP처럼 forward()를 호출해서 처리할 수 있는 경우에 사용한다

  4. 렌더링 view.render()

    • view.render() 호출되고 InternalResourceView는 forward()를 사용해서 JSP 실행