728x90
반응형
프론트 컨트롤러 종속성제거, 뷰리졸버 구현
- 이전에 반복되는 코드들을 줄인다.
- 프론트컨트롤러에 많은 역할을 주고 일반 컨트롤러에서는 종속성을 제거한다.
서블릿 종속성을 제거한다.
- 컨트롤러 입장에서 HttpServletRequest, HttpServletResponse 가 꼭 필요하진 않다.
- 그렇다면 requset 에서 model을 가져다 썼는데 어떻게 해결할까?
- 직접 만들어서 사용한다.
종속성을 제거의 장점
- 불필요한 코드 request, response 를 줄일수 있다.
- 만약 파일의 경로가 변경되면 프론트컨트롤러 만 손보면 된다.
- 유지보수가 간편해 진다.
뷰이름 중복제거
- 컨트롤러마다 뷰이름이 계속해서 등장하고 절대경로를 사용한다.
- 상대경로로 변경하여 구현한다.
/WEB-INF/views/new-form.jsp -> new-form
/WEB-INF/views/save-result.jsp -> save-result
/WEB-INF/views/members.jsp -> members
구조
- 기존에는 모든 컨트롤러들이 repuest 와 response 를 가지고 있었다.
- 종속성제거를 적용하여 이를 해결한다.
- 모델도 직접 만들어서 사용한다.
Controller Interface
- 반환타입은 ModelView 이다.
- repuest 와 response 는 빠지게 되었다.
package hello.servlet.web.frontcontroller.v3;
import hello.servlet.web.frontcontroller.ModelView;
import java.util.Map;
public interface ControllerV3 {
// v2 와 비교해보면 상당히 단순해졌다.
ModelView process(Map<String, String> paramMap);
}
Front Controller
- 맵핑을 담당한다.
- 컨트롤러에게 넘어온 데이터들을
- createParamMap 메서드를 통해 데이터를 다 담는다
- setAttribute 에 담는다. - viewResolver 를 통해 뷰를 생성한뒤 render 를 수행한다.
- 논리 이름을 물리이름으로 변경하는 역할을 담당한다.
// /front-controller/v1/* 주소의 * 때문에 어떤 url이 들어와도 일단 해당 컨트롤러가호출된다.
@WebServlet(name = "frontControllerServletV3", urlPatterns = "/front-controller/v3/*")
public class FrontControllerServletV3 extends HttpServlet {
private Map<String, ControllerV3> controllerMap = new HashMap<>();
// 프론트 컨트롤러 map 셋팅
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 req, HttpServletResponse resp) throws ServletException, IOException {
String requestURI = req.getRequestURI();
ControllerV3 controllerV3 = controllerMap.get(requestURI);
if (controllerV3 == null) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
// 모델 뷰를 가져오는 부분
Map<String, String> paramMap = createParamMap(req);
ModelView mv = controllerV3.process(paramMap);
// 뷰리졸버 구현 논리 이름을 물리 이름으로 변경해야 된다.
String viewName = mv.getViewName();
MyView view = viewResolver(viewName);
view.render(mv.getModel(), req, resp);
}
private MyView viewResolver(String viewName) {
MyView view = new MyView("/WEB-INF/views/" + viewName + ".jsp");
return view;
}
// 레벨을 맞춰주기 위해 메서드로 뽑아준다.
private Map<String, String> createParamMap(HttpServletRequest req) {
// paramMap을 넘겨줘야한다.
Map<String, String> paramMap = new HashMap<>();
req.getParameterNames().asIterator()
.forEachRemaining(paramName -> paramMap.put(paramName, req.getParameter(paramName)));
return paramMap;
}
}
ModelView class
- view name 과 map으로 데이터를 담는다.
package hello.servlet.web.frontcontroller;
import java.util.HashMap;
import java.util.Map;
public class ModelView {
private String viewName;
public ModelView(String viewName) {
this.viewName = viewName;
}
// jsp 에서 쓸수 있도록 데이터를 담아 둔다.
private Map<String, Object> model = new HashMap<>();
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;
}
}
MemberFormController
- 따로 데이터를 처리할게 없기 때문에
- 뷰 이름만 담아서 리턴한다.
package hello.servlet.web.frontcontroller.v3.controller;
import hello.servlet.domain.member.MemberRepository;
import hello.servlet.web.frontcontroller.ModelView;
import hello.servlet.web.frontcontroller.v3.ControllerV3;
import java.util.Map;
public class MemberFormControllerV3 implements ControllerV3 {
@Override
public ModelView process(Map<String, String> paramMap) {
return new ModelView("new-form");
}
}
MemberListController
- Repository 에서 모든 데이터를 꺼내온다.
- 모델뷰에서 모델을 가져온뒤 데이터를 담는다.
public class MemberListControllerV3 implements ControllerV3 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
public ModelView process(Map<String, String> paramMap) {
List<Member> members = memberRepository.findAll();
ModelView mv = new ModelView("members");
mv.getModel().put("members", members);
return mv;
}
}
MemberSaveController
- 프론트 컨트롤러에서 데이터를 받아
- 데이터를 저장한다.
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);
memberRepository.save(member);
ModelView mv = new ModelView("save-result");
mv.getModel().put("member",member);
return mv;
}
}
결론
- 해당 과정을 통해 프론트컨틀로러에게 위임할수 있는 책임을 다 위임하고
- 나머지 컨트롤러들에게는 쉽게 구현하도록 책임을 최소화 시켰다.
참고
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/lecture/71191
728x90
반응형
'Spring > spring framework 구현 스터디' 카테고리의 다른 글
[Spring] 프론트 컨트롤러 5 : 어댑터 적용 (0) | 2021.10.30 |
---|---|
[Spring] 프론트 컨트롤러 4 : 개선편 (0) | 2021.10.26 |
[Spring] 프론트 컨트롤러 2 : 적용, 뷰 분리 (0) | 2021.10.21 |
[Spring] 프론트 컨트롤러 1 : 개념 (0) | 2021.10.18 |
[Spring] MVC 패턴 적용 (0) | 2021.10.17 |
댓글