본문 바로가기
Spring

Spring #2 : 스프링 MVC (230116)

by haheehee 2023. 1. 17.

스프링에서의 MVC 기능

- 모델2 아키텍처를 지원

- 스프링과 다른 모듈과의 연계가 용이

- 타일즈(tiles)나 사이트메시(sitemesh) 같은 View 기술과 연계 용이

- 태그 라이브러리를 통해 message 출력, theme 적용, 입력 폼을 쉽게 구현 가능

 

스프링 프레임워크 MVC 구성 요소

구성요소 description
DispatcherServlet 클라이언트의 요청을 전달받아 해당 요청에 대한 컨트롤러를 선택하여 클라이언트의 요청 전달
컨트롤러가 반환한 값을 View에 전달하여 알맞은 응답 생성.
HandlerMapping 클라이언트가 요청한 URL을 처리할 컨트롤러를 지정
Controller 클라이언트의 요청을 처리한 후 그 결과를 DispatcherServlet에 전달
ModelAndView 컨트롤러가 처리한 결과 및 뷰 선택에 필요한 정보를 저장
ViewResolver 컨트롤러의 처리 결과를 전달할 뷰를 지정
View 컨트롤러의 처리 결과 화면을 생성
RequestDispatcher dispatch = request.getRequestDispatcher(nextPage);
dispatch.forward(request, response);

 


스프링 프레임워크 MVC 기능 과정

  1. 브라우저가 DispatcherServlet에 URL로 접근하여 정보 요청
  2. 핸들러 매핑에서 요청에 대해 매핑된 컨트롤러가 있는지 요청
  3. 매핑된 컨트롤러에 대해 처리 요청
  4. 컨트롤러가 클라이언트의 요청 처리 결과와 View 이름을 ModelAndView에 저장 -> DispatcherServlet으로 반환
  5. DispatcherServlet에서는 컨트롤러에서 보내온 View 이름을 ViewResolver로 보내 해당 View를 요청
  6. ViewResolver는 요청한 View를 전송
  7. View의 처리 결과를 DispatcherServlet으로 전송
  8. DispatcherServlet은 최종 결과를 브라우저로 전송

 

** DispatcherServlet이 브라우저와 웹 사이에 있다. (스프링프레임워크가 관여)

** Handler mapping은 Simple과 Multi 두 가지가 있다.

 


SimpleUrlController 스프링 MVC 실습 #1

 

SimpleUrlController 실행과정

  1. 브라우저에서 http://locahost:8080/prosp01/test/index.do로 요청
  2. DispatcherServlet은 요청에 대해 미리 action-servlet.xml에 매핑된 SimpleUrlController를 요청
  3. 컨트롤러는 요청에 대해 test 폴더에 있는 index.jsp를 브라우저로 전송

SimpleUrlController Spring Framework 실습 필요파일들

파일 description
web.xml 브라우저에서 *.do로 요청 시, 스프링의 DispatcherServlet 클래스가 요청받을 수 있게 서블릿 매핑
action-servlet.xml 스프링 프레임워크에서 필요한 빈들 설정
SimpleUrlController.java 매핑된 요청에 대해 컨트롤러 기능 수행
index.jsp 요청에 대해 컨트롤러가 브라우저로 전송하는 JSP

 

 

프로젝트는 Dynamic Web Project로 생성.

Target runtime을 꼭 Apache Tomcat v9.0으로 설정해주기.

 

해당 라이브럴리들을 webapp-WEB-INF-lib폴더에 복사-붙여넣기,

복사-붙여넣기한 JAR파일들 Build Path

 

webapp폴더에 WEB-INF 폴더 안에 web.xml, action-servlet.xml 파일 생성

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.Jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
	<servlet>
		<servlet-name>action</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>action</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
</web-app>

web.xml

 

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<bean id="simpleUrlController" class="com.spring.ex01.SimpleUrlController" />
	<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props>
				<prop key="/test/index.do">simpleUrlController</prop>
			</props>
		</property>
	</bean>
</beans>

action-servlet.xml

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>spring 테스트입니다.</title>
</head>
<body>
	<h1>index.jsp파일입니다.</h1>
	<p>Hello Spring!</p>
</body>
</html>

webapp폴더에 test폴더 생성 후, 

그 안에 index.jsp파일 생성

 

package com.spring.ex01;

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

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class SimpleUrlController implements Controller {
	@Override 
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		return new ModelAndView("index.jsp");
	}
}

com.spring.ex01패키지 생성 후, 

그 안에 SimpleUrlController.java 파일 생성

 

-- 결과 --

 


MultiActionController 스프링 MVC 실습 #2

 

MultiActionController 

