🎨
스프링 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 프레임워크 만들기

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

Previous단순하고 실용적인 컨트롤러 - v4Next⭐️유연한 컨트롤러2 - v5(어댑터 도입, 인터페이스3,4 처리)

Last updated 3 years ago

Was this helpful?

인터페이스 3 뿐만 아니라 4 그리고 확장해서 인터페이스 종류와 상관없이 들어오는 모든 요청 URL과 이에 따른 인터페이스를 처리하기 위해 어댑터라는 개념을 도입한다.

  1. 어댑터 인터페이스를 구현한다. - supports : 들어오는 요청 지원 가능한지 판단 - ModelView handle : 처리 가능한 컨트롤러 호출하고 실행 (컨트롤러는 ModelView를 반환하는 컨트롤러)

package hello.servlet.web.frontcontroller.v5;

import hello.servlet.web.frontcontroller.ModelView;

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

//shift F6 : Rename
public interface MyHandlerAdapter {
    //들어오는 컨트롤러를 지원할 수 있는지 판단
    boolean supports(Object handler);
    ModelView handle(HttpServletRequest req, HttpServletResponse res,Object handler) throws ServletException, IOException;
}

2. 어댑터 구현체를 만든다. - Controller32를 처리할 수 있는 어댑터라고 하면 될 것 같다. 1) 첫번째로 들어온 객체가 ControllerV32인지 판단하는 supports를 구현한다. 인터페이스 ControllerV32의 인스턴스라면 true를 반환한다. Front Controller에서 supports로 ControllerV32만 걸러서 handle메서드를 실행할 것이기 때문에 아handle메서드는 handler가 ControllerV32라고 확정하고 생각해도 된다. 2) handle 메서드는 컨트롤러를 호출해서 실행하고, ModelView를 반환한다(ControllerV32와 동일)

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

import hello.servlet.web.frontcontroller.ModelView;
import hello.servlet.web.frontcontroller.v32.ControllerV32;
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 ControllerV32HandlerAdapter implements MyHandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return (handler instanceof ControllerV32);
    }
    @Override
    public ModelView handle(HttpServletRequest req, HttpServletResponse res, Object handler) throws ServletException, IOException {
        ControllerV32 controller = (ControllerV32) handler;
        Map<String, String> paramMap = createParamMap(req);
        ModelView mv = controller.process(paramMap);

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

}

3. Front Controller 새로 구성 기존에는 private Map<String,ControllerV4> controllerMap 으로 해서 특정 인터페이스만 받았지만, 이 부분의 value를 Object로 받음으로써 다양한 인터페이스들을 받을 수 있다!!!

  • initHandlerMappingMap() : URI에 따른 컨트롤러를 맵핑한다!

  • initHandlerAdapters() : MyHandlerAdapter 리스트인 handlerAdapters에 MyHandlerAdapter 구현체인 ControllerV32HandlerAdapter()를 넣는다!⭐️⭐️⭐️⭐️⭐️

  • service() getHandler(req) : 요청 URI에 따른 컨트롤러를 반환한다! 예를 들어 req가 v5/v3/new-form이면 handlerMappingMap에따라 MemberFormControllerV32가 리턴된다!(handler = MemberFormControllerV32) ❤️⭐️getHandlerAdapter(handler) : MyHandlerAdapter 리스트인 handlerAdapters를 다 뒤진다. (참고로 handlerAdapters에는 ControllerV32HandlerAdapter()가 있다) MyHandlerAdapter 인터페이스 변수 adapter는 리스트를 돌면서 ControllerV32HandlerAdapter를 받는다. =>조건문 검사 : adapter.supports(handler) => handler가 ControllerV32인터페이스 인스턴스인지 검사해서 맞다면 true가 리턴된다. (그렇지 않으면 IllegalArgumentException으로 예외처리) true이면 이 ControllerV32HandlerAdapter()가 adapter로 리턴된다! 이까지 정리가 되면 이제 끝났다! 다시 돌아와서 adapter의 handle메서드로 컨트롤러 호출, 실행하고 ModelView를 반환한다. 뷰리졸버로 뷰 매칭하고, 랜더링한다.

//import문 생략
@WebServlet(name="frontControllerServletV5", urlPatterns = "/front-controller/v5/*")
public class FrontControllerServletV5 extends HttpServlet {
    private final Map<String,Object> handlerMappingMap = new HashMap<>();
    private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();

    //생성자
    public FrontControllerServletV5(){
        initHandlerMappingMap();//맵핑 정보 넣는다!Object기 때문에 인터페이스 종료 상관없이 다 들어감.
        initHandlerAdapters();
    }
    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());
    }
    private void initHandlerAdapters() {
        handlerAdapters.add(new ControllerV32HandlerAdapter());//MyHandlerAdapter 구현체
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        //URI 맵핑하고 그에 따른 객체 리턴하는 함수로 구현!
        //코드가 깔끔해진다! 아 handler를 찾는구나!
        Object handler = getHandler(req);//핸들러 찾아와.MemberFormControllerV32반환.
        if(handler == null){
            res.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        MyHandlerAdapter adapter = getHandlerAdapter(handler);//핸들러 어댑터 찾아와.
        ModelView mv = adapter.handle(req, res, handler);//실제 컨트롤러 호출해서 ModelView 반환.

        String viewName = mv.getViewName();
        MyView view = viewResolver(viewName);
        view.render(mv.getModel(),req,res);
    }

    private MyHandlerAdapter getHandlerAdapter(Object handler) {//핸들러로 V32가 들어오면
        //handler = MemberFormControllerV32
        for (MyHandlerAdapter adapter : handlerAdapters) {//리스트 다 뒤진다.
            if(adapter.supports(handler)){//V32가 있으면 support는 지원할 수 있으므로 true리턴
                return adapter;//MyHandlerAdapter adapter를 리턴한다!
            }
        }
        throw new IllegalArgumentException("Handler Adapter를 찾을 수 없습니다.handler"+handler);
    }

    private Object getHandler(HttpServletRequest req) {
        //URI가 들어오면 handlerMappingMap에서 찾는다!
        //다양한 URL이 들어올 수  있고, 이에 따라 다양한 인터페이스가 실행되야하기 때문에 Object로 받는다!
        String requestURI = req.getRequestURI();// 이것은 /front-controller/v2/members/new-form와 같다
        return handlerMappingMap.get(requestURI);
    }
    private MyView viewResolver(String viewName) {
        return new MyView("/WEB-INF/views/" + viewName + ".jsp");
    }

}
구조 이해 정말 중요⭐️⭐️⭐️⭐️⭐️