🎨
스프링 MVC
  • Initial page
  • 웹 애플리케이션 이해
    • 웹 서버, 웹 애플리케이션 서버
    • 서블릿
    • 동시 요청 - 멀티 쓰레드
    • HTML, HTTP API, CSR, SSR
    • 자바 백엔드 웹 기술 역사
  • 2. 서블릿
    • 프로젝트 생성
    • Hello 서블릿
    • HttpServletRequest - 개요
    • HttpServletRequest - 기본 사용법
    • HTTP 요청 데이터 - 개요
    • HTTP 요청 데이터 - GET 쿼리 파라미터
    • HTTP 요청 데이터 - POST HTML Form
    • HTTP 요청 데이터 - API 메시지 바디 - 단순 텍스트
    • HTTP 요청 데이터 - API 메시지 바디 - JSON
    • HttpServletResponse - 기본 사용법
    • HTTP 응답 데이터 - 단순 텍스트, HTML
    • HTTP 응답 데이터 - API JSON
    • Summary
  • 3. 서블릿, JSP, MVC 패턴
    • 회원관리 웹 애플리케이션 요구사항
    • 서블릿으로 회원 관리 웹 애플리케이션 만들기
    • NoClassDefFoundError(WebServlet) TroubleShooting
    • NumberFormatException TroubleShooting
    • HTML에서 한글이 보이지 않는 이슈 TroubleShooting
    • JSP로 회원 관리 웹 애플리케이션 만들기
    • MVC 패턴 - 개요
    • MVC 패턴 - 적용
    • MVC 패턴 - 한계
    • Summary
  • 4. MVC 프레임워크 만들기
    • 프론트 컨트롤러 패턴 소개
    • 프론트 컨트롤러 도입 - v1
    • View 분리 - v2
    • Model 분리 - v3
    • 단순하고 실용적인 컨트롤러 - v4
    • ⭐️유연한 컨트롤러1 - v5(어댑터 도입, 인터페이스3 처리)
    • ⭐️유연한 컨트롤러2 - v5(어댑터 도입, 인터페이스3,4 처리)
    • Summary
  • 5. 스프링 MVC - 구조 이해
    • ⭐️스프링 MVC 전체 구조
    • 핸들러 매핑과 핸들러 어댑터
    • 뷰 리졸버
    • 스프링 MVC - 시작하기
    • @Controller 등장!⭐️
    • 스프링 MVC - 컨트롤러 통합
    • 스프링 MVC - 실용적인 방식
    • Summary
  • 6. 스프링 MVC - 기본 기능
    • 프로젝트 생성
    • 로딩 간단히 알아보기
    • 요청 매핑
    • 요청 매핑 - API 예시
    • HTTP 요청 - 기본, 헤더 조회
    • HTTP 요청 파라미터 - 쿼리 파라미터, HTML, Form
    • HTTP 요청 파라미터 - @RequestParam
    • HTTP 요청 파라미터 - @ModelAttribute
    • HTTP 요청 메시지 - 단순 텍스트
    • HTTP 요청 메시지 - JSON
    • 응답 - 정적 리소스, 뷰 템플릿
    • HTTP 응답 - HTTP API, 메시지 바디에 직접 입력
    • HTTP 메시지 컨버터
    • 요청 매핑 핸들러 어댑터 구조
    • Summary
  • 7. 스프링 MVC - 웹 페이지 만들기
    • 프로젝트 생성
    • 요구사항 분석
    • 상품 도메인 개발
    • 상품 서비스 HTML
    • 상품 목록 - 타임리프
    • 상품 상세
    • 상품 등록 폼
    • 상품 등록 처리 - @ModelAttribute
    • 상품 수정
    • PRG Post/Redirect/Get
    • RedirectAttributes
    • Summary
  • What's Next?
Powered by GitBook
On this page

Was this helpful?

  1. 4. MVC 프레임워크 만들기

⭐️유연한 컨트롤러2 - v5(어댑터 도입, 인터페이스3,4 처리)

핵심 - 어댑터 목록 조회

handlerAdapters는 핸들러어댑터목록이다! List<MyHandlerAdapter>에는 MyHandlerAdapter 인터페이스를 구현한 V3 핸들러 어댑터, V4 핸들러 어댑터,...등이 있다!

⭐️for(MyHandlerAdapter : List<MyHandlerAdapter>)⭐️⭐️⭐️⭐️⭐️ 부모 인터페이스는 자식 객체를 품을 수 있다! 그러므로 인터페이스인 MyHandlerAdapter 타입의 리스트를 만들면 V3든 V4든 핸들러 어댑터 종류 상관없이 리스트에 저장이 가능하다!