- 여러 요청명에 대해 한 개의 컨트롤러에 구현된 각 메서드로 처리할 수 있음

클래스 description
MultiActionController URL 요청명으로 바로 컨트롤러를 지정해 사용 가능
PropertiesMethodNameResolver URL 요청명으로 컨트롤러의 설정 파일에서 미리 설정된 메서드를 바로 호출해 사용 가능
InternalResourceViewResolver JSP나 HTML파일가 같은 웹 어플리케이션의 내부 자원을 사용하여 뷰 생성 기능 제공
기본적으로 사용하는 View 클래스. prefix와 suffix 속성을 사용해 경로 지정 가능

MultiActionController Spring Framework 실습 필요파일들

파일 description
web.xml 브라우저에서 *.do로 요청 시, 스프링의 DispatcherServlet 클래스가 요청받을 수 있게 서블릿 매핑
action-servlet.xml 스프링 프레임워크에서 필요한 빈들 설정
UserController.java 매핑된 요청에 대해 컨트롤러 기능 수행
loginForm.jsp 로그인창
result.jsp 로그인 결과를 보여주는 JSP

 

web.xml은 그대로!!

 

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
		<property name="prefix" value="/test/" />
		<property name="suffix" value=".jsp" />
	</bean>
	
	<bean id="userUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props>
				<prop key="/test/*.do">userController</prop>
			</props>
		</property>
	</bean>
	
	<bean id="userController" class="com.spring.ex02.UserController">
		<property name="methodNameResolver">
			<ref local="userMethodNameResolver" />
		</property>
	</bean>
	
	<bean id="userMethodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
		<property name="mappings">
			<props>
				<prop key="/test/login.do">login</prop>
			</props>
		</property>
	</bean>
</beans>

action-servlet.xml

- <ref>태그의 local속성 : "현재 xml파일 안의" 라는 뜻.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<% request.setCharacterEncoding("utf-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인창</title>
</head>
<body>
	<form name="frmLogin" method="post" action="${contextPath}/test/login.do">
		<table border="0" width="80%" align="center">
			<tr align="center">
				<td>아이디</td>
				<td>비밀번호</td>
			</tr>
			<tr align="center">
				<td><input type="text" name="userID" value="" size="20"></td>
				<td><input type="password" name="passwd" value="" size="20"></td>
			</tr>
			<tr>
				<td align="right"><input type="submit" value="로그인" /></td>
				<td align="left"><input type="reset" value="다시입력" /></td>
			</tr>
		</table>
	</form>
</body>
</html>

loginForm.jsp (test폴더 안)

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<% request.setCharacterEncoding("utf-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>결과</title>
</head>
<body>
	<table border="1" width="50%" align="center">
		<tr align="center">
			<td>아이디</td>
			<td>비밀번호</td>
		</tr>
		<tr align="center">
			<td>${userID}</td>
			<td>${passwd}</td>
		</tr>
	</table>
</body>
</html>

result.jsp파일 (test폴더 안)

 

package com.spring.ex02;

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

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

public class UserController extends MultiActionController {
	public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String userID = "";
		String passwd = "";
		ModelAndView mav = new ModelAndView();
		request.setCharacterEncoding("utf-8");
		userID = request.getParameter("userID");
		passwd = request.getParameter("passwd");
		mav.addObject("userID", userID);
		mav.addObject("passwd", passwd);
		mav.setViewName("result");
		
		return mav;
	}
}

UserController.java 클래스.

com.spring.ex02패키지 안에 생성해주면 된다.

MultiActionController를 extends해줌.

 

-- 결과 --

loginForm.jsp에서 서버로 실행

데이터를 입력하고 로그인

login.do가 실행되며 입력한 데이터가 출력된다.

 


MultiActionController : 회원 정보 출력실습 #3

...
    <bean id="userMethodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
		<property name="mappings">
			<props>
				<prop key="/test/login.do">login</prop>
				<prop key="/test/memberInfo.do">memberInfo</prop>
			</props>
		</property>
	</bean>
...

action-servlet.xml

 

...
    public ModelAndView memberInfo(HttpServletRequest request, HttpServletResponse response) throws Exception {
		request.setCharacterEncoding("utf-8");
		ModelAndView mav = new ModelAndView();
		String id = request.getParameter("id");
		String pwd = request.getParameter("pwd");
		String name = request.getParameter("name");
		String email = request.getParameter("email");
		mav.addObject("id", id);
		mav.addObject("pwd", pwd);
		mav.addObject("name", name);
		mav.addObject("email", email);
		mav.setViewName("memberInfo");
		
		return mav;
	}
}

UserController.java

