프론트컨트롤러 패턴을 직접 만들어보자!

박경현·2023년 3월 27일
0

MVC프레임워크를 1-10까지 전부 직접 만들어볼거다

프론트 컨트롤러 패턴 소개

프론트 컨트롤러 패턴 도입전

각각의 클라이언트들이 직접 호출을 했었다!
모든 컨트롤러가 각각의 서블릿을 가져야했다!

도입 후

문지기 역할을 하는 컨트롤러를 앞에 놔둠으로써 입구를 하나로 정의한다!

프론트 컨트롤러도 결국 서블릿이다
요청에 맞는 컨트롤러를 찾아서 호출해주는 방식이다!
프론트 컨트롤러를 제외한 나머지 컨트롤러는 서블릿을 가지지 않아도 된다!

스프링의 웹 MVC의 DispatcherServlet이 Front Controller 패턴으로 구현되어 있다

첫번째로 만든 방식-> 단순하게 컨트롤러에서 뷰도 출력해버리자 V1

이 방식은 컨트롤러에서 뷰로 이동하는 부분이 중복된다!

v1 코드

ControllerV1 interface

public interface ControllerV1 {
	void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}

controller/MemberFormControllerV1.java

public class MemeberFormControllerV1 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)
        dispather.forward(request,response);
    }
}

controller/MemberListControllerV1.java

public class MemberListControllerV1 implements ControllerV1 {
	private MemberRepository memberRepository = MemberRepository.getInstance();
    @Override
    public void process(HttpServletRequest request, HttpServletResponse response) {
    	List<Member> members = memberRepository.findAll();
        request.setAttribute("members",members);
        String viewPath = "/WEB-INF/views/members.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request,response);
    }
}

FrontController

@WebServlet(name="frontControllerServletV1", urlPatterns="/front-controller/v1/*")
public class FrontControllerServletV1 extends HttpServlet {
	private Map<String,ControllerV1> controllerV1Map = new HashMap<>();
    
    public FrontControllerServletV1() {
    	controllerV1Map.put("/front-controller/v1/new-form", new MemberFormControllerV1());
        controllerV1Map.put("/front-controller/v1/members/save", new MemberSaveControllerV1());
        controllerV1Map.put("/front-controller/v1/members", new MemberListControllerV1());
    }
    
    @Override
    protected void service(HttpRequest request, HttpResponse response)throws ServletException, IOException {
    	String requestURI = request.getRequestURI();
        ControllerV1 controllerV1 = controllerV1Map.get(requestURI);
        if (controllerV1 =null) {
        	resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        controllerV1.process(request,response);
    }
}

두번째로 만든 방식-> 컨트롤러와 뷰를 분리하자 V2

컨트롤러는 MyView라는 객체를 만들어서 반환하면 FrontController가 view를 호출!
FrontControllerV2에서 MyView를 요청해서 view를 렌더해주기!!
각각의 컨트롤러들은 jsp의 경로를 주면 됨!

V2 코드

ControllerV2 코드 interface

public interface ControllerV2 {
    MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}

MyView - String으로 viewPath를 받으면 이걸 통해 view를 불러준다!

public class MyView {
	private String viewPath;
    public MyView(String viewPath) {this.viewPath = viewPath;}
    
    public void render(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    	RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forwar(request,response);
    }
}

controllerV2/MemberFormControllerV2

public class MemberFormControllerV2 implements ControllerV2 {
	@Override
    public MyView process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    	return MyView("/WEB-INF/views/new-form.jsp");
    }
}

controllerV2/MemberSaveControllerV2

public class MemberSaveControllerV2 implements ControllerV2 {
    private 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);

        String viewPath = "/WEB-INF/views/save-result.jsp";
        return new MyView(viewPath);
    }
}

FrontControllerServletV2

@WebServlet(name="frontControllerServletV2", urlPatterns="/front-controller/v2/*")
public class FrontControllerServletV2 extends HttpServlet {
	private Map<String, ControllerV2> controllerV2Map = new HashMap<>();
    
    public FrontControllerServletV2() {
        controllerV2Map.put("/front-controller/v2/new-form", new MemberFormControllerV2());
        controllerV2Map.put("/front-controller/v2/save", new MemberSaveControllerV2());
        controllerV2Map.put("/front-controller/v2/members", new MemberListControllerV2());
    }
    
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	String requestURI = request.getRequestURI();
        ControllerV2 controllerV2 = controllerV2Map.get(requestURI);
        
        if (controllerV2 ==null) {
        	response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        MyView view = controllerV2.process(request,response);
        view.render(resquest,response);
    }

}
profile
SW로 문제를 해결하려는 열정만 있는 대학생

0개의 댓글