본문 바로가기

학원/복기

[Spring] MVC2 예제 (Spring X)

xyz.itwill.09.mvc 패키지 생성

 

Spring MVC에 대해 배우기 전에 이전에 했던 MVC2 패턴을 Spring 스럽게 만들어 보는 연습을 해볼 것이다.

 


Member (DTO 클래스) 선언 

//회원정보를 저장하기 위한 클래스 - DTO
@AllArgsConstructor
@Data
public class Member {
	private String id;
	private String name;
	private String address;
}

 

 

컨트롤러(Controller)

: 컨트롤러는 클라이언트의 모든 요청을 받아 URL 주소를 분석하여 요청 처리 클래스(Model)의 메소드를 호출하여 클라이언트의 요청을 처리하고 JSP 문서(Veiw)로 스레드를 이동하여 응답처리 되도록 프로그램의 흐름을 제어하는 기능을 제공한다. 컨트롤러는 서블릿 (Servlet)으로 구현한다.

 

컨트롤러 기능을 제공하기 위한 서블릿 클래스를 선언한다.

  • 생성된 서블릿 클래스는 클라이언트의 모든 요청을 받아 처리하는 단일 진입점의 역할을 수행할 것이다. 이를 Front Controller Pattern이라고 부른다.
  • [web.xml] 파일에서 클래스를 서블릿(웹프로그램)으로 등록하고 클라이언트의 모든 요청을 처리할 수 있도록 URL 패턴을 설정해주어야 한다.

 

DispatcherServlet (컨트롤러)

//컨트롤러
public class DispatcherServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	//클라이언트의 요청을 처리하기 위한 자동 호출되는 메소드를 오버라이드 선언
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1.클라이언트의 요청 URL 주소를 분석하여 요청정보를 반환받아 저장
		String requestURI=request.getRequestURI();
		String contextPath=request.getContextPath();
		String command=requestURI.substring(contextPath.length());
		
		//2.클라이언트의 요청정보를 이용하여 요청 처리 클래스(Model)의 객체를 제공받아 객체의
		//메소드 호출하여 클라이언트의 요청을 처리하고 응답 관련 정보(View)를 반환받아 저장
		//인터페이스로 참조변수를 선언하면 인터페이스를 상속받은 모든 자식클래스의 객체 저장 가능
		/*
		Controller controller=null;
		//클라이언트의 요청정보를 비교하여 요청 처리 클래스(Model)로 객체를 생성하여 저장
		if(command.equals("/list.itwill")) {
			controller=new ListController();
		} else if(command.equals("/view.itwill")) {
			controller=new ViewController();
		}
		*/
		
		//HandlerMapping 클래스로 객체 생성
		// => HandlerMapping 클래스 :클라이언트의 요청정보와 요청 처리 클래스의 객체가 엔트리로
		//저장된 Map 객체를 제공하기 위한 클래스
		HandlerMapping handlerMapping=new HandlerMapping();
		//HandlerMapping 객체의 메소드를 호출하여 매개변수에 전달된 요청정보에 대한 요청 처리
		//클래스의 객체를 반환받아 저장
		Controller controller=handlerMapping.getController(command);
		
		//요청 처리 클래스의 메소드를 호출하여 클라이언트의 요청을 처리하고 응답 처리할 JSP
		//문서의 이름(ViewName)을 반환받아 저장
		String viewName=controller.handleRequest(request, response);
		
		//3.JSP 문서로 포워드 이동하여 클라이언트에게 처리결과가 응답되도록 처리
		// => 요청 처리 메소드의 반환값(ViewName)을 이용하여 JSP 문서의 경로를 완성하여 포워드 이동
		//ViewResolver 클래스로 객체 생성
		// => ViewResolver 클래스 : 요청 처리 메소드의 반환값(ViewName)을 이용하여 응답 처리할
		//JSP 문서의 경로를 완성하여 반환하는 메소드
		ViewResolver viewResolver=new ViewResolver();
		String view=viewResolver.getView(viewName);//응답할 JSP 문서의 경로를 반환받아 저장
		request.getRequestDispatcher(view).forward(request, response);//JSP 문서로 포워드 이동
	}
}

 

 

모델 기능을 제공하는 클래스가 반드시 상속받아야하는 인터페이스를 선언한다.

  • 모든 모델 클래스에 동일한 메소드가 작성되도록 규칙을 제공해야 한다. 
  • Contoller에서 모델 클래스의 객체로 요청 처리 메소드를 쉽게 호출하기 위해 위해 인터페이스가 필요하다.

 

Controller (인터페이스)

//모델 기능을 제공하는 클래스가 반드시 상속받아야 하는 인터페이스
public interface Controller {
	//모든 Model 기능의 클래스에서 반드시 작성할 요청 처리 메소드를 추상메소드로 선언 
	String handleRequest(HttpServletRequest request, HttpServletResponse response) 
		throws ServletException, IOException;
}

 

 

모델 기능을 제공하기 위한 클래스를 선언한다. 

  • 요청 처리 메소드가 추상메소드로 선언된 인터페이스를 상속받아 작성한다.
  • 클라이언트 요청을 한개의 요청 처리 클래스를 사용하여 요청 처리하는데, 이를 Command Pattern이라 부른다.
  • *모델(Model)은 클라이언트의 요청을 처리하기 위한 명령이 작성된 요청 처리 메소드가 선언된 클래스를 뜻한다.

 

