프론트 컨트롤러 패턴 - 스프링
프론트 컨트롤러 패턴
프론트 컨트롤러 패턴이란?
-
REST AP를 구현할 때, 한개의 URL에 하나의 서블릿을 대응해야만 했던 구조에서 코드의 중복을 줄이기 위해 고안된 패턴
-
따라서 프론트 컨트롤러를 여러 서블릿 컨트롤러들의 앞단에 두어 일종의 ‘수문장’ 역할을 하게 둠
→ 이를 통해 컨트롤러 공통영역을 처리해 줄 수 있도록 함.
프론트 컨트롤러 도입 전의 관계도
-
REST AP를 구현할 때, 한개의 URL에 하나의 서블릿을 대응해야만 했던 구조에서 코드의 중복을 줄이기 위해 고안된 패턴
-
따라서 프론트 컨트롤러를 여러 서블릿 컨트롤러들의 앞단에 두어 일종의 ‘수문장’ 역할을 하게 둠
→ 이를 통해 컨트롤러 공통영역을 처리해 줄 수 있도록 함.
프론트 컨트롤러 도입 전의 관계도
프론트 컨트롤러 도입 후의 관계도
Front Controller의 특징
Front Controller 패턴의 특징을 살펴보자
- 프론트 컨트롤러 서블릿 하나로 클라이언트의 모든 요청을 수행한다.
- 해당 요청을 수행할 컨트롤러를 찾아서 호출한다.
- 공통 로직을 처리 가능(코드의 중복 제거)
Front controller 이 공통 로직을 처리하고, 각 상황에 따라 해당 역할을 수행할 컨트롤러를 실행한다.
그렇다면 프론트 컨트롤러를 회원 등록을 하고 회원 리스트를 볼 수 있는 코드에 적용해보자.
우선 현재는 클라이언트로 이름와 나이를 입력 받아 그 정보로 회원을 등록하기 위한 서블릿, 입력 받은 정보를 전달받아 회원을 저장하는 서블릿,모든 회원 목록 리스트를 반환하는 서블릿, MvcMemberFormServlet
,MemberSaveServlet
,MemberListServlet
이렇게 세가지가 있다.
MvcMemberFormServlet 코드
@WebServlet(name = "mvcMemberFormServlet",urlPatterns ="/servlet-mvc/members/new-form")
public class MvcMemberFormServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String viewPath ="/WEB-INF/views/new-form.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request,response);
}
}
MvcMemberSaveServlet 코드
@WebServlet(name = "mvcMemberSaveServlet", urlPatterns = "/servlet-mvc/members/save")
public class MvcMemberSaveServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(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);
//Model에 데이터를 보관한다.
request.setAttribute("member", member);
String viewPath = "/WEB-INF/views/save-result.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
MvcMemberSaveServlet 코드
@WebServlet(name = "mvcMemberListServlet",urlPatterns = "/servlet-mvc/members")
public class MvcMemberListServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
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);
}
}
Front Controller 로 구조 변경
우선 인터페이스를 만들어준다 → 각 컨트롤러들은 이 인터페이스를 통해 구현한다. 프론트 컨트롤러에서 이 인터페이스를 호출해 각 구현체들을 컨트롤러로써 사용한다. → 이는 로직의 일관성을 가져갈 수 있다.
ControllerV1
public interface ControllerV1 {
void process(HttpServletRequest request , HttpServletResponse response) throws ServletException, IOException;
}
Fornt ControllerV1
@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 {
String requestURI = request.getRequestURI();
ControllerV1 controller = controllerMap.get(requestURI);
if (controller == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
controller.process(request, response);
}
}
- Map을 이용하여 요청이 들어온 url에 따라 해당하는 컨트롤러가 호출 될 수 있도록 한다.
- /front-controller/v1/ 을 통해 /front-controller/v1 의 하위 모든 경로에 대한 요청을 받는다.
→ 는 모든 것을 포함한다는 의미
MemberFormControllerV1
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);
}
}
MemberSaveControllerV2
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);
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);
}
}
MemberListControllerV2
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);
String viewPath = "/WEB-INF/views/members.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
위의 프런트 컨트롤러를 적용함으로써
Front controller 이 공통 로직을 처리하고, 각 상황에 따라 해당 역할을 수행할 컨트롤러를 실행할 수 있게 되었다.
또한 맵핑 되어있는 url을 통한 접근을 404에러로 처리할 수 있게 되었다.
Author And Source
이 문제에 관하여(프론트 컨트롤러 패턴 - 스프링), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@cjh8746/프론트-컨트롤러-패턴-스프링저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)