본문 바로가기

Spring

[Spring] MVC2 패턴 동작과정1

반응형

MVC2의 과정을 Spring 스타일로 제작 

★동작 순서★
사용자의 요청 --*.do --> DS -> HM -> C호출 -> 경로정보를 반환 -> VR -> 사용자에게 화면을 제공 

 


1. Dispatcher Servlet(DS) 

- 기존 FrontController 역할을 하는 서블릿을 Dispatcher Servlet라고 부름 

- URL Mapping은 *.do로 생성 

- 서블릿 파일 생성과 동시에 web.xml에 매핑이 됨 

- web.xml 에서 매핑이 완료되었기 때문에 


2. Controller 

 

2-1) interface 생성 

 

- controller 파일들의 메서드를 강제하기 위해서 interface를 생성 

- 기존에 Action Forward로 페이지 이동 처리 했던 것과 달리 이제는 경로만 VeiwResolver에 Stirng 값으로 전달 

package com.kim.biz.controller;

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

//기존 Action 역할 
public interface Controller {
	String handleRequest(HttpServletRequest request, HttpServletResponse response);
	// 기존에는 AF execute -> VR 경로만 String으로 전달
}

 

 

 

2-2) 각종 Controller 생성

 

- 각 기능마다 생성되는 Controller 들은 interface를 implements 함

- ViewResolver에서 처리해주기 때문에 경로인 "login"만 반환 

package com.kim.biz.controller;

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

import com.kim.biz.member.MemberVO;
import com.kim.biz.member.impl.MemberDAO;

public class LoginController implements Controller {

	@Override
	public String handleRequest(HttpServletRequest request, HttpServletResponse response) {
		String mid=request.getParameter("mid");
		String mpw=request.getParameter("mpw");
		MemberVO mVO=new MemberVO();
		mVO.setMid(mid);
		mVO.setMpw(mpw);
		
		MemberDAO mDAO=new MemberDAO();
		mVO=mDAO.selectOneMember(mVO);
		
		if(mVO==null) {
			return "login"; // VR가 .jsp를 추가하기때문에 생략해서 반환
		}
		else {
			return "main.do";
		}
	}
}

3. HandlerMapping

 

- client의 request URL에 매핑되는 Controller를 찾아 DispatcherServelt에 반환 - Mappings에 생성자 주입 - private를 붙여 싱글톤 패턴이 유지되게 하는데 이는 객체의 무분별한 생성으로 인하여 메모리가 낭비되는걸 막기 위함! 

 

싱글톤 패턴이란?

  • 클래스의 인스턴스가 1개만 생성되는 것을 보장하는 디자인 패턴 
  • 2개 이상의 객체가 만들어지지 않게 함! 
  • 간단하게 생각하면 private를 이용해서 new로 생성하지 못하게 할 수 있음
package com.kim.biz.controller;

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

public class HandlerMapping {  // 싱글톤 패턴이 유지됨 -> 객체의 무분별한 생성을 막기위해 
	//input : 어떤 요청에 대해 == String
	//output : 무슨 Controller 객체를 제공해야하는지 == Controller 
	private Map<String, Controller> mappings; //의존 관계 -> DI => 생성자 주입 
	
	public HandlerMapping() {
		mappings=new HashMap<String,Controller>();
		mappings.put("/login.do", new LoginController());
	}
	
	public Controller getController(String command) {
		return mappings.get(command);
	}
}

4. ViewResolver 

- Controller가 반환한 View Name을 기반으로 View Name에 맞는 View를 찾아 Dispatcher Servelt에 리턴 

- 어디로 가야하는지 경로를 만들어 줌 

package com.kim.biz.controller;

public class ViewResolver {
	public String prefix; //의존 관계 -> DI => setter 주입 
	public String suffix; //의존 관계 -> DI => setter 주입 
	public String getPrefix() {
		return prefix;
	}
	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}
	public String getSuffix() {
		return suffix;
	}
	public void setSuffix(String suffix) {
		this.suffix = suffix;
	}
	
	
	public String getView(String viewName) { //경로를 만들어줌 
		return prefix+viewName+suffix;
	}
}

 

DS를 최종적으로 종합해보자면, 

HM, VR 의존 관계로 DI 

HM은 생성자 주입-> new 

VR은 setter 주입 -> set 해줌 

package com.kim.biz.controller;

import java.io.IOException;

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


public class DispatcherServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	//의존관계 
	private HandlerMapping handlerMapping;
	private ViewResolver viewResolver;
	
	//init() 통해서 DI 
	public void init() throws ServletException{
		handlerMapping=new HandlerMapping(); //생성자 주입 -> new하면 됨
		viewResolver=new ViewResolver(); // setter 주입이기 때문에 => set 해주어야 함 
		
		viewResolver.setPrefix("./");
		viewResolver.setSuffix(".jsp");
	}

    public DispatcherServlet() {
        super();

    }

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

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8"); //필터가 없기 때문에 인코딩을 이렇게 해줌 
		
		doAction(request,response);
	}
	
	private void doAction(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String command=request.getRequestURI();
		command=command.substring(command.lastIndexOf("/"));
		System.out.println(command);
		
		//HM에서 요청에 맞는 controller를 가져옴 
		Controller ctrl=handlerMapping.getController(command);
		// controller가 로직 수행 하고 경로를 반환 
		String viewName=ctrl.handleRequest(request, response);
		
		String view=null;
		if(viewName.contains(".do")) {
			view=viewName;
		}else {
			view=viewResolver.getView(viewName);
		}
		response.sendRedirect(view);
		
	}
}

 

구성요소 설명
DispatcherServlet 클라이언트의 요청을 전달받아 요청에 맞는 컨트롤러가 리턴한 결과값을 View에 전달
HandlerMapping 클라이언트의 요청(URL)을 어떤 컨트롤러가 처리할지 결정
Controller 클라이언트의 요청을 처리한 뒤, 결과를 DispatcherServlet에 전달
ViewResolver 컨트롤러의 처리결과를 생성할 뷰 결정 

 

 

Spring MVC2 패턴2 장점 

 

※ 메모리를 불필요하게 사용하던 객체들이 현저히 줄어듦
※ 하드코딩 X (코드의 불필요한 반복패턴이 줄어듦) => 코드가 간결해짐 
※ 결합도가 낮아짐 / 응집도가 높아짐 

반응형