728x90
Spring MVC에서 HandlerAdapater가 필요한 이유
위 사진은 Spring MVC 구조이다.
여기서 다른 건 다 알겠는데 왜 Handler Adapter 존재 이유에 대해 궁금해졌다.
V4구조 처럼 프론트 컨트롤러에서 요청에 대한 매핑 정보를 가져온 후 바로 해당 컨트롤러를 호출하면 되지 않나?
HandlerAdapater가 없다면
아래 코드는 HandlerAdapter가 없는 프론트 컨트롤러이다. 우리가 사용할 컨트롤러를 `controllerMap`에 저장해 두었다가 사용한다.
@WebServlet(name = "frontControllerServletV4", urlPatterns = "/front-controller/v4/*")
public class FrontControllerServletV4 extends HttpServlet {
//매핑 정보: 어떤 url이 호출되면 controllerV1 호출
private Map<String, ControllerV4> controllerMap = new HashMap<>();
public FrontControllerServletV4() {
controllerMap.put("/front-controller/v4/members/new-form", new MemberFormControllerV4());
controllerMap.put("/front-controller/v4/members/save", new MemberSaveControllerV4());
controllerMap.put("/front-controller/v4/members", new MemberListControllerV4());
}
...
}
컨트롤러를 저장하는 Map의 구조를 잘 보면
private Map<String, ControllerV4> controllerMap = new HashMap<>();
타입이 `ControllerV4` 로 고정되어 있다. 따라서 해당 프로젝트에서는 `ControllerV4`만 사용할 수 있다.
다양한 컨트롤러를 사용하고 싶다면 어댑터 패턴을 사용하면 된다.
Adapter 패턴을 적용한 HandlerAdapter 도입
- 요청이 온다
- 요청에 맞는 핸들러(컨트롤러) 조회
- 조회한 핸들러(컨트롤러)를 처리할 수 있는 핸들러 어댑터 조회
- 핸들러 어댑터를 통해서 조회한 핸들러를 처리할 수 있도록 변환, 어댑터가 핸들러(컨트롤러 대신 호출)
- ModelAndView 반환
핸들러 어댑터: 중간에 어댑터 역할을 하는 어댑터. 이 어댑터 덕분이 다양한 종류의 컨트롤러를 호출할 수 있다.
HandlerAdpater 직접 구현해보기
MyHandlerAdapter 구현해서 여러 타입 컨트롤러 사용하기
public interface MyHandlerAdapter {
boolean supports(Object handler);
ModelView handler(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException;
}
- `supports()`
- 요청에 맞는 핸들러(컨트롤러)를 매핑 정보에서 조회한 후, 해당 핸들러(컨트롤러)를 처리할 수 있는 어댑터를 어댑터 목록에서 찾아오는 역할
- 처리할 수 있는 핸들러이면 true반환, 아니면 false 반환
- `handle()`
- 핸들러(컨트롤러) 호출해주고 ModelAndView 를 반환
프론트 컨트롤러에 어댑터 적용
@WebServlet(name = "frontControllerServletV5", urlPatterns = "/front-controller/v5/*")
public class FrontControllerServletV5 extends HttpServlet {
/**
* 이전 코드
* >> private Map<String, ControllerV4> controllerMap = new HashMap<>();
* 지금은 아무 컨트롤러나 다 들어가야하므로 특정 컨트롤러 지정하는 것이 아니라 Object로 설정
*/
private final Map<String, Object> handlerMappingMap = new HashMap<>();
//어댑터가 여러개 담겨있고 그 중 하나를 꺼내 사용해야하므로 List 사용
private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();
public FrontControllerServletV5() {
//매핑 정보 넣기
initHandlerMappingMap();
//해당 컨트롤러 어댑터 List에 저장
initHandlerAdapters();
}
private void initHandlerMappingMap() {
handlerMappingMap.put("/front-controller/v5/v3/members/new-form", new MemberFormControllerV3());
handlerMappingMap.put("/front-controller/v5/v3/members/save", new MemberSaveControllerV3());
handlerMappingMap.put("/front-controller/v5/v3/members", new MemberListControllerV3());
}
private void initHandlerAdapters() {
handlerAdapters.add(new ControllerV3HandlerAdapter());
}
...
}
MyHandlerAdapter구현한 구현체는 모두 핸들러(컨트롤러)로 사용할 수 있다.
728x90
'Spring > Spring MVC' 카테고리의 다른 글
[Spring] HttpSession이 세션을 만들고, 가져오는 과정 (0) | 2024.10.26 |
---|---|
[Spring] Spring Session (1) | 2024.10.26 |
[웹 애플리케이션 이해] 동시 요청 - 멀티 쓰레드 (2) | 2024.10.07 |
[웹 애플리케이셔 이해] 서블릿, 서블릿 컨테이너 (0) | 2024.10.07 |
[Spring Boot] WAS를 사용하면 WS는 필요없다? (0) | 2024.10.06 |