MVC 프레임워크
프론트 컨트롤러 패턴
- 특징
- 프론트 컨트롤러 서블릿 하나로 클라이언트의 요청 받음
- 프론트 컨트롤러가 요청에 맞는 컨트롤러 찾아 호출
- 공통 처리
- 프론트 컨트롤러 제외한 나머지 컨트롤러 서블릿 사용x
프론트 컨트롤러 도입1
- 컨트롤러 인터페이스-> - 회원 등록 컨트롤러, 회원 저장 컨트롤러, 회원 목록 컨트롤러
void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
프론트 컨트롤러
@WebServlet(name = "frontControllerServletV1", urlPatterns = "/front-controller/v1/*") public class FrontControllerServletV1 extends HttpServlet { private Map<String, ControllerV1> controllerMap = new HashMap<>(); public FrontControllerServletV1() { controllerMap.put("/front-controller/v1/members/new-form", new MemberFormControllerV1()); controllerMap.put("/front-controller/v1/members/save", new MemberSaveControllerV1()); controllerMap.put("/front-controller/v1/members", new MemberListControllerV1()); } @Override protected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { String requestURI = request.getRequestURI(); ControllerV1 controller = controllerMap.get(requestURI); if (controller == null) { response.setStatus(HttpServletResponse.SC_NOT_FOUND); return; } controller.process(request, response); } }
View 분리2
MyView
private String viewPath; public MyView(String viewPath) { this.viewPath = viewPath; } public void render(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath); dispatcher.forward(request, response); }
- 컨트롤러 인터페이스
구현MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
Override public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { return new MyView("/WEB-INF/views/new-form.jsp"); }
- 프론트 컨트롤러
MyView view = controller.process(request, response); view.render(request, response);
Model 추가3
- 서블릿 종속성 제거: 요청 파라미터 정보-> 자바의 Map, request 객체-> 별도의 Model 객체
- 뷰 이름 중복 제거: 컨트롤러는 뷰의 논리 이름 반환
ModelView
private String viewName; private Map<String, Object> model = new HashMap<>(); public ModelView(String viewName) { this.viewName = viewName; }
컨트롤러 인터페이스
ModelView process(Map<String, String> paramMap);
구현
@Override public ModelView process(Map<String, String> paramMap) { //paramMap: request통해 받은 파라미터 정보 String username = paramMap.get("username"); int age = Integer.parseInt(paramMap.get("age")); Member member = new Member(username, age); memberRepository.save(member); ModelView mv = new ModelView("save-result"); mv.getModel().put("member", member); return mv; }
- 프론트 컨트롤러
//createParamMap: request통해 받은 파라미터 정보 담기 Map<String, String> paramMap = createParamMap(request); ModelView mv = controller.process(paramMap); String viewName = mv.getViewName(); //viewResolver: 논리 뷰 이름(members)-> 물리 뷰 경로로 변경(/WEB-INF/views/members.jsp) MyView view = viewResolver(viewName); view.render(mv.getModel(), request, response);
MyView
public void render(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //model.forEach((key, value) -> request.setAttribute(key, value) modelToRequestAttribute(model, request); RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath); dispatcher.forward(request, response); }
단순하고 실용적인 컨트롤러4
- 컨트롤러 인터페이스
구현//model 만들지 않고 사용하면된다, String 반환 String process(Map<String, String> paramMap, Map<String, Object> model);
model.put("member", member); return "save-result";
프론트 컨트롤러
모델 객체 프론트 컨트롤러에서 생성해서 넘김 Map<String, Object> model = new HashMap<>(); //논리 이름 직접 반환 String viewName = controller.process(paramMap, model);
### 유연한 컨트롤러5
- 컨트롤러 인터페이스
//v3
ModelView process(Map<String, String> paramMap);
//v4
String process(Map<String, String> paramMap, Map<String, Object> model);
둘다 사용하려면? 어댑터 패턴
- 어댑터 인터페이스
```
//handler는 컨트롤러
boolean supports(Object handler);
//어댑터 통해서 실제 컨트롤러 호출
ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException;
구현v3
@Override
public boolean supports(Object handler) {
return (handler instanceof ControllerV3);
}
@Override
public ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) {
ControllerV3 controller = (ControllerV3) handler;
Map<String, String> paramMap = createParamMap(request);
ModelView mv = controller.process(paramMap);
return mv;
}
구현v4
ControllerV4 controller = (ControllerV4) handler;
Map<String, String> paramMap = createParamMap(request);
Map<String, Object> model = new HashMap<>();
String viewName = controller.process(paramMap, model);
//형식맞추기
ModelView mv = new ModelView(viewName);
mv.setModel(model);
return mv;
프론트 컨트롤러
private final Map<String, Object> handlerMappingMap = new HashMap<>(); private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>(); public FrontControllerServletV5() { initHandlerMappingMap(); initHandlerAdapters(); } private void initHandlerMappingMap() { handlerMappingMap.put("/front-controller/v5/v3/members/new-form", new MemberFormControllerV3()); handlerMappingMap.put("/front-controller/v5/v3/members/save", new MemberSaveControllerV3()); handlerMappingMap.put("/front-controller/v5/v3/members", new MemberListControllerV3()); handlerMappingMap.put("/front-controller/v5/v4/members/new-form", new MemberFormControllerV4()); handlerMappingMap.put("/front-controller/v5/v4/members/save", new MemberSaveControllerV4()); handlerMappingMap.put("/front-controller/v5/v4/members", newMemberListControllerV4()); } private void initHandlerAdapters() { handlerAdapters.add(new ControllerV3HandlerAdapter()); handlerAdapters.add(new ControllerV4HandlerAdapter()); } @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Object handler = getHandler(request); if (handler == null) { response.setStatus(HttpServletResponse.SC_NOT_FOUND); return; } MyHandlerAdapter adapter = getHandlerAdapter(handler); ModelView mv = adapter.handle(request, response, handler); MyView view = viewResolver(mv.getViewName()); view.render(mv.getModel(), request, response); }
링크
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1
'스프링' 카테고리의 다른 글
타임리프 (0) | 2022.06.16 |
---|---|
[스프링] 스프링 MVC (0) | 2022.06.09 |
[스프링] 서블릿, JSP, MVC 패턴 (0) | 2022.06.09 |
[스프링] 웹 애플리케이션 이해, 서블릿 (0) | 2022.06.09 |
스프링 핵심원리 (0) | 2022.06.01 |