복습

Model 2 전체 흐름 정리

- Controller 클래스가 클라이언트의 요청을 받음, WebServlet 어노테이션으로 Controller 클래스로 찾아감

- Service 클래스는 여러개를 만드는데 공통적인 내용을 부모 인터페이스로 만들고 그것을 상속받아서 사용함

- DAO 클래스에서 검색한 결과를 View 페이지에 출력할땐, select 를 수행후 결과를 Service 클래스로 다시 돌아가고, View 페이지에 결과를 출력

- 돌려줄 값이 많을때는 Service 클래스에서 돌려줄 값을 request 객체로 공유 설정 해야한다.

- 공유 설정 후 포워딩 함, 포워딩 된 JSP 파일에서 공유된 값을 가져와서 표현 언어로 출력


JSTL (JSP Standard Tag Library)

- 널리 사용되는 커스텀 태그를 표준으로 만든 태그 라이브러리

- 태그 중 일종, 사용자 정의 태그의 표준

- View 페이지에서 결과를 출력할때 EL, JSTL 이 같이 사용된다.

- 라이브러리가 필요하다

* 사용자 정의 태그 = 개발자가 만들어 쓰는 태그

 

JSTL 환경 구축

- JSTL 을 쓰기 위해서는 라이브러리가 필요하므로 가장 먼저 라이브러리를 구한다.

 

JSTL 라이브러리 구하기

https://tomcat.apache.org/taglibs/standard/

 

Apache Taglibs - Apache Standard Taglib: JSP[tm] Standard Tag Library (JSTL) implementations

<!-- Copyright 1999-2011 The Apache Software Foundation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/

tomcat.apache.org

- JSTL 1.2 버전을 다운로드

- 해당 프로젝트의 WebContent/WEB-INF/lib 폴더에 jstl-1.2.jar 를 저장한다

 

JSTL 라이브러리

- 5개 종류의 JSTL 라이브러리가 있다

- prefix 에 접두어를 쓰면 사용할 수 있다.

- 이 라이브러리를 관리하는 기관의 URI 주소를 써야한다, 주소를 설정해야 그 라이브러리를 불러온다는 의미

+ JSP 태그 중 사용자 정의 태그이다.

 

JSTL 예제

실습 준비

- 한글이름은 문제가 생길수 있으므로 '사용자 정의태그(JSTL)' 을 'JSTL' 로 이름 수정

- JSTL/lib/jstl-1.2.jar 파일을 WEB-INF/lib 안으로 복사

 

JSTL 예시

- JSTL/Core/ex1/setTag.jsp

<%@ page contentType = "text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:set var="num1" value="${20}" />
<c:set var="num2">
10.5
</c:set>
<c:set var="today" value="<%= new java.util.Date() %>" />

<html>
	<head>
		<title>set 태그와 remove 태그</title>
	</head>

	<body>
		변수 num1 = ${num1} <br>
		변수 num2 = ${num2} <br>
		num1 + num2 = ${num1 + num2} <br>
		오늘은 ${today} 입니다.

		<c:remove var="num1" scope="page" />

		<p>
		삭제한 후의 num1 = ${num1} <br>
		삭제한 후의 num1 + num2 = ${num1 + num2}
	</body>
</html>

 

라이브러리 불러오기 (setTag.jsp 부분)

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

- 라이브러리는 5개 종류가 있다

- 그 중 하나인 코어 라이브러리, 이때 라이브러리를 불러오는 형식

- 어떤 라이브러리를 사용하냐에 따라 prefix 가 정해져 있다

- 코어 라이브러리를 쓸때는 접두어를 "c" 를 쓴다

- 또한 코어에 해당하는 uri 값을 불러온다

- 이 코드가 JSP의 사용자 정의 태그(tag libary tag) 이다.

 

JSTL 지원 라이브러리

라이브러리 하위 기능 접두어 관련 URI
코어 변수 지원
흐름 제어
URL 처리
c http://java.sun.com/jsp/jstl/core
XML XML 코어
흐름 제어
XML 변환
x http://java.sun.com/jsp/jstl/xml
국제화 지역
메세지 형식
숫자 및 날짜 형식
fmt http://java.sun.com/jsp/jstl/fmt
데이터베이스 SQL sql http://java.sun.com/jsp/jstl/sql
함수 콜렉션 처리
String 처리
fn http://java.sun.com/jsp/jstl/functions

- 90% 이상 코어 라이브러리만 사용, 10% 는 국제화 라이브러리 사용

- 코어 라이브러리는 preifx값을 "c" 라고 쓰고 코어 라이브러리를 관리하는 기관 uri 를 쓴다

- 코어 라이브러리의 주요 기능은 변수 생성, 변수 삭제, 조건식, 반복식, URL 처리

- 국제화 라이브러리는 주로 날짜 시간을 년월일시분초 등의 패턴을 지정할때 사용된다, Model 2에서 SimpleDateFormat 의 역할

 

JSP 라이브러리 : 코어 라이브러리

코어 라이브러리 지원 태그

- set 태그 : 변수를 정의(생성)할때 사용

- remove 태그 : 변수를 제거할때 사용

- if 태그 : if문과 유사

- choose - when - otherwise 태그 : JSLT 에선 if-else 가 없으므로 if-else 처럼 쓰고 싶을때 사용

- forEach 태그 : for문과 유사

 

태그 사용법

set 태그 사용법

- 태그들이 어떤 라이브러리에 포함되어있냐에 따라 접두어를 가장 먼저 쓴다

ex) set 태그는 코어 라이브러리이므로 접두어 c 를 쓴다

- 각 태그마다의 속성을 알아야 한다

 

JSTL 예제 1

코어 라이브러리

set 태그 / EL 출력

- JSTL/Core/ex1/setTag.jsp (중복)

<%@ page contentType = "text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:set var="num1" value="${20}" />
<c:set var="num2">
10.5
</c:set>
<c:set var="today" value="<%= new java.util.Date() %>" />

<html>
	<head>
		<title>set 태그와 remove 태그</title>
	</head>

	<body>
		변수 num1 = ${num1} <br>
		변수 num2 = ${num2} <br>
		num1 + num2 = ${num1 + num2} <br>
		오늘은 ${today} 입니다.

		<c:remove var="num1" scope="page" />

		<p>
		삭제한 후의 num1 = ${num1} <br>
		삭제한 후의 num1 + num2 = ${num1 + num2}
	</body>
</html>

- 한글 인코딩을 가장 위에서 하고 있다

- 사용자 정의 태그로 코어(Core) 라이브러리를 불러옴

 

코어 라이브러리 불러오기 (setTag.jsp 부분)

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

- JSTL 태그를 쓰기 위해서는 그 태그가 포함된 라이브러리를 먼저 불러와야한다

- 이 코드가 없으면 에러는 없지만 변수 값 등이 출력이 되지 않음

- 해당 라이브러리의 uri 를 모르면 Ctrl + Space 중 선택한다

 

태그 사용하기 (setTag.jsp 부분)

- 태그앞에 접두어를 붙여야한다

 

set 태그 : 변수 정의 (setTag.jsp 부분)

<c:set var="num1" value="${20}" />

- num1 변수를 정의하면서 num1 에 20 을 할당하고 있다

- 아래와 똑같다

<c:set var="num1" value="20" />

- 또는 set 태그 사이에 값을 입력해도 값이 저장된다.

<c:set var="num2">
10.5
</c:set>

- 변수 선언 하고 객체를 저장할 수도 있다

<c:set var="today" value="<%= new java.util.Date() %>" />

- today 변수에는 Date 객체가 저장되었다

 

변수 값 출력 (setTag.jsp 부분)

		변수 num1 = ${num1} <br>
		변수 num2 = ${num2} <br>
		num1 + num2 = ${num1 + num2} <br>
		오늘은 ${today} 입니다.

- 출력시 JSTL 과 EL 이 같이 쓰인다 , 지금은 EL 로 출력하고 있다.

- 첫 줄은 num1 변수안의 값을 출력하고 있다

- 일반적인 JSP 변수를 ${} (EL) 안에 쓰면 출력되지 않지만 JSTL 로 정의된 변수를 ${} (EL)안에 쓰면 출력된다