ListController

  • 클라이언트가 [/list.itwill]의 URL 주소로 요청한 경우 컨트롤러에 의해 실행된 요청 처리 클래스
//모델 기능을 제공하기 위한 클래스
public class ListController implements Controller {
	//요청 처리 메소드 : 클라이언트의 요청을 처리하기 위한 명령을 작성하기 위한 메소드 
	// => 응답 처리할 JSP 문서의 이름(ViewName)을 반환한다. 
	@Override
	public String handleRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//요청 처리 명령 작성 - 데이터 처리 : Service 클래스의 메소드를 호출 
		List<Member> memberList=new ArrayList<Member>();
		memberList.add(new Member("abc", "홍길동", "서울시 강남구"));
		memberList.add(new Member("xyz", "임꺽정", "인천시 월미구"));
		memberList.add(new Member("opq", "전우치", "수원시 팔달구"));
		
		//요청에 대한 처리결과를 JSP 문서에 제공하기 위해 request 속성값으로 저장 
		request.setAttribute("memberList", memberList);
		
		//처리결과를 제공받아 클라이언트에게 응답처리할 JSP 문서의 이름(ViewName)을 반환
		return "member_list";
	}
}

 

ViewController

  • 클라이언트가 [/view.itwill]의 URL 주소로 요청한 경우 컨트롤러에 의해 실행될 요청 처리 클래스
//모델 기능을 제공하기 위한 클래스
public class ViewController implements Controller {

	@Override
	public String handleRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		Member member=new Member("test", "일지매", "서울시 종로구");
		request.setAttribute("member", member);
		return "member_view";
	}
	
}

HandlerMapping

//클라이언트의 요청정보와 요청 처리 클래스의 객체를 Map 객체의 엔트리로 저장하여 제공하는 기능의 클래스
public class HandlerMapping {
	//Map 객체를 저장하기 위한 필드
	// => 엔트리의 제네릭으로 맵키는 요청정보를 저장하기 위해 String 클래스로 설정하고
	//맵값은 요청 처리 클래스의 객체를 저장하기 위해 Controller 인터페이스로 설정
	private Map<String, Controller> mappings;
	
	public HandlerMapping() {
		mappings=new HashMap<String, Controller>();
		mappings.put("/list.itwill", new ListController());
		mappings.put("/view.itwill", new ViewController());
	}
	
	//매개변수로 클라이언트의 요청정보를 전달받아 요청을 처리하기 위한 객체를 Map 객체에서
	//검색하여 반환하는 메소드
	public Controller getController(String command) {
		return mappings.get(command);
	}
}

 

ViewResolver

//응답 관련 정보를 제공하기 위한 클래스
public class ViewResolver {
	//매개변수로 ViewName을 전달받아 응답처리할 JSP 문서의 경로를 생성하여 반환
	public String getView(String viewName) {
		return "/WEB-INF/mvc/"+viewName+".jsp";
	}
}

 

 

동작하려면 [web.xml]에서 DispatcherServlet을 서블릿으로 등록해주어야 한다.

 

web.xml

...
	<!-- servlet : 클래스를 서블릿으로 등록하기 위한 엘리먼트 -->
	<servlet>
		<!-- servlet-name : 서블릿을 구분하기 위한 식별자를 설정하기 위한 엘리먼트 -->
		<servlet-name>mvc</servlet-name>
		<!-- servlet-class : 서블릿으로 구현하기 위한 클래스를 설정하는 엘리먼트 -->
		<!-- DispatcherServlet : 컨트롤러 기능을 제공하는 클래스 - Front Controller -->
		<servlet-class>xyz.itwill09.mvc.DispatcherServlet</servlet-class>
	</servlet>
	
	<!-- servlet-mapping : 서블릿에 URL 주소를 등록하기 위한 엘리먼트 -->
	<servlet-mapping>
		<!-- servlet-name : 등록된 URL 주소로 실행될 서블릿의 식별자를 설정하기 위한 엘리먼트 -->
		<servlet-name>mvc</servlet-name>
		<!-- url-pattern : 서블릿을 실행하기 위한 URL 주소(패턴)를 설정하기 위한 엘리먼트 -->
		<!-- => 컨트롤러 기능을 제공하는 클래스는 클라이언트의 모든 요청을 받아 처리할 수 있도록 설정 -->
		<url-pattern>*.itwill</url-pattern>
	</servlet-mapping>
...

 

 

member_list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>    
<%-- 회원목록을 제공받아 출력하는 JSP 문서 --%>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>회원목록</h1>
	<hr>
	<c:forEach var="member" items="${memberList}">
		<p>아이디 = ${member.id }, 이름 = ${member.name }, 주소 = ${member.address }</p>
	</c:forEach>
</body>
</html>

member_view.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 회원정보를 제공받아 출력하는 JSP 문서 --%>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>회원정보</h1>
	<hr>
	<p>아이디 = ${member.id }, 이름 = ${member.name }, 주소 = ${member.address }</p>
</body>
</html>