[스프링프레임워크 DAY3 - C4)]-MVC 프레임워크 개발
"앞 절에서는 MVC1-2를 이용한 웹 프로젝트 개발에 관해 학습했다. 여기서 부터는 드디어 프레임워크를 활용한 웹 프로젝트 제작에 대하서 배운다."
4.1 MVC 프레임워크 구조
: MVC2 패턴의 DIspatcherServlet.java 파일을 보면, 웹에서 사용 되는 모든 로직이 한 개의 클래스에 모여있다. 이런 식이라면 유지보수 및 개발이 상당히 어려워 진다. 따라서 하나의 서블릿안에 모든 로직을 넣기 보다는 각각의 Controller 별로 나누어 구현 하는 것이 효과적이다.
#1. 첨부자료 1 - MVC2 패턴에서 모든 로직이 모여져 있는 DIspatcherServlet.java의 분기 로직(* MVC2 참고)
"편의상 메모장에서 스캔 했지만... 여하튼 모든 *.do의 로직들이 한개의 서블릿에 모여 있다는 것은 향후 유지보수가 어렵다는 반증이다. 업무단 로직별로 .java 파일을 나누어서 유지할 필요가 있다. "
#2. 첨부자료 2 - MVC 프레임 워크에서의 개괄도
클래스 | 기능 |
DIspatcherServlet | 유일한 서블릿 클래스로서 모든 클라이언트의 요청을 가장 먼저 처리하는 컨트롤러 이다. |
HandlerMapping | 클라이언트의 요청을 처리할 Controller 매핑 |
Controller | 실질적인 클라이언트의 요청 처리 |
ViewResolver | Controller가 리턴한 View 이름으로 실행될 JSP 경로 완성 |
" 원래 프레임워크에서 쓰이는 Controller가 존재( 클래스 5절에 간단하게 구현 된다.) 한다. 하지만, 여기서는 인터페이스 컨트롤러를 직접 구현하여 학습해 볼 것이다. 특히 DIspatcherServlet.java의 소스를 자세히 살펴 보도록 하자.. "
4.2 MVC 프레임워크 구현
" 여기서는 DispathcerServlet/Controller 인터페이스/HandlerMapping/ViewResolver 에 대한 내용만 업로드 한다. 나머지 구체적인 Controller들은 이하 파일로 남겨놓겠다."
4.2.1. Controller 인터페이스 작성
: MVC 프레임워크에서 실질적인 로직들을 처리하는 Controller들을 같은 타입으로 묶기 위한 인터페이스이다. 해당 인터페이스를 통해 실질적인 컨트롤러들이 같은 자료형을 갖게 된다.
#1. 첨부자료 - 인터페이스 컨트롤러 소스
package com.springbook.view.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Controller {
String handleRequest(HttpServletRequest request, HttpServletResponse response);
}
4.2.2. HandlerMapping 클래스 작성
#2. 첨부자료 - HandlerMapping 클래스 작성
package com.springbook.view.controller;
import java.util.HashMap;
import java.util.Map;
import com.springbook.view.board.DeleteBoardController;
import com.springbook.view.board.GetBoardController;
import com.springbook.view.board.GetBoardListController;
import com.springbook.view.board.InsertBoardController;
import com.springbook.view.board.LogoutController;
import com.springbook.view.board.UpdateBoardController;
import com.springbook.view.user.LoginController;
public class HandlerMapping {
//1. key : String, value : Controller
private Map<String, Controller> mappings;
//2. HandlerMapping 이 실행되면 무조건 실행 된다.
public HandlerMapping() {
mappings = new HashMap<String, Controller>();
mappings.put("/login.do", new LoginController());
mappings.put("/getBoardList.do", new GetBoardListController());
mappings.put("/getBoard.do", new GetBoardController());
mappings.put("/insertBoard.do", new InsertBoardController());
mappings.put("/updateBoard.do", new UpdateBoardController());
mappings.put("/deleteBoard.do", new DeleteBoardController());
mappings.put("/logout.do", new LogoutController());
}
public Controller getController(String path) {
return mappings.get(path);
}
}
: HandlerMapping은 모든 Controller들의 객체를 저장하고 있다가, 클라이언트의 요청이 들어올 시 특정 Controller를 반환하는 기능이다. HashMap의 정보를 보면 *.do가 어느 객체와 매핑되어있는지를 확인 가능하다.
"Map은 Key : value로 매핑이 되어있다. 결국 path가 key 값이고 해당 객체가 value가 되는 것이다. 결국 컨트롤러에 해당하는 value 값을 반환한다. 개발적으로도 클래스가 실행되면 생성자가 가장 먼저 실행 된다는 것 기억하자."
4.2.3. ViewResolver 클래스 작성
#3. 첨부자료 - ViewResolver 클래스 작성
package com.springbook.view.controller;
public class ViewResolver {
public String prefix;
public String suffix;
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public String getView(String viewName) {
return prefix + viewName + suffix;
}
}
"결국 로직 처리 후에는 다른 페이지로 이동(* Response.sendredirect ) 한다. 이 때, 로직들이 리턴할 View 화면의 생성을 지원하는 클래스이다. "
4.2.4. DispatcherServlet 클래스 작성
#4. 첨부자료 - 4.DispatcherServlet 클래스 작성
package com.springbook.view.controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
import com.springbook.biz.user.UserVO;
import com.springbook.biz.user.impl.UserDAO;
/**
* Servlet implementation class DispatcherServlet
*/
//@WebServlet(name = "action", urlPatterns = { "*.do" })
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private HandlerMapping handlerMapping;
private ViewResolver viewResolver;
public void init() throws ServletException {
handlerMapping = new HandlerMapping();
viewResolver = new ViewResolver();
viewResolver.setPrefix("./");
viewResolver.setSuffix(".jsp");
}
/**
* @see HttpServlet#HttpServlet()
*/
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// response.getWriter().append("Served at: ").append(request.getContextPath());
System.out.println("투입get");
process(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// doGet(request, response);
System.out.println("투입post1");
request.setCharacterEncoding("EUC-KR");
process(request, response);
}
private void process(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 1. 클라이언트의 요청 path 정보를 추출한다.
String uri = request.getRequestURI();
System.out.println(uri);
System.out.println(uri.lastIndexOf("/"));
String path = uri.substring(uri.lastIndexOf("/")); /*substring 처음 시작 부터 ~ 끝위치 전까지 뽑아낸다.*/
System.out.println(path);
// 2. HandlerMapping 을 통해 path에 해당되는 Controller를 검색한다.
Controller ctrl = handlerMapping.getController(path);
// 3. 검색된 Controller를 실행한다.
String viewName = ctrl.handleRequest(request, response);
// 4. ViewResolver를 통해 viewName에 해당하는 화면을 검색한다.
String view = null;
if (!viewName.contains(".do")) {
view = viewResolver.getView(viewName);
} else {
view = viewName;
}
// 5. 검색된 화면으로 이동한다.
response.sendRedirect(view);
}
}
" Viewresolver, Controller, HandlerMapping 모두 Dispatcher 서블릿에 의해서 처리된다. 이하에서 MVC프레임워크의 웹 처리 방식을 살펴보자 "
4.3 Login 로직의 실행 순서
" Login 로직의 실행 순서에 대해서 살펴 볼 것이다. MVC 프레임워크 컨테이너 동작 순으로 서술하겠다."
4.3.1 Login.jsp 실행
1) 소스
#1. 첨부자료 - Login.jsp
#2. 첨부자료 - DispatcherServlet.java(1)
#3. 첨부자료 - DispatcherServlet.java(2)
#4. 첨부자료 - LoginController.java
#5. 첨부자료 - ViewResolver.java
2) 설명
2-1) 클라이언트 측에서 method = "post" 방식으로 "login.do"를 실행 시켰다.
2-2) 역시, DispatcherServlet이 먼저 대응하여, "Post" 방식으로 요청을 받는다.
2-3) process 메소드에서 path를 추출하여 분기처리 한 후, path로 매핑 되어있는 LoginController를 호출한다.
2-4) LoginController에서 로직 처리를 한 후, 리턴 값으로 "getBoardList.do"를 반환한다. View에 저장
2-5) response.sendRedirect(View)를 통해 다음동작(*getBoardList.do)을 실행한다.
2-6) getBoardList.do는 method = "get" 방식으로 서블릿과 연동된다.
2-7) ViewResolver에서 .jsp 파일을 리턴값으로 반환한다.
[로그]
* MVC 프레임워크 웹개발 최종 결과물