회원가입 창에서 전송된 회원 정보를 addObject()메소드를 사용하여 ModelAndView객체에 바인딩

setViewName() 메소드로 memberInfo.jsp에 포워딩

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<% request.setCharacterEncoding("utf-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인창</title>
</head>
<body>
	<form method="post" action="${contextPath}/test/memberInfo.do">
		<h1 class="text_center">회원가입창</h1>
		<table border="0" width="80%" align="center">
			<tr>
				<td width="200"><p align="right">아이디</td>
				<td width="400"><input type="text" name="id"></td>
			</tr>
			<tr>
				<td width="200"><p align="right">비밀번호</td>
				<td width="400"><input type="password" name="pwd"></td>
			</tr>
			<tr>
				<td width="200"><p align="right">이름</td>
				<td width="400"><input type="text" name="name"></td>
			</tr>
			<tr>
				<td width="200"><p align="right">이메일</td>
				<td width="400"><input type="text" name="email"></td>
			</tr>
			<tr>
				<td></td>
				<td align="left"><input type="submit" value="가입하기">
					<input type="reset" value="다시입력"></td>
			</tr>
		</table>
	</form>
</body>
</html>

memberForm.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<% request.setCharacterEncoding("utf-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인창</title>
</head>
<body>
	<table border="1" width="100%" align="center">
		<tr align=center bgcolor="lightblue">
			<td><b>아이디</b></td>
			<td><b>비밀번호</b></td>
			<td><b>이름</b></td>
			<td><b>이메일</b></td>
		</tr>
		<tr align=center>
			<td>${id}</td>
			<td>${pwd}</td>
			<td>${name}</td>
			<td>${email}</td>
		</tr>
	</table>
</body>
</html>

memberInfo.jsp

 

-- 결과 --

실행결과창

데이터를 입력한 후, 

가입하기 버튼을 누르면

입력한 회원정보가 출력된다.

 


MultiActionController : 로그인 정보 출력실습 #4

MultiActionController와 PropertiesMethodNameResolver를 이용한 메소드 이름 설정방법

- 요청명 : /test/login.do  => 호출메소드 이름 : login()

- 요청명 : /test/memberInfo.do  => 호출메소드 이름 : memberInfo()

 

...
public class UserController extends MultiActionController {
	public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String userID = "";
		String passwd = "";
		String viewName = getViewName(request);	// getViewName()메소드를 호출해 요청명에서 확장명 .do를 제외한 뷰이름을 가지고옴
		ModelAndView mav = new ModelAndView();
		request.setCharacterEncoding("utf-8");
		userID = request.getParameter("userID");
		passwd = request.getParameter("passwd");
		mav.addObject("userID", userID);
		mav.addObject("passwd", passwd);
		// mav.setViewName("result");
		mav.setViewName(viewName);
		System.out.println("ViewName : " + viewName);
		
		return mav;
	}
	
    private String getViewName(HttpServletRequest request) throws Exception {
		String contextPath = request.getContextPath();
		String uri = (String) request.getAttribute("javax.servlet.include.request_uri");
		if(uri==null || uri.trim().equals("")) {
			uri = request.getRequestURI();
		}
		
		int begin = 0;
		if(!((contextPath==null)||("".equals(contextPath)))) {
			begin = contextPath.length();
		}
		int end;
		if(uri.indexOf(";")!=-1) {
			end = uri.indexOf(";");
		} else if(uri.indexOf("?")!=-1) {
			end = uri.indexOf("?");
		} else {
			end = uri.length();
		}
		
		String fileName = uri.substring(begin, end);
		if(fileName.indexOf(".")!=-1) {
			fileName = fileName.substring(0, fileName.lastIndexOf("."));
		}
		if(fileName.lastIndexOf("/")!=-1) {
			fileName = fileName.substring(fileName.lastIndexOf("/"), fileName.length());
		}
		
		return fileName;
	}
	...
}

UserController.java

request.getContextPath() => 프로젝트 이름 (prosp02)

 

String uri = (String)request.getAttribute("javax.servlet.include.request_uri");

if(uri == null || uri.trim().equals("")) { uri = request.getRequestURI(); }

=> uri가지고 오는 것. 그런데, 보통 첫번째 줄에서 나오지 않아서 if문안의 실행문으로 가지고옴.

 

ModelAndView => 웹브라우저의 출력뷰와, 출력뷰에 제공한 데이터를 저장한 객체

.addObject() => 데이터 저장

.setViewName() => 출력뷰 저장

 

 

 

실습#2의 result.jsp-> login.jsp로 이름 변경

나머지 파일 실습#2와 동일

 

-- 결과 --

 

 

 

 

댓글