온 코딩

[Spring] (게시판예제)스프링 MVC 구조 구현 - DispatcherServlet, HadlerMapping , Controller, ViewResolver 직접 만들기 본문

복습 ARCHIVE/모델별 프로젝트

[Spring] (게시판예제)스프링 MVC 구조 구현 - DispatcherServlet, HadlerMapping , Controller, ViewResolver 직접 만들기

SummerON 2021. 6. 22. 11:28

각 클래스의 역할 

클래스 기능
DispatcherServlet 유일한 서블릿 클래스로서 모든 클라이언트의 요청을 가장 먼저 처리하는 Front Controller
HandlerMapping 클라이언트 요청을 처리할 Controller 맵핑
Controller 실질적인 클라이언트 요청 처리
ViewResolver Controller가 리턴한  View 이름으로 실행될 JSP 경로 구성

 

패키지 구조

 

1. Controller - 모든 ~~Controller들은 Controller를 구현 받음

package com.hhw.view.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface Controller {
	String handleRequest(HttpServletRequest request, HttpServletResponse response);
}

실제 컨트롤러에서 요청 처리 후 뷰 이름 반환

package com.hhw.view.user;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.hhw.biz.user.UserVO;
import com.hhw.biz.user.impl.UserDAO;
import com.hhw.view.controller.Controller;

public class LoginController implements Controller {

	public LoginController() {
	}

	@Override
	public String handleRequest(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("컨트롤러 : 로그인 처리");
		// 1. 사용자 입력 정보 추출
		String id = request.getParameter("id");
		String password = request.getParameter("password");

		// 2. DB연동처리
		UserVO vo = new UserVO();
		vo.setId(id);
		vo.setPassword(password);

		UserDAO userDAO = new UserDAO();
		UserVO user = userDAO.getUser(vo);
		// null혹은 조회된 결과 값을 가지고 있음

		// 3. 화면 네비게이션 - 나중에 뷰리졸버 처리 할 예정이어서 문자열만 리턴 / 화면전환 안함
		if (user != null) {
			HttpSession session = request.getSession();
			session.setAttribute("name", user.getName());
			
			return "getBoardList.do";
		} else {
			return "login";
		}
	}
}

 

2. HandlerMapping

package com.hhw.view.controller;

import java.util.HashMap;
import java.util.Map;

import com.hhw.view.user.LoginController;

public class HandlerMapping {

	private Map<String, Controller> mappings;
	
	public HandlerMapping() {
		mappings = new HashMap<String,Controller>();
		mappings.put("/login.do", new LoginController());
		
	}
	
	public Controller getController(String path){
		return mappings.get(path);
		//"/login.do" 키 값이 들어오면 로그인 컨트롤러 반환 
	}

}

 

3. ViewResolver

package com.hhw.view.controller;

public class ViewResolver {

	public String prefix; // Controller가 리턴한 파일의 경로
	public String suffix; // Controller가 리턴한 파일의 구체적인 확장자
	
	public ViewResolver() {
		
	}

	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;
		//Controller가 리턴한 파일명을 이용하여 최종 경로를 완성하여 반환
	}
}

 

4. DispatcherServlet

- 디스패쳐 서블릿 만들때 자동으로 web.xml 파일에 서블릿 맵핑이 되어 있음 

  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>com.hhw.view.controller.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

=> 모든 .do로 끝나는 url 패턴들은 디스패처 서블렛에 요청 사항이 전달 됨 

package com.hhw.view.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.hhw.biz.board.BoardVO;
import com.hhw.biz.board.impl.BoardDAO;



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("./"); // webapp위치 : http://localhost:portNum/classname 
    	viewResolver.setSuffix(".jsp");
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		process(request, response);
	}


	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		process(request, response);
	}
	
	private void process(HttpServletRequest request, HttpServletResponse response ) throws IOException{
		//1. 클라이언트의 요청 path 정보 추출
		String uri = request.getRequestURI();
		String path = uri.substring(uri.lastIndexOf("/"));
		
		//2. HandlerMapping을 통해  path에 해당하는 Controller를 검색하고 객체를 생성한다.
		Controller ctrl = handlerMapping.getController(path);
		
		//3. 생성 된 Controller를 실행하여 viewName(화면위치)를 반환 받는다.
		String viewName = ctrl.handleRequest(request, response);
		
		//4. ViewResolver를 통해 viewName에 해당하는 화면을 검색한다.
		String view = null;
		if(!viewName.contains(".do")){
        //".do"를 포함하지 않으면 -> 액션 없이 바로 jsp로 전환
			view = viewResolver.getView(viewName);
		}else{
        //".do"포함하고 있으면 액션 처리
			view = viewName;
		}
		
		//5. 검색된 화면으로 이동
		response.sendRedirect(view);
	}

}

DispatcherServlet에서 요청사항이 처리 되는 과정  

1. 웹주소줄 형태의 요청사항 => doGet() => process() 실행

2. method="post" 형태의 요청 사항 => doPost() => 인코딩 후 process() 실행 

* 만약 파라미터가 같이 전달 되면 각 파라미터들은 각 메서드의 첫번째 매개변수인 request내부의 params 영역에 저장

 

Comments