자바/SpringFrameWork

[스프링프레임워크 DAY3 - C4)]-MVC 프레임워크 개발

itboxer91 2020. 6. 20. 16:33

"앞 절에서는 MVC1-2를 이용한 웹 프로젝트 개발에 관해 학습했다. 여기서 부터는 드디어 프레임워크를 활용한 웹 프로젝트 제작에 대하서 배운다."

4.1 MVC 프레임워크 구조

: MVC2 패턴의 DIspatcherServlet.java 파일을 보면, 웹에서 사용 되는 모든 로직이 한 개의 클래스에 모여있다. 이런 식이라면 유지보수 및 개발이 상당히 어려워 진다. 따라서 하나의 서블릿안에 모든 로직을 넣기 보다는 각각의 Controller 별로 나누어 구현 하는 것이 효과적이다.

 

#1. 첨부자료 1 - MVC2 패턴에서 모든 로직이 모여져 있는 DIspatcherServlet.java의 분기 로직(* MVC2 참고)

 

<MVC2 패턴의 DispatcherServlet.jsva(캡처본)>

"편의상 메모장에서 스캔 했지만... 여하튼 모든 *.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

<Login.jsp 소스 첨부>

#2. 첨부자료 - DispatcherServlet.java(1)

<DispatcherServlet 소스 첨부 - (1)>

#3. 첨부자료 - DispatcherServlet.java(2)

<DispatcherServlet 소스 첨부-(2) >

#4. 첨부자료 - LoginController.java

<LoginController 소스 첨부>

#5. 첨부자료 - ViewResolver.java

 

<ViewResolver 소스 첨부>

 

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 프레임워크 웹개발 최종 결과물

BoardWeb2006.zip
0.06MB