우선 이건 인프런의 김영한 강사님의 강의를 들으면서 본인이 스터디하고, 복습하기 위해 작성되는 글입니당,,,
frontCotroller를 도입하여 각 controller들의 앞단에 frontController를 두어 특정 urlPattern이 오게 되면 frontController 서블릿이 생성 되고 해당 urlPattern에 맞춰 최종적으로 view를 클라이언트에게 reponse 하게 된다.
package hello.servlet.web.frontcontroller.v1;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public interface ControllerV1 {
void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
-> 역할은 각 구현되는 controller들 앞에서 interface 역할을 한다.
package hello.servlet.web.frontcontroller.v1.controller;
import hello.servlet.web.frontcontroller.v1.ControllerV1;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//회원 등록 폼 컨트롤러
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);
}
}
-> 인터페이스를 구현한 MemberFormControllerV1이고, 해당 구현 객체의 역할은
new-form.jsp 화면을 클라이언트에게 최종적으로 반환 한다.
// /front-controller/v1/* : v1 하위에 있는 모든 폴더들을 요청할때 현재 이 서블릿을 무조건 호출 하게 된다.
@WebServlet(name = "frontControllerServletV1", urlPatterns = "/front-controller/v1/*")
public class FrontControllerServletV1 extends HttpServlet {
private Map<String, ControllerV1> controllerV1Map = new HashMap<>();
//frontControllerServletV1 이 생성 되면서 각 frontcontroller 를 생성한뒤 map에 넣는다.
public FrontControllerServletV1(){
controllerV1Map.put("/front-controller/v1/memebers/new-form", new MemberFormControllerV1());
controllerV1Map.put("/front-controller/v1/memebers/save", new MemberSaveControllerV1());
controllerV1Map.put("/front-controller/v1/memebers", new MemberListControllerV1());
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("FrontController Test");
String requestURI = req.getRequestURI();
ControllerV1 controllerV1 = controllerV1Map.get(requestURI);
if (controllerV1 == null) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
controllerV1.process(req,resp);
}
}
각 코드 설명은 아래와 같다.
@WebServlet(name = "frontControllerServletV1", urlPatterns = "/front-controller/v1/*")
해당 어노테이션은 frontControllerServletV1 이라는 이름으로 서블릿을 등록했고,
urlPattern으로 등록된 경로로 하위에 있는 모든 객체들은 이 서블릿을 호출한다.
private Map<String, ControllerV1> controllerV1Map = new HashMap<>();
//frontControllerServletV1 이 생성 되면서 각 frontcontroller 를 생성한뒤 map에 넣는다.
public FrontControllerServletV1(){
controllerV1Map.put("/front-controller/v1/memebers/new-form", new MemberFormControllerV1());
controllerV1Map.put("/front-controller/v1/memebers/save", new MemberSaveControllerV1());
controllerV1Map.put("/front-controller/v1/memebers", new MemberListControllerV1());
}
Map을 생성해서 key는 url value는 frontcontroller의 구현 객체로 하여 frontControllerServletV1 생성자를 통해 각 frontcontoller를 put 한다.
String requestURI = req.getRequestURI();
ControllerV1 controllerV1 = controllerV1Map.get(requestURI);
if (controllerV1 == null) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
controllerV1.process(req,resp);
requestURI는 "/front-controller/v1/memebers/new-form" 의 호출 값을 저장하고,
ControllerV1 타입으로 map에서 get 해온다.
그리고 process 메서드로 req,rep 값을 전달한다.
오늘 강의에서 핵심은 FrontControllerServletV1을 통해서 controller 인터페이스의 process 메서드를 호출하여 각 구현체를 담당하는 controller를 호출 후 최종적으로 클라이언트에게 view를 리턴하는 과정이라고 생각하며, 특히 인터페이스를 사용하여 process 메서드를 통해 각각의 구현 controller를 호출 할 수 있는 다형성도 중요하다고 생각한다.