이전 포스팅에서 만든 v3 컨트롤러는 서블릿 종속성을 제거하고 뷰 경로의 중복을 제거하는 잘 설계한 컨트롤러이다.

그런데 실제 컨트롤러 인터페이스를 구현하는 개발자 입장에서 본다면? 항상 ModelView객체를 생성하고

반환해야하는 부분이 번거롭다.

좋은 프레임워크란 아키텍처도 중요하지만, 그와 더불어 실제 개발하는 개발자가 단순하고 편리하게 사용 할 수 있어야한다.

 

이번에는 v3를 조금 변경하여 개발자들이 편리하게 개발할 수 있는 v4를 만들어보았다.

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/lecture/71192?volume=1.00&tab=note&speed=0.75&mm=close

기본적인 구조는 이전 버전과 같다. 대신에 컨트롤러가 ModelView를 반환하지 않고 ViewName을 반환한다.

package hello.servlet.web.frontcontroller.v4;

import java.util.Map;

public interface ControllerV4 {

    /**
     *
     * @param paraMap
     * @param model
     * @return viewName
     */
    String process(Map<String, String> paraMap, Map<String,Object> model);
}

먼저 Controller4인터페이스를 만들었다.

이전과는 다르게 파라미터로 model객체를 넘겨준다(빈 객체)

반환값은 문자열로 논리주소를 반환한다.

package hello.servlet.web.frontcontroller.v4.controller;


import hello.servlet.web.frontcontroller.v4.ControllerV4;

import java.util.Map;

public class MemberFormControllerV4 implements ControllerV4 {

    @Override
    public String process(Map<String, String> paraMap, Map<String, Object> model) {
        return "new-form" ;
    }
}
package hello.servlet.web.frontcontroller.v4.controller;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import hello.servlet.web.frontcontroller.v4.ControllerV4;

import java.util.Map;

public class MemberSaveControllerV4 implements ControllerV4 {

    MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    public String process(Map<String, String> paraMap, Map<String, Object> model) {
        String username = paraMap.get("username");
        int age = Integer.parseInt(paraMap.get("age"));

        Member member = new Member(username,age);
        memberRepository.save(member);
        model.put("member",member);
        return "save-result";
    }
}
package hello.servlet.web.frontcontroller.v4.controller;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import hello.servlet.web.frontcontroller.v4.ControllerV4;

import java.util.List;
import java.util.Map;

public class MemberListControllerV4 implements ControllerV4 {

    MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    public String process(Map<String, String> paraMap, Map<String, Object> model) {
        List<Member> members = memberRepository.findAll();
        model.put("members",members);
        return "members";
    }
}

회원 가입, 회원 저장, 회원 목록 컨트롤러들도 만들었다.

저장, 목록에서 모델에 데이터를 put으로 넣고 

논리 이름을 반환하고 있다.

package hello.servlet.web.frontcontroller.v4;

import hello.servlet.web.frontcontroller.MyView;
import hello.servlet.web.frontcontroller.v4.controller.MemberFormControllerV4;
import hello.servlet.web.frontcontroller.v4.controller.MemberListControllerV4;
import hello.servlet.web.frontcontroller.v4.controller.MemberSaveControllerV4;

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

@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> paraMap = createParamMap(request);
        Map<String, Object> model = new HashMap<>();  // 추가됨

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

        MyView view = viewResolver(viewName);

        view.render(model,request,response);
    }

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

    private Map<String, String> createParamMap(HttpServletRequest request) {
        Map<String, String> paraMap = new HashMap<>();
        request.getParameterNames().asIterator()
                .forEachRemaining(paramName -> paraMap.put(paramName, request.getParameter(paramName)));
        return paraMap;
    }
}

model을 넘겨주는것이 추가 되고 

viewName에 각각 컨트롤러의 반환값이 들어온다.

view객체는 viewName만 받고  render()는 파라미터값으로 model만, request, response만 받으면 된다.

바뀐 것은 많이 없지만 개발자입장에서 군더더기 없는 코드를 작성할 수 있다.

 

 

'웹프로그래밍 > 스프링 MVC' 카테고리의 다른 글

30. 유연한 컨트롤러2 - V5  (0) 2022.03.30
29. 유연한 컨트롤러1 - V5  (0) 2022.03.30
27. Model 추가 - V3  (0) 2022.03.28
26. View 분리 - v2  (0) 2022.03.26
25. 프론트 컨트롤러 도입 - v1  (0) 2022.03.25

+ Recent posts