- num1, num2, today 는 JSTL 로 정의된 변수이므로 ${} (EL) 안에서 출력된다

- today 변수 출력시 영미권 날짜 시간 형식으로 출력된다.
- JSTL 로 정의된 변수는 표현식 태그로 출력할 수 없고, EL 로 출력해야한다

+ EL 안 에서 산술연산을 포함한 각종 연산이 된다.

 

변수 삭제 (제거) (setTag.jsp 부분)

		<c:remove var="num1" scope="page" />

- remove 태그는 코어(Core) 라이브러리에 포함된 라이브러리 이므로 접두어 쓰기

- var = "삭제할 변수명" scope ="4가지 영역 중 하나"

		삭제한 후의 num1 = ${num1} <br>
		삭제한 후의 num1 + num2 = ${num1 + num2}

- num1 이 삭제되었으므로 아무값도 나타나지 않음, 오류는 발생하지 않고 나타나지 않음

- num1 이 삭제되더라도 num1 + num2 에서 오류가 발생하는 것이 아니라 num2 값만 나옴

 

- 실행 결과 캡처


EL 에서 출력 가능한 변수

- 일반적인 변수는 ${} 에서 출력불가

- 일반적인 변수더라도 request 로 공유한 변수는 ${} 에서 출력 가능

- JSTL 로 정의한 변수는 ${} 에서 출력 가능

+ JSTL 로 정의한 변수는 EL 태그로만 출력 가능하다!

 

1. 일반적인 JSP 변수를 EL 로 출력시 출력되지 않음

		<% 
			String str = "JSP변수";
		%>
		변수 : str1 = <%=str %> <br> <!-- "JSP변수" 출력 -->
		변수 : str2 = ${str} <br> <!-- 출력 안됨 -->

- 출력되지 않음, 오류가 발생하진 않음

 

2. 일반적인 JSP 변수를 EL 로 출력하고 싶으면 공유 설정해야함

		<% 
			String str = "JSP변수";
			request.setAttribute("st", str);	// 공유 설정
		%>
		변수1 : str1 = <%=str %> <br> <!-- "JSP변수" 출력 -->
		변수2 : str2 = ${str} <br> <!-- 출력 안됨 -->
		변수3 : str3 = ${st} <br> <!-- "JSP변수" 출력-->

- 현재는 현재 페이지에서 공유 설정하므로 page 부터 모든 4개 영역 공유 설정해도 유효 영역이므로 EL 로 출력 가능

- 지금은 현재 request 로 공유 설정

- 공유된 값은 EL로 출력됨

 

+ EL을 쓰지 않고 str3 와 같은 결과를 출력하려면?

- 아래는 EL 태그를 써서 간략하게 공유된 값을 출력하고 있다

		변수3 : str3 = ${st} <br> <!-- "JSP변수" 출력-->

- EL 태그를 쓰지 않고 이것과 같은 코드는 아래

		<%
			String s = (String) request.getAttribute("st");
		%>
		변수4 : str4 = <%=s %> <br>	<!-- "JSP변수" 출력 -->

- EL 태그를 쓰지 않고 공유된 값을 출력하고 싶으면 먼저 getAttribute() 로 다운캐스팅해서 변수에 저장

- 이후 그 변수를 표현식 태그로 출력

+ getAttribute() 는 Object 를 돌려주므로 안의 값의 자료형인 String 형으로 다운캐스팅 명시해야함

3. JSTL set 태그로 정의된 변수

<c:set var="num1" value="${20}" />

- JSTL set 태그로 정의된 변수 num1

		변수 num1 = ${num1} <br>

- EL 태그로 출력 가능하다

 

EL 로 출력가능 한 것

1. set 태그로 정의한 변수

2. 현재 공유 설정된 변수

- 이 두가지 밖에 없다


if 태그

- if문과 같은 역할

- JSTL 에는 if 태그만 있다, if-else, if-else if 없음

- 형식 :

- 조건식이 참이면 if 태그 안의 내용이 실행되고, 조건식이 거짓이면 if 태그 안의 내용이 실행되지 않음

 

JSTL 예제 2

코어 라이브러리

if 태그

- JSTL/Core/ex2/if/ifTagForm.jsp

<%@ page contentType = "text/html; charset=utf-8" %>

<html>	
	<body>
	<form method=post action=ifTag.jsp>
	이름 <input type=text name=name><br>
	나이<input type=text name=age><br>
	<input type=submit value="전송">
	</form>
	</body>
</html>

 

- action으로 지정된 ifTag.jsp 파일을 생성하자

- JSTL/Core/ex2/if/ifTag.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:if test="true">
	무조건 실행 <br>
</c:if>

<c:if test="${param.name == 'toto'}">
	당신의 이름은 ${param.name } 입니다. <br>
</c:if>

<c:if test="${param.age >= 20}">
	당신의 나이는 20세 이상 입니다.
</c:if>

- EL 에선 request.getParamter() 대신 객체 param 을 사용 가능

 

taglib 추가 : 코어 라이브러리 추가 (ifTag.jsp 부분)

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

 

if 태그 사용 1 (ifTag.jsp 부분)

<c:if test="true">
	무조건 실행 <br>
</c:if>

 

if 태그 사용 2 / EL 객체 param (ifTag.jsp 부분)

<c:if test="${param.name == 'toto'}">
	당신의 이름은 ${param.name } 입니다. <br>
</c:if>

- param 은 EL 에 쓸 수 있는 객체

- test 속성은 바깥쪽에 " ", 안쪽엔 ' ' 를 써야함

- EL에서는 equals() 가 아닌 비교연산자 == 를 써야함

- EL로 조건식을 쓰고 있다

- param.name 은 request.getParameter("name") 과 같다

- 즉 이름 입력양식에 사용자가 'toto' 를 입력한 경우에만 아래의 문장이 출력된다.

 

if 태그 사용 3 / EL 객체 param (ifTag.jsp 부분)

<c:if test="${param.age >= 20}">
	당신의 나이는 20세 이상 입니다.
</c:if>

- param.name 은 request.getParameter("age") 과 같다

- EL 안에서 비교연산자를 사용할 수 있다

- 나이 입력 양식에 20 이상의 값을 입력한 경우에 if 태그 안의 문장이 실행되어 아래처럼 출력됨


choose - when - otherwise 태그

- if만 있고 if-else 나 if-else if 기능을 하는 태그는 없다

- 다만 if-else if 와 비슷한 역할을 수행하는 태그가 있다, 조건식을 여러개 쓸 때 사용하는 태그가 있다

- choose - when - otherwise 태그를 써서 조건식을 여러개 쓸 수 있다

- switch-case 문이나 if-else if문과 비슷

- 형식 : 

- 조건식을 쓸 때는 if 태그가 아닌 when 태그로 조건식을 만듬, if 대신 when 이 사용됨

- 조건식이 참이면 when 태그 안의 내용을 실행함

- when 태그를 여러개 써서 조건식을 여러개 사용한다

- 맨 마지막에 쓰이는 otherwise 태그는 switch-case문의 default 와 같은 역할, otherwise는 쓰지 않아도 됨

 

choose - when - otherwise 태그 주의

- 조건식들이 여러개 오는 경우 여러개 조건식을 모두 만족한다고 다 실행되지 않음

- if-else if 문과 마찬가지로 가장 먼저 만족하는 위의 조건 태그 안의 내용 1개만 실행하고 choose 태그를 빠져나감

- 즉, if 문이 여러개 있는게 아니라 if-else if 문과 같은 방식으로 동작

- 위의 조건을 다 만족하지 않을때는 otherwise 태그 안의 내용을 실행

 

JSTL 예제 3

코어 라이브러리

choose - when - otherwise 태그

- JSTL/Core/ex3/choose/ifTagForm.jsp

<%@ page contentType = "text/html; charset=utf-8" %>

<html>	
	<body>
	<form method=post action=chooseTag.jsp>
	이름 <input type=text name=name><br>
	나이<input type=text name=age><br>
	<input type=submit value="전송">
	</form>
	</body>
</html>

 

- action으로 지정된 chooseTag.jsp 파일을 생성하자

 

