4️⃣   V4

🤔💭 구현체 컨트롤러들의 코드가 단순해져서 좋긴 한데, 항상 ModelView 객체를 생성해야 한다는 점이 조금 불편하네..?

출처: 김영한의 스프링MVC (인프런)

💡 이번에는 각 구현체 컨트롤러에서 새로운 객체를 생성하지 않아도 값을 넘길 수 있도록 하고, 컨트롤러들은 오로지 viewPath 만 넘길 수 있도록 개선해보자 !

⚡️   4-1. Controller4

  • V4 에서 사용할 인터페이스는 Model 로 사용할 Map 객체를 파라미터로 전달되도록 할 것이다.
package hello.servlet.web.frontcontroller.v4;

import java.util.Map;

public interface ControllerV4 {
    /**
     *
     * @param paramMap
     * @param model
     * @return viewName
     */
    String process(Map<String, String> paramMap, Map<String, Object> model);
}

⚡️   4-2. FrontControllerServletV4

  • 전체적인 구조는 V3 과 크게 다르지 않지만, V3 에서 각 구현체 컨트롤러별로 ModelView 객체를 생성해야 했다는 점을 개선하기 위해 오로지 프론트 컨트롤러에서만 Map 객체를 생성할 것이다.

  • 생성한 Map 객체를 파라미터로 넘겨서 구현체 컨트롤러에서는 해당 파라미터에 값을 put 하기만 하면 된다.



@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(); //요청주소 uri 를 그대로 받아올 수 있다.

        ControllerV4 controller = controllerMap.get(requestURI); //맵에서 해당 uri 의 구현객체를 꺼내온다.
        if(controller == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND); //웹 상태코드를 404로 바꾸고 리턴.
            return;
        }

        //파라미터값을 가져와서 paramMap 에 넣는다.
        Map<String, String> paramMap = createParamMap(request);
        //모델 객체를 생성..
        Map<String, Object> model = new HashMap<>();
        //파라미터값(paramMap) 과 모델 객체를 컨트롤러에 넘겨서 비즈니스 로직을 수행하게 한다.
        String viewName = controller.process(paramMap, model);

        MyView view = viewResolver(viewName);

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

⚡️   4-3. 각 구현체 컨트롤러들…


public class MemberFormControllerV4 implements ControllerV4 {

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

}


public class MemberSaveControllerV4 implements ControllerV4 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

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

        Member member = new Member(username, age);
        memberRepository.save(member);

        model.put("member", member);
        return "save-result";
    }
}

public class MemberListControllerV4 implements ControllerV4 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

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

🤔💭 아주 완벽해졌어! 이제 더 손볼 곳이 없겠는걸! ( 정말 그럴까 … ? )