김영한님의 스프링 MVC 1편을 보면서 중요해보이는 부분을 메모하였다.
스프링의 MVC 구조를 파악하기 위해 직접 MVC 프레임워크를 간단하게 만드는 작업을 하였고, FrontControllerServlet을 앞 단에 두어 요청을 받는 식으로 프레임워크를 만들었다.
이때 점점 FrontControllerServlet을 개선하면서 실제 스프링 MVC 구조와 유사하게 바꿔갔다.
// FrontControllerServletV5
@WebServlet(name = "frontControllerServletV5", urlPatterns = "/front-controller/v5/*")
public class FrontControllerServletV5 extends HttpServlet {
private final Map<String, Object> handlerMappingMap = new HashMap<>(); // url:handler(controller) mapping
private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();
...
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 핸들러 가져오기 (조회)
Object handler = getHandler(request);
if (handler == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
// 2. 핸들러 어댑터 찾기
MyHandlerAdapter adapter = getHandlerAdapter(handler);
// 3. 핸들러 어댑터에서 모델뷰 추출 -> 4. 핸들러 어댑터를 통해 핸들러 실행 -> 5. 모델뷰 반환
ModelView mv = adapter.handle(request, response, handler);
String viewName = mv.getViewName(); // 논리 이름(new-form,...)
// 6. 뷰 리졸버를 통해 뷰 찾기 -> 7. view 반환
MyView view = viewResolver(viewName); // 논리 이름을 물리 이름으로 바꿔줌 (new-form -> /WEB-INF/views/new-form.jsp)
// 8. 뷰 렌더링
view.render(mv.getModel(),request,response);
}
...
// 1. 핸들러 가져오기 (조회)
Object handler = getHandler(request);
if (handler == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
private Object getHandler(HttpServletRequest request) {
String requestURI = request.getRequestURI();
return handlerMappingMap.get(requestURI); // URI에 맞는 핸들러 매핑
}
// 2. 핸들러 어댑터 찾기
MyHandlerAdapter adapter = getHandlerAdapter(handler);
private MyHandlerAdapter getHandlerAdapter(Object handler) {
for (MyHandlerAdapter adapter : handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
throw new IllegalArgumentException("handler adapter not found. handler=" + handler);
}
ModelView mv = adapter.handle(request, response, handler);
@Override
public ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
ControllerV4 controller = (ControllerV4) handler;
Map<String, String> paramMap = createParamMap(request);
Map<String, Object> model = new HashMap<>();
String viewName = controller.process(paramMap, model);
ModelView mv = new ModelView(viewName);
mv.setModel(model);
return mv;
}
이와 같은 코드가 실행될 것이다
ModelAndView 반환: 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView로 변환해서 반환한다.
viewResolver 호출: 뷰 리졸버를 찾고 실행한다.
// 6. 뷰 리졸버를 통해 뷰 찾기 -> 7. view 반환
MyView view = viewResolver(viewName); // 논리 이름을 물리 이름으로 바꿔줌 (new-form -> /WEB-INF/views/new-form.jsp)
...
private MyView viewResolver(String viewName) {
return new MyView("/WEB-INF/views/" + viewName + ".jsp");
}
// 8. 뷰 렌더링
view.render(mv.getModel(),request,response);
Reference
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1