[Spring]프론트 컨트롤 개념 및 예제(프론트 컨트롤러 도입)
프론트 컨트롤이란
- 프론트 컨트롤러 서블릿 하나로 클라이언트의 요청을 받는다.
- 프론트 컨트롤러가 요청에 맞는 컨트롤러를 찾아서 호출한다.
프론트 컨트롤이 실행되는 순서
- 클라이언트가 FrontController로 요청
- FrontController는 요청된 매핑정보 확인
- 매핑 정보 확인 후 controller 호출
- 해당 controller에 맞는 jsp로 이동
- jsp로 이동후 클라이언트에게 응답
공통 코드
@Getter
@Setter
@ToString
public class Member {
private Long id;
private String username;
private int age;
public Member(String username, int age) {
this.username = username;
this.age = age;
}
public Member() {
}
}
public class MemberRepository {
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L;
private static final MemberRepository instance = new MemberRepository();
public static MemberRepository getInstance() {
return instance;
}
private MemberRepository() {
}
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
public Member findById(Long id) {
return store.get(id);
}
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
public void clearStore() {
store.clear();
}
}
프론트 컨트롤이 적용 안된 코드
@WebServlet(name="mvcMemberInputSerlvet", urlPatterns = "/mvc/members/input")
class MvcMemberInputSerlvet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String path = "/WEB-INF/view/input.jsp"; //urlPatterns를 입력했을때 이동하는 경로
// Controller에서 View로 이동할때 사용하는 메소드 => getReuqestDispatcher(이동할 경로)
RequestDispatcher dispatcher = request.getRequestDispatcher(path);
// 다른 서블릿이나 JSP로 이동할 수 있는 기능, 서버 내부에서 다시 호출 발생
dispatcher.forward(request,response);
}
}
@WebServlet(name = "mvcMemberSaveServlet", urlPatters = "/mvc/members/save"
class MvcMemberSaveServlet extends HttpServlet {
// 이 부분은 정보를 저장하기 위해 싱글톤 패턴으로 구현된 객체이다.
private MemberRepsoitory memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//input.jsp에서 입력된 name값과 age값 받기
String name = 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 path = "/WEB-INF/view/save.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(path);
dispatcher.forward(request,response);
}
}
@WebSerblet(name ="mvcMemberListServlet", urlPatterns="/mvc/members"
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();
String path = "/WEB-INF/view/members.jsp";
request.setAttribute("members",member);
RequestDispatcher dispatcher = request.getRequestDispatcher(path);
dispatcher.forward(request,response);
}
}
처음 부분에 설명했듯이 프론트 컨트롤은 서블릿 하나로 클라이언트의 요청을 받는데 프론트컨트롤 패턴을 안 한 코드를 보면 여러 개의 서블릿이 클라이언트의 요청을 받는다.
이제 프론트 컨트롤 패턴을 적용한 코드를 보겠다.
프론트 컨트롤 패턴 적용 코드
public interface Controller {
void process(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
}
public MemberInputController implements Controller {
@Override
void process(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
String path = "/WEB-INF/view/input.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(path);
dispatcher.forward(request,response);
}
}
public MemberSaveController implements Controller {
private MemberRepository memberRepository = MemberRepository.getInstatnce();
@Override
void process(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
Member member = new Member(name, age);
memberRepository.save(member);
request.setAttribute("member",member);
String path = "/WEB-INF/view/save.jsp";
RequestDispatcher dispatcher = request.getRequsetDispatcher(path);
dispatcher.forward(request,response);
}
}
public MemberListController implements Controller {
private MemberRepository memberRepository = MemberRepository.getInstatnce();
@Override
void process(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
List<Member> members = memberRepository.findAll();
String path = "/WEB-INF/view/members";
request.setAttribute("members",members);
RequestDispatcher dispatcher = request.getRequsetDispatcher(path);
dispatcher.forward(request,response);
}
}
프론트 컨트롤 패턴을 적용한 코드와 안 한 코드를 비교해보면 차이점을 바로 알 수 있다.
이제 프론트컨트롤을 적용한 코드에 하나의 서블릿으로 요청을 받는 코드를 작성하겠다.
@WebServlet(name="frontControllerServlet", urlPatterns="/frontcontroller/*")
// /frontcontroller/* => frontcontroller 하위에 뭐가 들어와도 상관이 없다
public class FrontControllerServlet extends HttpServlet {
private Map<String, Controller> controllerMap = new HashMap();
public FrontControllerServlet() {
// 생성자 안에 controllerMap.put을 한이유
// => 서블릿이 서블릿 컨테이너로 들어가지면서 객체가 생성이 되기때문에
// 미리 저장해서 사용할려고
controllerMap.put("/frontcontroller/input", new MemberInputController());
controllerMap.put("/frontcontroller/save", new MemberSaveController());
controllerMap.put("/frontcontroller/members", new MemberListController());
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//만약 localhost:9090/frontcontroller/input 으로 요청을 하면
// requestURI = /frontcontroller/input
String requestURI = request.getRequestURI();
//controllerMap.get(requestURI) => 키값이 requestURI이니깐
// 만약 requestURI = /frontcontroller/input 일 경우 new MemberInputController() 인스턴스가 생성
Controller controller = controllerMap.get(requestURI);
controller.process(request,request);
}
}
정리
프론트 컨트롤 적용 안 한 코드 : 여러 개의 서블릿으로 클라이언트의 요청을 받는다.
프론트 컨트롤 적용한 코드 : 하나의 서블릿으로 클라이언트의 요청을 받는다.
밑으로 내려갈수록 발전된 프론트 컨트롤 패턴 활용
프론트 컨트롤러 도입 - https://hoestory.tistory.com/12
view분리 - https://hoestory.tistory.com/13
Model 추가 - https://hoestory.tistory.com/17
단순하고 실용적 컨트롤러 - https://hoestory.tistory.com/19
유연한 컨트롤 -
'Spring Boot > MVC' 카테고리의 다른 글
[Spring]프론트 컨트롤 개념 및 예제(단순하고 실용적인 컨트롤러) (0) | 2021.12.18 |
---|---|
[Spring]프론트 컨트롤 개념 및 예제(Model 추가) (0) | 2021.12.02 |
[Spring]프론트 컨트롤 개념 및 예제(View 분리) (0) | 2021.11.28 |
댓글
이 글 공유하기
다른 글
-
[Spring]프론트 컨트롤 개념 및 예제(단순하고 실용적인 컨트롤러)
[Spring]프론트 컨트롤 개념 및 예제(단순하고 실용적인 컨트롤러)
2021.12.18 -
[Spring]프론트 컨트롤 개념 및 예제(Model 추가)
[Spring]프론트 컨트롤 개념 및 예제(Model 추가)
2021.12.02 -
[Spring]프론트 컨트롤 개념 및 예제(View 분리)
[Spring]프론트 컨트롤 개념 및 예제(View 분리)
2021.11.28