이번에 분리할 부분은 view이다. view를 처리하는 객체를 만들어보자
public class MyView {
String viewPath;
public MyView(String viewPath){
this.viewPath = viewPath;
}
public void render(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher requestDispatcher = request.getRequestDispatcher(viewPath);
requestDispatcher.forward(request,response);
}
}
지금 위에 보이는 코드를 보면 RequestDispatcher가 있는걸로 보아 실제 화면으로 가는 기능인것 같은데 실제 가는 경로는 넣는 부분에 viewPath라는 변수가 들어온다. 이 말인 즉슨, 다른 곳에서 기본생성자로 viewPath를 받는 호출이 생기게 되서 받은 매개변수로 포워딩 하는 모습을 보게 될 것이다. 다음에 보게 작성할 코드는 각각의 기능 컨트롤러에서 사용할 기능을 묶은 interface를 만들겠다.
public interface ControllerV2 {
MyView process (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
이 코드는 앞서 V1에서도 사용한 코드이다. 이제 각각의 순 기능이 잇는 컨트롤러들을 만들어보자. 앞서 V1에서 만든 코드와 거의 흡사하지만 차이점이 있다.
public class MemberFormControllerV2 implements ControllerV2 {
@Override
public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
return new MyView("/WEB-INF/views/new-form.jsp");
}
}
public class MemberListControllerV2 implements ControllerV2 {
MemberRepository memberRepository = MemberRepository.getInstance();
@Override
public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Member> members = memberRepository.findAll();
request.setAttribute("members", members);
return new MyView("/WEB-INF/views/members.jsp");
}
}
public class MemberSaveControllerV2 implements ControllerV2 {
MemberRepository memberRepository = MemberRepository.getInstance();
@Override
public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
Member member = new Member(username, age);
memberRepository.save(member);
request.setAttribute("member", member);
return new MyView("/WEB-INF/views/save-result.jsp");
}
}
앞에서 사용한 방식과의 차이점은 V1에서는 각각의 컨트롤러에서 직접 디스패처로 포워딩을 했지만 포워딩을 하는 뷰로 이동하는 객체를 따로 만들었기 때문에 그 객체의 기본생성자를 호출해서 viewPath에 담아서 리턴을 한 모습이다. 이제 각각의 컨트롤러로 이동할 수 있는 FrontController만 만들면 끝난다.
@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 request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("frontControllerServletVdd2.service");
String requestURI = request.getRequestURI();
ControllerV2 controller = controllerMap.get(requestURI); // 해당 키 값의 value 추출
if(controller == null){
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
MyView myView = controller.process(request,response);
myView.render(request,response);
}
}
이번 FrontController 역시 앞서 만들었던 V1에서 V2로 수정을 하고 실제 service되는 부분을 보게 되면 우리는 매핑된 주소에 따라 각각의 컨트롤러의 생성자를 만들었고 이 컨트롤러의 순기능들을 실행하고 ( 입력 , 저장 , 목록보기 ) 각각의 컨트롤러에서 기능이 모두 수행되면 지정한 viewPath를 가지고 myView라는 포워딩이 실제로 실행되는 객체에 기본 생성자를 만들어 viewPath까지 만들게 되어 그 값으로 render라는 메서드가 실행되면서 포워딩이 되게 된다.
'spring' 카테고리의 다른 글
Front Controller (4) (0) | 2023.03.19 |
---|---|
Front Controller (3) (0) | 2023.03.18 |
Front Controller (1) (0) | 2023.03.16 |
MVC 적용하기 (0) | 2023.03.08 |
MVC 개요 (0) | 2023.03.05 |