앞서 만든 컨트롤러는 서블릿 종속성을 제거하고 뷰 경로의 중복을 제거하여 컨트롤러를 설계했다.
하지만 컨트롤러 인터페이스를 구현해야하는 입장에서 보면 항상 ModelView객체를 생성하여 반환해야하는 부분은 번거롭다.
이를 실용성을 가지도록 변경해보자
새로운 구조
- 컨트롤러가 ModelView를 반환하는 것이 아니라 ViewName만 반환한다.
컨트롤러 Interface
회원 Form 컨트롤러
- viewName만 반환해준다.
회원 Save 컨트롤러
- 모델을 parameter로 제공받기 때문에 새로운 회원객체를 만들어 model에 put해주면 된다.
- 역시 마찬가지로 viewName만 반환
회원 List 컨트롤러
모델을 처리하는 과정은 FrontController에서, 각 구현 컨트롤러는 모델에 put만 해주고 viewName만 반환하면 된다.
FrontController
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;
}
//paramMap을 넘겨줘야함
Map<String, String> paramMap = createParamMap(request);
Map<String, Object> model = new HashMap<>();
String viewName = controller.process(paramMap, 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> paramMap = new HashMap<>();
request.getParameterNames().asIterator()
.forEachRemaining(paramName->paramMap.put(paramName, request.getParameter(paramName)));
return paramMap;
}
}
- FrontController에서 Map으로 된 model을 생성하여 넘겨주고, 구현체에서 모델에 값을 담아 사용한다.
- 이를 통해 넘겨 받은 viewName을 통해 render를 하여 View를 클라이언트에게 제공한다.
프레임워크나 공통 기능이 많은 일을 처리해야 사용하는 사용자(각 구현체)가 편리해진다.
반응형
'Spring > Spring MVC' 카테고리의 다른 글
Spring MVC 전체 구조 (0) | 2021.04.30 |
---|---|
유연한 컨트롤러 (0) | 2021.04.28 |
Model 추가 (0) | 2021.04.18 |
View 분리 (0) | 2021.04.14 |
프론트 컨트롤러 패턴 (0) | 2021.04.13 |