스프링/3. 스프링 MVC

26. 모델 추가

sdafdq 2023. 8. 6. 19:34

기존 모델을 request로 썼었다.

 

 

이제는 컨트롤러에서 호출 시 MyView가 아닌 Model과 View가 섞인 ModelView를 반환, 또 바뀐점은 컨트롤러는 이제 /WEB-INF/views/save-result.jsp 이런 full path가 아닌 save-result논리 경로만 생각한다.

 

그리고,  viewResolver를 호출하면 MyView를 반환. 이 viewResolver에서 full path를 만들어서 반환해서 MyView로 반환해 준다.

 

 

@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 {
        ControllerV3 controller = controllerMap.get(request.getRequestURI());
        if(controller == null){
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        Map<String, String> paramMap = createParamMap(request);

        ModelView mv = controller.process(paramMap);
        MyView view = viewResolver(mv.getViewName());

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

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

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

기존이랑 비슷하고,

 

원래 기존에는 컨트롤러에게 전달할 때 유저요청의 파라미터라든지 그런 게 필요해서 request, 혹은 response 등 굉장히 servlet에 종속적이었다.

 

이제 이거를 paramMap 이라고 만들어 거기다 유저요청의 파라미터만 저장해두고,

그걸 컨트롤러에 넘긴다.

 

public class MemberSaveControllerV3 implements ControllerV3 {
    private MemberRepository memberRepository = MemberRepository.getInstance();
    @Override
    public ModelView process(Map<String ,String> paramMap) {
        String name = paramMap.get("username");
        int age = Integer.parseInt(paramMap.get("age"));
        Member member = new Member(name,age);
        Member savedMember = memberRepository.save(member);

        ModelView mv = new ModelView("save-result");
        mv.addData("member", savedMember);
        return mv;
    }
}

넘겨진 파라미터는 저렇게 사용되어진다.

저렇게 만들고, 논리경로와 함께 ModelView를 만들어 준 다음, view(jsp)에게 전할 데이터를 Model에 넣어준 뒤, ModelView를 return 시켜준다.

ModelView는 View에 표시할 정보들을 Model에 담는거기 때문에 같이 한 듯.

 

viewResolve는 프론트컨트롤러에서 만들어줬다. 이제 저기서 MyView를 return해준다.

 

그리고, view를 render() 해 줄때, model도 같이 보내준다.

 

    public void render(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }

    public void render(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        modelToRequestAttribute(model, request);
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }

    private static void modelToRequestAttribute(Map<String, Object> model, HttpServletRequest request) {
        model.forEach((key, value)-> request.setAttribute(key,value));
    }

이런 식으로 오버로드 해 줬다.

모델이 있을경우, 그냥 그걸 request.setAttribute로 담아준다. jsp는 request.getAttribute()를 사용하기 때문이다.

 

 

public class ModelView {
    private String viewName;
    private Map<String, Object> model = new HashMap<>();

    public ModelView(String viewName) {
        this.viewName = viewName;
    }


    public void addData(String key, Object obj){
        model.put(key, obj);
    }

    public String getViewName() {
        return viewName;
    }

    public void setViewName(String viewName) {
        this.viewName = viewName;
    }

    public Map<String, Object> getModel() {
        return model;
    }

    public void setModel(Map<String, Object> model) {
        this.model = model;
    }
}

getter, setter까지 추가해줬다.

addData는 내가 기존 밸류 건드리는거 막으려고 해놨다.

'스프링 > 3. 스프링 MVC' 카테고리의 다른 글

28. 유연한 컨트롤러  (0) 2023.08.07
27. 단순화  (0) 2023.08.06
25. 프론트 컨트롤러 공통로직(뷰 추가)  (0) 2023.08.06
24. 프론트 컨트롤러 도입.  (0) 2023.08.06
23. 프론트 컨트롤러  (0) 2023.08.06