- JSTL/Core/ex3/choose/chooseTag.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<ul>
	<c:choose>
		<c:when test="${param.name == 'toto'}">
			<li>당신의 이름은 ${param.name } 입니다.</li>
		</c:when>
		<c:when test="${param.age >= 20}">
			<li>당신의 나이는 20세 이상 입니다.</li>
		</c:when>
		<c:otherwise>
			<li>당신의 이름은 'toto'가 아니고, 나이는 20세 이상이 아닙니다.</li>
		</c:otherwise>
	</c:choose>
</ul>

</body>
</html>

- EL 로 조건식을 쓰고 있다

- 필요하면 when 태그를 계속 추가해서 조건식을 추가하면 된다

- if-else if 처럼 가장 먼저 만족한 조건의 내용을 실행하고 빠져나감

- 마지막은 otherwise 태그로 끝난다,어느 when 태그의 조건식도 만족하지 않으면 실행됨

 

- 모든 when 태그를 만족할 때

- 모든 2개의 when 조건절을 만족하지만 가장 위의 조건을 만족하고, 빠져나가기 때문에 첫번째 when 태그 안의 내용만 실행됨

 

- 모든 when 태그를 만족하지 않을때

- otherwise 태그 안의 내용이 실행됨


JSTL 예제 4

코어 라이브러리

catch 태그, out 태그

- JSTL/Core/ex33/jstl_core_ex1.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>JSTL core 라이브러리 사용 예제 1</title>
</head>
<body>
<c:set var="test" value="Hello JSTL!"/>
<h3>&lt;c:set&gt; 사용 후 : <c:out value="${test}"/></h3>
<h3>&lt;c:set&gt; 사용 후 : ${test}</h3>

<c:remove var="test"/>
<h3>&lt;c:remove&gt; 사용 후 : <c:out value="${test}"/></h3>

<c:catch var="err">
<%=10/0%>
</c:catch>
<h3>&lt;c:catch&gt;로 잡아낸 오류 : <c:out value="${err}"/></h3>

<c:if test="${5<10}">
<h3>5는 10보다 작다.</h3>
</c:if>
<c:if test="${6+3==9}">
<h3>6 + 3 은 9이다.</h3>
</c:if>

<c:choose>
	<c:when test="${5+10==50}">
		<h3>5+10은 50이다.</h3>
	</c:when>
	
	<c:otherwise>
		<h3>5+10은 50이 아니다.</h3>
	</c:otherwise>
</c:choose>
</body>
</html>

- 코어 라이브러리를 불러오고 있다

- body 태그 안에서 set 태그로 test 란 변수 정의

 

< , > 출력 (jstl_core_ex1.jsp 부분)

<h3>&lt;c:set&gt; 사용 후 : <c:out value="${test}"/></h3>

- 그냥 < 나 > 를 쓰면 동작하므로 부등호기호를 만들어서 <, > 를 출력하기 위해서 사용

- $lt; 는 '<' 를 만들어줌 (less than)

- $gt; 는 '>' 를 만들어줌 (greater than)

 

out 태그로 브라우저 출력 (jstl_core_ex1.jsp 부분)

<h3>&lt;c:set&gt; 사용 후 : <c:out value="${test}"/></h3>

- EL로 출력시켜도 되지만 이렇게 JSTL out 태그로 브라우저에 출력시켜도 된다

- value 속성값으로 출력시킬 값을 적는다

 

- 아래와 같은 역할

<h3>&lt;c:set&gt; 사용 후 : ${test}</h3>

- 변수 test는 JSTL set 태그로 정의한 변수 이므로 EL을 써서도 출력 가능

 

+ remove 태그로 test 변수 삭제 후 out 객체로 출력시 아무런 값이 출력되지 않음

<c:remove var="test"/>
<h3>&lt;c:remove&gt; 사용 후 : <c:out value="${test}"/></h3>

 

catch 태그로 예외처리 (jstl_core_ex1.jsp 부분)

<c:catch var="err">
<%=10/0%>
</c:catch>
<h3>&lt;c:catch&gt;로 잡아낸 오류 : <c:out value="${err}"/></h3>

- 0 으로 나눌때 발생하는 아리스매틱 예외를 catch 태그를 사용해서 err 변수로 잡는다

- catch 태그 안에 예외가 발생할 수 있는 가능성이 있는 문장을 넣음

- 그 err 변수를 출력하면 어떤 예외가 발생했는지 확인 가능

 

- 전체 출력 캡처


forEach 태그

- for문과 같은 역할을 하는 태그

- 크게 2가지 형식이 있다

- 첫번째 형식 :

- var 속성으로 forEach 에서 사용할 변수 지정

- begin 속성으로 시작값을 지정, end 속성으로 끝 값을 지정

- step 속성으로 증가치 설정, step 속성 생략시 기본 증가치는 1

- 반드시 값 좌우에는 " " 가 있어야 정상 동작한다, 숫자더라도 속성값은 " " 붙여야함 

- 반복문이 돌아가며 forEach 태그 안의 내용이 출력됨

 

- 두번째 형식 : 

- items 속성값으로는 순차적인 자료구조가 온다. ex) 배열, 리스트

- 이 배열, 리스트를 forEach문 바깥 위에서 정의하고 바로 itmes 자리에 들어가면 안됨

- 배열과 리스트를 먼저 request 객체로 공유하고, 공유한 값이 이 items 자리에 들어가야한다

- 또는 set 태그로 정의된 배열, 변수명 등도 items 속성값 자리에 올 수 있다

 

- 두가지 형식이 모두 자주 사용됨

 

JSTL 예제 5

코어 라이브러리

forEach 태그

- JSTL/Core/ex4/forEach/forEachTag.jsp

<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page contentType = "text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
    java.util.HashMap mapData = new java.util.HashMap();
    mapData.put("name", "최범균");
    mapData.put("today", new java.util.Date());
%>
<c:set var="intArray" value="<%= new int[] {1,2,3,4,5} %>" />
<c:set var="map" value="<%= mapData %>" />
<html>
<head><title>forEach 태그</title></head>
<body>
<h4>1부터 100까지 홀수의 합</h4>
<c:set var="sum" value="0" />
<c:forEach var="i" begin="1" end="100" step="2">
<c:set var="sum" value="${sum + i}" />
</c:forEach>
결과 = ${sum}

<h4>구구단: 4단</h4>
<ul>
<c:forEach var="i" begin="1" end="9">
   <li>4 * ${i} = ${4 * i}
</c:forEach>
</ul>

<h4>int형 배열</h4>

<c:forEach var="i" items="${intArray}" begin="2" end="4">
    [${i}]
</c:forEach>

<h4>Map</h4>

<c:forEach var="i" items="${map}">
    ${i.key} = ${i.value}<br>
</c:forEach>
<br><br>

<%
	List list = new ArrayList();
	list.add("자바");
	list.add("웹표준");
	list.add("JSP");
	list.add("오라클");
	list.add("스프링");
	list.add("파이썬");
	list.add("텐서플로우");
	
	request.setAttribute("slist",list);	// 공유설정
%>
<!-- 방법1. -->
<c:forEach var="s" items="${slist}">
	${s} <br>
</c:forEach>
<br><br>

<%
	// 기존 코드로 처리
	List li = (List) request.getAttribute("slist");
	for(int i=0; i<li.size(); i++) {
		String str = (String) li.get(i);
		out.println(str + "<br>");
	}
%>
<br><br>

<!-- 방법2. -->
<c:set var="s1" value="<%=list %>"/>
<c:forEach var="s2" items="${s1}">
	${s2} <br>
</c:forEach>

</body>
</html>

- 코어 라이브러리를 taglib 로 불러옴

- 스크립틀릿 태그로 Map 객체를 생성하고, 키, 밸류 쌍으로 2개의 데이터를 넣음

ex) 키 "name", 밸류 "최범균"

- 1 부터 5까지 원소를 가진 int 형 배열을 가지고 있는 변수 intArray 정의

- Map 객체 mapData 를 가지고 있는 변수 map 정의 

 

forEach 태그 사용 1 / forEach 첫번째 형식 (forEachTag.jsp 부분)

<h4>1부터 100까지 홀수의 합</h4>
<c:set var="sum" value="0" />
<c:forEach var="i" begin="1" end="100" step="2">
<c:set var="sum" value="${sum + i}" />
</c:forEach>
결과 = ${sum}

