장성호's
장성호's blog
장성호's
  • 분류 전체보기
    • 알고리즘
      • 백준
      • 이론
    • WEB
      • Spring 인강
      • 네트워크
    • 개인 프로젝트
      • 쇼핑몰 만들기

블로그 메뉴

  • 홈
  • 깃허브
전체 방문자
오늘
어제
반응형
hELLO · Designed By 정상우.
장성호's

장성호's blog

[Spring] 스프링 공부 #22
WEB/Spring 인강

[Spring] 스프링 공부 #22

2022. 4. 5. 13:40
반응형

단순하고 실용적인 컨트롤러 -v4

동작과정은 모델을 추가한 v3와 거의 유사하다.

컨트롤러가 더이상 ModelView를 반환하지 않고, ViewName만 반환한다.

 

컨트롤러 인터페이스

public interface ControllerV4 {
    /**
     * @param paramMap
     * @param model
     * @return viewName
     */

    String process(Map<String, String> paramMap, Map<String, Object> model);
}

 

프론트 컨트롤러

@WebServlet(name = "frontControllerServletV4", urlPatterns = "/front-controller/v4/*")
public class FrontControllerServletV4 extends HttpServlet {

    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());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("FrontControllerServletV3.service");

        String requestURI = request.getRequestURI();

        ControllerV4 controller = controllerMap.get(requestURI);
        if (controller == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        //paraMap을 넘겨줘야 한다.
        Map<String, String> paramMap = createParamMap(request);
        Map<String, Object> model = new HashMap<>();
        String viewName = controller.process(paramMap, model);

        //논리이름 ex) new-form, save
        MyView view = viewResolver(viewName);

        view.render(model, request, response);

    }

    private MyView viewResolver(String viewName) {
        MyView view = new MyView("/WEB-INF/views/" + viewName + ".jsp");
        return view;
    }

    private 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;
    }
}

이제 컨트롤러가 직접 뷰의 이름을 반환하기 때문에 더 편리해졌다.

 

유연한 컨트롤러 1 - v5

V3 형태와 V4 형태의 컨트롤러를 모두 사용하기 위해서는 어댑터 패턴을 적용해야 한다.

 

어댑터 패턴

클래스의 인터페이스를 사용자가 기대하는 다른 인터페이스로 변환하는 디자인 패턴이다.

호환성이 없는 인터페이스 때문에 함께 동작할 수 없는 클래스들이 함께 동작 가능하게 해준다.

 

어댑터 패턴을 적용한 구조

V3 컨트롤러와 V4 컨트롤러가 함께 동작하게 하기 위해서 핸들러 어댑터와 핸들러를 추가했다.

 

프론트 컨트롤러

@WebServlet(name = "frontControllerServletV5", urlPatterns = "/front-controller/v5/*")
public class FrontControllerServletV5 extends HttpServlet {

    private final Map<String, Object> handleMappingMap = new HashMap<>();
    private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();

    public FrontControllerServletV5() {
        initHandlerMappingMap();
        initHandlerAdapters();
    }


    private void initHandlerMappingMap() {
        handleMappingMap.put("/front-controller/v5/v3/members/new-form", new MemberFormControllerV3());
        handleMappingMap.put("/front-controller/v5/v3/members/save", new MemberSaveControllerV3());
        handleMappingMap.put("/front-controller/v5/v3/members", new MemberListControllerV3());
        
        handleMappingMap.put("/front-controller/v5/v4/members/new-form", new MemberFormControllerV4());
        handleMappingMap.put("/front-controller/v5/v4/members/save", new MemberSaveControllerV4());
        handleMappingMap.put("/front-controller/v5/v4/members", new MemberListControllerV4());
    }
    
    private void initHandlerAdapters() {
        handlerAdapters.add(new ControllerV3HandlerAdapter());
        handlerAdapters.add(new ControllerV4HandlerAdapter());
    }

    @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. handle 호출
        ModelView mv = adapter.handle(request, response, handler);
//      5. ModelView 반환


        String viewName = mv.getViewName();
//      6. viewResolver 호출
        MyView view = viewResolver(viewName);
//      7. MyView 반환


//      8. render(model) 호출
        view.render(mv.getModel(), request, response);

    }

    private MyHandlerAdapter getHandlerAdapter(Object handler) {
        for (MyHandlerAdapter adapter : handlerAdapters) {
            if (adapter.supports(handler)) {
                return adapter;
            }
        }
        throw new IllegalArgumentException("handler adapter를 찾을 수 없습니다. adapter=" + handler);
    }

    private Object getHandler(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        return handleMappingMap.get(requestURI);
    }

    private MyView viewResolver(String viewName) {
        MyView view = new MyView("/WEB-INF/views/" + viewName + ".jsp");
        return view;
    }

}

V3 핸들러 어댑터

public class ControllerV3HandlerAdapter implements MyHandlerAdapter {

    @Override
    public boolean supports(Object handler) {
        return (handler instanceof ControllerV3);
    }

//  4.handler 호출
    @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 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;
    }
}

V4 핸들러 어댑터

public class ControllerV4HandlerAdapter implements MyHandlerAdapter {

    @Override
    public boolean supports(Object handler) {

        return (handler instanceof ControllerV4);
    }

    //  4.handler 호출
    @Override
    public ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
        ControllerV4 controller = (ControllerV4) handler;

        Map<String, String> paramMap = createParamMap(request);
        HashMap<String, Object> model = new HashMap<>();

        String viewName = controller.process(paramMap, model);

        ModelView mv = new ModelView(viewName);
        mv.setModel(model);

        return mv;
    }

    private 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;
    }
}

 

출처

[인프런] 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -

www.inflearn.com

어댑터 패턴

https://ko.wikipedia.org/wiki/%EC%96%B4%EB%8C%91%ED%84%B0_%ED%8C%A8%ED%84%B4#:~:text=%EC%96%B4%EB%8C%91%ED%84%B0%20%ED%8C%A8%ED%84%B4(Adapter%20pattern)%EC%9D%80,%EB%93%A4%EC%9D%B4%20%ED%95%A8%EA%BB%98%20%EC%9E%91%EB%8F%99%ED%95%98%EB%8F%84%EB%A1%9D%20%ED%95%B4%EC%A4%80%EB%8B%A4. 

 

어댑터 패턴 - 위키백과, 우리 모두의 백과사전

 

ko.wikipedia.org

 

반응형
저작자표시 비영리 변경금지 (새창열림)

'WEB > Spring 인강' 카테고리의 다른 글

[Spring] 스프링 공부 #24  (0) 2022.04.06
[Spring] 스프링 공부 #23  (0) 2022.04.05
[Spring] 스프링 공부 #21  (0) 2022.04.05
[Spring] 스프링 공부 #20  (0) 2022.04.04
[Spring] 스프링 공부 #19  (0) 2022.03.31
    'WEB/Spring 인강' 카테고리의 다른 글
    • [Spring] 스프링 공부 #24
    • [Spring] 스프링 공부 #23
    • [Spring] 스프링 공부 #21
    • [Spring] 스프링 공부 #20
    장성호's
    장성호's
    장성호's 개발 공부 블로그

    티스토리툴바