서블릿이란?
- 서블릿이란 동적 페이지를 만들 때 사용되는 자바 기반의 웹 애플리케이션 프로그램밍 기술이다.
- 다시말해서 서블릿은 웹 프로그래밍에서 클라이언트 요청을 처리하고 처리 결과를 클라이언트에게 전송하는 기술이다.
- 자바로 구현된 CGI이다.
- html을 사용해서 요청에 응답한다.
- java thread를 통해서 동작한다.
- MVC 패턴중 Controller로 이용된다.
- HTTP 변경시 Servlet을 재 컴파일한다.
- HTTP 프로토콜 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속받는다.
- UDP보다 속도가 느리다.
SpringMVC 구조
- Spring MVC의 구조는 위와 같다.
- 동작순서는 아래와 같다.
1. 핸들러 조회: 핸들러 매핑을 통해 요청 URL에 매핑된 핸들러를 조회한다.
2. 핸들러 어댑터 조회: 핸들러를 실행할 수 있는 핸들러 어댑터를 조회한다.
3. 핸들러 어댑터 실행: 핸들러 어댑터를 실행한다.
4. 핸들러 실행: 핸들러 어댑터가 실제 핸들러를 실행한다.
5. ModelAndView 반환: 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView로 변환해서 반환한다.
6. viewResolver 호출: 뷰 리졸버를 찾고 실행한다.
7. View 반환: 뷰 리졸버는 뷰의 논리 이름을 물리 이름으로 바꾸고, 렌더링 역할을 담당하는 뷰 객체를 반환한다.
8. 뷰 렌더링: 뷰를 통해서 뷰를 렌더링 한다.
- 핸들러 매핑 인터페이스: org.springframework.web.servlet.HandlerMapping
- 핸들러 어댑터 인터페이스: org.springframework.web.servlet.HandlerAdapter
- 뷰 리졸버 인터페이스: org.springframework.web.servlet.ViewResolver
HandlerMapping (핸들러 매핑)
- 핸들러 매핑: 해당 요청을 처리할 수 있는 핸들러를 찾는다,
- 먼저 1순위로 RequestMappingHandlerMapping 을 조회한다. -> @RequestMapping이라는 어노테이션이 붙었을때 사용가능하다.실무에서는 거의 99프로 이 매핑을 사용하게 된다.
- 만약 @RequestMapping 어노테이션이 붙지 않은 요청일 경우 2순위로 BeanNameUrlHandlerMapping을 조회한다. -> 스프링 빈의 이름으로 핸들러를 찾는다.
HandlerAdaper (핸들러 어댑터)
- 핸들러 어댑터: 핸들러 매핑을 통해서 찾은 핸들러를 실행할 수 있는 해들러 어댑터가 필요하다.
- 먼저 1순위로 RequestMappingHandlerAdapter 를 조회한다. -> @RequestMapping이라는 어노테이션이 붙었을때 사용가능하다.실무에서는 거의 99프로 이 매핑을 사용하게 된다.
- 2순위로 HttpRequestHandlerAdapter 를 조회한다. -> HttpRequestHandler 처리
- 3순뤼로 SimpleControllerHandlerAdapter 를 조회한다. -> Controller 인터페이스를 처리한다.
실무에서는 거의 @RequestMapping 형식으로 요청을 받기 때문에 RequestMappingHandlerMapping 와 RequestMappingHandlerAdapter 를 사용한다.
핸들러 매핑과 어댑터의 동작 과정
- MyHttpRequestHandler -> HttpRequestHandler를 상속받아서 핸들러를 임의로 구현한다.
package hello.servlet.web.springmvc.old;
import org.springframework.stereotype.Component;
import org.springframework.web.HttpRequestHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component("/springmvc/request-handler")
public class MyHttpRequestHandler implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("MyHttpRequestHandler.handleRequest");
}
}
- 위와 같이 핸들러가 구성 되어있으면 Spring은 어떻게 동작하는지 알아보자.
- 먼저 @RequestMapping 형식이 아니기 때문에 1순위인 RequestMappingHandlerMapping이 아닌 2순위인 BeanNameUrlHandlerMapping가 실행 되어 MyHttpRequestHandler를 반환한다.
- 그 다음으로 HandlerAdapter의 supports()를 순서 대로 호출한다.
- 먼저 @RequestMapping 형식이 아니기 때문에 1순위인 RequestMappingHandlerAdapter가 아닌 HttpRequestHandlerAdapter를 호출한다.
- HttpRequestHandlerAdapter 가 HttpRequestHandler 인터페이스를 지원하므로 대상이 된다.
- 디스패처 서블릿이 조회한 HttpRequestHandlerAdapter 를 실행하면서 핸들러 정보도 함께 넘겨준다.
- HttpRequestHandlerAdapter 는 핸들러인 MyHttpRequestHandler 를 내부에서 실행하고, 그 결과를 반환한다.
뷰 리졸버
- 뷰 리졸버: 컨트롤러가 반환한 논리 뷰 이름을 실제 물리 뷰 경로로 변경한다.
- 1순위로: BeanNameViewResolver를 호출한다. -> 빈 이름으로 뷰를 찾아서 반환한다.
- 2순위로: InternalResourceViewResolver -> JSP를 처리할 수 있는 뷰를 반환한다.
- 동작과정을 보자
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component("/springmvc/old-controller")
public class OldController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("OldController.handleRequest");
return new ModelAndView("new-form");
}
}
- 먼저 1순위인 BeanNameViewResolver를 호출한다. -> 하지만 new-form 이라는 이름의 스프링 빈으로 등록된 뷰를 찾아야 하는데 없다.
- 그렇기 때문에 InternalResourceViewResolver 가 호출된다.
- InternalResourceViewResolver는 InternalResourceView 를 반환한다.
- InternalResourceView 는 JSP처럼 포워드 forward() 를 호출해서 처리할 수 있는 경우에 사용한다.
- view.render() 가 호출되고 InternalResourceView 는 forward() 를 사용해서 JSP를 실행한다.
REFERENCES
- 김영한님의 스프링 MVC 1편
- kohen.tistory.com/29
'Spring' 카테고리의 다른 글
싱글톤 컨테이너 (0) | 2022.02.26 |
---|---|
스프링 타입 컨버터 (0) | 2022.02.26 |
서블릿 예외처리 (0) | 2022.02.26 |
빈 스코프 (0) | 2022.02.26 |
빈 생명주기와 콜백 (0) | 2022.02.26 |