- set 태그로 합을 저장할 변수 sum 을 정의하고 누적에 영향을 주지 않는 0 으로 초기화

- forEach 태그에서 루프를 돌릴 변수 i , 시작값은 1, 끝값은 100, 증가치는 2, 홀수만 누적되는 반복문임

- sum 변수에 누적시키기 위해 sum 변수를 set 태그로 다시 정의하고 sum + i 로 값 누적, sum = sum + i 와 같다


forEach 태그 사용 2 / forEach 첫번째 형식 (forEachTag.jsp 부분)

<h4>구구단: 4단</h4>
<ul>
<c:forEach var="i" begin="1" end="9">
   <li>4 * ${i} = ${4 * i}
</c:forEach>
</ul>

- 1 부터 9 까지를 i 변수에 하나씩 전달해서 구구단 4단 출력

- forEach 에서 루프를 돌릴 변수인 i 를 출력할때는 그냥 출력해선 안되고 EL 로 출력해야한다.

 

forEach 태그 사용 3 / forEach 두번째 형식 (forEachTag.jsp 부분)

<h4>int형 배열</h4>

<c:forEach var="i" items="${intArray}" begin="2" end="4">
    [${i}]
</c:forEach>

- items 속성도 쓰고 있고, begin, end 속성도 쓰고 있다

<items 속성>

- items 속성값으로는 배열, 리스트가 주로 들어감

- 바로 배열, 리스트가 들어갈 수는 없고 "set 태그로 정의한 변수"가 들어가든지, "request 로 공유한 변수"가 들어가야함

- 지금은 위에서 "set 태그로 정의한 변수"인 intArray 가 items 로 들어감

- set 태그로 정의되었고, intArray 라는 변수가 배열이므로 items 속성값으로 들어갈 수 있다.

- intArray 에서 하나씩 원소를 가져와서 변수 i 에게 전달한다.

<begin 속성, end 속성>

- begin, end 속성이 없을때는 intArray 배열 안의 원소들을 모두 i 로 넘어가서 출력된다

- begin, end 속성이 있을때는 intArray 배열 안의 원소 중 배열 index 가 2부터 4인 원소가 i 로 넘어간다

 

+ 배열에서 첫번째 인덱스는 0

 

forEach 태그 사용 4 / forEach 두번째 형식 (forEachTag.jsp 부분)

<h4>Map</h4>

<c:forEach var="i" items="${map}">
    ${i.key} = ${i.value}<br>
</c:forEach>

- 맵 객체를 가지고 있는 변수 map 이 items 속성으로 들어갔다, 주로 배열, 리스트가 들어가지만 여기선 맵이 들어갔다

- 맵을 통해서 첫번째 데이터부터 i 로 전달되서 key 와 value 값을 출력

- set 태그로 정의한 변수이므로 items 속성에 들어갈 수 있다

 

forEach 태그 사용 5 / forEach 두번째 형식 (forEachTag.jsp 부분)

 

- List 가 items 속성에 들어갔다

- list 에 들어있는 원소값들을 forEach 태그로 출력시키고 있다

+ 이렇게 List 를 공유설정하고 포워딩 한 다음, 포워딩된 곳에서 foEach로 List 를 출력하는 경우가 많다

 

JSP 에서 정의한 list 를 바로 items 에 넣으면?

- list 를 바로 사용하면 출력되지 않음

 

forEach items 속성 사용 방법 2가지

1. 배열이나 리스트를 request 객체로 공유하고 공유 네임값이 items 자리에 와야한다. (forEachTag.jsp 부분)

<%
	List list = new ArrayList();
	list.add("자바");
	list.add("웹표준");
	list.add("JSP");
	list.add("오라클");
	list.add("스프링");
	list.add("파이썬");
	list.add("텐서플로우");
	
	request.setAttribute("slist",list);	// 공유설정
%>
<!-- 방법1. -->
<c:forEach var="s" items="${slist}">
	${s} <br>
</c:forEach>

- itmes 에 공유 네임값인 "slist" 를 적는다

- slist 로부터 원소가 하나씩 s 로 넘어와서 하나씩 출력된다

- 잘 출력된다.

 

+ 위와 같은 기능, forEach 태그를 쓰지 않는 경우

리스트 안의 모든 원소를 출력하는 것을 기존 코드로 처리시 (forEachTag.jsp 부분)

<%
	// 기존 코드로 처리
	List li = (List) request.getAttribute("slist");
	for(int i=0; i<li.size(); i++) {
		String str = (String) li.get(i);
		out.println(str + "<br>");
	}
%>

- 똑같이 출력된다.

 

2. 배열이나 리스트를 set 태그로 정의한 후, 그변수가 items 자리에 와야 한다. (forEachTag.jsp 부분)

<!-- 방법2. -->
<c:set var="s1" value="<%=list %>"/>
<c:forEach var="s2" items="${s1}">
	${s2} <br>
</c:forEach>

- set 태그로 정의된 변수는 items 속성값으로 올 수 있다

- 잘 출력된다.

 

- 전체 출력 캡처

 

실제 활용

- 목록을 가져오는 Service 클래스에서 목록을 가져오기 위한 6개 변수와 리스트를을 request 객체로 공유설정

- 이후 그 리스트 안 DTO 객체들을 View 페이지에서 출력하기 위해 forEach 문의 items 에 리스트 공유 네임값을 쓴다 


 

forTokens 태그

- 자바의 StringTokenizer 과 비슷

- 특정 구분기호로 파싱함

 

JSTL 예제 6

코어 라이브러리

forTokens 태그

- JSTL/Core/ex5/forTokens/forTokensTag.jsp

<%@ page contentType = "text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<head><title>forTokens 태그</title></head>
<body>

콤마와 점을 구분자로 사용:<br>
<c:forTokens var="token" 
             items="빨강색,주황색.노란색.초록색,파랑색,남색.보라색"
             delims=",.">
${token} 
</c:forTokens>

</body>
</html>

-  코어 라이브러리를 taglib 태그로 불러옴

- forTokens 태그를 사용

- var 속성값 : 값들을 받기 위한 임의의 변수명

- itmes 속성값 : 어떤 문자열이 있다

- delims 속성값 : 구분기호가 들어감, 여러개 구분기호 사용 가능

- 여기서는 , 와 . 으로 잘라서 token 변수로 전달하고, 그걸 EL로 출력한다

+ forEach, forTokens 에서 값들을 받는 변수는 그 태그 사이에서 EL 로 출력함


JSTL 예제 7

코어 라이브러리

forEach 태그, forTokens 태그

- JSTL/Core/ex44/jstl_core_ex2.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>JSTL core 라이브러리 사용 예제 2</title>
</head>
<body>
<c:forEach var="test" begin="1" end="10" step="2">
	<b>${test}</b>&nbsp;
</c:forEach>
<br>
<c:forTokens var="alphabet" items="a,b,c,d,e,f,g,h,i,j,k,l,m,n" delims=",">
	<b>${alphabet}</b>&nbsp;
</c:forTokens>
<br>
<c:set var="data" value="홍길동,김길동,고길동"/>
<c:forTokens var="varData" items="${data}" delims=",">
	<b>${varData}</b>&nbsp;
</c:forTokens>
</body>
</html>

- forEach 태그로 1 ~ 10까지 2씩 증가된 값을 출력하고 있다, 1 3 5 7 9 가 출력됨

- forTokens 태그로 itmes 의 문자들을 , 로 구분해서 파싱해서 alphabet 변수에 저장 후 하나씩 출력

+ forTokens 의 itmes 에 바로 파싱할 문자열을 넣을 수도 있다

- set 태그로 data 변수를 만들어서 "홍길동,김길동,고길동" 값을 할당하고, forTokens itmes 로 data 를 써서 그 문자열을 구분기호 , 로 파싱해서 varData 에 저장 후 하나씩 출력

+ 변수 data 는 set 태그로 정의한 변수이므로 items 로 들어갈 수 있다.

 

+ &nbsp : 수평간격을 벌려줌

+ <b> : bold


기타 코어 라이브러리 태그

- import 태그 : 다른 문서를 불러올 수 있다.


