본문 바로가기

교육 및 세미나/신입사원 교육

12일차(2018.01.18)

Spring MVC

Model 1

Model 2

웹 개발을 위한 MVC 패턴이 적용된 Spring Framework.

Spring 에서는 DispatcherServlet 클래스가 컨트롤러 역할을 수행하게 된다.

Spring MVC의 주요 구성 요소

- DispatcherServlet

- HandlerMapping

- Controller : 우리가 작성. 액션 처리.

- ModelAndView

- ViewResolver

- View : 우리가 작성. 결과 출력.

- web.xml : 우리가 작성. DispatcherServlet 서블릿 객체 등록.

- dispatcher-servlet.xml : 우리가 작성.

ex)

http://www.fjoejlsli.lif/aaa.html (Model1)

http://www.leifninekf.iie/bbb.jsp (Model1)

http://www.eioowpd.dom/ccc (Model2)

Spring MVC 실행 흐름

- 사용자 요청 → DispatcherServlet

- DispatcherServlet  → HandlerMapping 에 주소 분석 요청.

- DispatcherServlet  → 특정 Controller 객체 호출 및 결과 수신.

결과는 ModelAndView 객체

※ ModelAndView 객체

: View 객체 정보와 결과값이 들어있는 객체.

- DispatcherServlet  → ViewResolver 에 View 객체 분석 요청.

- DispatcherServlet  → 특정 View 객체에 Model 객체를 넘겨주고 결과 출력.

Spring MVC 에서 내가 해야할 일

- Controller

: 액션 처리를 담당하는 Controller 클래스 작성.

- View

: 결과 출력용 JSP 페이지 작성.

- web.xml

: 서블릿 주소와 DispatcherServlet 클래스 등록.

- dispatcher-servlet.xml

: 내가 작성한 사용자 정의 Controller 객체 등록. URL 매핑 주소 등록.

Spring MVC 관련 실습

① MVC 패턴 이해하기

- 다이나믹 웹 프로젝트 생성 (→ 실무에서는 Spring Project 생성 )

: mvc01

- 톰캣 서버 등록

: port 8090

- 기타 환경 설정

: 폰트, 줄번호, 편집포맷, 인코딩 방식 등...

- SpringMVC 환경 설정을 위한 라이브러리 등록

: WebContent > WEB-INF > lib 경로에 등록

·경로1 : C:\spring-framework-with-docs\spring-framework-3.0.2.RELEASE\dist

파일① → org.springframework.aop-3.0.2.RELEASE.jar

파일② → org.springframework.asm-3.0.2.RELEASE.jar

파일③ → org.springframework.beans-3.0.2.RELEASE.jar

파일④ → org.springframework.context-3.0.2.RELEASE.jar

파일⑤ → org.springframework.core-3.0.2.RELEASE.jar

파일⑥ → org.springframework.expression-3.0.2.RELEASE.jar

파일⑦ → org.springframework.web.servlet-3.0.2.RELEASE.jar

파일⑧ → org.springframework.web-3.0.2.RELEASE.jar

파일⑨ → org.springframework.jdbc-3.0.2.RELEASE.jar

파일⑩ → org.springframework.transaction-3.0.2.RELEASE.jar

·경로2 : C:\spring-framework-dependencies\org.apache.commons\com.springsource.org.apache.commons.logging\1.1.1

파일⑪ → com.springsource.org.apache.commons.logging-1.1.1.jar

·경로3 : C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib

파일⑫ → ojdbc6.jar

·경로4 : E:\Downloads\jakarta-taglibs-standard-1.1.2\lib

파일⑬ → jstl.jar

파일⑭ → standard.jar

- 물리적 파일 구성

HelloController.java

  • 사용자 정의 컨트롤러 → com.test.mvc 패키지 경로에 구성
/*=================================
 * HelloController.java
 * -액션 처리 페이지
 * -Controller 인터페이스 구현
 *=================================
 */
