728x90
반응형
프론트 컨트롤러 적용 과 뷰 분리
프론트 컨트롤러를 직접 만들어 보자.
프론트 컨트롤러 적용
전체적인 구조
ControllerV1 interface
인터페이스로 만든 이유
- 다형성으로 필요한 컨트롤러들을 구현한다.
public interface ControllerV1 {
void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
MemberFormContrellerV1
- 앞서 구현한 기존로직과 동일하다.
- 다른점은 ControllerV1 을 상속받아 구현을 하였다.
public class MemberFormControllerV1 implements ControllerV1 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
public void process(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<Member> members = memberRepository.findAll();
req.setAttribute("members", members);
String viewPath = "/WEB-INF/views/new-form.jsp";
RequestDispatcher dispatcher = req.getRequestDispatcher(viewPath);
dispatcher.forward(req,resp);
}
}
MemberSaveControllerV1
- 역시 동일하다.
public class MemberSaveControllerV1 implements ControllerV1 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
public void process(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
int age = Integer.parseInt(req.getParameter("age"));
Member member = new Member(username, age);
memberRepository.save(member);
//Model 데이터 보관
req.setAttribute("member",member);
String viewPath = "/WEB-INF/views/save-result.jsp";
RequestDispatcher dispatcher = req.getRequestDispatcher(viewPath);
dispatcher.forward(req,resp);
}
}
MemberLIstControllerV1
public class MemberLIstControllerV1 implements ControllerV1 {
@Override
public void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
FrontControllerServletv1 핵심이다.
- 여기서는 서블릿을 상속받아 FrontController 를 구현하였다.
- urlpatterns 의 마지막 * 은 해당 URI 계층의 모든 요청을 처리하기 위해서이다.
- Map 으로 Key 는 urlpattern, value 는 다형성을 이용하여 요청에 맞는 컨트롤러를 호출한다.
// /front-controller/v1/* 주소의 * 때문에 어떤 url이 들어와도 일단 해당 컨트롤러가호출된다.
@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 req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("FrontControllerServletV1.service");
String requestURI = req.getRequestURI();
ControllerV1 controllerV1 = controllerMap.get(requestURI);
if (controllerV1 == null) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
controllerV1.process(req, resp);
}
}
뷰 분리
코드를 보면 뷰 즉 JSP 를 호출 foward 하는 부분이 중복적으로 발생한다.
이것을 하나의 객체에서 관리해보자.
MyView class
- dispatcher 를 가져오는 로직과
- forward 로직을 여기서 호출한다.
public class MyView {
private String viewPath;
public MyView(String viewPath) {
this.viewPath = viewPath;
}
public void render(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
RequestDispatcher dispatcher = req.getRequestDispatcher(viewPath);
dispatcher.forward(req, resp);
}
}
Controller Interface
- 위예제와 동일하지만 다른점은 반환타입이 MyView 이다.
// 기존과 동일하지만 반환을 MyView로 한다.
public interface ControllerV2 {
MyView process(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
}
FrontControllerServletV2
- 이전코드와 동일하지만 핵심은
- 아래 두 코드이다.
- view 를 반환 받아서 render 를 호출하여 foward 로직을 수행한다.
MyView view = controllerV2.process(req, resp);
view.render(req, resp);
// /front-controller/v1/* 주소의 * 때문에 어떤 url이 들어와도 일단 해당 컨트롤러가호출된다.
@WebServlet(name = "frontControllerServletV2", urlPatterns = "/front-controller/v2/*")
public class FrontControllerServletV2 extends HttpServlet {
private Map<String, ControllerV2> controllerMap = new HashMap<>();
public FrontControllerServletV2() {
controllerMap.put("/front-controller/v2/members/new-form", new MemberFormControllerV2());
controllerMap.put("/front-controller/v2/members/save", new MemberSaveControllerV2());
controllerMap.put("/front-controller/v2/members", new MemberListControllerV2());
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String requestURI = req.getRequestURI();
ControllerV2 controllerV2 = controllerMap.get(requestURI);
if (controllerV2 == null) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
MyView view = controllerV2.process(req, resp);
view.render(req, resp);
}
}
MemberFormController
로직을 보면 MyView 호출
public class MemberFormControllerV2 implements ControllerV2 {
@Override
public MyView process(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
return new MyView("/WEB-INF/views/new-form.jsp");
}
}
728x90
반응형
'Spring > spring framework 구현 스터디' 카테고리의 다른 글
[Spring] 프론트 컨트롤러 4 : 개선편 (0) | 2021.10.26 |
---|---|
[Spring] 프론트 컨트롤러 3 : 종속성제거, 뷰리졸버 구현 (0) | 2021.10.23 |
[Spring] 프론트 컨트롤러 1 : 개념 (0) | 2021.10.18 |
[Spring] MVC 패턴 적용 (0) | 2021.10.17 |
[Spring] MVC 패턴 (0) | 2021.10.12 |
댓글