JSTL 라이브러리 : 국제화 라이브러리

- 숫자나 날짜 출력에 사용하는 라이브러리

- SimpleDateFormat 이 사용불가능할때 사용

- formatDate 태그 : 자바의 SimpldDateFormat 과 비슷한 역할

- formatDate 태그를 가장 많이 사용, 원하는 포맷으로 날짜 포맷팅

- formatNumber 태그 : 자바의 DecimalFormat 과 비슷한 역할

- timeZone 태그 : 특정 타임존(시간대)을 지정

 

JSTL 예제 8

국제화 라이브러리

formatDate 태그 / 날짜 포맷 지정

- JSTL/fmt/ex6/use_DateFormat.jsp

<%@ page contentType = "text/html; charset=utf-8" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<head><title>numberFormat 태그 사용</title></head>
<body>

<c:set var="now" value="<%= new java.util.Date() %>" />
${now } <br>
<c:out value="${now }"/> <br><br>

<fmt:formatDate value="${now}" type="date" dateStyle="full" /> <br>
<fmt:formatDate value="${now}" type="date" dateStyle="short" /> <br>
<fmt:formatDate value="${now}" type="time" /> <br>
<fmt:formatDate value="${now}" type="both" 
                dateStyle="full" timeStyle="full" /> <br>
<fmt:formatDate value="${now}" pattern="z a h:mm" /> <br>
<fmt:formatDate value="${now}" pattern="yyyy-MM-dd a hh:mm:ss EEE요일"/> <!-- 12시간제 --> <br>
<fmt:formatDate value="${now}" pattern="yyyy-MM-dd a HH:mm:ss EEE요일"/> <!-- 24시간제 -->

</body>
</html>

- 코어 라이브러리와 국제화 라이브러리를 불러오고 있다.

 

국제화 라이브러리 불러오기 (use_DateFormat.jsp 부분)

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

 

- prefix 는 "fmt" 이다

 

- now 변수에 Date 객체 생성해서 저장, now 변수는 현재시간을 가지고 있다.

 

now 변수를 그냥 출력한다면?

- EL 또는 out 객체로 출력

${now } <br>

- 위는 EL 출력, 아래는 out 객체로 출력

<c:out value="${now }"/> <br>

- 영미권 날짜 형식으로 나온다

 

- Model 2 에서는 SimpleDateFormat 과 EL 을 동시 사용 불가

- JSTL 국제화 라이브러리의 DateFormat 태그로 원하는 포맷으로 바꿔야한다

 

formatDate 태그 속성

- 앞에 fmt 란 prefix 를 쓰고 있다, value 속성값이 날짜 시간이 들은 변수가 된다.

- type 속성값으로 "date" 는 연월일(날짜) "time" 은 시분초(시간) "both"는 날짜와 시간이 모두 출력됨

- dateStyle 속성값으로 "full" 이면 복잡, "short" 이면 간략하게 나옴

 

dateStyle = "full" 일때 :날짜가 자세히 출력

dateStyle = "short" 일때 : 날짜가 간략히 출력

type = "time" 일때

- 시간만 출력됨

type = "both" 이고, dateStyle = "full" 이고, timeStyle = "full" 일때

- 날짜, 시간 둘 다 나오고, 둘 다 자세하게 나옴

 

formatDate 태그 패턴 지정

<fmt:formatDate value="${now}" pattern="z a h:mm" /> <br>

- pattern 속성으로 패턴 지정

- z :타임존, a : 오전/오후, h : 시간, mm : 분

- hh 는 12시간제 시간, HH 는 24시간제 시간

<fmt:formatDate value="${now}" pattern="yyyy-MM-dd a hh:mm:ss EEE요일"/> <!-- 12시간제 --> <br>
<fmt:formatDate value="${now}" pattern="yyyy-MM-dd a HH:mm:ss EEE요일"/> <!-- 24시간제 -->


JSTL 예제 9

국제화 라이브러리

timeZone 태그 / 타임존 지정

- JSTL/fmt/ex6/use_timezone_tag.jsp

<%@ page contentType = "text/html; charset=utf-8" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<head><title>timeZone 태그 사용</title></head>
<body>

<c:set var="now" value="<%= new java.util.Date() %>" />

<fmt:formatDate value="${now}" type="both" 
                dateStyle="full" timeStyle="full" />

<br>
<fmt:timeZone value="Hongkong">
<fmt:formatDate value="${now}" type="both" 
                dateStyle="full" timeStyle="full" />
</fmt:timeZone>

</body>
</html>

- Date 객체를 가지고 있는 now 변수, 현재 시간 가지고 있다

- formatDate로 날짜, 시간 둘 다 출력하고 둘 다 자세히 출력함

 

- timeZone 태그의 value 로 특정 시간대(타임존)를 지정 가능, 여기선 "Hongkong" 으로 지정

- timeZone 을 홍콩으로 설정하고 날짜를 출력하면 홍콩 타임존의 날짜와 시간이 출력됨

 

- 타임존을 특정 지역으로 설정 후, 날짜 출력하면 특정 타임존의 날짜와 시간 출력 가능

- 위는 한국 시간, 아래는 홍콩 시간


formatNumber 태그

- Java 에서 소수점 자리를 제어할때 사용했던 DecimalFormat 클래스와 유사

- 형식 :

- 여러 속성들이 있다

 

JSTL 예제 10

국제화 라이브러리

formatNumber 태그 / 숫자 포맷 지정

- JSTL/fmt/ex6/use_number_tag.jsp

<%@ page contentType = "text/html; charset=utf-8" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<head><title>formatNumber 태그 사용</title></head>
<body>

<c:set var="price" value="10000" />
<fmt:formatNumber value="${price}" type="number" var="numberType" />
숫자: ${numberType} <br>

통화: <fmt:formatNumber value="${price}" type="currency" currencySymbol="$" /><br>
통화: <fmt:formatNumber value="${price}" type="currency" currencySymbol="\\" /><br>

퍼센트: <fmt:formatNumber value="${price}" type="percent" groupingUsed="true" /> <br>
퍼센트: <fmt:formatNumber value="${price}" type="percent" groupingUsed="false" /> <br>

패턴: <fmt:formatNumber value="${price}" pattern="00000000.00"/>

</body>
</html>

- set 태그로 price 변수를 정의하고 10000 으로 초기화

- formatNumber 태그로 이 10000 을 어떻게 출력할지 지정

- type 이 "number" 면 숫자 단위로 출력하겠다는 의미

- var 속성값은 변수명

 

숫자로 출력

<fmt:formatNumber value="${price}" type="number" var="numberType" />
숫자: ${numberType} <br>

- price 에 저장된 값을 숫자단위로 받아서 numberType 이라는 변수에 저장

- 이 numbeType 변수를 출력하면 일반적인 숫자가 출력됨

 

통화 단위로 출력

통화: <fmt:formatNumber value="${price}" type="currency" currencySymbol="$" /><br>
통화: <fmt:formatNumber value="${price}" type="currency" currencySymbol="\\" /><br>

- currencySymbol 속성으로 통화 단위 지정

+ 원(won) 출력하려면 "\\" 으로 역슬래시를 두번

 

퍼센트 % 출력

퍼센트: <fmt:formatNumber value="${price}" type="percent" groupingUsed="true" /> <br>
퍼센트: <fmt:formatNumber value="${price}" type="percent" groupingUsed="false" /> <br>

- true 설정시 3자리씩 끊어서 출력, false 설정시 끊어져 있지 않음

 

숫자 패턴 지정

패턴: <fmt:formatNumber value="${price}" pattern="00000000.00"/>

- pattern 속성에 포맷 작성

- 0 으로 패턴 지정 : 자리값이 맞지 않으면 0 을 채워서 출력


JSP 라이브러리 : 함수 라이브러리

- 쉽게 말하면 함수이다

- Java 의 String 클래스의 메소드와 유사한 메소드들이 많다

 

JSTL 예제 11

함수 라이브러리

여러가지 태그들

- JSTL/fn/use_function.jsp

<%@ page contentType = "text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<html>
<head><title>함수 사용</title></head>
<body>
<c:set var="str1" value="Functions <태그>를 사용합니다. " />
<c:set var="str2" value="사용" />
<c:set var="tokens" value="1,2,3,4,5,6,7,8,9,10" />

