-
프론트 컨트롤러 패턴스프링/스프링 MVC 패턴 2023. 2. 10. 21:19
프론트 컨트롤러가 있기 전까지는 컨트롤러에 공통된 과정이 있더라도 클라이언트가 요청할 때마다 계속해서 반복해야만 했다.
하지만 프론트 컨트롤러를 도입한다면 공통된 컨트롤러는 프론트 컨트롤러에서 처리하고 이후에 각각의 컨트롤러로 넘어가서 반복작업을 하지 않아도 된다는 장점이 있다.
프론트 컨트롤러
- 프론트 컨트롤러 서블릿 하나로 클라이언트의 요청을 받음
- 프론트 컨트롤러가 요청에 맞는 컨트롤러를 찾아서 호출
- 이전에는 고객의 요청이 오면 서블릿 매칭으로 각각 연결이 됐는데, 모든 요청이 프론트 컨트롤러로 가고 그 프론트 컨트롤러에서 이후 컨트롤러로 가게된다.
- 프론트 컨트롤러를 제외한 나머지 컨트롤러는 서블릿을 사용하지 않아도 된다.
인터페이스 생성
public interface ControllerV1 { void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException; }
이제 다형성을 이용해서 가입, 저장, 목록을 한번에 처리할 것이다.
가입
public class MemberFormControllerV1 implements ControllerV1 { private MemberRepository memberRepository = MemberRepository.getInstance(); @Override public void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String viewPath = "/WEB-INF/views/new-form.jsp"; RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath); // view에서 model로 get 하게 해주는거 dispatcher.forward(request, response); // 서블릿과 jsp의 연결 } }
저장
public class MemberSaveControllerV1 implements ControllerV1 { private MemberRepository memberRepository = MemberRepository.getInstance(); @Override public void 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); System.out.println("member = " + member); memberRepository.save(member); //Model에 데이터를 보관한다. request.setAttribute("member", member); String viewPath = "/WEB-INF/views/save-result.jsp"; RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath); dispatcher.forward(request, response); } }
목록
public class MemberListControllerV1 implements ControllerV1 { private MemberRepository memberRepository = MemberRepository.getInstance(); @Override public void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List<Member> members = memberRepository.findAll(); request.setAttribute("members", members); // 모델에 담을 때는 setAttribute를 사용 String viewPath = "/WEB-INF/views/members.jsp"; RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath); dispatcher.forward(request, response); } }
기존 서블릿이랑 완전히 동일하다.
차이점이 있다면 메서드 이름이 process라는 것과 @WebServlet 애노테이션을 사용하지 않았다는 것이다.
@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 request, HttpServletResponse response) throws ServletException, IOException { System.out.println("FrontControllerServletV1.service"); String requestURI = request.getRequestURI(); ControllerV1 controller = controllerMap.get(requestURI); // 위의 함수에서 url이 넘어오면 아래 new가 반환됨 if (controller == null) { response.setStatus(HttpServletResponse.SC_NOT_FOUND); return; } controller.process(request, response); } }
인터페이스에서 상속받아서 구현체로 만든 3가지의 클래스를 다형성을 사용해서 해당 url을 key 값으로 만들어서 key 값이 들어오면 해당 클래스의 process가 호출되어서 해당 로직을 수행하는 프로그램을 만들었다.
프론트 컨트롤러를 이용하면 동일한 반복 코드는 프론트 컨트롤러에서 입력하고 나머지만 각각의 컨트롤러에서 수행하면 된다.
'스프링 > 스프링 MVC 패턴' 카테고리의 다른 글
view resolver (0) 2023.02.12 핸들러 어댑터 (0) 2023.02.12 MVC 패턴 (0) 2023.02.10 JSP를 이용한 회원가입 (0) 2023.02.10 서블릿을 이용한 회원가입 만들기 (0) 2023.02.10