인프런의 김영한님의 mvc 기본 1편을 들으면서 정리한 내용
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);
}
서블릿의 종속성이 제거된 인터페이스를 만들어준다.
과정
JSP는 request.getAttribure()로 데이터를 조회하기 때문에, 모델의 데이터를 꺼내서 request.setAttribute()로 담아둠.
@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;
}
}
컨트롤러가 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버전에서 엄청나게 바뀌진 않았지만 개발자 입장에서는 사용하기 편한 코드가 완성되었다.