length(str1) = ${fn:length(str1)} <br>
toUpperCase(str1) = "${fn:toUpperCase(str1)}" <br>
toLowerCase(str1) = "${fn:toLowerCase(str1)}" <br>
substring(str1, 3, 6) = "${fn:substring(str1, 3, 6)}" <br>
substringAfter(str1, str2) = "${fn:substringAfter(str1, str2)}" <br>
substringBefore(str1, str2) = "${fn:substringBefore(str1, str2)}" <br>
trim(str1) = "${fn:trim(str1)}" <br>
replace(str1, src, dest) = "${fn:replace(str1, " ", "-")}" <br>
indexOf(str1, str2) = "${fn:indexOf(str1, str2)}" <br>
startsWith(str1, str2) = "${fn:startsWith(str1, 'Fun')}" <br>
endsWith(str1, str2) = "${fn:endsWith(str1, "합니다.")}" <br>
contains(str1, str2) = "${fn:contains(str1, str2)}" <br>
containsIgnoreCase(str1, str2) = "${fn:containsIgnoreCase(str1, str2)}" <br>

<c:set var="array" value="${fn:split(tokens, ',')}" />

join(array, "-") = "${fn:join(array, "-")}" <br>
escapeXml(str1) = "${fn:escapeXml(str1)}" <br>

</body>
</html>

- 코어 라이브러리와 함수 라이브러리를 불러오고 있다

- set 태그로 str1,str2,str3 을 정의하며 각각 문자열로 초기화 한다

 

함수 라이브러리 불러오기 (use_function.jsp 부분)

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

- prefix 가 "fn" 이다

 

함수 사용 형식 (use_function.jsp 부분)

length(str1) = ${fn:length(str1)} <br>

- 함수 라이브러리를 쓸 때는 EL 안 (${}) 에서 쓴다

- prefix 인 fn 을 쓰고 : 다음 함수명을 써서 사용한다

 

함수 종류

- legnth(문자열) : 문자열의 길이 구해줌

- toUpperCase(문자열) : 문자열을 대문자로 변환

- toLowerCase(문자열) : 문자열을 소문자로 변환

- subString(문자열,시작,끝) :문자열 추출

- 인덱스 3 ~ 5까지 str1 문자열을 추출

- substringAfter(문자열 str1, 문자열 str2) : str1의 문자를 str2문자 다음의 문자를 추출

- str1에서 str2 인 '사용' 이라는 문자 다음의 것을 추출

- substringBefor(문자열 str1, 문자열 str2) : str1의 문자를 str문자 이전의 문자를 추출

- trim(문자열) : 공백을 없애줌

- replace(str1, " ", "-") : str1 의 공백을 "-" 으로 치환

 

- 전체 출력 캡처


JSTL 라이브러리 : 데이터베이스 라이브러리

- DB 연동이 되어야한다

- 실습 위해 테이블도 만들어야함

- INSERT, UPDATE, DELETE 는 update 태그, SELECT 는 query 태그 사용

 

JSTL 예제 12

실습 준비

- totoro 계정을 사용할 것이므로 오라클 totoro 계정을 연결해야한다

- 테이블명이 test 로 되어있다, 컬럼은 2개

create table test(
	num number,
	name varchar2(10),
	primary key(num) );

- totoro 계정으로 들어가서 테이블을 생성하자

- WebContent/sql/myoracle.jsp 에서 연결 후 테이블 생성

- 생성 후 확인

- test 테이블이 생성되었다

- num 컬럼, name 컬럼이 있고, num 컬럼이 기본키이다

 

JSTL 예제 12

데이터베이스 라이브러리

여러가지 태그들

- JSTL/sql/ex7/jstl_sql_ex.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
<html>
<head>
<title>JSTL sql 라이브러리 사용 예제</title>
</head>
<body>

<sql:setDataSource var="conn" driver="oracle.jdbc.driver.OracleDriver" 
				url="jdbc:oracle:thin:@localhost:1521:xe"
				user="totoro" 
				password="totoro123"/>

<sql:update dataSource="${conn}">
	INSERT INTO test (num, name) VALUES (1, '홍길동')
</sql:update>
<sql:update dataSource="${conn}">
	INSERT INTO test (num, name) VALUES (2, '조준동')
</sql:update>
<sql:update dataSource="${conn}">
	INSERT INTO test (num, name) VALUES (3, '홍길동')
</sql:update>
<sql:update dataSource="${conn}">
	INSERT INTO test (num, name) VALUES (4, '홍길순')
</sql:update>

<sql:query var="rs" dataSource="${conn}">
	SELECT * FROM test WHERE name=?
	<sql:param>홍길동</sql:param>
</sql:query>

<c:forEach var="data" items="${rs.rows}">
	<c:out value="${data['num']}"/>
	<c:out value="${data['name']}"/>
	<br>
</c:forEach>

</body>
</html>

- 연결하고, insert 수행하고, select 수행하고 있다

- INSERT, UPDATE, DELETE 는 update 태그, SELECT 는 query 태그 사용

 

데이터베이스 라이브러리 부르기

<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

- prefix 는 "sql"

 

DB 접속 설정

<sql:setDataSource var="conn" driver="oracle.jdbc.driver.OracleDriver" 
				url="jdbc:oracle:thin:@localhost:1521:xe"
				user="totoro" 
				password="totoro123"/>

- user 속성과 password 를 실제 오라클 계정과 유저네임과 비밀번호로 설정

- 정보가 모두 일치하면 실행 시 하나의 Connection 객체가 생성된다

 

INSERT 수행

<sql:update dataSource="${conn}">
	INSERT INTO test (num, name) VALUES (1, '홍길동')
</sql:update>
<sql:update dataSource="${conn}">
	INSERT INTO test (num, name) VALUES (2, '조준동')
</sql:update>
<sql:update dataSource="${conn}">
	INSERT INTO test (num, name) VALUES (3, '홍길동')
</sql:update>
<sql:update dataSource="${conn}">
	INSERT INTO test (num, name) VALUES (4, '홍길순')
</sql:update>

- update 태그로 INSERT 수행

- dateSource 속성에 아까 만든 Connection 객체 conn 을 넣는다

- 삽입 확인

 

SELECT 수행

<sql:query var="rs" dataSource="${conn}">
	SELECT * FROM test WHERE name=?
	<sql:param>홍길동</sql:param>
</sql:query>

<c:forEach var="data" items="${rs.rows}">
	<c:out value="${data['num']}"/>
	<c:out value="${data['name']}"/>
	<br>
</c:forEach>

- ? 자리에 값을 설정할때 param 태그 사용,

- 즉 name 이 "홍길동" 인 데이터를 검색

- rs 가 검색결과를 받는다, Java의 ResultSet 과 비슷

- forEach 문의 itmes 에 rs.rows 로 한 행씩 가져와서 한 행의 'num' 컬럼의 값, 'name' 컬럼의 값을 출력하고 있다

 

- 1번만 실행해야한다, 결과 캡처

 

 


- Java Servlet, EL, JSTL 끝났다

- 이제 Model 2 로 완성된 프로그램 만들 것

- Controller 클래스 1개 Java Servlet 클래스로 만들기

- Service 클래스 여러개 만들기, 상속을 통해 통일성 있게 구현

- DTO, DAO 는 기존 Model 1 의 DAO, DTO 와 같다


 

JSP Model 2 회원관리 프로그램 만들기

 

회원관리 프로그램 : 주요 기능 소개

1. Connection Pool

2. request, session 객체 공유 설정

- 로그인 성공시 session 공유 시작, 로그아웃시 session 강제로 삭제

- 출력할 것들을 request 객체로 공유 설정

3. Controller 클래스 : Java Servlet

4. Model = Service + DAO

- Service, DTO, DAO 클래스

5. View (화면 인터페이스)

- 공유된 값을 EL , JSTL 사용해서 출력

 

회원관리 프로그램 : 프로그램 구조 설명, 구조도

- 이렇게 구조를 만들기 위해

- Model 2 에서는 DAO, DTO 가 다른 패키지에 있다