private MyHandlerAdapter getHandlerAdapter(Object handler) {
    //handler = MemberFormControllerV4
    for (MyHandlerAdapter adapter : handlerAdapters) {//리스트 다 뒤진다.
        if(adapter.supports(handler)){//Controller3Adapter 먼저 검사하고, 조건 불충족하면 다음 Controller4Adapter 조건 검사
            return adapter;//MyHandlerAdapter adapter를 리턴한다!
        }
    }
    throw new IllegalArgumentException("Handler Adapter를 찾을 수 없습니다.handler"+handler);
}

이제 컨트롤러4가 들어왔을 때도 어댑터로 처리할 수 있는 코드를 작성해본다. 다음 3가지만 추가해서 수정해주면 메인 코드에서는 수정할 것이 없다! initHandlerMappingMap()과 initHandlerAdapters()은 설정을 하는 부분이기 때문에 이 부분도 메인에서 분리하고, 컨트롤러 핸들링하는 어댑터만 추가해서 구현해주면 메인에는 수정할 것이 하나도 없어지게 된다!

이렇게 인터페이스에 의존하도록 설계하면 OCP를 만족하면서, 확장성 좋게 추가 및 수정이 가능하고, 메인 코드는 전혀 수정할 필요가 없게 된다!

  • initHandlerMappingMap() : 컨트롤러4 uri가 들어와도 맵핑할 수 있도록 맵에 추가한다.

  • initHandlerAdapters() : handlerAdapters 리스트에 컨트롤러4에 대한 처리할 수 있도록 ControllerV4HandlerAdapter를 추가한다!

private void initHandlerMappingMap() {
    handlerMappingMap.put("/front-controller/v5/v32/members/new-form",new MemberFormControllerV32());
    handlerMappingMap.put("/front-controller/v5/v32/members/save",new MemberSaveControllerV32());
    handlerMappingMap.put("/front-controller/v5/v32/members",new MemberListControllerV32());
    //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());
}
private void initHandlerAdapters() {
    handlerAdapters.add(new ControllerV32HandlerAdapter());//MyHandlerAdapter 구현체로 ControllerV32 추가!
    handlerAdapters.add(new ControllerV4HandlerAdapter());//MyHandlerAdapter 구현체로 ControllerV4 추가!
}
  • MyHandlerAdapter를 상속받는 ControllerV4HandlerAdapter 구현 핵심⭐️❤️ 원래 ControllerV4는 String 타입의 View name 만을 반환하지만, 전체 어댑터 구조를 ModelView를 반환하도록 설계하였기에 이 View name을 가지고 어댑터가 ModelView를 생성해서 리턴하도록 한다! ControllerV4에서와 똑.같.이 빈 Map 객체 model 먼저 생성하고, 컨트롤러에 넣어주면서 컨트롤러 내부에서 비즈니스 로직 실행하며 model에 데이터 넣어준다.

package hello.servlet.web.frontcontroller.v5.adapter;

import hello.servlet.web.frontcontroller.ModelView;
import hello.servlet.web.frontcontroller.v4.ControllerV4;
import hello.servlet.web.frontcontroller.v5.MyHandlerAdapter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class ControllerV4HandlerAdapter implements MyHandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return (handler instanceof ControllerV4);
    }

    @Override
    public ModelView handle(HttpServletRequest req, HttpServletResponse res, Object handler) throws ServletException, IOException {
        //handler를 V4로 캐스팅한다!(전체 부모 객체 Object로 들어온 애를 그 하위 버전 인터페이스로 캐스팅하는 것이다~!)
        ControllerV4 controller = (ControllerV4) handler;
        
        HashMap<String, Object> model = new HashMap<>();
        Map<String, String> paramMap = createParamMap(req);

        String viewName = controller.process(paramMap, model);//Model과 paramMap 두개 파라미터를 받는다!

        //어댑터는 viewName가지고 ModelView를 생성해준다!!!
        //Model과 View를 셋팅해준다!
        ModelView mv = new ModelView(viewName);//뷰 이름 셋팅
        mv.setModel(model);//모델 셋팅

        return mv;
    }
    private Map<String, String> createParamMap(HttpServletRequest req) {
        //컨트롤러의 process에 Map<String,String> paramMap을 넘겨줘야한다!!!!!!
        Map<String,String> paramMap = new HashMap<>();
        req.getParameterNames().asIterator()
                .forEachRemaining(paramName->paramMap.put(paramName, req.getParameter(paramName)));
        return paramMap;
    }
}
Previous⭐️유연한 컨트롤러1 - v5(어댑터 도입, 인터페이스3 처리)NextSummary

Last updated 3 years ago

Was this helpful?