package com.test.mvc;

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 HelloController implements Controller
{
	// Controller 인터페이스가 가지고 있는 메소드 오버라이딩
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception{
		// 결과값으로 반환해 줄 ModelAndView 객체 생성
		ModelAndView mav = new ModelAndView();
		
		//View 페이지에 대한 정보 설정
		// -- 실제 View 페이지의 주소 설정
		mav.setViewName("/WEB-INF/view/Hello.jsp");
		
		// Model 객체 정보 설정
		// -- mav.addObject("식별자","데이터")
		mav.addObject("hello", "Hello, SpringMVC World~!!!");
		// -- addObject() 는 setAttribute 한 것과 같은 효과
		
		// 결과 반환 → ModelAndView 객체
		return mav;
		
	}
}

Hello.jsp

  •  : 일단은 WebContent 경로에 직접 구성
.another_category { border: 1px solid #E5E5E5; padding: 10px 10px 5px; margin: 10px 0; clear: both; } .another_category h4 { font-size: 12px !important; margin: 0 !important; border-bottom: 1px solid #E5E5E5 !important; padding: 2px 0 6px !important; } .another_category h4 a { font-weight: bold !important; } .another_category table { table-layout: fixed; border-collapse: collapse; width: 100% !important; margin-top: 10px !important; } * html .another_category table { width: auto !important; } *:first-child + html .another_category table { width: auto !important; } .another_category th, .another_category td { padding: 0 0 4px !important; } .another_category th { text-align: left; font-size: 12px !important; font-weight: normal; word-break: break-all; overflow: hidden; line-height: 1.5; } .another_category td { text-align: right; width: 80px; font-size: 11px; } .another_category th a { font-weight: normal; text-decoration: none; border: none !important; } .another_category th a.current { font-weight: bold; text-decoration: none !important; border-bottom: 1px solid !important; } .another_category th span { font-weight: normal; text-decoration: none; font: 10px Tahoma, Sans-serif; border: none !important; } .another_category_color_gray, .another_category_color_gray h4 { border-color: #E5E5E5 !important; } .another_category_color_gray * { color: #909090 !important; } .another_category_color_gray th a.current { border-color: #909090 !important; } .another_category_color_gray h4, .another_category_color_gray h4 a { color: #737373 !important; } .another_category_color_red, .another_category_color_red h4 { border-color: #F6D4D3 !important; } .another_category_color_red * { color: #E86869 !important; } .another_category_color_red th a.current { border-color: #E86869 !important; } .another_category_color_red h4, .another_category_color_red h4 a { color: #ED0908 !important; } .another_category_color_green, .another_category_color_green h4 { border-color: #CCE7C8 !important; } .another_category_color_green * { color: #64C05B !important; } .another_category_color_green th a.current { border-color: #64C05B !important; } .another_category_color_green h4, .another_category_color_green h4 a { color: #3EA731 !important; } .another_category_color_blue, .another_category_color_blue h4 { border-color: #C8DAF2 !important; } .another_category_color_blue * { color: #477FD6 !important; } .another_category_color_blue th a.current { border-color: #477FD6 !important; } .another_category_color_blue h4, .another_category_color_blue h4 a { color: #1960CA !important; } .another_category_color_violet, .another_category_color_violet h4 { border-color: #E1CEEC !important; } .another_category_color_violet * { color: #9D64C5 !important; } .another_category_color_violet th a.current { border-color: #9D64C5 !important; } .another_category_color_violet h4, .another_category_color_violet h4 a { color: #7E2CB5 !important; } \n\n\n

기본적인 페이지 구성

\n\n\n

${hello }

\n\n\n\n"}}" data-ve-attributes="{"typeof":"mw:Extension/syntaxhighlight","about":"#mwt3"}">
<%@ page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello.jsp</title>
</head>
<body>

<h1>기본적인 페이지 구성</h1>

<!-- EL 표현 -->
<h1>${hello }</h1>

</body>
</html>

web.xml

  • DispatcherServlet 을 프론트 컨트롤러로 등록 → 서블릿 매핑 : WebContent > WEB-INF 경로
<?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">
	<display-name>mvc01</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	
	<!-- Spring MVC 프레임워크 등록 -->
	<!-- -DispatcherServlet 객체 등록 -->	
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	</servlet>
	
	<!-- 요청하는 서블릿 주소를 확장자 형태로 등록 -->
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>*.nds</url-pattern>
	</servlet-mapping>
	
	
	
</web-app>

dispatcher-servlet.xml

  • 사용자 정의 컨트롤러 매핑 : WebContent < WEB-INF 경로
\n\t \n\t \n\t \n\t \t \n\n"}}" data-ve-attributes="{"typeof":"mw:Extension/syntaxhighlight","about":"#mwt3"}">
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	<context:component-scan base-package="org.springframework.samples.petclinic.web" />
	 
	<!-- ※ 『dispatcher-servlet.xml』파일의 기본 설정 내용을 작성하는 과정에서
            스프링에서 제공하는 Document를 참조해서 작성할 수 있도록 한다.
            → C:\spring-framework-with-docs\spring-framework-3.0.2.RELEASE\docs\spring-framework-reference\pdf
			   경로의 spring-framework-reference.pdf 파일에서
			   페이지 이동 메뉴 450 페이지 (pdf 425 페이지) 의 내용을 기본 내용으로 작성할 수 있도록 한다. -->
	 <!-- 이곳에서 해야 할 일은 각각의 사용자 정의 컨트롤러 객체 등록 및 URL 매핑을 하는 것이다. -->
	 
	 <!-- 사용자 정의 컨트롤러 객체 등록 -->
	 <!-- -『name=""』속성에 URL 매핑 주소를 등록한다. -->
	 <!-- 이 때, 확장자는 web.xml 에 등록한 『.nds』으로 구성한다. -->
	 <!-- -『class=""』속성은 Controller 객체의 클래스 이름을 패키지 경로를 포함하여 등록한다. -->
	 <bean name="/hello.nds" class="com.test.mvc.HelloController"></bean>
	 <!-- → 사용자가 hello.nds을 요청하면 HelloController 가 일을 할 수 있도록 해줘라~!!! 라는 의미 -->	   
</beans>

※ 이전의 실습 과정에서 스프링 관련 환경 설정 파일(xml)은 파일 이름의 구성을 임의로 설정하는 것이 가능하였지만... 지금과 같은 실습 환경에서는 DispatcherServlet 이 이 이름을 가진 파일을 찾아서 해당 설정 내용을 읽어들이는 상황이기 때문에 임의로 이름을 변경해서는 안된다.

※ 『dispatcher-servlet.xml』파일의 기본 설정 내용을 작성하는 과정에서 스프링에서 제공하는 Document를 참조해서 작성할 수 있도록 한다. → C:\spring-framework-with-docs\spring-framework-3.0.2.RELEASE\docs\spring-framework-reference\pdf

경로의 spring-framework-reference.pdf 파일에서 페이지 이동 메뉴 450 페이지 (pdf 425 페이지) 의 내용을 기본 내용으로 작성할 수 있도록 한다.

- 사용자 요청 주소

http://localhost:8090/mvc01/hello.nds

- 요청

② 데이터 송수신 실습

- 데이터 송신 / 수신 실습

- 다이나믹 웹 프로젝트 생성 (→ 실무에서는 Spring Project 생성 )

: mvc02

- SpringMVC 환경 설정을 위한 라이브러리 등록

: WebContent > WEB-INF > lib 경로에 ... mvc01 에서 등록했던 항목들 복사&붙여넣기 등록

- 물리적 파일 구성

SendController.java

  • 사용자 정의 컨트롤러 : com.test.mvc 패키지 경로에 구성
/*============================
	SendController.java
	- 사용자 정릐의 컨트롤러
 =============================*/
package com.test.mvc;

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 SendController implements Controller
{

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception
	{
		ModelAndView mav = new ModelAndView();
		
		mav.setViewName("/WEB-INF/view/Send.jsp");
		
		return mav;
	}
	
}

Send.jsp

  •  : 일단은 WebContent > WEB-INF > view 경로에 직접 구성
if (!window.T) { window.T = {} } window.T.config = {"TOP_SSL_URL":"https://www.tistory.com","PREVIEW":false,"ROLE":"guest","PREV_PAGE":"","NEXT_PAGE":"","BLOG":{"id":2859442,"name":"hihellloitland","title":"27","isDormancy":false,"nickName":"hihelllo","status":"open","profileStatus":"normal"},"NEED_COMMENT_LOGIN":false,"COMMENT_LOGIN_CONFIRM_MESSAGE":"","LOGIN_URL":"https://www.tistory.com/auth/login/?redirectUrl=https://hihellloitland.tistory.com/22","DEFAULT_URL":"https://hihellloitland.tistory.com","USER":{"name":null,"homepage":null,"id":0,"profileImage":null},"SUBSCRIPTION":{"status":"none","isConnected":false,"isPending":false,"isWait":false,"isProcessing":false,"isNone":true},"IS_LOGIN":false,"HAS_BLOG":false,"IS_SUPPORT":false,"TOP_URL":"http://www.tistory.com","JOIN_URL":"https://www.tistory.com/member/join","ROLE_GROUP":"visitor"}; window.T.entryInfo = {"entryId":22,"isAuthor":false,"categoryId":748688,"categoryLabel":"교육 및 세미나/신입사원 교육"}; window.appInfo = {"domain":"tistory.com","topUrl":"https://www.tistory.com","loginUrl":"https://www.tistory.com/auth/login","logoutUrl":"https://www.tistory.com/auth/logout"}; window.initData = {}; window.TistoryBlog = { basePath: "", url: "https://hihellloitland.tistory.com", tistoryUrl: "https://hihellloitland.tistory.com", manageUrl: "https://hihellloitland.tistory.com/manage", token: "1f2S/A+7ZlR9NXQqjaHW4DDSZUCecFRctiCrs/668PPJbwUmLVR8/KTweEsiARe1" }; var servicePath = ""; var blogURL = ""; \n\nInsert title here\n \n\n\n\t
\n\t\t

데이터 전송 실습

\n\t\t
\n\t
\n\n\t
\n\t\t\n\t\t
\n\t\t\t이름 : \n\t\t\t
\n\t\t\t\n\t\t\t\n\t\t
\n\t
\n\n\n\n"}}" data-ve-attributes="{"typeof":"mw:Extension/syntaxhighlight","about":"#mwt3"}">
<%@ page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<div>
		<h1>데이터 전송 실습</h1>
		<hr>
	</div>

	<div>
		<!-- form 엘리먼트의 action 속성은 데이터를 넘기며 요청하게 되는 페이지 -->
		<form action="receive.nds" method="get">
			이름 : <input type="text" name="userName">
			<br>
			<!-- default: submit -->
			<button type="submit">전송</button>
		</form>
	</div>

</body>
</html>

ReceiveController.java

  • 사용자 정의 컨트롤 : com.test.mvc 패키지 경로에 구성
package com.test.mvc;

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 ReceiveController implements Controller
{

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception
	{
		// 결과값으로 반환할 ModelAndView 객체 생성
		ModelAndView mav = new ModelAndView();
		
		// Send.jsp 로부터 넘어온 데이터 수신
		request.setCharacterEncoding("UTF-8");
		String userName = request.getParameter("userName");
		
		//뷰에 값을 넘겨주기 위해서 객체 추가
		mav.addObject("userName", userName);
		
		//뷰 지정
		mav.setViewName("/WEB-INF/view/Receive.jsp");
		
		// 결과값 반환
		return mav;
	}

}

Receive.jsp

  •  : 일단은 WebContent > WEB-INF > view 경로에 직접 구성
if (!window.T) { window.T = {} } window.T.config = {"TOP_SSL_URL":"https://www.tistory.com","PREVIEW":false,"ROLE":"guest","PREV_PAGE":"","NEXT_PAGE":"","BLOG":{"id":2859442,"name":"hihellloitland","title":"27","isDormancy":false,"nickName":"hihelllo","status":"open","profileStatus":"normal"},"NEED_COMMENT_LOGIN":false,"COMMENT_LOGIN_CONFIRM_MESSAGE":"","LOGIN_URL":"https://www.tistory.com/auth/login/?redirectUrl=https://hihellloitland.tistory.com/22","DEFAULT_URL":"https://hihellloitland.tistory.com","USER":{"name":null,"homepage":null,"id":0,"profileImage":null},"SUBSCRIPTION":{"status":"none","isConnected":false,"isPending":false,"isWait":false,"isProcessing":false,"isNone":true},"IS_LOGIN":false,"HAS_BLOG":false,"IS_SUPPORT":false,"TOP_URL":"http://www.tistory.com","JOIN_URL":"https://www.tistory.com/member/join","ROLE_GROUP":"visitor"}; window.T.entryInfo = {"entryId":22,"isAuthor":false,"categoryId":748688,"categoryLabel":"교육 및 세미나/신입사원 교육"}; window.appInfo = {"domain":"tistory.com","topUrl":"https://www.tistory.com","loginUrl":"https://www.tistory.com/auth/login","logoutUrl":"https://www.tistory.com/auth/logout"}; window.initData = {}; window.TistoryBlog = { basePath: "", url: "https://hihellloitland.tistory.com", tistoryUrl: "https://hihellloitland.tistory.com", manageUrl: "https://hihellloitland.tistory.com/manage", token: "1f2S/A+7ZlR9NXQqjaHW4DDSZUCecFRctiCrs/668PPJbwUmLVR8/KTweEsiARe1" }; var servicePath = ""; var blogURL = ""; \n\nReceive.jsp\n \n\n\n
\n\t

데이터 전송 실습 → 데이터 수신

\n\t
\n
\n
\n\t

안녕하세요 [${userName}]님

\n\t

매우 반갑습니다.

\n
\n\n\n\n"}}" data-ve-attributes="{"typeof":"mw:Extension/syntaxhighlight","about":"#mwt3"}">
<%@ page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Receive.jsp</title>
</head>
<body>

<div>
	<h1>데이터 전송 실습 → 데이터 수신</h1>
	<hr>
</div>
<div>
	<h2>안녕하세요 [${userName}]님</h2>
	<h2>매우 반갑습니다.</h2>
</div>

</body>
</html>

web.xml

  • DispatcherServlet 을 프론트 컨트롤러로 등록 → 서블릿 매핑 : WebContent > WEB-INF 경로
<?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">
	<display-name>mvc01</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	
	<!-- Spring MVC 프레임워크 등록 -->
	<!-- -DispatcherServlet 객체 등록 -->	
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	</servlet>
	
	<!-- 요청하는 서블릿 주소를 확장자 형태로 등록 -->
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>*.nds</url-pattern>
	</servlet-mapping>
</web-app>

dispatcher-servlet.xml

  • 사용자 정의 컨트롤러 매핑 : WebContent < WEB-INF 경로
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	<context:component-scan base-package="org.springframework.samples.petclinic.web" />
	 
	<!-- ※ 『dispatcher-servlet.xml』파일의 기본 설정 내용을 작성하는 과정에서
            스프링에서 제공하는 Document를 참조해서 작성할 수 있도록 한다.
            → C:\spring-framework-with-docs\spring-framework-3.0.2.RELEASE\docs\spring-framework-reference\pdf
			   경로의 spring-framework-reference.pdf 파일에서
			   페이지 이동 메뉴 450 페이지 (pdf 425 페이지) 의 내용을 기본 내용으로 작성할 수 있도록 한다. -->
	 <!-- 이곳에서 해야 할 일은 각각의 사용자 정의 컨트롤러 객체 등록 및 URL 매핑을 하는 것이다. -->
	 
	 <bean name="/send.nds" class="com.test.mvc.SendController"></bean>
	 <bean name="/receive.nds" class="com.test.mvc.ReceiveController"></bean>
	   
</beans>

- 사용자 요청 주소

http://localhost:8090/mvc01/send.nds

- 요청

③ Database 연동 데이터 송/수신

- 데이터 송신 / 수신 실습

- 데이터베이스 연동 실습

- 다이나믹 웹 프로젝트 생성 (→ 실무에서는 Spring Project 생성 )

: mvc03

- SpringMVC 환경 설정을 위한 라이브러리 등록 및 기본 설정들을

mvc00 에 있는 src 와 WebContent 를 복사&붙여넣기(덮어쓰기)로 대체.

- 구현할 기능

·이름, 전화번호를 입력받아 데이터베이스에 저장.

·해당 리스트를 읽어다가 화면에 출력.

- 페이지 기본 레이아웃 (화면 구성)

회원관리

-----------------------------------------

이름 : [        ] → <input type="text">

전화 : [        ] → <input type="text">

<  전  송	> → <button>

전체 인원 수 2명

-----------------------------------------

번호	이름	전화번호

1     최진규	010-1111-1111

2     김준협   010-2222-2222

- 물리적 파일 구성

mvc03_scott.sql

  • 데이터베이스 관련 객체 구성
SELECT USER
FROM DUAL;
--==>> SCOTT

-- 데이터베이스 준비
CREATE TABLE TBL_MEMBERLIST
( MID NUMBER
, NAME VARCHAR2(30)
, TEL  VARCHAR2(40)
, CONSTRAINT MEMBERLIST_MID_PK PRIMARY KEY(MID)
);
--==>> Table TBL_MEMBERLIST이(가) 생성되었습니다.

--○ 시퀀스 생성
CREATE SEQUENCE MEMBERLISTSEQ
NOCACHE;
--==>> Sequence MEMBERLISTSEQ이(가) 생성되었습니다.

--○ 데이터 입력
INSERT INTO TBL_MEMBERLIST(MID, NAME, TEL) VALUES(MEMBERLISTSEQ.NEXTVAL, '명소희', '010-9283-6776');

--○ 커밋
COMMIT;

--○ 확인
SELECT MID, NAME, TEL
FROM TBL_MEMBERLIST;
--==>> 1	명소희	010-9283-6776

SELECT COUNT(*) AS COUNT
FROM TBL_MEMBERLIST;
--==> 1

SELECT COUNT(*) AS COUNT FROM TBL_MEMBERLIST;

SELECT MID, NAME, TEL
FROM TBL_MEMBERLIST
ORDER BY MID;
--> 한 줄 구성
SELECT MID, NAME, TEL FROM TBL_MEMBERLIST ORDER BY MID;

MemberDTO.java

  • 사용자 정의 자료형 클래스(DTO)
/*=======================================
   2. MemberDTO.java
   - 사용자 정의 자료형 클래스(DTO)
=======================================*/

package com.test.mvc;

public class MemberDTO
{
	// 주요 속성 구성
	private String mid, name, tel;

	// getter / setter 구성
	public String getMid()
	{
		return mid;
	}

	public void setMid(String mid)
	{
		this.mid = mid;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public String getTel()
	{
		return tel;
	}

	public void setTel(String tel)
	{
		this.tel = tel;
	}
}

IMemberDAO.java

  • 인터페이스
/*=======================
   3. IMemberDAO.java
   - 인터페이스
=======================*/

package com.test.mvc;

import java.sql.SQLException;
import java.util.ArrayList;

public interface IMemberDAO
{
	public ArrayList<MemberDTO> lists() throws SQLException, ClassNotFoundException;
	public int memberInsert(MemberDTO member) throws SQLException, ClassNotFoundException;
	public int count() throws SQLException, ClassNotFoundException;	
}

MemberDAO.java

  • 데이터베이스 액션 처리 전용 클래스
  • Connection 객체에 대한 의존성 주입(DI)
  • setter 메소드 구성(의존성 주입을 위한 준비)
/*=================================================
   4. MemberDAO.java
   - 데이터베이스 액션 처리 전용 클래스
   - Connection 객체에 대한 의존성 주입(DI)
   - setter 메소드 구성(의존성 주입을 위한 준비)
=================================================*/

package com.test.mvc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.sql.DataSource;

public class MemberDAO implements IMemberDAO
{
	private DataSource dataSource;

	public void setDataSource(DataSource dataSource)
	{
		this.dataSource = dataSource;
	}
	
	
	@Override
	public ArrayList<MemberDTO> lists() throws SQLException, ClassNotFoundException
	{
		ArrayList<MemberDTO> result = new ArrayList<MemberDTO>();
		
		Connection conn = dataSource.getConnection();
		
		String sql = "SELECT MID, NAME, TEL FROM TBL_MEMBERLIST ORDER BY MID";
		PreparedStatement pstmt = conn.prepareStatement(sql);
		ResultSet rs = pstmt.executeQuery();
		while (rs.next())
		{
			MemberDTO dto = new MemberDTO();
			dto.setMid(rs.getString("MID"));
			dto.setName(rs.getString("NAME"));
			dto.setTel(rs.getString("TEL"));
			
			result.add(dto);
		}
		rs.close();
		pstmt.close();
		
		return result;
	}

	@Override
	public int memberInsert(MemberDTO member) throws SQLException, ClassNotFoundException
	{
		int result = 0;
		
		Connection conn = dataSource.getConnection();
		
		String sql = "INSERT INTO TBL_MEMBERLIST(MID, NAME, TEL) VALUES(MEMBERLISTSEQ.NEXTVAL, ?, ?)";
		PreparedStatement pstmt = conn.prepareStatement(sql);
		pstmt.setString(1, member.getName());
		pstmt.setString(2, member.getTel());
		
		result = pstmt.executeUpdate();
		pstmt.close();
		
		return result;
	}

	@Override
	public int count() throws SQLException, ClassNotFoundException
	{
		int result = 0;
		
		Connection conn = dataSource.getConnection();
		
		String sql = "SELECT COUNT(*) AS COUNT FROM TBL_MEMBERLIST";
		PreparedStatement pstmt = conn.prepareStatement(sql);
		ResultSet rs = pstmt.executeQuery();
		while (rs.next())
			result = rs.getInt("COUNT");
		rs.close();
		pstmt.close();
		
		return result;
	}
	
}

MemberListController.java

  • 사용자 정의 컨트롤러 : com.test.mvc 패키지 경로에 구성
  • 리스트 출력 액션 처리 클래스
  • DAO 객체에 대한 의존성 주입(DI)
  • setter 메소드 구성(의존성 주입을 위한 준비)
package com.test.mvc;

import java.util.ArrayList;

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 MemberListController implements Controller
{
	private IMemberDAO dao;
	
	public void setDao(IMemberDAO dao)
	{
		this.dao = dao;
	}

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception
	{
		ModelAndView mav = new ModelAndView();
		
		int count = dao.count();
		ArrayList<MemberDTO> list = dao.lists();
		
		mav.setViewName("/WEB-INF/view/MemberList.jsp");
		mav.addObject("count", count);
		mav.addObject("list", list);
		
		return mav;
	}
}

MemberList.jsp

  •  : WebContent > WEB-INF > view 경로에 구성
  • 회원 리스트 출력을 위한 뷰
  • 회원 정보를 추가할 수 있도록 폼 화면 구성
if (!window.T) { window.T = {} } window.T.config = {"TOP_SSL_URL":"https://www.tistory.com","PREVIEW":false,"ROLE":"guest","PREV_PAGE":"","NEXT_PAGE":"","BLOG":{"id":2859442,"name":"hihellloitland","title":"27","isDormancy":false,"nickName":"hihelllo","status":"open","profileStatus":"normal"},"NEED_COMMENT_LOGIN":false,"COMMENT_LOGIN_CONFIRM_MESSAGE":"","LOGIN_URL":"https://www.tistory.com/auth/login/?redirectUrl=https://hihellloitland.tistory.com/22","DEFAULT_URL":"https://hihellloitland.tistory.com","USER":{"name":null,"homepage":null,"id":0,"profileImage":null},"SUBSCRIPTION":{"status":"none","isConnected":false,"isPending":false,"isWait":false,"isProcessing":false,"isNone":true},"IS_LOGIN":false,"HAS_BLOG":false,"IS_SUPPORT":false,"TOP_URL":"http://www.tistory.com","JOIN_URL":"https://www.tistory.com/member/join","ROLE_GROUP":"visitor"}; window.T.entryInfo = {"entryId":22,"isAuthor":false,"categoryId":748688,"categoryLabel":"교육 및 세미나/신입사원 교육"}; window.appInfo = {"domain":"tistory.com","topUrl":"https://www.tistory.com","loginUrl":"https://www.tistory.com/auth/login","logoutUrl":"https://www.tistory.com/auth/logout"}; window.initData = {}; window.TistoryBlog = { basePath: "", url: "https://hihellloitland.tistory.com", tistoryUrl: "https://hihellloitland.tistory.com", manageUrl: "https://hihellloitland.tistory.com/manage", token: "1f2S/A+7ZlR9NXQqjaHW4DDSZUCecFRctiCrs/668PPJbwUmLVR8/KTweEsiARe1" }; var servicePath = ""; var blogURL = ""; \n\nMemberList.jsp\n\n\n\n\n\n\n \n\n\n
\n\t

회원 관리

\n\t
\n
\n\n
\n\t
\n\t\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t
이름\n\t\t\t\t\t\n\t\t\t\t
전화\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\t\t모든 항목을 입력해야 합니다.\n\t\t\t\t
\n\t
\n\t\n\t\n\t

전체 인원 수 : ${count }명

\n\t\n\t\n\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\n\t
번호이름전화번호
${member.mid }${member.name }${member.tel }
\n
\n\n\n\n\n"}}" data-ve-attributes="{"typeof":"mw:Extension/syntaxhighlight","about":"#mwt3"}">
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MemberList.jsp</title>
<link rel="stylesheet" href="main.css">
<style type="text/css">
	#errMsg
	{
		display: none; color: red; font-size: small; 
	}
</style>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript">
	$(document).ready(function()
	{
		$("#submitBtn").click(function()
		{
			$("#errMsg").css("display", "none");
			if ($("#name").val()==""||$("#tel").val()=="")
			{
				$("#errMsg").css("display", "inline");
				return;
			}
			
			$("#memberForm").submit();
		});
	});
</script>

</head>
<body>

<div>
	<h1>회원 관리</h1>
	<hr>
</div>

<div>
	<form action="memberInsertForm.nds" method="post" id="memberForm">
	
		<table style="border: 0px;">
			<tr>
				<th>이름</th>
				<td>
					<input type="text" name="name" id="name" class="txtBox">
				</td>
			</tr>
			<tr>
				<th>전화</th>
				<td>
					<input type="text" name="tel" id="tel" class="txtBox">
				</td>
			</tr>
			<tr>
				<th colspan="2">
					<button type="button" id="submitBtn">전 송</button>
				</th>
			</tr>
			<tr>
				<th colspan="2">
					<span id="errMsg">모든 항목을 입력해야 합니다.</span>
				</th>
			</tr>
		</table>
	</form>
	
	<!-- EL 표현에 의한 인원 수 출력 -->
	<p>전체 인원 수 : ${count }명</p>
	
	<table border="1" cellpading="5" id="customers">
		<tr>
			<th>번호</th><th>이름</th><th>전화번호</th>
		</tr>
		
		<c:forEach var="member" items="${memberList }">
		<tr>
			<td>${member.mid }</td><td>${member.name }</td><td>${member.tel }</td>
		</tr>
		</c:forEach>
		
	</table>
</div>


</body>
</html>

MemberInsertController.java 

  • 사용자 정의 컨트롤러 : com.test.mvc 패키지 경로에 구성
  • 회원 정보 입력 액션 처리 클래스
  • DAO객체에 대한 의존성 주입(DI)
  • setter 메소드 구성(의존성 주입을 위한 준비)

dispatcher-servlet.xml

  • 사용자 정의 컨트롤러 매핑 : WebContent > WEB-INF 경로
  • 사용자 요청 주소 등록
  • SimpleDriverDataSource 객체 등록
  • (기본 JDBC 로 구성해도 무방함)
  • 의존객체 주입 설정
  • DAO 객체 등록
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	<context:component-scan base-package="org.springframework.samples.petclinic.web" />
	
	<!-- 이곳에서 해야 할 일은 각각의 사용자 정의 컨트롤러 객체 등록 및 URL 매핑을 하는 것이다. -->
	
	<bean id="localDataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
		<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"></property>
		<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"></property>
		<property name="username" value="scott"></property>
		<property name="password" value="tiger"></property>
	</bean>
	
	<bean id="memberDAO" class="com.test.mvc.MemberDAO">
		<property name="dataSource">
			<ref bean="localDataSource"/>
		</property>
	</bean>
	
	<bean name="/memberlist.nds" class="com.test.mvc.MemberListController">
		<property name="dao">
			<ref bean="memberDAO"/>
		</property>
	</bean>
	
	
</beans>

web.xml

  • DispatcherServlet 을 프론트 컨트롤러로 등록 → 서블릿 매핑 : WebContent > WEB-INF 경로
<?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">
	<display-name>mvc01</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	
	<!-- Spring MVC 프레임워크 등록 -->
	<!-- - DispatcherServlet 객체 등록 -->
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	</servlet>
	
	<!-- 요청하는 서블릿 주소를 확장자 형태로 등록 -->
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>*.nds</url-pattern>
	</servlet-mapping>
	
</web-app>

사용자 요청 주소

http://localhost:8090/mvc03/memberlist.nds


'교육 및 세미나 > 신입사원 교육' 카테고리의 다른 글

11일차(2018.01.17)  (0) 2018.01.19
10일차(2018.01.16)  (0) 2018.01.19
9일차(2018.01.15)  (0) 2018.01.15
8일차(2018.01.12)  (0) 2018.01.12
7일차(2018.01.11)  (0) 2018.01.12