- 같은 기능을 하는 클래스들끼리 묶어서 패키지 안에 저장

- controller 패키지 안에 Controller 클래스, dao 패키지 안에 DAO 클래스, model 패키지 안에 Model 클래스(DTO)

- service 패키지 안에 Service 클래스들

 

<환경 설정>

- WebContent 에 폼, 유효성 검사 되어있는 파일이 있는 폴더 member 넣기

- META-INF 에 context.xml

- 자료실 위해서 cos.jar, JSTL 쓰려면 jstl, 오라클 쓰려면 ojdbc6.jar

<Controller 클래스>

- Controller 클래스는 Java Servlet 클래스로 만듬

- Controller 클래스 WebServlet 어노테이션에 패턴 지정, .do 하면 무조건 여기로 찾아옴

<Service 클래스>

- Service 클래스의 부모 인터페이스는 Action.java, 추상메소드 execute() 만을 가짐

- 그 인터페이스를 상속받은 많은 구현 클래스들을 만듬

- 어떤 방식으로 포워딩할지 결정하는 Service 클래스 : ActionForward.java

 

회원관리 프로그램 : 프로젝트 생성

- model2member 라는 이름으로 새로운 프로젝트 만들기

- 초기에 보여줄 파일인 index.jsp 를 WebContent 폴더 안에 생성

 

회원관리 프로그램 : HTML, Javascript 파일 가져오기

- 폼과 유효성 검사가 되어있는 파일을 가져오기

- 이 기본 파일들을 바탕으로 프로그램 구현

 

회원관리 프로그램 : 몇가지 환경 구축

1) WebContent/WEB-INF/lib 폴더 하위에 라이브러리 3개 넣기

- 자료실 위해서 cos.jar, JSTL 쓰려면 jstl-1.2.jar, 오라클 쓰려면 ojdbc6.jar 라이브러리

 

2) member 폴더 안의 context.xml 파일을 META-INF 폴더로 옮기기

- 커넥션 풀의 환경설정 파일이다

- context.xml

<Context> 
  <Resource name="jdbc/orcl" 
   auth="Container"
   type="javax.sql.DataSource" 
   username="totoro" 
   password="totoro123"
   driverClassName="oracle.jdbc.driver.OracleDriver"
   factory="org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory"
   url="jdbc:oracle:thin:@localhost:1521:xe"
   maxActive="500"  
   maxIdle="100"/>  
</Context>

<!--  p423 참조
 maxActive="500"  컨넥션풀이 관리하는 컨넥션의 최대 갯수
		          (기본값 : 8)
 maxIdle="100" 	  컨넥션풀이 관리하는 최대 유휴 갯수(기본값 : 8)          
-->

- 500 개의 커넥션이 미리 연결되어있다

 

회원관리 프로그램 : Connection Pool 테스트

- dbcpAPITest.jsp 파일을 실행해서 커넥션 풀에서 커넥션 가져오기 테스트

<%@ page language="java" contentType="text/html; charset=EUC-KR"%>
<%@ page import="java.sql.*"%>
<%@ page import="javax.sql.*" %>
<%@ page import="javax.naming.*" %>
<%
 	Connection conn = null; 
	
	try {
  		Context init = new InitialContext();
  		DataSource ds = (DataSource) init.lookup("java:comp/env/jdbc/orcl");
  		conn = ds.getConnection();
  		
  		out.println("<h3>연결되었습니다.</h3>");
	}catch(Exception e){
		out.println("<h3>연결에 실패하였습니다.</h3>");
		e.printStackTrace();
 	}
%>

- 커넥션 풀에서 커넥션 가져오기 테스트 성공

+ 추후 DAO 클래스 만들때 커넥션풀에서 커넥션 구하기 3줄 코드를 DAO 클래스에 넣을 것

  		Context init = new InitialContext();
  		DataSource ds = (DataSource) init.lookup("java:comp/env/jdbc/orcl");
  		conn = ds.getConnection();

 

회원관리 프로그램 : member2 테이블 생성

- totoro 오라클 계정에 member2 테이블을 생성

- Model 1 시간에 만들었던 회원 관리 프로그램과 같은 테이블명만 다르다

create table member2(
id varchar2(20) primary key,
passwd varchar2(20) not null,
name varchar2(20) not null,
jumin1 varchar2(6) not null,
jumin2 varchar2(7) not null,
mailid varchar2(30), 
domain varchar2(30), 
tel1 varchar2(5),
tel2 varchar2(5),
tel3 varchar2(5),
phone1 varchar2(5),
phone2 varchar2(5),
phone3 varchar2(5),
post varchar2(10),
address varchar2(200),
gender varchar2(20),
hobby varchar2(50),
intro varchar2(2000),
register timestamp );

- WebContent 하위에 sql 폴더를 만들고 안에 member.sql 파일 생성

- 커넥션 프로파일을 Oracle_11, New Oracle(totoro), xe 로 해준다

- member2 테이블을 생성

- member2 테이블 생성 확인

 

회원관리 프로그램 : DAO 와 DTO 클래스 만들기

- Model 2 에서는 DAO, DTO 의 패키지가 달라진다

- 해당 클래스를 사용할때 반드시 import 를 해야하고, 접근제어자는 public 이어야한다

 

- 프로그램 구조도 대로 src안에 model 패키지를 만들고 그 안에 DTO 클래스를 만든다
- 프로그램 구조도 대로 src안에 dao 패키지를 만들고 그 안에 DAO 클래스를 만든다

 

회원관리 프로그램 : DTO 클래스 작성

- 테이블 member2 create 문에서 가져와서 DTO 클래스에 복붙 후 수정

- varchar2 는 String 으로, number 는 Int 로, timestamp 는 Timestamp로 바꿔서 자바 변수(프로퍼티) 만들기

+ 프로퍼티의 접근제어자는 private

+ java.sql 의 Timestamp import

- 이후 getter / setter 메소드 추가

 

- DTO 클래스 완성 코드

- MemberDTO.java

// DTO (Date Transfer Object)
package model;

import java.sql.Timestamp;

public class MemberDTO {
	private String id;
	private String passwd;
	private String name;
	private String jumin1;
	private String jumin2;
	private String mailid; 
	private String domain;
	private String tel1;
	private String tel2;
	private String tel3;
	private String phone1;
	private String phone2;
	private String phone3;
	private String post;
	private String address;
	private String gender;
	private String hobby;
	private String intro;
	private Timestamp register;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPasswd() {
		return passwd;
	}
	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getJumin1() {
		return jumin1;
	}
	public void setJumin1(String jumin1) {
		this.jumin1 = jumin1;
	}
	public String getJumin2() {
		return jumin2;
	}
	public void setJumin2(String jumin2) {
		this.jumin2 = jumin2;
	}
	public String getMailid() {
		return mailid;
	}
	public void setMailid(String mailid) {
		this.mailid = mailid;
	}
	public String getDomain() {
		return domain;
	}
	public void setDomain(String domain) {
		this.domain = domain;
	}
	public String getTel1() {
		return tel1;
	}
	public void setTel1(String tel1) {
		this.tel1 = tel1;
	}
	public String getTel2() {
		return tel2;
	}
	public void setTel2(String tel2) {
		this.tel2 = tel2;
	}
	public String getTel3() {
		return tel3;
	}
	public void setTel3(String tel3) {
		this.tel3 = tel3;
	}
	public String getPhone1() {
		return phone1;
	}
	public void setPhone1(String phone1) {
		this.phone1 = phone1;
	}
	public String getPhone2() {
		return phone2;
	}
	public void setPhone2(String phone2) {
		this.phone2 = phone2;
	}
	public String getPhone3() {
		return phone3;
	}
	public void setPhone3(String phone3) {
		this.phone3 = phone3;
	}
	public String getPost() {
		return post;
	}
	public void setPost(String post) {
		this.post = post;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public String getHobby() {
		return hobby;
	}
	public void setHobby(String hobby) {
		this.hobby = hobby;
	}
	public String getIntro() {
		return intro;
	}
	public void setIntro(String intro) {
		this.intro = intro;
	}
	public Timestamp getRegister() {
		return register;
	}
	public void setRegister(Timestamp register) {
		this.register = register;
	}
	
}

 

회원관리 프로그램 : DAO 클래스 작성

DAO 에 들어갈 내용

1. 싱글톤

2.  정적메소드 getInstance() 생성

3. Connection Pool 에서 커넥션 구해오는 메소드

4. 그 이후 회원가입, 중복검사, 탈퇴 등의 메소드

 

1. 싱글톤

- 자기자신의 클래스로 객체 생성을 한번만 하고 static 을 붙여 공유 , private 설정

 

2. 정적메소드 getInstance() 생성

 

3. Connection Pool 에서 커넥션 구해오는 메소드

- 메소드 호출시 Connection Pool 에서 커넥션을 구해주도록 함

- 커넥션 구할때 예외처리를 해야한다, 여기선 throws 로 Exception 던지기

+ Connection 클래스 import

- 테스트할때 사용했던 이 3줄을 복사해서 넣는다

- 단축키 Ctrl + Shift + O 로 import 시키기

- javax.naming.Context 를 선택후 Next, 다음은 javax.sql.DataSource 선택후 Finish

+ Context 와 DataSource 둘 다 Interface 이다

- getConnection() 메소드 완성

- 가져온 커넥션을 리턴하는 코드로 바꿈

+ 리턴자료형을 private 으로 해서 DAO 클래스 내에서만 호출가능하도록 함

 

- 현재까지 DAO 클래스 BoardDBBean.java 코드

// DAO (Date Access Object)
package dao;

import java.sql.Connection;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

public class MemberDAO {

