강의 내용이 있기 때문에 출처를 밝힙니다 !
임의로 추가, 수정, 삭제한 내용들이 있으니 정확한 이해를 위해서는 강의를 구매하시는 것을 추천드립니다 😅
출처 : 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 (인프런 강의)
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1
Controller 내부의 JSP 이동 부분 분리하기
FrontController 를 통한 MVC 패턴 구조 개선[1] 에서 수정했던 코드 중 모든 컨트롤러에서 JSP 로 이동하는 로직이 중복된다.
viewPath 를 설정하고 RequestDispathcer 의 forward() 메서드를 통해 JSP 로 이동하는데, 이 부분을 따로 분리할 수 있겠다.
즉, 컨트롤러에서 JSP 로 바로 이동하는게 아니라, Controller -> View -> JSP 이렇게 중간에 객체 하나를 더 끼워넣는 것이다.
public class MemberFormControllerV1 implements ControllerV1 {
@Override
public void process(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String viewPath = "WEB-INF/views/new-form.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
public class MemberListControllerV1 implements ControllerV1 {
private final MemberRepository repository = MemberRepository.getInstance();
@Override
public void process(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
List<Member> members = repository.findAll();
request.setAttribute("members", members);
String viewPath = "/WEB-INF/views/members.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
// MemberSaveControllerV1 은 생략
기존의 FrontController 패턴 도입 다이어그램
1. FrontController 에 사용할 호출할 Controller 를 미리 담는다.
2. 미리 등록해둔 Controller 를 URL 을 Key 값으로 해서 알맞은 컨트롤러를 찾아 생성한다.
3. Controller 는 작업을 마치며 forward() 를 통해 JSP 로 이동한다.
View 를 분리한 다이어그램
기존 다이어그램에서는 Controller 에서 바로 JSP forward 를 진행했지만 이번에는 View 를 반환하는 것으로 수정했다.
Controller 는 View 를 반환하고, View 의 render() 메서드를 통해 JSP 로 이동하도록 해보자.
1. MyView 클래스 생성
render() 메서드를 생성해, 각 Controller 에서 진행하던 forward() 로직을 추가한다.
이제 JSP 로 이동하기 위해서는 무조건 MyView 클래스를 거쳐야한다 !
public class MyView {
private final String viewPath;
public MyView(String viewPath) {
this.viewPath = viewPath;
}
public void render(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOExcetpion {
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
2. Controller 인터페이스 수정
기존의 Controller 구현체들은 자기 자신이 JSP 로의 forward 책임을 지니고 있어 Controller 인터페이스 process() 메서드가 무언가를
반환할 필요가 없었다. (그냥 자기가 forward 해서 실행하고 작업이 끝나기 때문에 ..)
하지만 이제 JSP 로의 forward 는 MyView 클래스가 책임져야 하기 때문에 process() 의 반환타입을 MyView 로 수정한다.
public interface ControllerV2 {
MyView process(HttpServletRequest request, HttpServeltResponse response)
throws ServletExcetion, IOExcetion;
}
3. FrontController 수정
위의 이유로 인해 Controller 는 MyView 를 반환하도록 수정하고, MyView 의 render() 메서드를 통해 JSP 로 forward 책임을 넘긴다.
@WebServlet(name = "frontControllerServletV2", urlPatterns = "/front-controller/v2/*")
public class FrontControllerServletV2 extends HttpServlet {
private final 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 request, HttpServletResponse response)
throws ServletException, IOException {
String requestURI = request.getRequestURI();
ControllerV2 controller = controllerMap.get(requestURI);
if (controller == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
MyView view = controller.process(request, response);
view.render(request, response);
}
}
이제 이전보다 중복되는 코드가 많이 지워진 것을 알 수 있다.
하지만 각 Controller 구현체의 process() 메서드 인자로 HttpServletRequest, HttpServletResponse 를 받고 있는데, 이게 쓰이는
곳도 있고 없는 곳도 있는 것을 확인할 수 있다. (MemberFormControllerV2 클래스에서는 한 번도 안쓰이고 있다 😅)
다음 포스팅에서 이 부분을 개선해보도록 하자 !
'Servlet' 카테고리의 다른 글
FrontController 를 통한 MVC 패턴 구조 개선 [1] (0) | 2022.04.03 |
---|---|
Servlet 에 MVC 패턴 도입하기 (0) | 2022.04.03 |
[POST] 클라이언트 요청 Body 를 서버로 전달하기 (0) | 2022.03.30 |
[GET] 클라이언트 요청 쿼리 파라미터를 서버로 전달하기 (0) | 2022.03.30 |