스프링/스프링 MVC 패턴
핸들러 어댑터
chanhee01
2023. 2. 12. 13:46
핸들러 어댑터란 여러 핸들러를 설정하고 그 중 하나를 선택해야 할 상황이 있을 때 핸들러를 매핑해줄 수 있는 장치이다.
public interface MyHandlerAdapter {
boolean supports(Object handler);
ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException;
}
핸들러 어댑터 인터페이스를 만들어서 하나의 어댑터로 여러 사이트에 매핑 될 수 있다.
public FrontControllerServletV5() {
initHandlerMappingMap();
initHandlerAdapters();
}
private void initHandlerAdapters() {
handlerAdapters.add(new ControllerV3HandlerAdapter());
handlerAdapters.add(new ControllerV4HandlerAdapter());
}
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());
//V4 추가
handlerMappingMap.put("/front-controller/v5/v4/members/new-form", new MemberFormControllerV4());
handlerMappingMap.put("/front-controller/v5/v4/members/save", new MemberSaveControllerV4());
handlerMappingMap.put("/front-controller/v5/v4/members", new MemberListControllerV4());
}
프론트 컨트롤러에서 V3와 V4의 핸들러 어댑터를 추가해준다.
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object handler = getHandler(request);
if (handler == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
MyHandlerAdapter adapter = getHandlerAdapter(handler);
ModelView mv = adapter.handle(request, response, handler);
String viewName = mv.getViewName();
MyView view = viewResolver(viewName);
view.render(mv.getModel(), request, response);
}
웹 사이트에서 V3에 있는 url로 요청이 오면 V3 핸들러 어댑터로 연결된다.
public class ControllerV3HandlerAdapter implements MyHandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof ControllerV3);
}
@Override
public ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
ControllerV3 controller = (ControllerV3) handler;
Map<String, String> paramMap = createParamMap(request);
ModelView mv = controller.process(paramMap);
return mv;
}
private static Map<String, String> createParamMap(HttpServletRequest request) {
Map<String, String> paramMap = new HashMap<>();
request.getParameterNames().asIterator()
.forEachRemaining(paramName -> paramMap.put(paramName, request.getParameter(paramName)));
return paramMap;
}
V3의 핸들러 어댑터는 위와 같다.
supports 메서드는 핸들러가 V3이면 true를 반환해주고 아니면 실행을 안한다는 메서드이다.
handle 메서드는 V3에 있는 메서드들 중에서 하나를 호출한다는 것이다.
만약에 http:/localhost:8080/front-controller/v5/v3/members으로 접근했다면
public class MemberListControllerV3 implements ControllerV3 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
public ModelView process(Map<String, String> paramMap) {
List<Member> members = memberRepository.findAll();
ModelView mv = new ModelView("members");
// members라는 html 파일을 서버에 넘김
mv.getModel().put("members", members);
return mv;
}
}
위의 클래스로 접근 할 것이고, process를 실행해서 members라는 호출해서 사용자가 볼 수 있게 해줄 것이다.
반대로 V4를 사용할 경우에는 핸들러 어댑터가 V4에 접근해서 해당하는 클래스들을 실행 할 것이다.
이처럼 핸들러 어댑터는 하나의 인터페이스로 여러 상황에 접근해야할 경우가 있을 때 사용하면 된다.