	// 싱글톤 : 객체 생성을 한번만 수행 하는 것.
	private static MemberDAO instance = new MemberDAO();
	
	public static MemberDAO getInstance() {
		return instance;
	}
	
	// 커넥션풀에서 커넥션을 구해오는 메소드
	private Connection getConnection() throws Exception {
 		Context init = new InitialContext();
  		DataSource ds = (DataSource) init.lookup("java:comp/env/jdbc/orcl");
  		return ds.getConnection();
	}
	
	// 회원가입
}

 

4. 그 이후 회원가입, 중복검사, 탈퇴 등의 메소드

- 그 이후 회원가입, 중복검사, 탈퇴 등의 메소드가 오면 된다

- 이 DAO 메소드를 "Service 클래스"에서 호출해서 SQL문 실행할 것

- 그래서 값이 Service -> DAO 로 넘어간다

 

회원관리 프로그램 : Controller 클래스

- Java Servlet 클래스로 만든다

- 모든 요청의 진입점

- src에서 오른마우스를 클릭해서 Servlet 선택

- controller 패키지, MemberController 클래스 를 만든다

 

- MemberController.java (수정 전)

package controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class MemberController
 */
@WebServlet("*.do")	// do 확장자
public class MemberController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	// doGet(), doPost() 메소드에서 공통적인 작업을 처리하는 메소드
	protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String requestURI = request.getRequestURI();
		String contextPath = request.getContextPath();
		String command = requestURI.substring(contextPath.length());
		
		System.out.println("requestURI : " + requestURI); // requestURI : /model2member/Login.do
		System.out.println("contextPath : " + contextPath); // contextPath : /model2member
		System.out.println("command : " + command); // command : /Login.do
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("get");
		doProcess(request, response);	// doProcess() 호출
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("post");
		doProcess(request, response);	// doProcess() 호출
	}

}

- 오류 생겼을때 어느정도까지 실행되었는지 확인하기 위해서 System.out.println(); 으로 브라우저에 출력

- doGet() 과 doPost() 에 같은 내용을 써야한다

- 요청 방식에 따라 서로 다른 일을 하는게 더 이상함

- doGet() 과 doPost() 에서 처리할 내용은 동일해야하므로 따로 공통적인 작업을 처리하는 메소드 doProcess() 를 만듬

- 그 메소드 doProcess() 를 doGet(), doPost() 에서 호출하도록 함

- doGet(), doPost() 는 자동으로 호출되는 메소드이므로 doGet(), doPost() 의 매개변수 request, response 를 doProcess() 호출시 전달

- doProcess() 안의 내용은 아래에

 

WebServlet 어노테이션 이름값으로 "*.do" 로 임의로 설정

@WebServlet("*.do")	// do 확장자

- "*.do" 는 do 확장자로 요청하는 요청을 받는다는 의미

- "*.do" 는 앞쪽의 파일명은 어떤 이름이어도 상관없고, 확장자가 do 인 모든 요청을 받는다는 의미

- 이 확장자는 임의로 설정한다, 주로 회사명

 

ex) 네이버에서 확장자는 .naver 사용

 

+ WebContent/memer/memberform.jsp 에서 form 의 action 값을 확인해보자

- 앞의 이름과 상관없이 확장자가 do 이므로 무조건 MemberController 클래스로 찾아감

 

+ WebContent/memer/loginform.jsp 에서 form 의 action 값을 확인해보자

- 앞의 이름과 상관없이 확장자가 do 이므로 무조건 MemberController 클래스로 찾아감

 

- Model 2에서 모든 클라이언트의 요청은 하나의 Controller 클래스로 가야한다

- WebServlet 어노테이션을 "*.do" 로 설정시 클라이언트(폼)에서 do 확장자로 요청하면 무조건 그 요청을 받음

- 이 패턴 *.do 에 맞으면 그곳으로 찾아감

 

doProcess() 안의 내용 (MemberController.java 부분)

	// doGet(), doPost() 메소드에서 공통적인 작업을 처리하는 메소드
	protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String requestURI = request.getRequestURI();
		String contextPath = request.getContextPath();
		String command = requestURI.substring(contextPath.length());
		
		System.out.println("requestURI : " + requestURI);
		System.out.println("contextPath : " + contextPath);
		System.out.println("command : " + command);
	}

- request 객체에서 제공되는 6개의 메소드 중 getRequestURI() 와 getContextPath() 를 쓰고 있다

- Controller 클래스는 요청을 어떤 서비스 클래스로 넘겨줄지 결정함

- getRequestURI() : 현재 프로젝트명과 요청 URI 를 구해줌 ex) /model12member/Login.do

- getContextPath() : 프로젝트 명을 구해줌 ex) /model12member

- substring() 으로 contextPath 변수(현재 프로젝트명) 의 길이 숫자부터 시작해서 추출

- 추출시 요청 URI 만 남게되고, 이 요청 URI 가 command 변수에 저장됨

 

- loginform.jsp 에서 Controller 클래스로 요청을 해보자

- loginform.jsp 실행하기

- 아무 값이나 로그인 폼에 입력하고 '로그인' 누르기

- 그럼 "/login.do" 로 요청, 확장자가 do 이므로 무조건 Controlelr 클래스로 찾아간다

- 값 전송방식이 post 이므로 doPost() 가 실행됨, doProcess() 호출됨

 

- 콘솔창 확인

- post  : doPost() 가 호출되었다는 의미

- requestURI 는 /model2member/Login.do 가 출력됨

- contextPath 는 /model2memer 가 출력됨

- command 는 /Login.do 가 출력됨

 

Controller 클래스에서 맞는 Service 클래스로 요청을 넘기는 방법 (MemberController.java 부분)

		String command = requestURI.substring(contextPath.length());

- contextPath.length() 는 13 이고, requestURI.substring(13) 은 requestURI 의 인덱스 13부터 쭉 출력하라는 의미

- requestURI는 /model2member/Login.do 이므로 13부터는 /Login.do 이고 이게 command 변수에 저장됨

- command 변수에는 최종적으로 요청 이름값이 저장됨 , 즉 action 값으로 지정된 "/Login.do" 가 저장됨

- 이제 어디서 요청이 왔는지 확인이 가능하다

ex) command 가 "/Login.do" 이면 로그인 페이지 와서 왔음을 알 수 있음

 

- 조건문과 command.equals() 를 사용해서 어디서 온 요청이냐에 따라 전달될 Service 클래스를 지정함

ex) command.equals("/Login.do")

 

+ Controller 클래스는 또한 포워딩 2가지 방법 중 어떤 방식으로 포워딩 될지도 처리함

- Dispatcher 방식으로 포워딩할지, Ridirect 방식으로 포워딩할지 Controller 클래스에서 정한다

 

 

 

 

+ Recent posts