MVC 프레임 워크 2

JIWOO YUN·2023년 11월 23일
0

MVC기본 1

목록 보기
3/5
post-custom-banner

인프런의 김영한님의 mvc 기본 1편을 들으면서 정리한 내용


v3부터


V3버전 - model을 추가

  • 서블릿 종속성 제거진행

컨트롤러 입장에서는 HttpServletRequest와 HttpServletResponse가 꼭 필요하지않음.

파라미터 정보는 자바의 Map으로 대신 넘기면 컨트롤러가 서블릿 기술을 몰라도 동작이 가능해진다.

  • 뷰 이름 중복 제거
    • 컨트롤러는 뷰의 논리 이름만 반환 -> 물리 위치의 이름은 프론트 컨트롤러에서 처리하도록 단순화 진행.
    • 이렇게 할 경우 뷰의 폴더 위치가 함께 이동해도 프론트 컨트롤러만 고치면 됨.

ModelView 클래스 생성

@Getter
@Setter
public class ModelView {

    private String ViewName;
    private Map<String,Object> model = new HashMap<>();

    public ModelView(String viewName) {
        ViewName = viewName;
    }


}

서블릿의 종속성을 제거하기 위해서 Model을 직접 만들고, 추가로 View 이름까지 전달하는 객체를 만들자.

public interface ControllerV3 {

    ModelView process(Map<String,String> paramMap);
}

서블릿의 종속성이 제거된 인터페이스를 만들어준다.

과정

  1. 매핑 정보를 통해서 컨트롤러를 조회한다.
  2. 조회한 컨트롤러를 통해서 컨트롤러를 조회 -> 각 컨트롤러는 ModelView를 반환해준다.(서블릿 종속성 제거) -> 서블릿 종속성 제거했기 때문에 request.setAddtribute() 사용이 불가능 -> Model이 별도로 필요하다.
  3. FrontController는 받은 ModelView를 통해서 ViewResolver 함수를 통해 물리 경로를 지정해준다.
  4. render할때 model을 가져가서 render를 진행한다.

JSP는 request.getAttribure()로 데이터를 조회하기 때문에, 모델의 데이터를 꺼내서 request.setAttribute()로 담아둠.

  • 그후 JSP로 포워드해서 JSP를 렌더링 진행.
@WebServlet(name = "frontControllerServletV3" , urlPatterns = "/front-controller/v3/*")
public class FrontControllerServletV3 extends HttpServlet {


    private Map<String, ControllerV3> controllerMap = new HashMap<>();

    //미리 생성자를 통해서 맵핑을 해둠.
    public FrontControllerServletV3() {
        controllerMap.put("/front-controller/v3/members/new-form",new MemberFormControllerV3());
        controllerMap.put("/front-controller/v3/members/save",new MemberSaveControllerV3());
        controllerMap.put("/front-controller/v3/members",new MemberListControllerV3());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String requestURI = request.getRequestURI();

        ControllerV3 controller = controllerMap.get(requestURI);

        if(controller == null){
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        Map<String, String> paramMap = createParamMap(request);
        ModelView mv = controller.process(paramMap);

        String viewName = mv.getViewName();
        //물리경로 추가
        MyView view = viewResolver(viewName);


        view.render(mv.getModel(),request,response);
    }

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

    private static Map<String, String> createParamMap(HttpServletRequest request) {
        Map<String,String> paramMap = new HashMap<>();
        //request 의 파라미터 이름
        request.getParameterNames().asIterator()
                .forEachRemaining(paramName -> paramMap.put(paramName, request.getParameter(paramName)));
        return paramMap;
    }
}

V4 버전 - 단순하고 실용적인 컨트롤러


컨트롤러가 ViewName만 반환하게 변경

public interface ControllerV4 {

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

model 객체는 파라미터로 전달 -> FrontController에서 생성되기 때문에 각자 따로 생성할 필요가없어짐.

public class MemberFormControllerV4 implements ControllerV4 {
    @Override
    public String process(Map<String, String> paramMap, Map<String, Object> model) {
        return "new-form";
    }
}

위의 코드처럼 뷰의 논리 이름만 반환을 해준다.

회원 등록이나 회원 조회의 경우 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 {
        String requestURI = request.getRequestURI();

        ControllerV4 controller = controllerMap.get(requestURI);

        if(controller == null){
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        Map<String, String> paramMap = createParamMap(request);
        //model 객체 생성
        HashMap<String,Object> model = new HashMap<>();
        String viewName = controller.process(paramMap, model);

        //논리이름에다가 물리 경로를 추가해준다.
        MyView view = viewResolver(viewName);


        //생성된 model을 넘겨줘서 render에서 request에 넣어줌.
        view.render(model,request,response);
    }

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

    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버전에서 엄청나게 바뀌진 않았지만 개발자 입장에서는 사용하기 편한 코드가 완성되었다.

profile
열심히하자
post-custom-banner

0개의 댓글