예습

ORM(Object Relational Mapping) 프레임 워크

- 기존 SQL 문만 따로 xml 로 뺀다

- 라이브러리가 지원된다

- 테이블의 컬럼명과 DTO 클래스의 필드명이 같은 이름이면 매핑이 바로 일어나게 한다

 

세션

- 세션값이 공유되기 때문에 계속해서 id 와 passwd 를 get/post 로 넘기지 않아도 된다

 

DBCP 환경설정

- url 은 오라클이 설치된 곳의 ip 주소가 들어간다

 

 

DAO 클래스에서 들어가는 것

DAO 클래스 싱글톤

- 객체를 한번만 생성해서 공유하는 개념

- 한번 만들어진 static 은 프로그램 종료시까지 메모리에 상주함

- 공유를 하기위해 멤버변수를 static 으로 설정한다

 

커넥션을 가져오는 코드

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

- init.lookup() 메소드로 Resource 를 찾아서 커넥션을 구해온다

- 이 3줄이 DAO 클래스에 들어간다

 

회원관리 프로그램 : 파일별 기능 및 구조 설명


회원관리 프로그램 : 회원 가입 기능

- memberform.html 파일은 이미 있다, 폼과 유효성검사가 완성되어 있음

- memberform.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입 폼</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>

<script src="http://dmaps.daum.net/map_js_init/postcode.v2.js"></script>
<script>
	function openDaumPostcode() {
		new daum.Postcode({
			oncomplete : function(data) {
				// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
				// 우편번호와 주소 정보를 해당 필드에 넣고, 커서를 상세주소 필드로 이동한다.
//				document.getElementById('join_zip1').value = data.postcode1;
				document.getElementById('post').value = data.zonecode;
				document.getElementById('address').value = data.address;
				
			}
		}).open();
	}
</script>

<!-- 외부 자바스크립트 파일 불러오기 -->
<script src="member.js"></script>

</head>
<body>

<form method="post" action="member.jsp"> 
<table border=1 width=450 align="center">
	<caption>회원 가입 폼</caption>
	<tr><td>ID</td>
		<td><input type=text autofocus="autofocus" id="id" name="id">
			<input type=button value="ID중복검사" id="idcheck">
		</td>
	</tr>
	<tr><td>비밀번호</td>
		<td><input type=password id="passwd" name="passwd">
		</td>
	</tr>
	<tr><td>성명</td>
		<td><input type=text id="name" name="name"></td>
	</tr>
	<tr><td>주민번호</td>
		<td><input type=text size=6 maxlength=6 id="jumin1" name="jumin1">-
			<input type=text size=7 maxlength=7 id="jumin2" name="jumin2">
		</td>
	</tr>
	<tr><td>E-Mail</td>
		<td><input type=text size=10 id="mailid" name="mailid">@
			<input type=text size=10 id="domain" name="domain">
			<select id="email">
				<option value="">직접입력</option>
				<option value="naver.com">네이버</option>
				<option value="daum.net">다음</option>
				<option value="nate.com">네이트</option>
				<option value="gmail.com">gmail</option>
			</select>	
		</td>
	</tr>
	<tr><td>전화번호</td>
		<td><input type=text size=4 maxlength=4 id="tel1" name="tel1">-
		    <input type=text size=4 maxlength=4 id="tel2" name="tel2">-
		    <input type=text size=4 maxlength=4 id="tel3" name="tel3">-
		</td>
	</tr>
	<tr><td>핸드폰</td>
		<td><select id="phone1" name="phone1">
				<option value="">번호선택</option>
				<option value="010">010</option>
				<option value="011">011</option>
				<option value="016">016</option>
				<option value="018">018</option>
				<option value="019">019</option>
			</select>-
			<input type=text size=4 maxlength=4 id="phone2" name="phone2">-
		    <input type=text size=4 maxlength=4 id="phone3" name="phone3">		
		</td>	
	</tr>
	<tr><td>우편번호</td>
		<td><input type=text size=5 maxlength=5 id="post" name="post">
			<input type=button value="우편검색" onClick="openDaumPostcode()">
		</td>
	</tr>
	<tr><td>주소</td>
		<td><input type=text size=45 id="address" name="address"></td>
	</tr>
	<tr><td>성별</td>
		<td><input type=radio id="male" name="gender" value="남자">남자
			<input type=radio id="female" name="gender" value="여자">여자
		</td>
	</tr>
	<tr><td>취미</td>
		<td><input type=checkbox id="h1" name="hobby" value="공부">공부
			<input type=checkbox id="h2" name="hobby" value="게임">게임
			<input type=checkbox id="h3" name="hobby" value="등산">등산
			<input type=checkbox id="h4" name="hobby" value="낚시">낚시
			<input type=checkbox id="h5" name="hobby" value="쇼핑">쇼핑
		</td>
	</tr>
	<tr><td>자기소개</td>
		<td><textarea rows=5 cols=50 id="intro" name="intro"
		     placeholder="자기소개를 100자 이내로 입력하세요"></textarea>		
		</td>
	</tr>
	<tr><td colspan=2 align=center>
			<input type=submit value="회원가입">
			<input type=reset value="취소">
		</td>
	</tr>		
</table>
</form>

</body>
</html>

- form 태그 action 에서 member.jsp 로 넘어가도록 지정

- setProperty action tag 를 사용하기 위해 form 태그 요소의 name 값을 DTO 프로퍼티명과 일치시켜야한다

+ 테이블 안 컬럼명 = DTO 필드명 = form 태그 요소의 name 값, 이 3가지를 일치시켜야 편하다

 

- member.jsp 파일을 만들 것

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="member.MemberDAO"%>
<%
	request.setCharacterEncoding("utf-8");
%>

<jsp:useBean id="member" class="member.MemberDTO"/>
<jsp:setProperty property="*" name="member"/>

<%
	String[] hobby = request.getParameterValues("hobby");
	String h = "";	// h = "공부-게임-등산-"
	for(String h1 : hobby) {
		h += h1 + "-";
	}
	member.setHobby(h);
	
	// DAO 객체 생성
	MemberDAO dao = MemberDAO.getInstance();
	int result = dao.insert(member);	//insert SQL문을 실행할 메소드 호출
	
	if(result == 1) {	// 회원가입 성공
%>
		<script>
			alert("회원가입 성공");
			location.href="loginform.html";
		</script>
<%	} else{ 	// 회원가입 실패   %>
		<script>
			alert("회원가입 실패");
			history.go(-1);
		</script>
<%	}%>

0. 화면 출력을 할때만 HTML 코드가 필요하다, 여기선 출력을 하지 않으므로 위의 2줄 제외하고 HTML 코드를 지운다

1. memberform.html 에서 한글값이 post 로 넘어오므로 한글 인코딩

2. 폼에서 넘어온 값을 DTO 객체에 저장해야하므로 DTO 객체를 생성하고 각 프로퍼티에 값 저장

- useBean action tag 의 class 속성에는 패키지부터 시작해서 클래스까지 적어줌

- setProperty action tag 의 property 속성에는 "*", id 속성에는 객체명을 써야하므로 member 를 쓴다

- DTO 객체에 저장 = 폼에서 넘어온 값을 힙메모리상에 저장

예외 : 취미 부분 조작

- 취미의 name 값은 hobby 이고 value 는 공부, 게임 등인데 여러개를 선택했을때 테이블의 hobby 에 저장해야한다

- 선택했던 취미를 테이블쪽 hobby 라는 컬럼에 저장할때 "- " (하이픈) 으로 연결해서 저장한다

- 나중에 수정하는 화면에서 내가 가입시 선택했던 취미를 체크해서 나타나게 할 것

- 그러기 위해선 이 값들을 구분기호로 구분해서 저장해야한다, 나중에 split() 을 하려면 구분기호 사용해야함

1) 값을 getParamterValues() 로 직접받아서 String 형 배열 hobby 에 저장한다

2) 그 배열에 저장된 값을 - 로 연결해서 h 변수에 누적한다 ex) h = "공부-게임-등산-"

3) DTO 객체 member 에 setHobby() setter 메소드로 직접 hobby 프로퍼티 값을 설정

3. DAO 객체 생성

- 메모리상에 저장된 데이터를 member 테이블에 insert 하기 위해서 DAO 클래스에 메소드를 만들어야한다

- 이 메소드를 이 파일 member.jsp 에서 호출해야하므로 DAO 객체를 먼저 만들어야함

- 정적메소드로 DAO 객체 리턴받음

4. insert SQL 문을 실행할 메소드 호출

- DAO 클래스의 insert() 라는 회원 정보를 DB 에 저장해주는 메소드를 실행 후 삽입 개수를 리턴받음

- 매개변수로는 폼에서 넘어온 값을 저장한 DTO 객체 member 를 넘김

- 값의 주소값을 저장한 객체 member 를 넘기는 것이므로 Call By Reference 이다

5. 가입 성공, 가입 실패 처리

- 리턴된 값 result 가 1이면 회원가입 성공, 아니면 회원 가입 실패

- 성공시 로그인 폼으로, 실패시 이전 페이지로 이동

 

DAO 클래스 가입 기능 작성

- DAO 클래스에서 insert() 메소드를 작성해야한다

- MemberDAO.java

// DAO (Data Access Object)

package member;
import java.sql.Connection;
import java.sql.PreparedStatement;

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();		
	}
	
	// 회원 가입
	public int insert(MemberDTO member) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		
		try {
			con = getConnection();	// 커넥션풀에서 커넥션을 구해온다
			
			String sql = "insert into member ";
			sql += " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,sysdate)";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			pstmt.setString(2, member.getPasswd());
			pstmt.setString(3, member.getName());
			pstmt.setString(4, member.getJumin1());
			pstmt.setString(5, member.getJumin2());
			pstmt.setString(6, member.getMailid());
			pstmt.setString(7, member.getDomain());
			pstmt.setString(8, member.getTel1());
			pstmt.setString(9, member.getTel2());
			pstmt.setString(10, member.getTel3());
			pstmt.setString(11, member.getPhone1());
			pstmt.setString(12, member.getPhone2());
			pstmt.setString(13, member.getPhone3());
			pstmt.setString(14, member.getPost());
			pstmt.setString(15, member.getAddress());
			pstmt.setString(16, member.getGender());
			pstmt.setString(17, member.getHobby());
			pstmt.setString(18, member.getIntro());
			
			result = pstmt.executeUpdate();		// SQL문 실행
			
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
			if(con != null) try { con.close();} catch(Exception e) {}
		}
		
		return result;
	}
	
}

<insert() 메소드 형식 작성>

- JSP 파일에서 이 DAO 로 접근하므로 public 이어야한다

- 매개변수로 넘어온 DTO 객체에 저장된 값을 DB 의 테이블에 삽입할 것이므로 매개변수 자료형은 DTO

- int 를 자료형으로 해서 삽입된 데이터 개수를 반환하도록 하자, void 여도 된다

<insert() 메소드 내용 작성>

1. Connection, PreparedStatement 객체를 try-catch문 위에 작성해서 try 뿐 아니라 finally 에서도 사용가능하도록 함

2. 커넥션 풀을 통해서 커넥션을 구해오는 코드는 같은 DAO 클래스 내 getConnection() 메소드에 있으므로 try 내에서 호출

- JDBC 방식이 아닌 DBCP 방식으로 DB 접속하는 방법

- getConnection() 으로 커넥션을 구해서 Connection 객체인 con 에 저장했다

+ 같은 클래스의 메소드이므로 메소드명만 작성

+ getConnection() 메소드에서 예외를 throws 로 던지므로 여기서 예외처리 try-catch 를 해야한다

3. insert 하는 SQL문을 작성하면서 테이블의컬럼수에 맞게 ? 를 18개, 마지막은 sysdate 로 가입한 날짜 등록

4. sql문을 읽어와서 Connection 객체 con 을 통해 PreparedStatement 객체 생성

5. 모두 varchar2 이므로 setString() 으로 ? 에 값 설정, 값은 전달받은 member 객체에서 getter 메소드로 값을 가져옴

6. insert sql 문을 executeUpdate() 로 실행하고, 결과는 result 변수로 받음

- insert 가 잘실행되면 1 이 리턴되고, 예외가 발생시 초기에 설정해둔 값인 0 이 result 값이다

7. finally 에서 PreparedStatemet 객체 pstmt 를 닫고 Connection 객체 con 을 닫기

+ DAO 클래스에 가입기능 구현 완료, 나머지 기능을 추가할 것

 

- 회원 가입이 잘 실행되는지 확인

- 회원가입을 성공하고 로그인 페이지로 가고 있다

- 오라클 테이블에서 삽입 확인

- 테이블을 봐서 회원가입 insert 가 잘 구현되었음을 확인 가능

 

회원관리 프로그램 : ID 중복검사 (동기적, 팝업창)

- ID 중복검사 두가지 방법으로 구현할 것

1. 동기적인 방식으로 팝업창을 띄워서 ID 중복검사

2. 비동기적인 방식으로 팝업창을 띄우지 않고 바로 아래에 '사용중인 아이디입니다' 메세지 뿌리기

 

1. 동기적인 방식으로 팝업창을 띄워서 ID 중복검사

+ id 보기 (memberform.html 부분)

 

- memberform.html 의 js 파일인 member.js 파일 중 중복검사 부분을 보자

- 팝업창을 띄워서 처리하는 부분이다

- id 로 태그를 구해와서 click() 이벤트로 처리하고 있다

- id값을 입력하지 않았을때는 유효성 검사를 하고, id 를 입력했을때 팝업창을 띄워서 처리하고 있다

- 주소값에 idcheck.jsp 팝업창 파일을 적고, get 방식으로 id 값을 전달한다, $("#id").val() 로 사용자가 입력한 값을 전달

- 팝업창 idcheck.jsp 파일을 열고 있다

 

- idcheck.jsp 파일을 보자

- 현재는 출력만 하고 있다

 

 

- 이젠 단순 출력이 아닌 DB 에서 중복된 ID 가 있는지 검색하는 메소드를 호출할 것

 

- idcheck.jsp 파일 작성

<%@page import="member.MemberDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
	String id = request.getParameter("id");

	MemberDAO dao = MemberDAO.getInstance();
	
	// id 중복검사 메소드 호출
	int result = dao.memberAuth(id);
	
	if(result == 1) {	// 중복 ID : 1
%>
		<%=id %> 는 중복 ID 입니다.	<br><br><br>
		<input type="button" value="닫기">
<%	} else{				// 사용가능한 ID : -1 %>
		<%=id %> 는 사용가능한 ID 입니다.
		<input type="button" value="닫기">
<%	} %>

- DAO 에 중복된 ID 가 있는지 검색하는 memberAuth() 메소드를 만들고 그걸 이 idcheck.jsp 에서 호출할것

- 호출시 폼에서 넘겨받은 id 를 매개변수로 전달해야한다
- 그러기 위해 id 값을 받아서 변수로 저장하고 DAO 객체를 생성

- 사용가능한 ID 인지 사용중인 ID 인지 검색해서 결과를 int 형 변수 result 에 받을 것이다

- 메소드에서 검색 후 사용가능 한 ID 는 -1 를 돌려주기로 임의로 정하고, 중복 ID 는 1 을 돌려주기로 하자

 

DAO 클래스 ID 중복검사 기능 작성 :  동기적 처리 (팝업창)

- DAO 클래스에서 memberAuth() 메소드를 작성해야한다

- MemberDAO.java (추가)

// DAO (Data Access Object)

package member;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

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();		
	}
	
	// ID 중복 검사
	public int memberAuth(String id) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			con = getConnection();	// 커넥션 풀에서 커넥션을 구해옴
			
			String sql = "select * from member where id=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, id);
			
			rs = pstmt.executeQuery();	// SQL문 실행
			
			if(rs.next()) {	// 조건식을 만족하는 데이터를 구해옴
				result = 1;
			}
			
		} catch(Exception e) {
			
		} finally {
			if(rs != null) try { rs.close();} catch(Exception e) {}
			if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
			if(con != null) try { con.close();} catch(Exception e) {}			
		}
		
		return result;
	}
	
	
	// 회원 가입
	public int insert(MemberDTO member) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		
		try {
			con = getConnection();	// 커넥션풀에서 커넥션을 구해온다
			
			String sql = "insert into member ";
			sql += " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,sysdate)";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			pstmt.setString(2, member.getPasswd());
			pstmt.setString(3, member.getName());
			pstmt.setString(4, member.getJumin1());
			pstmt.setString(5, member.getJumin2());
			pstmt.setString(6, member.getMailid());
			pstmt.setString(7, member.getDomain());
			pstmt.setString(8, member.getTel1());
			pstmt.setString(9, member.getTel2());
			pstmt.setString(10, member.getTel3());
			pstmt.setString(11, member.getPhone1());
			pstmt.setString(12, member.getPhone2());
			pstmt.setString(13, member.getPhone3());
			pstmt.setString(14, member.getPost());
			pstmt.setString(15, member.getAddress());
			pstmt.setString(16, member.getGender());
			pstmt.setString(17, member.getHobby());
			pstmt.setString(18, member.getIntro());
			
			result = pstmt.executeUpdate();		// SQL문 실행
			
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
			if(con != null) try { con.close();} catch(Exception e) {}
		}
		
		return result;
	}
	
}

<memberAuth() 메소드 형식 작성>

- 아이디가 중복인지 아닌지 int 형으로 돌려주므로 리턴 자료형은 int

- 아이디가 중복인지 DB 에서 검색해야하므로 매개변수로 아이디를 받아야한다

<memberAuth() 메소드 내용 작성>

1. Connection, PreparedStatement, ResultSet 객체 생성

- DB 에서 Select 를 해서 중복아이디가 있는지 검색하는 것이므로 결과를 받을 ResultSet 객체를 만들어야함

2. try-catch-finally 문을 만들고 try 안에서 getConnection() 으로 커넥션 풀에서 커넥션을 구해옴

3. select SQL 문을 작성하며 where 조건절에 기본키인 id 컬럼을 쓰고, 매개변수로 넘어온 id 를 넣음

4. Connection 객체 con 으로 작성한 SQL 문을 읽어서 PreparedStatement 객체 생성

5. id 를 ? 에 설정하고 sql 문을 executeQuery() 메소드로 sql문을 실행하고 결과를 ResultSet 객체인 rs 로 받음

- select 문은 ResultSet 객체에 검색결과를 받는다

6. 검색된 데이터는 1 개이므로 if 문으로 rs.next() 를 통해 데이터를 가져왔는지만(=검색되는지만) 판별

- rs.next() 는 잘 가져오면 true 반환

- DB 에 검색 결과가 있는지만 확인하면 되므로 데이터를 가져왔는지만 판별하면 됨, 데이터를 꺼내지 않아도 됨

7. 잘 가져오면 result 를 1 로 설정하고, 잘 가져오지 못하면 result 를 -1 로 설정함

- 그럼 이미 사용중인 ID 가 DB에 있는 경우 result 는 1 이됨

8. ResultSet 객체, PreparedStatement 객체, Connection 객체 닫기

+ 다른 메소드 더 추가할 것, 아직 DAO 미완성

 

- 추가된 ID 중복검사 부분 코드만

 

 

추가 작업

1. 팝업창의 '닫기' 를 눌렀을때 열려있는 팝업창을 닫기

2.. 중복 ID 인 경우 아이디 지우기

3. 사용가능한 ID 면 닫으면서 '비밀번호' 입력부분에 에 focus 들어가게 하기

 

- idcheck.jsp 파일을 보자

<%@page import="member.MemberDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
	$(document).ready(function(){
		$("#close1").click(function(){	// 중복 ID인 경우의 닫기 버튼 클릭
			opener.$("#id").val("").focus();
			window.close();
		});
		$("#close2").click(function(){	// 사용 가능한 ID인 경우의 닫기 버튼 클릭
			opener.$("#passwd").focus();
			window.close();
		});
	});

</script>

<%
	String id = request.getParameter("id");

	MemberDAO dao = MemberDAO.getInstance();
	
	// id 중복검사 메소드 호출
	int result = dao.memberAuth(id);
	
	if(result == 1) {	// 중복 ID : 1
%>
		<%=id %> 는 중복 ID 입니다.	<br><br><br>
		<input type="button" value="닫기" id="close1">
<%	} else{				// 사용가능한 ID : -1 %>
		<%=id %> 는 사용가능한 ID 입니다.
		<input type="button" value="닫기" id="close2">
<%	} %>

1. 중복ID 인 경우, 사용가능한 ID 인 경우 에 각각 있는 버튼들의 id 값을 다르게 설정해서 구분

2.  jQuery 라이브러리를 사용하기 위해 jQuery 라이브러리 불러오기

3. 그리고 <script> 태그 내에서 추가 작업 구현하기

- 중복 ID 인 경우 입력된 id 를 지우고, id 입력창이 포커스 후 팝업창 닫기

- 사용가능한 ID 인 경우 비밀번호 입력창에 포커스 후 팝업창 닫기

+ opener 는 부모 window 를 의미

+ opener 는 부모 window 의 id 입력창과 비번 입력창에 지우기, 포커스 등을 하기위해 사용

 

- 중복 아이디인 경우

 

- 사용가능한 아이디인 경우

 

 

회원관리 프로그램 : ID 중복검사 (비동기적, Ajax)

2. 비동기적인 방식으로 팝업창을 띄우지 않고 바로 아래에 '사용중인 아이디입니다' 메세지 뿌리기

 

- 우선 메세지가 나타날 영역을 만들기 위해 회원가입 폼에 div 태그를 추가해야한다

- 이후 외부 js 파일인 member.js 파일로 가서 팝업창으로 처리하는 부분을 주석으로 막기

- 아래에 ajax 로 ID 중복검사를 할 것

- 사용자가 ID 를 입력하지 않은 경우 if문에서 유효성 검사, ID 를 입력한 경우만 else 문에서 처리

- member.js 에 ajax 부분 추가

$(document).ready(function(){
	// ajax로 ID 중복검사
	$("#idcheck").click(function(){
		
		if($("#id").val() == "") {
			alert("ID를 입력하세요.");
			$("#id").focus();
			return false;
		} else {
			var id = $("#id").val();		// 사용자가 입력한 ID
			$.ajax({
				type : "post",				// get, post, put, delete
				url : "idcheck1.jsp",
				data : {"id" : id},			// json
				success : function(data) {	// callback 함수로 결과를 돌려받음
					alert(data);
					if(data == 1) {			// 중복 ID
						$("#myid").html("<font color=red>중복 ID입니다.</font>");
						$("#id").val("").focus();
					} else {				// 사용 가능한 ID
						$("#myid").html("<font color=red>사용 가능한 ID입니다.</font>");
						$("#passwd").val("").focus();
					}
				}
			});	// $.ajax() end
		} // else end
		
	});	// click end
});

- 사용자가 입력한 ID 값을 변수로 받아서 JSON 형태로 저장할 것

- ajax() 함수 사용해서 속성:속성값 형태로 옵션 적기

- post 로 전송하며, 요청할 파일명은 idcheck1.jsp 로 한다, 이후 idcheck1.jsp 파일을 생성할 것

+ type 옵션 중 get post 외에도 put, delete 도 있다, put 은 수정할때 요청하는 형식, delete 는 삭제할때 사용

- 사용자가 입력한 id 값을 전달해야하므로, data 옵션에서 전달되는 값의 형태는 json 형태로 작성

- 키와 밸류를 {"id" : id} 로 작성한다, 나중에 idcheck1.jsp 에서 request.getParameter("id") 로 값을 받을 수 있음

+ 두개 이상의 값을 전달할 때는 , 로 연결함

 

- success 다음의 내용은 결과를 잘 돌려받았을때만 실행됨, 이 function 은 콜백함수이고 data 로 값을 돌려받음

- 이 콜백함수로 리턴받는 결과는 idcheck1.jsp 에서 브라우저에 출력되는 값

- 중복 ID 는 1 을, -사용가능한 ID 는 - 1 받을 것임

- 1을 받으면 사용가능하다는 메세지를 div 태그에 뿌려줌, -1 을 받으면 사용불가능하다는 메세지를 div 에 뿌려줌

 

- 그럼 이제 idcheck1.jsp 에서 ID 중복검사 해주는 DAO 의 메소드를 호출해야함 (동기적 처리할때 구현해뒀던 메소드)

- 먼저 idcheck1.jsp 파일 생성 후 작성

<%@page import="member.MemberDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	String id = request.getParameter("id");
	System.out.println("id = " + id);
	
	MemberDAO dao = MemberDAO.getInstance();
	int result = dao.memberAuth(id);
	System.out.println("result = " + result);
// result : 1 (중복 ID)
// result : -1 (사용 가능한 ID)

	// 웹브라우저에 출력되는 값이 callback 함수로 리턴된다.
	out.println(result);
%>

- member.js 에서 ajax() json 으로 전송한 id 값을 request.getParameter() 로 받는다

- 키값을 통해서 밸류를 구해온다

- 값이 제대로 왔는지 한번 콘솔창에 출력해보는 것이 좋다,

- 이때 이건 콘솔창에서만 출력되고 브라우저 출력이 아니므로 ajax() 로 요청한 곳에 돌려주는 값이 아님

- DAO 클래스 안의 memberAuth() 메소드를 사용하기 위해 DAO 객체 생성 후 memberAuth(id) 호출한 후 리턴값을 받음

- ajax() 에 돌려주고 싶은 값은 브라우저에 출력하면 된다 (out 객체 또는 표현식 태그로 출력)

+ member.js 에서 1을 받으면 중복ID 라는 표시를 div 태그에 띄움

 

- 이제 memberform.html 을 실행 후 ID 중복검사를 실행해보자

 

+ 크롬은 히스토리 기능때문에 바로 반영이 되지 않음

- 히스토리 삭제 후 실행

 

- 결과 캡처

- 중복 ID 입력시

- 사용가능한 ID 입력시

 

회원관리 프로그램 : 로그인 기능

- 폼인 loginform.html 에서 넘어온 아이디와 비밀번호를 login.jsp 가 받을 것

- loginform.jsp 파일 대신 loginform.html 파일 사용

 

- loginform.html 파일을 먼저 보자

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 폼</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>

<!-- 외부 자바스크립트 파일 불러오기 -->
<script src="login.js"></script>

</head>
<body>

<form method="post" action="login.jsp">
<table border=1 width=350 align=center>
	<caption>로그인</caption>
	<tr>
		<td>ID</td> 
		<td><input type=text size=30 autofocus="autofocus" name="id" id="id"></td>
	</tr>
	<tr>
		<td>비밀번호</td>
		<td><input type=password size=30 name="passwd" id="passwd"></td>
	</tr>
	<tr>
		<td colspan=2 align=center>
			<!-- <button>Login</button> -->			    <!-- 전송기능 버튼 -->
			<!-- <button type=submit>Login</button>  --><!-- 전송기능 버튼 -->
			<!-- <button type=button>Login</button> --> <!-- 버튼 -->
			
			<!-- <input type=button value="login"> -->  <!-- 버튼 -->
			
			<input type=submit value="로그인">   <!-- 전송기능 버튼 -->
			<input type=reset value="취소">      <!-- 초기화 버튼 -->
		</td>
	</tr>

</table>
</form>

</body>
</html>

- form 을 통해 login.jsp 로 로그인폼에 입력한 아이디와 비밀번호를 전달

 

- login.jsp 파일은 이전에 만들었고, 단순히 전달받은 아이디와 비밀번호를 출력만 했다

- 1, 2라인 제외 지우고 이제 action tag 들을 사용해서 DTO 객체를 만들고 id, passwd 값을 객체에 저장하자

- login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="member.MemberDAO"%>

<%
	request.setCharacterEncoding("utf-8");
%>

<jsp:useBean id="member" class="member.MemberDTO"></jsp:useBean>
<jsp:setProperty property="*" name="member"/>

<%
	MemberDAO dao = MemberDAO.getInstance();
	int result = dao.memberCheck(member);	// 회원인증 처리
	
	if(result == 1) {	// 회원인증 성공
		session.setAttribute("id", member.getId());	// 세션으로 공유 설정
%>
	<script>
		alert("로그인 성공");
		location.href = "main.jsp";
	</script>
<%	} else { 			// 회원인증 실패 %>		
	<script>
		alert("로그인 실패");
		history.go(-1);
	</script>
<%	}			%>

1. 한글값이 post 방식으로 넘어오므로 한글 인코딩

2. DTO 객체만들기 위해 useBean action tag 사용, 아이디, 비번을 객체에 저장하기 위해 setProperty action tag 사용

3. 회원 인증을 해줄 DAO 메소드 memberCheck() 호출해서 사용할것이므로 DAO 객체 생성, DTO 객체 전달

- 회원 인증 : 로그인 폼에 입력한 아이디 비번과, DB 의 아이디 비번이 같아야함

4. 그 메소드에서 인증에 성공시 1을 리턴하게 할것이므로, result 가 1 인경우 세션으로 id 값을 공유 설정함

- 경우는 2가지 뿐이다, <일치, 불일치> 그러므로 메소드에서 int형 으로 리턴하게한다

- 로그인에 성공시, 여기서부터 세션 시작된것

- 이제부터는 로그인 되어있는 동안 id 값을 넘기지 않아도 된다

5. 이후 로그인 성공/실패 메세지 등을 처리함

 

- 이제 DAO 클래스 안에 memberCheck() 메소드 생성

 

DAO 클래스 회원 인증 기능 작성 (로그인)

- DAO 클래스에서 memberCheck() 메소드를 작성해야한다

- MemberDAO.java (추가)

// DAO (Data Access Object)

package member;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

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();		
	}
	
	// ID 중복 검사
	public int memberAuth(String id) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			con = getConnection();	// 커넥션 풀에서 커넥션을 구해옴
			
			String sql = "select * from member where id=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, id);
			
			rs = pstmt.executeQuery();	// SQL문 실행
			
			if(rs.next()) {	// 조건식을 만족하는 데이터를 구해옴
				result = 1;
			}
			
		} catch(Exception e) {
			
		} finally {
			if(rs != null) try { rs.close();} catch(Exception e) {}
			if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
			if(con != null) try { con.close();} catch(Exception e) {}			
		}
		
		return result;
	}
	
	
	// 회원 가입
	public int insert(MemberDTO member) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		
		try {
			con = getConnection();	// 커넥션풀에서 커넥션을 구해온다
			
			String sql = "insert into member ";
			sql += " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,sysdate)";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			pstmt.setString(2, member.getPasswd());
			pstmt.setString(3, member.getName());
			pstmt.setString(4, member.getJumin1());
			pstmt.setString(5, member.getJumin2());
			pstmt.setString(6, member.getMailid());
			pstmt.setString(7, member.getDomain());
			pstmt.setString(8, member.getTel1());
			pstmt.setString(9, member.getTel2());
			pstmt.setString(10, member.getTel3());
			pstmt.setString(11, member.getPhone1());
			pstmt.setString(12, member.getPhone2());
			pstmt.setString(13, member.getPhone3());
			pstmt.setString(14, member.getPost());
			pstmt.setString(15, member.getAddress());
			pstmt.setString(16, member.getGender());
			pstmt.setString(17, member.getHobby());
			pstmt.setString(18, member.getIntro());
			
			result = pstmt.executeUpdate();		// SQL문 실행
			
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
			if(con != null) try { con.close();} catch(Exception e) {}
		}
		
		return result;
	}
	
	// 로그인
	public int memberCheck (MemberDTO member) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			con = getConnection();	// 커넥션풀에서 커넥션을 구해온다
			
			String sql = "select * from member where id=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			rs = pstmt.executeQuery();	// SQL문 실행
			
			if(rs.next()) {			// ID 일치
				if(rs.getString("passwd").equals(member.getPasswd())) {
					result = 1;		// ID, 비번 일치 (회원인증 성공)
				} else {
					result = -1;	// 비번 불일치
				}
			} else {				// ID 불일치
					result = -2;
			}
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(rs != null) try { rs.close();} catch(Exception e) {}
			if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
			if(con != null) try { con.close();} catch(Exception e) {}					
		}
		
		return result;
	}
	
}

- 추가된 회원 인증 부분만 코드

<memberCheck() 메소드 형식 작성>

- JSP 파일에서 이 DAO 로 접근하므로 public 이어야한다

- 매개변수로 넘어온 DTO 객체에 저장된 아이디와 비번 으로 DB 의 테이블에서 검색해야하므로 매개변수 자료형은 DTO

- int 를 리턴자료형으로 해서 일치인지 불일치인지만 반환하자

<memberCheck() 메소드 내용 작성>

1. Connection, PreparedStatement, ResultSet 객체를 try-catch문 위에 작성해서 try 와 finally 에서도 사용가능하도록 함

- select SQL 문을 사용하므로 ResultSet 객체가 있어야한다

2. 커넥션 풀을 통해서 커넥션을 구해오는 코드는 같은 DAO 클래스 내 getConnection() 메소드에 있으므로 try 내에서 호출

- getConnection() 으로 커넥션을 구해서 Connection 객체인 con 에 저장했다

+ 같은 클래스의 메소드이므로 메소드명만 작성

3. select 하는 SQL문을 작성하면서 매개변수로 넘어온 객체의 id 값을 where 절에 넣어서 검색을 한다

4. sql문을 읽어와서 Connection 객체 con 을 통해 PreparedStatement 객체 생성

5. varchar2 이므로 setString() 으로 ? 에 값 설정

6. select sql 문을 executeQuery() 로 실행하고, 결과는 result 변수로 받음

7. rs.next() 가 true 이면 값을 가져왔다는 의미이고, 즉 DB 에 있는 id 와 일치한다는 의미이므로 if문 안에서 비밀번호 비교

- 아이디 일치시 안에서 또 if-else문을 만들어서 DB 검색결과의 비밀번호와 사용자가 입력한 비밀번호가 일치하는지 확인

1) 아이디가 일치할때, 비번 일치시 result = 1 으로 설정, 비번 불일치시 result = -1 으로 설정

2) 아이디도 일치하지 않았을땐 result = -2 로 설정

- 여기선 구체적으로 result 값을 지정하지만 result = -1 , result = -2 코드는 없는게 좋음

- '아이디가 틀렸습니다' '비밀번호가 틀렸습니다' 알려주는 것은 보안상 좋지 못함, '잘못된 정보입니다' 라고 보통 알림

8. finally 에서 ResultSet 객체 rs 닫고, PreparedStatemet 객체 pstmt 를 닫고, Connection 객체 con 을 닫기

 

+ DAO 클래스에 회원 인증(로그인) 기능 구현 완료, 나머지 기능을 추가할 것

 

- loginform.html 파일 실행해서 로그인(회원인증) 잘 구현되었는지 확인

- 맞는 아이디, 비밀번호 입력시

- main.jsp 가 아직 없어서 에러

- 잘못된 아이디, 비번 입력시

 

세션 유무(로그인 성공 유무) 에 따라 다른 화면 보여주기

- 로그인 성공시 main.jsp 파일로 넘어간다

- login.jsp 에서 로그인 성공시 세션을 설정했으므로 id 를 넘겨받을 필요 없이 설정된 세션에서 id 값 가져오기

- main.jsp 에서는 세션값이 있냐 없냐에 따라 다른 화면을 보여주기

- 세션값이 있는 경우 정상 로그인으로 판단하여 회원탈퇴등의 메뉴 나타나게 만들고

- 세션값이 없는 경우 로그인, 회원가입 메뉴가 나타나도록 만들기

 

- main.jsp 를 생성하고 작성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
	String id = (String) session.getAttribute("id");
	if(id != null) {	// 세션이 있는 경우 (정상적인 로그인)
%>
		<%=id %>님 환영합니다. <br><br><br>
		
		<a href="updateform.jsp">정보수정</a> <br>
		<a href="logout.jsp">로그아웃 </a> <br>
		회원탈퇴 <br>
<%	} else { 			// 세션이 없는 경우 %>			
		<a href="memberform.html">회원가입</a> <br>
		<a href="loginform.html">로그인</a> <br>
<%	}	%>

- session.getAttribute("id") 로 세션을 구해온다

- getAttribute() 메소드는 리턴자료형이 Object 이므로 원래 값의 자료형이었던 String 으로 다운캐스팅해야함

- id 값이 null 이 아닌경우는 세션이 있는 경우, null 인 경우는 세션이 없는 경우이다, if-else 문 처리

- 로그인 전엔 세션이 없다.

- 세션 유무에 따라 다른 화면을 보여준다

- 틀린 비밀번호를 입력했을때는 memberCheck() 과 login.jsp 로 처리하는 것이고, 여기는 세션이 없다는 뜻으로, 로그인이 아예 되어있지 않은상태이다

ex) 로그인을 아직 시도하지 않았을때

- 회원가입, 로그인은 각각의 폼으로 a 태그 링크를 걸고, 나머지 정보수정, 로그아웃, 회원탈퇴는 나중에 기능 구현 후 링크를 걸 것

 

- main.jsp 를 그냥 실행시 세션값이 없으므로 회원가입, 로그인 이 뜬다 

- loginform.jsp 에서 정상적으로 로그인 해야 정보수정, 로그아웃, 회원탈퇴 메뉴가 뜬다

 

회원관리 프로그램 : 로그아웃 기능

- 이제 로그아웃 기능을 구현하자

- 로그아웃 기능 구현은 이 두가지를 하면 됨

1. 세션 삭제 해서 연결 끊기

2. 로그아웃되었다는 메세지를 뿌리고, 로그인 페이지로 돌아가기

 

- logout.jsp 생성 후 작성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%	// 세션 삭제 : 서버와 클라이언트의 연결이 끊어짐
	session.invalidate();
%>

<script>
	alert("로그아웃");
	location.href = "loginform.html";
</script>

1. invalidate() 로 강제로 연결을 끊음

- 세션 삭제 : 서버와 클라이언트의 연결이 끊김

- 브라우저를 닫지 않아도 연결이 끊긴다

2. 로그아웃 메세지 뿌리고 '확인' 누르면 로그인 폼으로 돌아가기

 

- 로그인 폼에서 로그인을 하고 메인으로 간 다음 로그아웃을 해보자

 

회원관리 프로그램 : 정보수정 기능

- 정보수정 기능을 구현하자

- 정보수정 기능 구현 전에 수정폼 부터 구현해야한다

- updateform.jsp 파일에서 시작

- updateform.jsp 파일을 생성하고 memberform.html 의 내용을 그대로 복붙

- updateform.jsp 파일의 1, 2 라인은 남겨놓고 나머지 내용은 memberform.html 을 그대로 넣자

- 실행시 이렇게 회원 가입폼과 같아진다

- 이 폼에서 회원의 기본정보 ID 를 채워지면 회원 정보 폼과 유사해짐

- updateform.jsp 파일로 넘어올때 아무 값도 넘어오지 않았다

- 세션값으로 id 를 구해오면 된다

- 다음으로 세션으로 구한 이 id 를 가지고 DB 와 연결해서 한 사람의 모든 상세정보를 구해와야함

- DAO 의 한사람의 상세 정보를 구하는 메소드를 호출할 것이므로 DAO 객체를 만들기

- 그리고 select sql 문을 사용하는 메소드이므로 리턴자료형으로 돌려받아야함, 여기선 한사람의 상세정보이므로 List 가 아닌 DTO 자료형으로 리턴받으면 됨

- 이제 DAO 클래스에서 메소드 getMember() 를 만들자

 

DAO 클래스 수정폼에서 회원 상세정보 구하기

- MemberDAO.java (추가)

// DAO (Data Access Object)

package member;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

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();		
	}
	
	// ID 중복 검사
	public int memberAuth(String id) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			con = getConnection();	// 커넥션 풀에서 커넥션을 구해옴
			
			String sql = "select * from member where id=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, id);
			
			rs = pstmt.executeQuery();	// SQL문 실행
			
			if(rs.next()) {	// 조건식을 만족하는 데이터를 구해옴
				result = 1;
			}
			
		} catch(Exception e) {
			
		} finally {
			if(rs != null) try { rs.close();} catch(Exception e) {}
			if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
			if(con != null) try { con.close();} catch(Exception e) {}			
		}
		
		return result;
	}
	
	
	// 회원 가입
	public int insert(MemberDTO member) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		
		try {
			con = getConnection();	// 커넥션풀에서 커넥션을 구해온다
			
			String sql = "insert into member ";
			sql += " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,sysdate)";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			pstmt.setString(2, member.getPasswd());
			pstmt.setString(3, member.getName());
			pstmt.setString(4, member.getJumin1());
			pstmt.setString(5, member.getJumin2());
			pstmt.setString(6, member.getMailid());
			pstmt.setString(7, member.getDomain());
			pstmt.setString(8, member.getTel1());
			pstmt.setString(9, member.getTel2());
			pstmt.setString(10, member.getTel3());
			pstmt.setString(11, member.getPhone1());
			pstmt.setString(12, member.getPhone2());
			pstmt.setString(13, member.getPhone3());
			pstmt.setString(14, member.getPost());
			pstmt.setString(15, member.getAddress());
			pstmt.setString(16, member.getGender());
			pstmt.setString(17, member.getHobby());
			pstmt.setString(18, member.getIntro());
			
			result = pstmt.executeUpdate();		// SQL문 실행
			
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
			if(con != null) try { con.close();} catch(Exception e) {}
		}
		
		return result;
	}
	
	// 로그인
	public int memberCheck (MemberDTO member) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			con = getConnection();	// 커넥션풀에서 커넥션을 구해온다
			
			String sql = "select * from member where id=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			rs = pstmt.executeQuery();	// SQL문 실행
			
			if(rs.next()) {			// ID 일치
				if(rs.getString("passwd").equals(member.getPasswd())) {
					result = 1;		// ID, 비번 일치 (회원인증 성공)
				} else {
					result = -1;	// 비번 불일치
				}
			} else {				// ID 불일치
					result = -2;
			}			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(rs != null) try { rs.close();} catch(Exception e) {}
			if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
			if(con != null) try { con.close();} catch(Exception e) {}				
		}
		
		return result;
	}
	// 회원 수정폼 : 한 사람의 상세정보 구하기
	public MemberDTO getMember(String id) {
		MemberDTO member = new MemberDTO();
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			con = getConnection();	// 커넥션풀에서 커넥션을 구해온다
			
			String sql = "select * from member where id=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, id);
			rs = pstmt.executeQuery();	// SQL문 실행
			
			if(rs.next()) {
//				member.id = "test";	// 접근 안됨(private 접근제어자)
				member.setId(rs.getString("id"));
				member.setPasswd(rs.getString("passwd"));
				member.setName(rs.getString("name"));
				member.setJumin1(rs.getString("jumin1"));
				member.setJumin2(rs.getString("jumin2"));
				member.setMailid(rs.getString("mailid"));
				member.setDomain(rs.getString("domain"));
				member.setTel1(rs.getString("tel1"));
				member.setTel2(rs.getString("tel2"));
				member.setTel3(rs.getString("tel3"));
				member.setPhone1(rs.getString("phone1"));
				member.setPhone2(rs.getString("phone2"));
				member.setPhone3(rs.getString("phone3"));
				member.setPost(rs.getString("post"));
				member.setAddress(rs.getString("address"));
				member.setGender(rs.getString("gender"));
				member.setHobby(rs.getString("hobby"));
				member.setIntro(rs.getString("intro"));
				member.setRegister(rs.getTimestamp("register"));
			}
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(rs != null) try { rs.close();} catch(Exception e) {}
			if(pstmt != null) try { pstmt.close();} catch(Exception e) {}
			if(con != null) try { con.close();} catch(Exception e) {}				
		}
		return member;
	}
}

<getMember() 메소드 형식 작성>

- id 에 해당하는 1명의 상세정보를 구하는 것이므로 매개변수로 id 를 넘기고 DTO 클래스로 리턴한다

- 위에서 DTO 객체를 생성하고 거기에 내용을 담아서 반환해야함

<getMember() 메소드 내용 작성>

1. Connection, PreparedStatement, ResultSet 객체를 try-catch문 위에 작성해서 try 와 finally 에서도 사용가능하도록 함

- select SQL 문으로 1명 정보를 구해오므로 ResultSet 객체가 있어야한다

2. 커넥션 풀을 통해서 커넥션을 구해오는 코드는 같은 DAO 클래스 내 getConnection() 메소드에 있으므로 try 내에서 호출

- getConnection() 으로 커넥션을 구해서 Connection 객체인 con 에 저장했다

+ 같은 클래스의 메소드이므로 메소드명만 작성

3. select 하는 SQL문을 작성하면서 매개변수로 넘어온 id 를 where 절에 넣어서 해당하는 사람을 검색 한다

4. sql문을 읽어와서 Connection 객체 con 을 통해 PreparedStatement 객체 생성

5. id 컬럼은 varchar2 이므로 setString() 으로 ? 에 값 설정

6. select sql 문을 executeQuery() 로 실행하고, 결과는 result 변수로 받음

7. rs.next() 에서 가져온 데이터가 있으면, 그 데이터를 가져와서 DTO 객체 member의 프로퍼티들에 저장하기

- 데이터 1개이므로 if 문 사용

8. Setter 메소드로 DTO 객체 member 의 프로퍼티에 값들을 rs.getString(컬럼명) 으로 가져와서 저장

- member.id = XX 는 접근제어자가 private 이라서 안되므로 Setter 메소드로 값을 할당해야함

+ 나중에 MyBatis 등을 쓰면 setter 메소드 코드로 인해 길어진 코드를 줄일 수 있다

+ 이때 rs.getString('hobby") 는 하이픈으로 연결된 값

+ register 는 timestamp 형이므로 rs 에서 getTimestamp() 로 가져와야한다

9. finally 에서 ResultSet 객체 rs 닫고, PreparedStatemet 객체 pstmt 를 닫고, Connection 객체 con 을 닫기

 

+ DAO 클래스에 수정폼에서 회원 상세정보를 구해오는 기능 구현 완료, 나머지 기능을 추가할 것

 

- updateform.jsp (이어서)

- 상세정보를 구하는 DAO 클래스의 메소드 작성 후 다시 updateform.jsp 로 돌아와서 리턴받은 값을 화면에 뿌려주자

- 취미 같은 경우는 하이픈이 이어진 상태이므로 split() 으로 파싱하고 가공해서 체크표시가 되어있게끔 할것

- 먼저 리턴받은 DTO 객체인 member 에서 getHobby() 로 '공부-게임-' 같은 값을 가져온 후 - 로 파싱해서 String 배열인 h 에 저장

 

- form 태그의 action 값을 update.jsp 로 수정

+ 테이블 태그의 캡션값도 '회원 수정 폼' 으로 바꾸기

- 회원 수정폼이므로 ID 값은 수정하지 못하도록 입력양식을 지우고 출력만 시킴

 

- 그 다음 비밀번호가 맞는 경우만 수정할 수 있도록 비밀번호의 입력폼은 그대로 둠, value 설정 안함

- 성명 에는 성명이 출력되도록 value 속성으로 출력

 

- 비밀번호 제외하고 나머지도 성명과 같은 방식으로 value 값 설정

- updateform.jsp 부분 코드

 

예외

- textarea 는 value 속성이 없기때문에 textarea 태그 사이 내용에 설정해야만 내용이 textarea 에 나타남

1.휴대폰 번호 앞자리는 value 값 설정을 다른방식으로 해야한다

2. 라디오버튼인 성별 처리

3. 체크박스인 취미 처리

- 이 3가지를 수정폼에 나타나게 하는 처리가 복잡하다

 

1. 휴대폰 번호 앞자리 처리

- 양식은 select 이다

- 사용자가 가입시 010 을 선택했다면, 여기 수정폼에서 010 이 선택된 상태로 만들어야한다

- phone1 컬럼의 값 010 과 select 의 010 과 같으면 선택되도록 만듬

- phone1 컬럼의 값 011 과 select 의 011 이 같으면 선택되도록 만듬, ...

- select-option 에서 사용자의 휴대폰 앞자리번호와 같은지 if 문으로 확인

- 이런 방식으로 처리한다

+ <%="selected" %> 대신 그냥 selected 로 해도 된다,

+ <%="selected"%> 는 출력을 하는 거지만 option 태그 안에서 출력이므로 선택이 되는 것임

+ 그냥 selected 라고 해도 적히므로 그냥 selected 로 적어도 된다

 

- 010 뿐 아니라 나머지 휴대폰 앞자리도 마찬가지로 처리

 

2. 라디오버튼인 성별 처리

- 휴대폰 앞자리와 비슷하게 조건문을 써서 사용자가 가입시 입력한 성별과 일치하면 chekced

- 라디오버튼은 selected 대신 checked 되면 체크된 상태로 나타남

 

3. 체크박스인 취미 처리

- 앞의 휴대폰 앞자리와 라디오버튼처럼 일일히 조건문으로 검사하지 않고 jQuery 로 처리하면 간결하게 처리 가능

+ 취미는 가입시 2개이상 선택하도록 만들어졌다

- 취미를 위쪽에서 파싱해서 String 배열인 h 에 저장해뒀다

ex) h 배열의 취미를 하나씩 가져오는데 만약 '공부' 와 '게임' 이인 경우

- input 이 checkbox 인걸 구해오는데 name 이 hobby 인것 5개 중 value 값이 '공부' 인것만 구해와서 체크해라

- input 이 checkbox 인걸 구해오는데 name 이 hobby 인것 5개 중 value 값이 '게임' 인것만 구해와서 체크해라

 

- updateform.jsp 에 추가할 것들이 있다

- updateform.jsp 에서 id 가 넘어가지 않으므로 hidden 으로 넘겨주자
+ 넘겨야 update.jsp 에서 update 할때 id 로 update 를 할 수 있다 (지금은 update 가 아니라 업데이트폼을 하고 있다)

+ id를 세션으로 구해도 되지만 form 으로 전송하는 김에 한번에 전송

 

- updateform.jsp 전체 코드

<%@page import="member.MemberDAO"%>
<%@page import="member.MemberDTO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<%
	String id = (String) session.getAttribute("id");

	MemberDAO dao = MemberDAO.getInstance();
	
	// 한 사람의 상세정보 구해오기
	MemberDTO member = dao.getMember(id);
	
	// h[0]="공부", h[1]="게임", h[2]="등산"...
	String[] h = member.getHobby().split("-");
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 수정 폼</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>

<script src="http://dmaps.daum.net/map_js_init/postcode.v2.js"></script>
<script>
	function openDaumPostcode() {
		new daum.Postcode({
			oncomplete : function(data) {
				// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
				// 우편번호와 주소 정보를 해당 필드에 넣고, 커서를 상세주소 필드로 이동한다.
//				document.getElementById('join_zip1').value = data.postcode1;
				document.getElementById('post').value = data.zonecode;
				document.getElementById('address').value = data.address;
				
			}
		}).open();
	}
</script>

<!-- 외부 자바스크립트 파일 불러오기 -->
<script src="member.js"></script>

<script>
$(document).ready(function(){
	<% for(String s : h) { %>
		$("input:checkbox[name='hobby'][value='<%=s%>']").attr("checked",true);
	<% } %>
});
</script>

</head>
<body>

<form method="post" action="update.jsp"> 
<input type="hidden" name="id" value="<%=member.getId() %>">
<table border=1 width=450 align="center">
	<caption>회원 수정 폼</caption>
	<tr><td>ID</td>
		<td><%=member.getId() %></td>
	</tr>
	<tr><td>비밀번호</td>
		<td><input type=password id="passwd" name="passwd">
		</td>
	</tr>
	<tr><td>성명</td>
		<td><input type=text id="name" name="name" value="<%=member.getName()%>"></td>
	</tr>
	<tr><td>주민번호</td>
		<td><input type=text size=6 maxlength=6 id="jumin1" 
		name="jumin1" value="<%=member.getJumin1()%>">-
			<input type=text size=7 maxlength=7 id="jumin2" 
		name="jumin2" value="<%=member.getJumin2()%>">
		</td>
	</tr>
	<tr><td>E-Mail</td>
		<td><input type=text size=10 id="mailid" 
		name="mailid" value="<%=member.getId()%>">@
			<input type=text size=10 id="domain" 
		name="domain" value="<%=member.getDomain()%>">
			<select id="email">
				<option value="">직접입력</option>
				<option value="naver.com">네이버</option>
				<option value="daum.net">다음</option>
				<option value="nate.com">네이트</option>
				<option value="gmail.com">gmail</option>
			</select>	
		</td>
	</tr>
	<tr><td>전화번호</td>
		<td><input type=text size=4 maxlength=4 id="tel1" 
			name="tel1" value="<%=member.getTel1() %>">-
		    <input type=text size=4 maxlength=4 id="tel2" 
		  	name="tel2" value="<%=member.getTel2() %>">-
		    <input type=text size=4 maxlength=4 id="tel3" 
		    name="tel3" value="<%=member.getTel3() %>">-
		</td>
	</tr>
	<tr><td>핸드폰</td>
		<td><select id="phone1" name="phone1">
				<option value="">번호선택</option>
				
				<option value="010"
					<%if(member.getPhone1().equals("010")) { %>
						<%="selected" %>
					<%} %>>010</option>
					
				<option value="011"
					<%if(member.getPhone1().equals("011")) { %>
						<%="selected" %>
					<%} %>>011</option>
					
				<option value="016"
					<%if(member.getPhone1().equals("016")) { %>
						<%="selected" %>
					<%} %>>016</option>
					
				<option value="018"
					<%if(member.getPhone1().equals("018")) { %>
						<%="selected" %>
					<%} %>>018</option>
				
				<option value="019"
					<%if(member.getPhone1().equals("019")) { %>
						<%="selected" %>
					<%} %>>019</option>
				
			</select>-
			<input type=text size=4 maxlength=4 id="phone2" 
			name="phone2" value="<%=member.getPhone2()%>">-
		    <input type=text size=4 maxlength=4 id="phone3" 
		    name="phone3" value="<%=member.getPhone3()%>">		
		</td>	
	</tr>
	<tr><td>우편번호</td>
		<td><input type=text size=5 maxlength=5 id="post" 
		name="post" value="<%=member.getPost()%>">
			<input type=button value="우편검색" onClick="openDaumPostcode()">
		</td>
	</tr>
	<tr><td>주소</td>
		<td><input type=text size=45 id="address" 
		name="address" value="<%=member.getAddress()%>"></td>
	</tr>
	<tr><td>성별</td>
		<td><input type=radio id="male" name="gender" value="남자"
			<%if(member.getGender().equals("남자")){ %>
				<%="checked" %>
			<%} %>>남자
		
			<input type=radio id="female" name="gender" value="여자"
			<%if(member.getGender().equals("여자")){ %>
				<%="checked" %>
			<%} %>>여자
		</td>
	</tr>
	<tr><td>취미</td>
		<td><input type=checkbox id="h1" name="hobby" value="공부">공부
			<input type=checkbox id="h2" name="hobby" value="게임">게임
			<input type=checkbox id="h3" name="hobby" value="등산">등산
			<input type=checkbox id="h4" name="hobby" value="낚시">낚시
			<input type=checkbox id="h5" name="hobby" value="쇼핑">쇼핑
		</td>
	</tr>
	<tr><td>자기소개</td>
		<td><textarea rows=5 cols=50 id="intro" name="intro"
		     placeholder="자기소개를 100자 이내로 입력하세요"><%=member.getIntro() %></textarea>		
		</td>
	</tr>
	<tr><td colspan=2 align=center>
			<input type=submit value="회원수정">
			<input type=reset value="취소">
		</td>
	</tr>		
</table>
</form>

</body>
</html>

- 로그인 폼에서 로그인 하고 '정보수정' 을 눌렀을때 나타나는 완성된 수정 폼 캡처

 

복습

DTO

- 자바빈의 프로퍼티명과 테이블의 컬럼명, 폼에서 넘어온 name 값을 일치시켜야 한다

DAO

- DAO 에는 싱글톤이 들어가고 나머지는 메소드로 구성됨

- 검색된 결과를 DTO 객체 생성해서 전송

 

DAO 클래스로 DB 연동 예제 1

1. 실습 준비 및 테이블 생성

+ DAO / DTO 클래스가 없어서 생기는 오류

- JSP 파일들은 다 있고 필요한 아래의 테이블을 먼저 생성해야함

create  table  member2( 
			id varchar2(12) primary key,
			passwd varchar2(12) not null,
			name varchar2(10) not null,
			jumin1 varchar2(6) not null,
			jumin2 varchar2(7) not null,
			email varchar2(30),
			blog varchar2(50),
			reg_date date not null);

+ 숫자더라도 값의 변화가 자주 일어나지 않는 값은 varchar2 타입으로 처리하는게 좋다

+ 주민번호는 자주 바뀌지 않으므로 숫자지만 문자형인 varchar2 로 처리 

+ 값의 변화가 자주 일어나는 값은 number 타입으로 처리 ex) 조회수는 자주바뀌므로 숫자데이터로 처리

- sql/myoracle.sql 에서 테이블 생성 완료

 

- 이제 DAO, DTO 클래스 만들 것

- DAO / DTO 클래스 이 패키지로 만들기

 

2. DTO / DAO 클래스 만들기

JavaBeanMember.register - LogonDataBean.java (DTO)
JavaBeanMember.register - LogonDBBean.java (DAO)

+ Model 2 에선 DAO 클래스와 DTO 클래스가 다른 패키지에 있다

+ 지금 Model  1 에선 같은 패키지에 넣어서 import 할 필요없이 만듬

- JavaBeanMember.register 패키지 먼저 생성 후 class 자바 파일 만들기

 

3. DTO 클래스 만들기

- 오라클의 자료형을 자바의 자료형으로 가져온다

- 접근제어자는 private, varchar2 는 String, number 는 int 로, date 는 Date로 변경

- getter setter 메소드 추가

- DTO 클래스 완성

- LogonDataBean.java

// DTO (Data Transfer Object)
package JavaBeanMember.register;
import java.util.Date;

public class LogonDataBean {

	private String id;	// 프로퍼티
	private String passwd;
	private String name;
	private String jumin1;
	private String jumin2;
	private String email;
	private String blog;
	private Date reg_date;
	
	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 getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getBlog() {
		return blog;
	}
	public void setBlog(String blog) {
		this.blog = blog;
	}
	public Date getReg_date() {
		return reg_date;
	}
	public void setReg_date(Date reg_date) {
		this.reg_date = reg_date;
	}
	
}

 

4. DAO 클래스 만들기

- DB 연동은 이제 모두 DAO 클래스에서 처리

- 메소드만으로 구성

- JSP 에서 DAO 의 메소드를 호출해서 sql 문 실행

- Singleton 사용해서 객체 생성 1번만 수행해서 공유함

- 객체를 생성하자

- static 을 붙여서 공유, 외부에서 접근 못하도록 private 설정, 정적메소드인 getInstance() 를 통해서만 접근 가능

- getInstance() 메소드 만들기

- 이제 이 아래에 메소드를 생성함

- getInstance() 메소드의 리턴자료형이 해당 클래스명임, 리턴되는 값은 위에서 만들어진 인스턴스(객체)

- public 접근제어자 이므로 다른 폴더에 있는 JSP 파일에서 호출 가능한 메소드

- 그 메소드를 JSP 에서 호출 (registerPro.jsp 부분)

 

- 이 DAO 클래스는 싱글톤 외 나머지는 메소드로 구성된다


DAO 클래스로 DB 연동 예제 1 (이어서)

4. DAO 클래스 만들기 (이어서)

- 이제 DAO 클래스에 나머지 메소드를 추가해보자

- 폼과 다른 코드를 먼저 보고 어떤 메소드가 필요한지 확인

 

- registerForm.jsp (회원가입 양식)

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ include file="color.jsp" %>

<html>
<head>
	<title>회원가입</title>
	<link href="style.css" rel="stylesheet" type="text/css">
	<script language="JavaScript" src="script.js"></script>
</head>

<body bgcolor="<%=bodyback_c%>">
  <form name="regForm" method="post" action="registerPro.jsp" onsubmit="return inputCheck()">
    <table width="500" border="0" cellspacing="0" cellpadding="2"  align="center">
      <tr height="39" align="center" bgcolor="<%=title_c%>"> 
         <td colspan="3"><b>회원 가입</b></font></td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">아이디</td>
        <td width="200" bgcolor="<%=value_c%>"> 
		  <input type="text" name="id" size="20"> </td>
        <td width="200" bgcolor="<%=value_c%>">아이디를 입력하세요.</td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">비밀번호</td> 
        <td width="200" bgcolor="<%=value_c%>"> 
	      <input type="password" name="passwd" size="20"> </td>
      <td width="200" bgcolor="<%=value_c%>">비밀번호를 입력하세요</td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">비밀번호 확인</td>
        <td width="200" bgcolor="<%=value_c%>"> 
		  <input type="password" name="repasswd" size="20"> </td>
        <td width="200" bgcolor="<%=value_c%>">비밀번호를 재입력하세요.</td>
      </tr>
      <tr>  
        <td width="100" bgcolor="<%=title_c%>">이름</td>
        <td width="200" bgcolor="<%=value_c%>"> 
		  <input type="text" name="name" size="20"> </td>
        <td width="200" bgcolor="<%=value_c%>">이름을 입력하세요.</td>
      </tr>
      <tr>  
        <td width="100" bgcolor="<%=title_c%>">주민번호</td>
        <td width="200" bgcolor="<%=value_c%>"> 
		  <input type="text" name="jumin1" size="6" maxlength=6>-
		  <input type="text" name="jumin2" size="7" maxlength=7> </td>
        <td width="200" bgcolor="<%=value_c%>">주민번호를 입력하세요.</td>
      </tr>
      <tr> 
         <td width="100" bgcolor="<%=title_c%>">이메일</td>
         <td width="200" bgcolor="<%=value_c%>"> 
		   <input type="text" name="email" size="30"> </td>
         <td width="200" bgcolor="<%=value_c%>">이메일을 입력하세요.</td>
      </tr>
      <tr>  
         <td width="100" bgcolor="<%=title_c%>">블로그</td>
         <td width="200" bgcolor="<%=value_c%>"> 
		   <input type="text" name="blog" size="20"> </td>
         <td width="200" bgcolor="<%=value_c%>">블로그를 입력하세요.</td>
      </tr>
      <tr> 
         <td colspan="3" align="center"  bgcolor="<%=title_c%>"> 
           <input type="submit" value="회원가입" > 
              &nbsp; &nbsp; &nbsp; &nbsp;
           <input type="reset" value="다시작성"> 
         </td>
       </tr>
    </form>
  </table>
</body>
</html>

- 이 양식들의 name값은 DTO 클래스의 필드값과 같다, 같아야만 값이 DTO 로 전달되도록 설정해둠

- 비밀번호 name값인 passwd 는 DTO 클래스의 필드값과 같으므로 넘어가지만 비밀번호 확인의 name값인 repasswd 는 필드값과 같지 않으므로 넘어가지 않음

- DTO 클래스의 reg_date 필드는 가입폼에서 넘어가지 않음, 나중에 insert 수행시 sysdate 로 넣어주면 된다

- 가입시 입력한 정보들은 모두 registerPro.jsp 파일로 넘어간다

+ script.js 파일에서 유효성 검사

 

- registerPro.jsp

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="JavaBeanMember.register.LogonDataBean" %>
<%@ page import="JavaBeanMember.register.LogonDBBean" %>
<%@include file="color.jsp" %>

<% 
  request.setCharacterEncoding("euc-kr");

  LogonDataBean	regBean1 = new LogonDataBean();
//regBean1.id="test";
%>

<jsp:useBean id="regBean" class="JavaBeanMember.register.LogonDataBean" />
<jsp:setProperty name="regBean" property="*" />

<%
//	regBean.id="test";
%>


<%
	LogonDBBean manager = LogonDBBean.getInstance();
	int result=manager.insertMember(regBean);

	if(result==1){
%>	
	<script>
		alert("회원가입 성공");
		location.href="list.jsp";
	</script>
	
<% }else{%>

	<script>
		alert("회원가입 실패");
		history.go(-1);
	</script>

<% } %>


<%-- <html>
<head>
<title>회원가입 확인</title>
<link href="style.css" rel="stylesheet" type="text/css">
<script language="JavaScript" src="script.js"></script>
</head>

<body bgcolor="<%=bodyback_c%>">
    <table width="500" border="0" cellspacing="0" cellpadding="2"  align="center">
      <tr height="39" align="center" bgcolor="<%=title_c%>"> 
        <td colspan="2"><b>회원 가입 확인</b></td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">아이디</td>
        <td width="400" bgcolor="<%=value_c%>">
		  <jsp:getProperty name="regBean" property="id" /></td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">비밀번호</td>
        <td width="400" bgcolor="<%=value_c%>"> 
		  <jsp:getProperty name="regBean" property="passwd" /> </td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">이름</td>
        <td width="400" bgcolor="<%=value_c%>"> 
		  <jsp:getProperty name="regBean" property="name" /> </td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">이메일</td>
        <td width="400" bgcolor="<%=value_c%>"> 
		  <jsp:getProperty name="regBean" property="email" /> </td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">블로그</td>
        <td width="400" bgcolor="<%=value_c%>"> 
		  <jsp:getProperty name="regBean" property="blog" /> </td>
      </tr>
  </table>
</body>
</html> --%>

1. 폼을 통해 post 방식으로 한글값이 넘어가므로 인코딩

2. useBean action tag 로 폼에서 넘어온 데이터를 저장하기 위해 DTO 객체를 생성했다,

- class 속성에는 패키지부터 자바빈 클래스까지 이므로 JavaBeanMember.register.LoganDataBean 으로 설정

+ 위쪽에 자바빈 객체를 직접 생성하는 코드는 useBean action tag 와 같은 코드이다

3. setProperty action tag 로 그 DTO 객체인 regBean 의 프로퍼티에 폼에서 넘어온 name 값이 같은 모든 값을 저장함

+ repasswd 는 넘어가지 않는다, DTO 의 reg_date 가 비어있다

 

- 메모리상에 저장된 데이터는 안정적이지 않음, DTO 클래스만으로는 안정적이지 않다

- 안정적인 곳인 DB 에 저장하기위해 DAO 클래스의 메소드를 호출해서 메모리에 저장된 데이터를 DB 에 저장해아함

 

4. DAO 객체 생성 (registerPro.jsp 부분)

	LogonDBBean manager = LogonDBBean.getInstance();
	int result=manager.insertMember(regBean);

- new 연산자로 DAO 객체를 생성하지 않고, DAO 객체를 getInstance() 정적메소드를 통해 가져온다 (싱글톤)

+ 매번 new 연산자로 힙메모리상에 공간을 만들면 메모리 소요가 심함, 그래서 싱글톤 사용

- 가져온 객체를 manager 변수에 저장

- DAO 객체를 가져오는 이유 : DAO 의 메소드를 호출해서 SQL 문 수행을 위해서

- 그리고 메소드 insertMember() 메소드를 호출함, insert 할 데이터는 id, passwd 같은 값이 아니라 이들의 주솟값을 가지고 있는 스택의 DTO 객체인 regBean 를 전달함, 즉 주솟값을 전달하는 Call By Reference 방식 사용

- insert 된 데이터의 개수를 돌려받고 그걸로 성공여부 확인할 것

- 이 메소드 insertMember 를 DAO 클래스에 만들어야한다, public int insertMember(DTO ) 로 만들어야함

 

+ 직접 DAO 객체를 생성할땐 import 해야함

 

 

- DAO 클래스로 돌아가서 메소드를 만들자

 

DAO 클래스 만들기

1. DAO 에 가입 기능 메소드 만들기

- LogonDBBean.java

// DAO (Data Access Object)
package JavaBeanMember.register;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class LogonDBBean {
	
	// 싱글톤 : 객체 생성을 한번만 수행하는 것
	private static LogonDBBean instance = new LogonDBBean();
	
	public static LogonDBBean getInstance() {	// 정적 메소드
		return instance;
	}
	
	// 회원가입 : 주솟값 전달에 의한 메소드 호출  (Call By Reference 방식)
	public int insertMember(LogonDataBean member) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			// JDBC 방식
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "insert into member2 values(?,?,?,?,?,?,?,sysdate)";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			pstmt.setString(2, member.getPasswd());
			pstmt.setString(3, member.getName());
			pstmt.setString(4, member.getJumin1());
			pstmt.setString(5, member.getJumin2());
			pstmt.setString(6, member.getEmail());
			pstmt.setString(7, member.getBlog());
			
			result = pstmt.executeUpdate();	// SQL문 실행
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}
		}
		return result;
	}
}

<insertMember() 메소드 형식 작성>

- JSP 에서 접근할 수 있도록 메소드는 접근제어자를 모두 public 으로 만들어야한다, default 도 안됨

- 주솟값을 가진 객체인 DTO 객체가 매개변수로 오게끔 LogonDataBean 을 매개변수 자료형으로 적는다

+ 주솟값이 아니라 값을 전달한다면 10 개의 값이 있으면 10 개의 매개변수를 써야함

- insert 후에 insert 된 데이터 개수를 돌려주기 위해 리턴 자료형을 int 로 설정했다, 꼭 해야하는 것은 아님

- insert 외에도 update / delete 등도 비슷하게 작성

- select 는 검색 결과를 JSP 파일로 돌려줘야하므로 리턴 자료형을 다르게 설정한다.

<insertMember() 메소드 내용 작성>

1. Connection, PreparedStatement 객체 먼저 생성 후 Driver 위치를 driver 변수에, xe 데이터베이스 url 를 url 변수에 저장

2. try-catch 예외처리 후 오라클용 JDBC 드라이버를 로딩하기 위해 Class.forName() 사용, Connection 객체 구해오기

3. SQL문 작성시 테이블 구조를 보고 ? 몇개 할지 결정, ? 7개와 마지막은 sysdate 로 입력하면 된다

4. Connection 객체 con 을 이용해서 PreparedStatement 객체 생성

5. 자료형에 따라 값을 설정하는 메소드가 다르다, 여기선 varchar2 이므로 setString() 으로 ? 에 값 설정

6. 매개변수 member 를 통해 member.getXX() 로 메모리상에 저장된 값을 리턴받아서 setString() 으로 DB 에 넣기

- Java 에서 getProperty 는 사용 불가하므로 getXX() 로 직접 가져오기

7. insert SQL 문을 실행하기 위해 executeUpdate() 메소드 사용, 성공시 돌려주는 삽입된 데이터를 result 변수에 저장

- select 만 executeQuery(), 나머지 DML 은 executeUpdate() 사용

- insert 는 여러개 삽입이 거의 불가능하므로 return 되는 값은 주로 1

8. 각 객체가 null 이 아닌경우, try-catch 문에서 PreparedStatement 객체 pstmt 먼저 닫고 Conenction 객체 con 닫기

- null 값이 아닌 경우 = 해당 객체가 생성이 되었다면

9. 메소드의 마지막에 result 변수를 돌려주는 코드 작성

+ 이 아래에 다른 메소드도 추가할 것 (아직 DAO 미완성)

- 완성 후 회원가입 기능 되는지 확인

- 결과 캡처

- 성공시 이동하는 목록 페이지는 아직 구현되지 않았으므로 500 오류가 뜬다

- sql 파일에서 가입이 되었는지 확인해보자

- 가입이 되었음을 확인 가능하다, insert 기능 구현이 잘 되었다

 

DAO 클래스 만들기

2. DAO 에 전체 목록 확인 기능 메소드 만들기

- 회원 목록을 보기위해 목록을 보여주는 list.jsp 파일을 완성하자

- 이 파일에서 DAO 클래스의 select 하는 메소드를 불러옴

- list.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@ page import="JavaBeanMember.register.LogonDBBean" %>  
<%@ page import="JavaBeanMember.register.LogonDataBean" %>  
<%@ page import="java.util.*" %>
    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>회원 목록</title>
</head>
<body>
<a href="registerForm.jsp">회원가입</a>


<table align=center width=1000 border=1>
	<tr><td>ID</td> 
		<td>비밀번호</td>
		<td> 이름 </td>
		<td> 주민번호 </td>
		<td> 이메일 </td>
		<td> BLOG </td>
		<td> 가입일 </td>
		<td>수정</td>
		<td>삭제</td>
	</tr>

<%
LogonDBBean manager = LogonDBBean.getInstance();
List<LogonDataBean> li = manager.selectMember();


	for(int i = 0; i < li.size(); i++) {
		LogonDataBean db = (LogonDataBean)li.get(i);
%>

	<tr><td><%=db.getId()%></td>
		<td><%=db.getPasswd()%></td>
		<td><%=db.getName()%></td>
		<td><%=db.getJumin1()%> - <%=db.getJumin2()%> </td>
		<td><%=db.getEmail()%></td>
		<td><%=db.getBlog()%></td>
		<td><%=db.getReg_date()%></td>
		<td><a href="updateForm.jsp?id=<%=db.getId()%>">수정</a></td>
		<td><a href="deleteForm.jsp?id=<%=db.getId()%>">삭제</a></td>
	</tr>
<% 
	}
%>

</table>
</body>
</html>

- 타이틀값 출력 후 데이터를 가져와야함

- DAO 객체를 생성한다, getInstance() 정적메소드로 DAO 객체를 구해와서 manager 에 저장

+ DAO 객체 생성 위해 DAO 클래스를 import 해야한다

 

- 전체 회원목록을 구해오기위한 메소드 selectMember() 메소드를 호출한다

- 목록을 구하는 메소드이므로 매개변수가 필요없다

- 10명, 20명의 검색된 데이터 (전체 데이터) 를 받아오기 위해서 리턴을 List 로 받아야한다

- 1개 데이터 검색하여 받아올때는 DTO 클래스가 와야하고, 2개 이상의 데이터를 검색할땐 List 가 와야한다

- 제네릭을 사용하므로 List 의 get() 으로 데이터를 하나씩 구해올때 다운캐스팅 할 필요 없음

+ 리스트의 메소드인 get() 은 Object 형으로 리턴

 

- DAO 클래스에서 selectMember() 메소드를 작성해야함

- DAO 클래스로 돌아가자

- LogonDBBean.java (추가)

// DAO (Data Access Object)
package JavaBeanMember.register;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class LogonDBBean {
	
	// 싱글톤 : 객체 생성을 한번만 수행하는 것
	private static LogonDBBean instance = new LogonDBBean();
	
	public static LogonDBBean getInstance() {	// 정적 메소드
		return instance;
	}
	
	// 회원가입 : 주솟값 전달에 의한 메소드 호출  (Call By Reference 방식)
	public int insertMember(LogonDataBean member) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			// JDBC 방식
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "insert into member2 values(?,?,?,?,?,?,?,sysdate)";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			pstmt.setString(2, member.getPasswd());
			pstmt.setString(3, member.getName());
			pstmt.setString(4, member.getJumin1());
			pstmt.setString(5, member.getJumin2());
			pstmt.setString(6, member.getEmail());
			pstmt.setString(7, member.getBlog());
			
			result = pstmt.executeUpdate();	// SQL문 실행
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}
		}
		return result;
	}
	// 전체 회원목록 구하기
	public List<LogonDataBean> selectMember() {
		List<LogonDataBean> list = new ArrayList<LogonDataBean>();
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "select * from member2";
			
			pstmt = con.prepareStatement(sql);
			rs = pstmt.executeQuery();
			
			while(rs.next()) {	// 데이터를 1개씩 가져온다.
				LogonDataBean member = new LogonDataBean();
//				member.id = "totoro";	// 접근 안됨 (private 접근 제어자)
				member.setId(rs.getString("id"));
				member.setPasswd(rs.getString("passwd"));
				member.setName(rs.getString("name"));
				member.setJumin1(rs.getString("jumin1"));
				member.setJumin2(rs.getString("jumin2"));
				member.setEmail(rs.getString("email"));
				member.setBlog(rs.getString("blog"));
				member.setReg_date(rs.getDate("reg_date"));
				
				list.add(member);
			}
		} catch(Exception e) {
			
		} finally {
			if(rs != null) try { rs.close(); } catch(Exception e) {}
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}			
		}
		
		return list;
	}
}

<selectMember() 형식 작성>

- select sql 문을 수행하는 메소드인 경우에는 리턴 자료형이 반드시 있어야한다

- 이때 리턴 자료형으로, 한개의 데이터를 구하면 DTO 클래스가 자료형으로 오고, 2개 이상의 데이터를 구하면 List가 온다

- 메소드 내에서 List 객체 list 를 만들고 그걸 return 한다

<selectMember() 내용 작성>

1. Connection, PreparedStatement, ResultSet 객체 먼저 생성 후 Driver 위치를 driver 변수에, xe 데이터베이스 url 를 url 변수에 저장

- ResultSet 객체는 검색결과를 돌려주는 객체

2. try-catch 예외처리 후 오라클용 JDBC 드라이버를 로딩하기 위해 Class.forName() 사용, Connection 객체 구해오기

3. SQL문 작성한다, 전체 데이터를 구해오므로 select * from member2;

4. Connection 객체 con 을 이용해서 PreparedStatement 객체 생성

5. ? 가 없는 sql 이므로 바로 executeQuer() 로 sql문 실행, 결과는 ResultSet 객체인 rs 가 받는다

- select 만 executeQuery(), 나머지 DML 은 executeUpdate() 사용

6. rs 에 있는 데이터들을 next() 메소드로 데이터 하나씩 가져와야한다

- DB 에서 가져온 데이터를 바로 list 에 저장하지 않음, 컬럼 단위로 잘라서 DTO 객체를 생성해서 메모리상에 저장을 선행

7. DTO 객체 member 를 생성한다

- DTO 객체에 선행 후 그 DTO 객체를 list 에 저장한다

- Java 이므로 useBean 사용불가하므로 직접 객체 생성

+ DTO 객체는 중간 저장소의 역할도 한다

8. DTO 객체 member 에 값을 저장한다

- 프로퍼티의 접근제어자가 private 이므로 DTO 객체 프로퍼티에 직접 값 설정 불가능, setter 메소드 사용

- JSP 에서는 setProperty action tag 로 가능하지만 Java이므로 직접 setXX() 메소드를 불러온다

- varchar2 인 컬럼 이므로 getString() 메소드를 사용한다, 매개변수에는 컬럼인덱스도 올 수 있고 컬럼명도 올 수 있음

- reg_date 컬럼은 자료형이 date 이므로 getDate() 사용해야한다.

9. 첫번째 사람의 데이터를 저장한 이 DTO 객체 member 를 List 0번방(메모리)에 add()사용해서 저장해야한다. 

- 그렇지 않으면 다음 사람의 데이터가 덮어버려서 마지막 사람의 데이터만 남게된다

- List 는 위에서 DTO 제네릭이 설정되었으므로 DTO 외의 자료형이 올 수 없음

- 매번 힙에 기억공간을 생성하고, 그 힙을 가리키는 member 객체를 list 에 순차적으로 저장

+ DTO 는 폼에서 넘어간 값도 저장하고, DB 에서 검색된 자료도 저장하는 중간 저장소 역할

10. 각 객체가 null 이 아닌경우, try-catch 문에서 ResultSet객체 rs 먼저 닫고, PreparedStatement 객체 pstmt 닫고 Conenction 객체 con 닫기

- null 값이 아닌 경우 = 해당 객체가 생성이 되었다면

- 닫을땐 반대로 닫는다

+ DTO 객체는 중간 저장소 역할

 

- 추가된 코드, 즉 회원목록 전체 검색 메소드 코드

+ 이 아래에 다른 메소드도 추가할 것 (아직 DAO 미완성)

 

- 데이터가 제대로 select 되는지 확인하기 위해 list.jsp 실행

- 다시 list.jsp 파일을 보면

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@ page import="JavaBeanMember.register.LogonDBBean" %>  
<%@ page import="JavaBeanMember.register.LogonDataBean" %>  
<%@ page import="java.util.*" %>
    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>회원 목록</title>
</head>
<body>
<a href="registerForm.jsp">회원가입</a>


<table align=center width=1000 border=1>
	<tr><td>ID</td> 
		<td>비밀번호</td>
		<td> 이름 </td>
		<td> 주민번호 </td>
		<td> 이메일 </td>
		<td> BLOG </td>
		<td> 가입일 </td>
		<td>수정</td>
		<td>삭제</td>
	</tr>

<%
LogonDBBean manager = LogonDBBean.getInstance();
List<LogonDataBean> li = manager.selectMember();


	for(int i = 0; i < li.size(); i++) {
		LogonDataBean db = (LogonDataBean)li.get(i);
%>

	<tr><td><%=db.getId()%></td>
		<td><%=db.getPasswd()%></td>
		<td><%=db.getName()%></td>
		<td><%=db.getJumin1()%> - <%=db.getJumin2()%> </td>
		<td><%=db.getEmail()%></td>
		<td><%=db.getBlog()%></td>
		<td><%=db.getReg_date()%></td>
		<td><a href="updateForm.jsp?id=<%=db.getId()%>">수정</a></td>
		<td><a href="deleteForm.jsp?id=<%=db.getId()%>">삭제</a></td>
	</tr>
<% 
	}
%>

</table>
</body>
</html>

- selectMember() 의 리턴을 List 로 받는다

- for문을 통해 LIst 안의 0번 내용을 DTO 객체 db 로 받고, 바로 <tr><td> 안에서 출력한다

- 그 다음 내용을 다시 DTO 객체 db 로 받고, 출력을 더이상 데이터가 없을때까지 반복

 

- select 가 잘 되었음을 확인 가능

- '회원가입' 을 클릭하여 다시 한명을 회원가입 시켜보자

- 이제 가입과, 목록확인 기능 완료

 

DAO 클래스 만들기

3. DAO 에 수정 기능 메소드 만들기 (+ select 로 한명 데이터 가져오기 메소드도 만들기)

- '수정' 기능을 구현하자

- list.jsp 에서 '수정' 을 누르면 그 데이터의 id 를 updateForm.jsp로 get 방식으로 전달함

list.jsp 부분

- '수정' 페이지는 가입한 정보를 먼저 보여주고 수정가능하다

- 가입한 정보를 보여주기위해선 또 DB 연동을 해야함

 

- updateForm.jsp

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="JavaBeanMember.register.LogonDBBean" %>  
<%@ page import="JavaBeanMember.register.LogonDataBean" %>  
<%@ include file="color.jsp" %>

<%
	String id = request.getParameter("id");

	LogonDBBean manager = LogonDBBean.getInstance();
	LogonDataBean db = manager.updateForm(id);
%>


<html>
<head>
	<title>회원수정</title>
	<link href="style.css" rel="stylesheet" type="text/css">
	<script language="JavaScript" src="script.js"></script>
</head>

<body bgcolor="<%=bodyback_c%>">
  <form name="regForm" method="post" action="updatePro.jsp" onsubmit="return inputCheck()">
    <input type=hidden name=id value="<%=db.getId() %>">
    <table width="500" border="0" cellspacing="0" cellpadding="2"  align="center">
      <tr height="39" align="center" bgcolor="<%=title_c%>"> 
         <td colspan="3"><b>회원 수정</b></font></td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">아이디</td>
        <td width="200" bgcolor="<%=value_c%>"> 
        	<%=db.getId() %>
		 <!--  <input type="text" name="id" size="20"> --> </td>
        <td width="200" bgcolor="<%=value_c%>">아이디를 입력하세요.</td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">비밀번호</td> 
        <td width="200" bgcolor="<%=value_c%>"> 
	      <input type="password" name="passwd" size="20"> </td>
      <td width="200" bgcolor="<%=value_c%>">비밀번호를 입력하세요</td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">비밀번호 확인</td>
        <td width="200" bgcolor="<%=value_c%>"> 
		  <input type="password" name="repasswd" size="20"> </td>
        <td width="200" bgcolor="<%=value_c%>">비밀번호를 재입력하세요.</td>
      </tr>
      <tr>  
        <td width="100" bgcolor="<%=title_c%>">이름</td>
        <td width="200" bgcolor="<%=value_c%>"> 
		  <input type="text" name="name" size="20" value="<%=db.getName()%>"> </td>
        <td width="200" bgcolor="<%=value_c%>">이름을 입력하세요.</td>
      </tr>
      <tr>  
        <td width="100" bgcolor="<%=title_c%>">주민번호</td>
        <td width="200" bgcolor="<%=value_c%>"> 
		  <input type="text" name="jumin1" size="6" maxlength=6 value="<%=db.getJumin1()%>">-
		  <input type="text" name="jumin2" size="7" maxlength=7 value="<%=db.getJumin2()%>"> </td>
        <td width="200" bgcolor="<%=value_c%>">주민번호를 입력하세요.</td>
      </tr>
      <tr> 
         <td width="100" bgcolor="<%=title_c%>">이메일</td>
         <td width="200" bgcolor="<%=value_c%>"> 
		   <input type="text" name="email" size="30" value="<%=db.getEmail()%>"> </td>
         <td width="200" bgcolor="<%=value_c%>">이메일을 입력하세요.</td>
      </tr>
      <tr>  
         <td width="100" bgcolor="<%=title_c%>">블로그</td>
         <td width="200" bgcolor="<%=value_c%>"> 
		   <input type="text" name="blog" size="20" value="<%=db.getBlog()%>"> </td>
         <td width="200" bgcolor="<%=value_c%>">블로그를 입력하세요.</td>
      </tr>
      <tr> 
         <td colspan="3" align="center"  bgcolor="<%=title_c%>"> 
           <input type="submit" value="회원수정" > 
              &nbsp; &nbsp; &nbsp; &nbsp;
           <input type="reset" value="다시작성"> 
         </td>
       </tr>
    </form>
  </table>
</body>
</html>

- request.getParameter() 로 넘어온 id 값을 받는다

- id 값으로 한명에 대한 상세정보를 구해와야하므로 DB 연동을 준비함

- DAO 객체를 getInstance() 로 구하고, updateForm() 메소드를 호출하며 매개변수로 id 값을 전달

- 결과 돌려받을때는 1명에 대한 정보를 돌려받으므로 DTO 클래스를 자료형으로 사용

 

- DAO 클래스에서 updateForm() 메소드를 추가하자

- LogonDBBean.java (추가)

// DAO (Data Access Object)
package JavaBeanMember.register;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class LogonDBBean {
	
	// 싱글톤 : 객체 생성을 한번만 수행하는 것
	private static LogonDBBean instance = new LogonDBBean();
	
	public static LogonDBBean getInstance() {	// 정적 메소드
		return instance;
	}
	
	// 회원가입 : 주솟값 전달에 의한 메소드 호출  (Call By Reference 방식)
	public int insertMember(LogonDataBean member) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			// JDBC 방식
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "insert into member2 values(?,?,?,?,?,?,?,sysdate)";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			pstmt.setString(2, member.getPasswd());
			pstmt.setString(3, member.getName());
			pstmt.setString(4, member.getJumin1());
			pstmt.setString(5, member.getJumin2());
			pstmt.setString(6, member.getEmail());
			pstmt.setString(7, member.getBlog());
			
			result = pstmt.executeUpdate();	// SQL문 실행
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}
		}
		return result;
	}
	// 전체 회원목록 구하기
	public List<LogonDataBean> selectMember() {
		List<LogonDataBean> list = new ArrayList<LogonDataBean>();
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "select * from member2";
			
			pstmt = con.prepareStatement(sql);
			rs = pstmt.executeQuery();
			
			while(rs.next()) {	// 데이터를 1개씩 가져온다.
				LogonDataBean member = new LogonDataBean();
//				member.id = "totoro";	// 접근 안됨 (private 접근 제어자)
				member.setId(rs.getString("id"));
				member.setPasswd(rs.getString("passwd"));
				member.setName(rs.getString("name"));
				member.setJumin1(rs.getString("jumin1"));
				member.setJumin2(rs.getString("jumin2"));
				member.setEmail(rs.getString("email"));
				member.setBlog(rs.getString("blog"));
				member.setReg_date(rs.getDate("reg_date"));
				
				list.add(member);
			}
		} catch(Exception e) {
			
		} finally {
			if(rs != null) try { rs.close(); } catch(Exception e) {}
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}			
		}
		
		return list;
	}
	// 회원 수정 폼 : 회원 1명 정보 구하기
	public LogonDataBean updateForm(String id) {
		LogonDataBean member = new LogonDataBean();
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "select * from member2 where id=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, id);
			rs = pstmt.executeQuery();	// SQL문 실행
			
			if(rs.next()) {
				member.setId(rs.getString("id"));
				member.setPasswd(rs.getString("passwd"));
				member.setName(rs.getString("name"));
				member.setJumin1(rs.getString("jumin1"));
				member.setJumin2(rs.getString("jumin2"));
				member.setEmail(rs.getString("email"));
				member.setBlog(rs.getString("blog"));
				member.setReg_date(rs.getDate("reg_date"));
			}
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(rs != null) try { rs.close(); } catch(Exception e) {}
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}				
		}
		
		return member;
	}
}

<updateForm() 메소드 형식 작성>

- select sql 문을 수행하는 메소드인 경우에는 리턴 자료형이 반드시 있어야한다

- 이때 리턴 자료형으로, 한개의 데이터를 구하면 DTO 클래스가 자료형으로 오고, 2개 이상의 데이터를 구하면 List가 온다

- updateForm()의 매개변수는 id 를 저장하므로 String, 리턴자료형은 한명의 상세정보를 돌려줘야하므로 DTO로 만들기

- 결과 줄때는 1명에 대한 정보를 돌려주므로 DTO 클래스를 리턴자료형으로 사용

<updateform() 메소드 내용 작성>

1. DTO 객체인 member 를 위쪽에 먼저 생성하고 아래에 return member; 로 리턴

2. Connection, PreparedStatement, ResultSet 객체 먼저 생성 후 Driver 위치를 driver 변수에, xe 데이터베이스 url 를 url 변수에 저장

- 이건 select 이므로, 검색 결과 돌려받을 ResultSet 객체를 생성해야한다

3. try-catch 예외처리 후 오라클용 JDBC 드라이버를 로딩하기 위해 Class.forName() 사용, Connection 객체 구해오기

4. SQL문 작성시 한명에 대한 상세정보(모든 속성)를 구하기때문에 where 조건절에 매개변수로 넘어온 id 사용

5. Connection 객체 con 을 이용해서 PreparedStatement 객체 생성

6. id 컬럼이 varchar2 이므로 setString() 으로 ? 에 매개변수로 넘어온 id 값 설정

7. select SQL 문을 실행하기 위해 executeQuery() 메소드 사용, 성공시 돌려주는 수정된 데이터를 result 변수에 저장

- select 만 executeQuery(), 나머지 DML 은 executeUpdate() 사용

8. 검색한 데이터인 rs 에 있는 데이터는 1개이므로 next() 메소드로 데이터 하나씩 가져오되 if 문을 사용한다

9.검색한 결과를 DTO 객체 member 에 setString() 으로 저장한다

10. 각 객체가 null 이 아닌경우, try-catch 문에서 ResultSet객체 rs 먼저 닫고, PreparedStatement 객체 pstmt 닫고 Conenction 객체 con 닫기

- null 값이 아닌 경우 = 해당 객체가 생성이 되었다면

11. 데이터는 1개이므로 메소드의 마지막에 List가 아닌 DTO 객체를 돌려주는 코드 작성

 

- 추가된 코드만 캡처

+ 이 아래에 다른 메소드도 추가할 것 (아직 DAO 미완성)

 

- 회원 수정 기능이 잘 구현되었는지 실행해보자

- list.jsp 실행 후 '수정' 누르기

- 회원 수정 폼이 완성되었음을 알 수 있다

- 아이디는 수정하지 못하게 출력만 하고 있다

- 나머지 정보를 수정하기위해서 updatePro.jsp 가 필요함

 

- updatePro.jsp 를 보기 전에 updateForm.jsp 파일을 먼저 보자

- updateForm.jsp

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="JavaBeanMember.register.LogonDBBean" %>  
<%@ page import="JavaBeanMember.register.LogonDataBean" %>  
<%@ include file="color.jsp" %>

<%
	String id = request.getParameter("id");

	LogonDBBean manager = LogonDBBean.getInstance();
	LogonDataBean db = manager.updateForm(id);
%>


<html>
<head>
	<title>회원수정</title>
	<link href="style.css" rel="stylesheet" type="text/css">
	<script language="JavaScript" src="script.js"></script>
</head>

<body bgcolor="<%=bodyback_c%>">
  <form name="regForm" method="post" action="updatePro.jsp" onsubmit="return inputCheck()">
    <input type=hidden name=id value="<%=db.getId() %>">
    <table width="500" border="0" cellspacing="0" cellpadding="2"  align="center">
      <tr height="39" align="center" bgcolor="<%=title_c%>"> 
         <td colspan="3"><b>회원 수정</b></font></td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">아이디</td>
        <td width="200" bgcolor="<%=value_c%>"> 
        	<%=db.getId() %>
		 <!--  <input type="text" name="id" size="20"> --> </td>
        <td width="200" bgcolor="<%=value_c%>">아이디를 입력하세요.</td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">비밀번호</td> 
        <td width="200" bgcolor="<%=value_c%>"> 
	      <input type="password" name="passwd" size="20"> </td>
      <td width="200" bgcolor="<%=value_c%>">비밀번호를 입력하세요</td>
      </tr>
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">비밀번호 확인</td>
        <td width="200" bgcolor="<%=value_c%>"> 
		  <input type="password" name="repasswd" size="20"> </td>
        <td width="200" bgcolor="<%=value_c%>">비밀번호를 재입력하세요.</td>
      </tr>
      <tr>  
        <td width="100" bgcolor="<%=title_c%>">이름</td>
        <td width="200" bgcolor="<%=value_c%>"> 
		  <input type="text" name="name" size="20" value="<%=db.getName()%>"> </td>
        <td width="200" bgcolor="<%=value_c%>">이름을 입력하세요.</td>
      </tr>
      <tr>  
        <td width="100" bgcolor="<%=title_c%>">주민번호</td>
        <td width="200" bgcolor="<%=value_c%>"> 
		  <input type="text" name="jumin1" size="6" maxlength=6 value="<%=db.getJumin1()%>">-
		  <input type="text" name="jumin2" size="7" maxlength=7 value="<%=db.getJumin2()%>"> </td>
        <td width="200" bgcolor="<%=value_c%>">주민번호를 입력하세요.</td>
      </tr>
      <tr> 
         <td width="100" bgcolor="<%=title_c%>">이메일</td>
         <td width="200" bgcolor="<%=value_c%>"> 
		   <input type="text" name="email" size="30" value="<%=db.getEmail()%>"> </td>
         <td width="200" bgcolor="<%=value_c%>">이메일을 입력하세요.</td>
      </tr>
      <tr>  
         <td width="100" bgcolor="<%=title_c%>">블로그</td>
         <td width="200" bgcolor="<%=value_c%>"> 
		   <input type="text" name="blog" size="20" value="<%=db.getBlog()%>"> </td>
         <td width="200" bgcolor="<%=value_c%>">블로그를 입력하세요.</td>
      </tr>
      <tr> 
         <td colspan="3" align="center"  bgcolor="<%=title_c%>"> 
           <input type="submit" value="회원수정" > 
              &nbsp; &nbsp; &nbsp; &nbsp;
           <input type="reset" value="다시작성"> 
         </td>
       </tr>
    </form>
  </table>
</body>
</html>

- 수정폼에 입력한 값을 name 값을 통해서 전달하고 있다

- id 값은 수정하지 못하게 출력만 시키고 있다

- id 값은 화면에 노출시키지 않고 hidden 객체로 updatePro.jsp 로 값 전달

- 비밀번호는 value 를 설정하지 않아서 사용자가 처음부터 입력해야한다

- 이름은 value 속성을 사용해서 DAO의 updateForm() 메소드로부터 받아온 DTO 객체의 값을 출력, 다른 정보도 마찬가지

ex) <%=db.getName()%>

 

- 다음으로 updatePro.jsp 를 보자

- select 하는 DAO 의 메소드를 호출하는 파일, 비밀번호가 DB의 비밀번호와 일치하는지 확인함

- registerPro.jsp 와 비슷한 구조이다

- updatePro.jsp

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="JavaBeanMember.register.LogonDataBean" %>
<%@ page import="JavaBeanMember.register.LogonDBBean" %>
<%@include file="color.jsp" %>

<% 
  request.setCharacterEncoding("euc-kr");

  LogonDataBean	regBean1 = new LogonDataBean();
// regBean1.id="test";
%>

<jsp:useBean id="regBean" class="JavaBeanMember.register.LogonDataBean" />
<jsp:setProperty name="regBean" property="*" />

<%
	LogonDBBean manager = LogonDBBean.getInstance();

	LogonDataBean old = manager.updateForm(regBean.getId());
	
	if(old.getPasswd().equals(regBean.getPasswd())){ // 비번 일치시	
		manager.update(regBean);	// update SQL문 실행
		
%>	
	<script>
		alert("회원수정 성공");
		location.href="list.jsp";
	</script>
	
<% }else{	// 비번 불일치	%>

	<script>
		alert("비밀번호가 일치하지 않습니다.");
		history.go(-1);
	</script>

<% } %>

- 수정폼에서 한글값이 post 로 넘어오므로 한글 인코딩

- useBean action tag 로 DTO 객체 regBean 을 생성하고 폼에서 넘어온 name 값을 DTO 프로퍼티명과 일치하는 곳으로 저장

- DB 를 update 하기 위해 DAO 객체를 getInstance() 로 생성

- updateForm() 이 여기서도 사용되어서 사용자의 id 값을 받아서 그 사용자의 상세 정보를 가져와서 변수 old 에 저장

- 그 상세정보 중에서 사용할 것은 사용자의 비번

<비번과 비번확인 일치 확인>

- DB 에 저장된 비번만 필요하므로 DB 에서 id 값으로 검색수행하여 받은 비번이 old.getPasswd() 이다

- 사용자가 입력하여 메모리에 잠시 저장되었다가 가져온 값이 regBean.getPasswd() 이다

- 두 값이 같은 경우, 즉 비밀번호와 비밀번호 확인 값이 같은 경우에만 회원 수정 시키는 메소드 update() 를 호출

- update()를 호출하며 사용자가 수정폼에서 입력한 정보를 담은 DTO 객체인 regBean 을 매개변수로 넘김

 

- DAO 클래스에서 update() 메소드를 추가하자

- LogonDBBean.java (추가)

// DAO (Data Access Object)
package JavaBeanMember.register;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class LogonDBBean {
	
	// 싱글톤 : 객체 생성을 한번만 수행하는 것
	private static LogonDBBean instance = new LogonDBBean();
	
	public static LogonDBBean getInstance() {	// 정적 메소드
		return instance;
	}
	
	// 회원가입 : 주솟값 전달에 의한 메소드 호출  (Call By Reference 방식)
	public int insertMember(LogonDataBean member) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			// JDBC 방식
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "insert into member2 values(?,?,?,?,?,?,?,sysdate)";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			pstmt.setString(2, member.getPasswd());
			pstmt.setString(3, member.getName());
			pstmt.setString(4, member.getJumin1());
			pstmt.setString(5, member.getJumin2());
			pstmt.setString(6, member.getEmail());
			pstmt.setString(7, member.getBlog());
			
			result = pstmt.executeUpdate();	// SQL문 실행
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}
		}
		return result;
	}
	// 전체 회원목록 구하기
	public List<LogonDataBean> selectMember() {
		List<LogonDataBean> list = new ArrayList<LogonDataBean>();
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "select * from member2";
			
			pstmt = con.prepareStatement(sql);
			rs = pstmt.executeQuery();
			
			while(rs.next()) {	// 데이터를 1개씩 가져온다.
				LogonDataBean member = new LogonDataBean();
//				member.id = "totoro";	// 접근 안됨 (private 접근 제어자)
				member.setId(rs.getString("id"));
				member.setPasswd(rs.getString("passwd"));
				member.setName(rs.getString("name"));
				member.setJumin1(rs.getString("jumin1"));
				member.setJumin2(rs.getString("jumin2"));
				member.setEmail(rs.getString("email"));
				member.setBlog(rs.getString("blog"));
				member.setReg_date(rs.getDate("reg_date"));
				
				list.add(member);
			}
		} catch(Exception e) {
			
		} finally {
			if(rs != null) try { rs.close(); } catch(Exception e) {}
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}			
		}
		
		return list;
	}
	// 회원 수정 폼 : 회원 1명 정보 구하기
	public LogonDataBean updateForm(String id) {
		LogonDataBean member = new LogonDataBean();
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "select * from member2 where id=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, id);
			rs = pstmt.executeQuery();	// SQL문 실행
			
			if(rs.next()) {
				member.setId(rs.getString("id"));
				member.setPasswd(rs.getString("passwd"));
				member.setName(rs.getString("name"));
				member.setJumin1(rs.getString("jumin1"));
				member.setJumin2(rs.getString("jumin2"));
				member.setEmail(rs.getString("email"));
				member.setBlog(rs.getString("blog"));
				member.setReg_date(rs.getDate("reg_date"));
			}
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(rs != null) try { rs.close(); } catch(Exception e) {}
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}				
		}
		
		return member;
	}
	// 회원 정보 수정
	public void update(LogonDataBean member) {
		Connection con = null;
		PreparedStatement pstmt = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "update member2 set name=?, jumin1=?, jumin2=?,";
			sql += "email=?, blog=? reg_date=sysdsate where id=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getName());
			pstmt.setString(2, member.getJumin1());
			pstmt.setString(3, member.getJumin2());
			pstmt.setString(4, member.getEmail());
			pstmt.setString(5, member.getBlog());
			pstmt.setString(6, member.getId());
			
			pstmt.executeUpdate();	// SQL문 실행

		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}					
		}
	}
}

<update() 메소드 형식 작성>

- 업데이트한 결과를 돌려줄 수도 있지만 지금은 돌려주지 않음, 리턴자료형을 void로 설정

- update()의 매개변수로는 DTO 객체를 받아야하므로 DTO

<update() 메소드 내용 작성>

1. Connection, PreparedStatement 객체 먼저 생성 후 Driver 위치를 driver 변수에, xe 데이터베이스 url 를 url 변수에 저장

2. try-catch 예외처리 후 오라클용 JDBC 드라이버를 로딩하기 위해 Class.forName() 사용, Connection 객체 구해오기

3. SQL문 작성시 각 컬럼들을 ? 를 사용해서 쓰고, reg_date 는 수정 날짜로 바꾸기 위해 sysdate 작성, 특정 1명을 수정하는 것이므로 where 절에 id 사용

4. Connection 객체 con 을 이용해서 PreparedStatement 객체 생성

5. 매개변수 member 를 통해 member.getXX() 로 메모리상에 저장된 값을 리턴받아서 setString() 으로 DB 에 넣기

- Java 에서 getProperty 는 사용 불가하므로 getXX() 로 직접 가져오기

6. update SQL 문을 실행하기 위해 executeUpdate() 메소드 사용

- select 만 executeQuery(), 나머지 DML 은 executeUpdate() 사용

7. 업데이트한 값을 돌려주는 경우도 있지만 지금은 돌려주지 않는 경우임

8. 각 객체가 null 이 아닌경우, try-catch 문에서 ResultSet객체 rs 먼저 닫고, PreparedStatement 객체 pstmt 닫고 Conenction 객체 con 닫기

- null 값이 아닌 경우 = 해당 객체가 생성이 되었다면

 

+ 추가된 코드 부분만

 

- list.jsp 실행해서 수정폼으로 가서 수정을 시도해보자

- 수정이 잘 되었음을 확인할 수 있다, update 기능이 잘 구현되었음

 

+ 틀린 비밀번호를 입력했을때

 

DAO 클래스 만들기

4. DAO 에 삭제 기능 메소드 만들기

- '삭제' 기능을 구현하자

- list.jsp 에서 '삭제' 를 누르면 해당 데이터(사람)의 id 를 get 방식으로 가져간다

list.jsp 부분

- '사람' 페이지는 가입한 정보를 보여주지 않으므로 수정처럼 중간에도 DB 연동을 할 필요는 없다

 

- deleteForm.jsp 를 보자

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="JavaBeanMember.register.LogonDBBean" %>  
<%@ page import="JavaBeanMember.register.LogonDataBean" %>  
<%@ include file="color.jsp" %>

<%
	String id = request.getParameter("id");	
%>
<html>
<head>
	<title>회원삭제</title>
	<link href="style.css" rel="stylesheet" type="text/css">
	<script language="JavaScript" src="script.js"></script>
</head>

<body bgcolor="<%=bodyback_c%>">
  <form name="regForm" method="post" action="deletePro.jsp" onsubmit="return inputCheck()">
    <input type=hidden name=id value="<%=id %>">
    <table width="500" border="0" cellspacing="0" cellpadding="2"  align="center">
      <tr height="39" align="center" bgcolor="<%=title_c%>"> 
         <td colspan="3"><b>회원 삭제</b></font></td>
      </tr>     
      <tr> 
        <td width="100" bgcolor="<%=title_c%>">비밀번호</td> 
        <td width="200" bgcolor="<%=value_c%>"> 
	      <input type="password" name="passwd" size="20"> </td>
      <td width="200" bgcolor="<%=value_c%>">비밀번호를 입력하세요</td>
      </tr>      
      <tr> 
         <td colspan="3" align="center"  bgcolor="<%=title_c%>"> 
           <input type="submit" value="회원삭제" > 
              &nbsp; &nbsp; &nbsp; &nbsp;
           <input type="reset" value="다시작성"> 
         </td>
       </tr>
    </form>
  </table>
</body>
</html>

- 앞에서 get 방식으로 넘어온 id 를 getParameter()로 받아서 id 변수에 저장함

- id 값을 화면에 출력시키지 않고 hidden 객체로 deletePro.jsp 로 넘김

- id 와 사용자가 삭제폼에서 입력한 passwd 를 넘김

 

- deletePro.jsp

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="JavaBeanMember.register.LogonDataBean" %>
<%@ page import="JavaBeanMember.register.LogonDBBean" %>
<%@include file="color.jsp" %>

<% 
  request.setCharacterEncoding("euc-kr");

  LogonDataBean	regBean1 = new LogonDataBean();
// regBean1.id="test";
%>

<jsp:useBean id="regBean" class="JavaBeanMember.register.LogonDataBean" />
<jsp:setProperty name="regBean" property="*" />

<%
	LogonDBBean manager = LogonDBBean.getInstance();

	LogonDataBean old = manager.updateForm(regBean.getId());
	
	if(old.getPasswd().equals(regBean.getPasswd())){ // 비번 일치시	
		manager.delete(regBean);	// delete SQL문 실행
		
%>	
	<script>
		alert("회원삭제 성공");
		location.href="list.jsp";
	</script>
	
<% }else{	// 비번 불일치시	%>

	<script>
		alert("비밀번호가 일치하지 않습니다.");
		history.go(-1);
	</script>

<% } %>

- 전달되는 값이 많지 않으므로 setProperty action tag 를 쓸 필요 없지만 여기선 쓰고 있다

- updateForm() 을 세번째 사용하고 있다, DB 에서 비번을 끄집어내서 사용자가 삭제폼에 입력한 비번과 일치하는지 확인

- old.getPasswd() 는 DB에서 가져온 비번이고 regBean.getPasswd() 는 사용자가 삭제폼에서 입력한 비번이다

- 두 비번이 일치하면 DAO 의 delete() 메소드를 호출함

- 삭제할때는 id 값이 들어가야한다, id 값만매개변수로 전달해도 되지만 지금은 regBean 객체 전체를 넘기고 있음

 

- DAO 클래스에서 delete() 메소드를 추가하자

- LogonDBBean.java (최종 DAO 클래스)

// DAO (Data Access Object)
package JavaBeanMember.register;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class LogonDBBean {
	
	// 싱글톤 : 객체 생성을 한번만 수행하는 것
	private static LogonDBBean instance = new LogonDBBean();
	
	public static LogonDBBean getInstance() {	// 정적 메소드
		return instance;
	}
	
	// 회원가입 : 주솟값 전달에 의한 메소드 호출  (Call By Reference 방식)
	public int insertMember(LogonDataBean member) {
		int result = 0;
		
		Connection con = null;
		PreparedStatement pstmt = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			// JDBC 방식
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "insert into member2 values(?,?,?,?,?,?,?,sysdate)";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			pstmt.setString(2, member.getPasswd());
			pstmt.setString(3, member.getName());
			pstmt.setString(4, member.getJumin1());
			pstmt.setString(5, member.getJumin2());
			pstmt.setString(6, member.getEmail());
			pstmt.setString(7, member.getBlog());
			
			result = pstmt.executeUpdate();	// SQL문 실행
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}
		}
		return result;
	}
	// 전체 회원목록 구하기
	public List<LogonDataBean> selectMember() {
		List<LogonDataBean> list = new ArrayList<LogonDataBean>();
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "select * from member2";
			
			pstmt = con.prepareStatement(sql);
			rs = pstmt.executeQuery();
			
			while(rs.next()) {	// 데이터를 1개씩 가져온다.
				LogonDataBean member = new LogonDataBean();
//				member.id = "totoro";	// 접근 안됨 (private 접근 제어자)
				member.setId(rs.getString("id"));
				member.setPasswd(rs.getString("passwd"));
				member.setName(rs.getString("name"));
				member.setJumin1(rs.getString("jumin1"));
				member.setJumin2(rs.getString("jumin2"));
				member.setEmail(rs.getString("email"));
				member.setBlog(rs.getString("blog"));
				member.setReg_date(rs.getDate("reg_date"));
				
				list.add(member);
			}
		} catch(Exception e) {
			
		} finally {
			if(rs != null) try { rs.close(); } catch(Exception e) {}
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}			
		}
		
		return list;
	}
	// 회원 수정 폼 : 회원 1명 정보 구하기
	public LogonDataBean updateForm(String id) {
		LogonDataBean member = new LogonDataBean();
		
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "select * from member2 where id=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, id);
			rs = pstmt.executeQuery();	// SQL문 실행
			
			if(rs.next()) {
				member.setId(rs.getString("id"));
				member.setPasswd(rs.getString("passwd"));
				member.setName(rs.getString("name"));
				member.setJumin1(rs.getString("jumin1"));
				member.setJumin2(rs.getString("jumin2"));
				member.setEmail(rs.getString("email"));
				member.setBlog(rs.getString("blog"));
				member.setReg_date(rs.getDate("reg_date"));
			}
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(rs != null) try { rs.close(); } catch(Exception e) {}
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}				
		}
		
		return member;
	}
	// 회원 정보 수정
	public void update(LogonDataBean member) {
		Connection con = null;
		PreparedStatement pstmt = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "update member2 set name=?, jumin1=?, jumin2=?,";
			sql += "email=?, blog=?,reg_date=sysdate where id=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getName());
			pstmt.setString(2, member.getJumin1());
			pstmt.setString(3, member.getJumin2());
			pstmt.setString(4, member.getEmail());
			pstmt.setString(5, member.getBlog());
			pstmt.setString(6, member.getId());
			
			pstmt.executeUpdate();	// SQL문 실행

		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}					
		}
	}
	
	// 회원 정보 삭제
	public void delete(LogonDataBean member) {
		Connection con = null;
		PreparedStatement pstmt = null;
		
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, "scott", "tiger");
			
			String sql = "delete from member2 where id=?";
			
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			
			pstmt.executeUpdate();	// SQL문 실행

		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(pstmt != null) try { pstmt.close(); } catch(Exception e) {}
			if(con != null) try { con.close(); } catch(Exception e) {}					
		}
	}
}

- update() 메소드와 거의 유사함, 이름만 delete() 로 바꿈

- sql 문을 delete sql문으로 수정한다, 한명의 데이터를 삭제하므로 where 절에 id 를 넣음

- deletePro.jsp 에서 객체 전체가 매개변수로 넘어왔으므로 member.getId() 로 아이디를 객체에서 가져와서 ? 에 설정

- 값을 돌려주는 부분은 없다

- 최종 DAO 클래스 이다

 

- 실행 확인

- list.jsp 에서 '삭제' 를 누르면

 

- 잘 삭제된다, delete 기능이 잘 구현되었음을 알 수 있다

 

+ 틀린 비번 입력시

 

+ 추가된 코드 부분만

- DAO 클래스 완료

 

+ 유효성검사 메세지 박스 한글값이 깨진다

- script.js 가 유효성 검사를 하는데 한글값이 꺠지므로 모든 파일의 인코딩을 EUC-KR 에서UTF-8 로 바꾸자

- 이후 script.js 를 바탕화면에 저장하고, 메모장으로 열기

- 파일-다른이름으로 저장

- 인코딩을 UTF-8 로 변경해준다

- 이후 이 파일을 다시 이클립스로 넣으면 한글 인코딩이 완료됨

 

 


DBCP 방식으로 DB 연동

 

- 여태까지 JDBC 방식으로 DB 와 연동했다

- 메소드 호출마다 매번 Driver 를 로딩했다, 시간소요, 서버측 메모리 자원 사용

 

- 이제 두번째 방법인 DBCP 방식으로 DB 연동 해볼것

- 완성된 프로그램은 모두 DBCP 방식으로 DB 연동할 것

 

DBCP 방식

- WAS 실행 시 미리 일정량의 DB Connection 객체를 생성하고 Pool 이라는 공간에 저장

- 그리고 DB 연결 요청이 있으면, 이 Pool 이라는 공간에서 Connection 객체를 가져다 쓰고 반환

 

- 데이터베이스와 연결된 커넥션을 미리 만들어서 풀 속에 저장하고 있다가 필요할 때에 커넥션을 풀에서 가져다 쓰고 다시 풀에 반환하는 기법

 

DBCP 특징

- 커넥션을 생성하는데 드는연결시간이 소비되지 않음

- 커넥션 풀이 저장된 커넥션을 재사용할 수 있다

- 접속이 빈번한 경우에 많이 쓴다

 

- 환경설정파일에서 몇개의 커넥션을 미리 만들어둘지 설정 가능

- 설정하지 않으면 기본적으로 8개의 커넥션 만듬

- 풀에서 커넥션을 가져오고 커넥션을 사용하고 커넥션을 close() 하면 풀에 반환됨

 

커넥션 풀 환경설정

- 커넥션 풀 환경설정 파일인 context.xml 파일은 META-INF 폴더 안에 저장해야함

- 오라클과 연동위해 lib 폴더 하위에 ojdbc6.jar 가 필요하다

 

context.xml 파일에 들어갈 내용

- 루트 엘리먼트 context, 부모 엘리먼트 Resource

- Resource 엘리먼트에 name 값을 jdbc/OracleDB 로 임의로 정함

- 나중에 이 name 값을 찾아오는 것

- driverClassName 속성값으로 오라클 드라이버 위치

- factory 속성값은 org.apache.tomcat.dbcp.dbcp2 까지가 패키지고, BasicDataSourceFactory 가 클래스 명이다

- maxActive 는 커넥션 풀이 관리하는 커넥션의 최대 개수, 500으로 설정시 500개를 미리 만들어둠

 

Connection Pool 에서 커넥션 구해오기

- 네임값인 jdbc/OracleDB 으로 찾아가야한다

- InitialContext 객체를 생성하고 lookup() 으로 Resource name 값을 찾아가서 커넥션을 구해옴

- DataSource 객체로 커넥션을 받아옴

 

Connection Pool 설정 실습

- 이 war 파일을 다운받아 이클립스로 import

- import 시 dbcpTest 라는 프로젝트가 생성됨

- 구조 확인, context.xml 은 META-INF 안에 있어야한다

 

- context.xml

- name 속성값은 임의로 설정한 이름이다

- 나중에 커넥션 풀에서 커넥션을 구할때는 Resource name값으로 구해옴

- factory 는 Apache Tomcat 안의 패키지안의 클래스명임

 

Connection Pool 에서 커넥션 구해오기

- 커넥션을 잘 구해오는지 Test

- 테스트 하기위한 파일인 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/OracleDB");
  		conn = ds.getConnection();
  		
  		out.println("<h3>연결되었습니다.</h3>");
	}catch(Exception e){
		out.println("<h3>연결에 실패하였습니다.</h3>");
		e.printStackTrace();
 	}
%>

1. 가장먼저 InitlaContext 객체 생성, 업캐스팅 방식으로 Context 객체 init 생성

2. 그 init.lookup() 으로 커넥션 풀 이름인 jdbc/OracleDB 로 그 커넥션을 요청하고 소스를 DataSource 객체 ds 에 저장

3. 그 ds 로 커넥션 객체를 구하기

- 테스트파일이라 JSP 로 만들었지만 나중에 완성된 프로그램에선 이 3줄이 DAO 클래스에 들어간다

 

- 커넥션 풀에서 커넥션 하나를 구해왔으면 "연결되었습니다" 가 출력된다

- 커넥션을 잘 구해왔음을 확인 가능

 

- 앞으로 완성된 프로그램은 모두 DBCP 방식으로 처리

- Model 1 으로 완성된 프로그램을 만들자

- 회원관리 기능부터 시작, 양식과 유효성 검사는 이전에 HTML, JS 에서 했던걸 가져오기


Model 1 DBCP 방식으로 회원관리 프로그램 만들기

 

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

1. Connection Pool

2. 액션 태그

- useBean action tag

- setProperty action tag

3. DTO, DAO 클래스

4. 세션(session)

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

 

회원관리 프로그램 : 오라클 계정 생성

- 복잡하므로 새로운 계정 생성해서 작업

- system 계정으로 접속 후 오라클에 새로운 계정을 생성

- 롤을 사용해서 권한 부여

create user totoro identified by totoro123;
grant connect, resource to totoro;

- 콘솔창에서 계정 생성과 권한 부여

 

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

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

- 이클립스에서 Dynamic Web Project 인 member 생성

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

 

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

- 폼과 유효성 검사 파일을 가져오기

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

 

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

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

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

2) lib 폴더 안에 오라클용 JDBC Driver 인 ojdbc.jar 가져오기, 다른 프로젝트에서 가져오면 된다

 

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

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

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

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

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

 

회원관리 프로그램 : 오라클 totoro 계정 커넥션 추가

- Data Source Management 에서 totoro 계정에 대한 Connection 추가

- scott계정 외 totoro 계정 커넥션도 추가

- Oracle 선택

- totoro 계정에 대한 커넥션임을 나타내기 위해 (totoro) 추가

- username, passwd 를 다르게 설정

- 이후 Finish 버튼 누르기

- totoro 계정으로 연결

 

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

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

- HTML 시간의 양식에 맞는 테이블을 그대로 생성해야한다 (아래)

create table member(
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 로 해준다

- member 테이블을 생성

- member 테이블 생성 확인

 

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

- 프로그램 구조도 대로 src 의 member 패키지에 DAO, DTO 클래스를 만든다

 

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

- 이걸 가져와서 DTO 클래스에 복붙

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

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

+ java.sql 의 Timestamp import

- getter / setter 메소드 추가

 

- DTO 클래스 완성 코드

// DTO (Data Transfer Object)

package member;
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

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

 

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

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

 

회원관리 프로그램 : 파일별 기능 및 구조 설명

 

회원관리 프로그램 : 추후 구현할 파일

- memberform.html 등의 폼들은 이전에 만들었던 파일을 그대로 가져왔다

+ 유효성 검사는 이미 되어있다

- member.jsp을 포함한 나머지 파일은 우리가 만들어야한다

- 팝업창으로 ID중복검사도 해보고 Ajax를 써서 비동기로 팝업창을 띄우지 않고 ID 중복검사도 할 것

 

복습

자바빈 관련 액션태그

- useBean, setProperty, getProperty

- 이런 것들을 이용해서 일일히 getParameter() 로 받던 것을 간략하게 쓸 수 있다

- Model 1 에서 자주 쓰임

+ Model 1 에서도 자바 클래스를 2개 씀 (DTO = 자바빈, DAO)

 

useBean action tag

- 프로퍼티에 값을 저장하기 위해 객체를 생성 = 힙메모리상에 값을 저장하기 위해 객체를 생성

- 자바빈 객체명 : sb, 프로퍼티 : name, msg 일때 이 프로퍼티의 주소값을 sb 가 가지고 있다

- Spring 에서도 xml 파일에서 bean 객체를 만들때도 사용한다

 

useBean action tag 속성

useBean action tag 속성 : id

- 객체명

 

useBean action tag 속성 : class 속성

- 자바빈 클래스 경로를 '패키지' 부터 지정

 

useBean action tag 속성 : scope 속성

- bean 객체를 어디까지 쓸건지 지정가능

- 4가지 영역명 (page, request, session, application) 이 scope 값으로 사용됨, 기본값 page

ex) scope 값이 page 면 생성된 bean 객체는 현재 페이지에서만 객체 사용가능

 

setProperty action tag

- 할당된 힙메모리에 값을 저장할때 사용

- setter 메소드를 불러서 값을 설정해줌

- property 속성에 "*" 을 쓰면 이름이 같은 앞쪽 폼에서 넘어오는 값들을 자동으로 자바빈 객체에 저장함

- 앞쪽 폼에서 넘어오는 name 값과 자바빈 프로퍼티의 이름이 같아야만 한다

 

setProperty action tag 속성

setPropertyaction tag 속성 :  name 속성

- useBean 에서 썼던 id 값 , 즉 객체명이 name 속성값

 

setPropertyaction tag 속성 :  value 속성

- 앞쪽 폼에서 값이 넘어오지 않아서 강제로 값을 저장할때 사용

+ 폼에서 넘어오지 않는 값이라도 getter setter 메소드를 만들어야 setProperty value 속성으로 값 전달이 가능하다

 

getProperty action tag

- getter 메소드를 불러서 값을 구해오고 출력까지 시켜줌

- 나중에는 이 태그 대신 getXX() 로 받는 경우가 많음

+ 폼에서 넘어오지 않는 값이라도 getter setter 메소드를 만들어야 getProperty 로 값 전달이 가능하다

 

forward action tag

- 비슷한 코드를 자바코드로 처리하므로 Model 2 에선 자주 사용되지 않음

 


자바빈 클래스

- 폼데이터 처리에 용이

- 재사용 가능, 효율적

- 컴포넌트 기반 구현 (JSP, DTO, DAO 분리되어 별도 기능 수행)
- 생성자를 통해서 프로퍼티에 값 전달이 불가능하므로 자바빈 클래스에서 생성자 대신 setter 메소드를 작성

 

자바빈 클래스 예시

- 들어가는 내용이 정해져 있다

- 필드(프로퍼티), setter 메소드, getter 메소드

 

프로퍼티

- 지금까지는 form 에서 넘어온 값들을 프로퍼티에 저장했음

- form에서 넘어온 값 뿐 아니라 DB 에서 검색한 값도 이 필드, 프로퍼티에 저장됨

- DAO 에서 DB 검색된 값을 저장하기위해 DAO 클래스에서 DTO 객체를 직접 생성해서 자바빈의 프로퍼티에 일시로 저장

- 자바코드인 DAO 에서는 setProperty 를 못쓰므로 setter 메소드로 직접 값 설정, getProperty 못쓰므로 getter 메소드로 직접 값 가져옴

- 중간 저장소 역할

+ action tag 들은 JSP 에서만 사용 가능

 

자바빈 클래스 생성시 주의

- form 에서 넘어온 값을 저장하고 싶다면 form 에서 넘어오는 name값 과 자바빈 프로퍼티 이름이 같아야한다

 

폼에서 넘어오지 않는 값 주의

- 폼에서 넘어오지 않는 값이라도 getter setter 메소드를 만들어야 setProperty value 속성으로 값 전달과 getProperty 로 값 구하는게 가능하다

 

예습

데이터베이스 접속 방식

1. JDBC(Java DataBase Connectivity) 방식

2. DBCP(DataBase Connection Pool) 방식

3. ORM(Object Relational Mapping) 프레임워크

ex) iBatis, MyBatis, hibernate, JPA etc

 

DAO

- 주로 메소드만으로 만들어지는 클래스

- 메소드에서 주로 SQL 문을 수행

- ORM 프레임 워크 로 처리시 간결한 코드 가능 (xml 로 작성)

ex) iBatis, MyBatis, hibernate, JPA etc

 

DTO 와 DAO

- DAO 의 메소드를 사용하기 위해 DTO 객체 주소값을 DAO 에 전달

- insert, update 위해 DAO 클래스에 DTO 객체 주소값을 메소드를 통해서 전달함

 

Model 2

- DTO 클래스와 DAO 클래스를 Model 2 에서도 사용함

- MVC 3가지 영역으로 기능을 분리시켜 개발

- 다음영역으로 넘어갈때 값이나 주소를 DTO 클래스에 저장해서 넘김


자바빈 예제 3

실습 준비

 

 

- 확장자가 java 인 자바빈 파일 LoginBean.java 를 src 안에 넣어야한다

- 패키지명이 beans 이므로 beans 패키지를 만든 후 LoginBean.java 를 그 안으로 복붙한다

 

자바빈 예제 3

- LoginBean.java

package beans;


public class LoginBean {	
	
	// 사용자가 폼에서 입력한 값을 저장하기 위한 필드
	private String userid;
	private String passwd;

	private String _userid;
	private String _passwd;
	
	// 생성자
	public LoginBean() {
		// 인증에 사용할 기본값 설정
		_userid = "myuser";
		_passwd = "1234";
	}
	
	// 아이디와 비밀번호가 맞는지 체크하는 메서드
	public boolean checkUser() {
		if(userid.equals(_userid) && passwd.equals(_passwd))
			return true;
		else
			return false;
	}		
	
	public void setUserid(String userid) {
		this.userid = userid;
	}
	
	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}	
	
	public String getUserid() {
		return userid;
	}
	
	public String getPasswd() {
		return passwd;
	}
}

- userid, passwd 프로퍼티는 사용자가 입력한 폼에서 넘어온 값을 저장하기 위한 필드

- _userid, _passwd 프로퍼티는 DB 에 저장된 값을 저장하기 위한 역할을 하는 필드 (DAO 관련)

- 로그인에 성공하기 위해서는 userid 와 _userid , passwd 와 _passwd 값이 일치되어야만 로그인 성공

- 여기선 DB 연결을 하진 않고 _userid 는 "myuser", _userpasswd 는 "1234" 로 생성자를 통해서 할당하도록 설정해뒀다

- 아이디와 비밀번호가 맞는지 확인하는 메소드인 checkUser() 가 있다, 이 메소드는 나중에 DAO 클래스에 있음

+ 자바빈의 프로퍼티가 private 이므로 getter setter 메소드로 값을 구해와야한다

+ 생성자 와 checkUser() 는 원래 DAO 클래스에 들어가야하는 내용임

 

- login_form.html

<html>
	<head><title>JSP Bean example</title>
	<meta charset="euc-kr">
	<script>

	</script>
	</head>

<body bgcolor="#FFFFFF" onLoad="document.myform.userid.focus()">
<center>
<H2>로그인 예제</H2>
<HR>

<form method="post" action="login.jsp" name="myform">
  <table width="250" border="1" align="center" bordercolordark="#FF0033" cellspacing="0" cellpadding="5">
    <tr bgcolor="#FF6666"> 
    <td colspan="2" height="21"> 
      <div align="center"><b><font size="2">로그인</font></b></div>
    </td>
  </tr>
  <tr bgcolor="#FFCCCC"> 
      <td> 아이디</td>
      <td> <b> 
        <input type="text" name="userid" size=10>
        </b> </td>
  </tr>
  <tr bgcolor="#FFCCCC"> 
      <td> 패스워드</td>
      <td> 
        <input type="password" name="passwd" size=10>
      </td>
  </tr>
  <tr bgcolor="#FFCCCC"> 
    <td height="42" colspan="2"> 
      <div align="center">
        <input type="submit" value="로그인" onClick="check()">
      </div>
    </td>
  </tr>
</table>
</form>
<p>

</body>
</html>

- login_form.html 은 가장 먼저 실행해야할 파일이다

- 사용자가 입력한 아이디와 패스워드를 login.jsp 로 post 방식으로 전송함

- 아이디의 name 값은 userid, 패스워드의 name 값은 passwd

 

- 결과 캡처

- 맞는 아이디, 패스워드 입력시

- 틀린 아이디, 패스워드 입력시

 

- login.jsp

<%@ page contentType="text/html;charset=euc-kr" %>
<jsp:useBean id="login" class="beans.LoginBean" />
<jsp:setProperty name="login" property="*" />

<HTML>
	<HEAD><TITLE> 로그인 예제 </TITLE></HEAD>
<BODY>
<center>
<H2>로그인 예제</H2>
<HR>

<% 
	if(!login.checkUser()) {
		out.println("로그인 실패 !!");	
	}else {
		out.println("로그인 성공 !!");
	}
%>

<HR>
사용자 아이디 : <jsp:getProperty name="login"  property="userid" /><BR>
사용자 패스워드 : <jsp:getProperty name="login" property="passwd" />
</BODY>
</HTML>

- login_form.html 에서 넘어가는 파일이다

- userBean action tag 로 login 이라는 자바빈(beans.LoginBean) 객체를 만든다, 힙메모리상에 프로퍼티 저장할 공간 생성

- setProperty action tag 로 객체 login 의 userid, passwd 프로퍼티에 넘어온 폼에서 넘어온 userid, passwd 값이 저장됨

- userBean action tag 로 Bean 객체를 만들때 생성자가 호출되었으므로 _userid 는 "myuser", _passwd 는 "1234" 로 설정

- 나중에 이 _userid, _passwd 는 DB 에서 가져온 값이 될 것이다

- 자바빈 객체의 checkUser() 메소드를 호출하여 아이디값과 비밀번호 값이 DB에 저장된 값인 _userid 와 _passwd 와 값이 같은지 체크함, 이 메소드는 나중에 DAO 클래스에 있음

+ userBean action tag 는 내부적으로 생성자 호출

+ setProperty action tag 는 내부적으로 setter 메소드 사용하므로 setter 메소드가 만들어져 있어야함, getter 도 마찬가지

+ 자바빈의 프로퍼티가 private 이므로 getter setter 메소드로 값을 구해와야한다

- getProperty 로 login 객체의 userid, passwd 프로퍼티값을 구해와서 출력함

 

자바빈 예제 4

실습 준비

- 확장자가 java 인 자바빈 파일 JoinBean.java 를 src 안에 넣어야한다\

- 패키지명이 join 이므로 join 패키지를 src 안에 만들고 패키지 안에 JoinBean.java 를 복붙한다

 

자바빈 예제 4

- JoinBean.java (자바빈 클래스)

package join;

public class JoinBean {
	private String id;
	private String pass;
	private String name;
	private String sex;
	private int age;
	private String email;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPass() {
		return pass;
	}
	public void setPass(String pass) {
		this.pass = pass;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	
}

- 프로퍼티와 각 프로퍼티의 getter setter 메소드 들이 있다

- 나이를 저장하는 프로퍼티인 age 의 자료형이 int 임을 주의해야함, 나중에 사용자가 나이 입력시 String 형 으로 들어온다

+ sex 의 자료형이 String 이다 (수정)

 

- joinForm.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"%>
<html>
<head>
<title>회원가입 폼</title>
</head>
<body>
<center>
<form action="joinChk.jsp" method="post">
<table border=0>
	<tr>
		<td align=right bgcolor="yellow"><font size=2>아이디 : </font></td>
		<td bgcolor="yellow"><input type="text" name="id"></td>
	</tr>
	<tr>
		<td align=right bgcolor="yellow"><font size=2>비밀번호 : </font></td>
		<td bgcolor="yellow"><input type="password" name="pass"></td>
	</tr>
	<tr>
		<td align=right bgcolor="yellow"><font size=2>이름 : </font></td>
		<td bgcolor="yellow"><input type="text" name="name"></td>
	</tr>
	<tr>
		<td align=right bgcolor="yellow"><font size=2>성별 : </font></td>
		<td bgcolor="yellow">
			<input type="radio" name="sex" value="남자"><font size=2>남</font>
			<input type="radio" name="sex" value="여자"><font size=2>여</font>
		</td>
	</tr>
	<tr>
		<td align=right bgcolor="yellow"><font size=2>나이 : </font></td>
		<td bgcolor="yellow"><input type="text" name="age"></td>
	</tr>
	<tr>
		<td align=right bgcolor="yellow"><font size=2>이메일주소 : </font></td>
		<td bgcolor="yellow"><input type="text" name="email"></td>
	</tr>
	<tr>
		<td align=center bgcolor="yellow" colspan=2>
			<input type="submit" value="가입">
			<input type="reset" value="다시 작성">
		</td>
	</tr>
</table>
</form>
</center>
</body>
</html>

- 가장 먼저 실행해야 하는 파일

- 가입하는 양식 폼이고 name 값은 자바빈 프로퍼티이름과 같게 설정한다

+ sex 의 자료형이 String 형이므로 라디오버튼에서 value 가 "남자" "여자" 라는 String 형이 됨, 즉 넘어가는 값이 String 형

 

- 결과 캡처

 

- joinChk.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"%>
<%request.setCharacterEncoding("euc-kr");%>
<jsp:useBean id="join" class="join.JoinBean"/>
<jsp:setProperty name="join" property="*"/>

<html>
<head>
<title>회원가입 입력 정보 확인 페이지</title>
</head>
<body>
<center>
<table border=1>
	<tr>
		<td bgcolor="yellow"><font size=2>아이디 : </td>
		<td bgcolor="yellow"><jsp:getProperty name="join" property="id"/></td>
	</tr>
	<tr>
		<td bgcolor="yellow"><font size=2>비밀번호 : </td>
		<td bgcolor="yellow"><jsp:getProperty name="join" property="pass"/></td>
	</tr>
	<tr>
		<td bgcolor="yellow"><font size=2>이름 : </td>
		<td bgcolor="yellow"><jsp:getProperty name="join" property="name"/></td>
	</tr>
	<tr>
		<td bgcolor="yellow"><font size=2>성별 : </td>
		<td bgcolor="yellow">
		<%-- <jsp:getProperty name="join" property="sex"/></td> --%>
		<%=join.getSex() %></td>
	</tr>
	<tr>
		<td bgcolor="yellow"><font size=2>나이 : </td>
		<td bgcolor="yellow"><jsp:getProperty name="join" property="age"/></td>
	</tr>
	<tr>
		<td bgcolor="yellow"><font size=2>이메일주소 : </td>
		<td bgcolor="yellow"><jsp:getProperty name="join" property="email"/></td>
	</tr>
</table>
</center>
</body>
</html>

- 한글값이 넘어올 수 있으므로 한글 인코딩을 한다

- useBean action tag 로 join 패키지의 JoinBean 이라는 자바빈 클래스의 객체 join 을 만든다, import 필요없음

- 힙메모리상에 기억공간이 생성되고 join 이 stack 에서 주소값을 가지고 있다

- setProperty action tag 로 객체 join 의 프로퍼티에 폼에서 넘어온 이름이 같은 값들을 저장한다
- 필드들의 접근제어자가 private 이므로 setter 메소드로 값을 전달하는것, 즉 setProperty 사용

- getProperty action tag 로 힙메모리에 저장된 프로퍼티 값을 가져와서 출력한다

- getProperty 는 setProperty 처럼 한꺼번에 처리 불가능하고 아이디 따로 비밀번호 따로 성별 따로 작성해야한다

+ sex 의 자료형을 int 에서 String 으로 수정한 이후 getProperty action tag 가 안되서 직접 getSex() 로 값을 불러옴

 

자바빈 예제 5

- javabean3 폴더의 내용

- DB 연동된 내용이므로 DB 연동 학습 한 후 돌아오기

- DAO 클래스를 만들어서 DB 연동을 한다

- 회원가입, 로그인, 삭제, 수정 등의 내용

 

+ 태그 중 지시어 태그 중 사용자 정의 태그라는 JSTL 만 남아있다 <%@ taglib %>

 


JSP DB 연동

JSP 와 Oracle 연동

 

데이터베이스 접속 방식 3가지

1. JDBC(Java DataBase Connectivity) 방식

- 이 방법으로 자바와 오라클 연동

- JDBC 드라이버 로딩하는데 시간 소요, 접속자 많으면 서버 부하

- 자바코드 대신 JSP 코드로 작성한다는 점만 다르고 자바-오라클 연동할 때와 같다

 

2. DBCP(DataBase Connection Pool) 방식

- 미리 Connection Pool 에 연결을 시켜둠 (Pool = 뭔가 모아둔 것, Connection Pool = 커넥션을 모아둔 것)

- 필요한 경우에 Connection Pool 에서 하나를 빌려와서 연결을 하고 연결 닫으면 Pool에 반환함

- 접속자가 많거나 접속이 빈번한 경우 주로 사용하는 방식

 

3. ORM(Object Relational Mapping) 프레임워크 

ex) iBatis, MyBatis, hibernate, JPA etc

- Object = DTO 객체, Mapping = 연결

- 프레임워크를 사용하면 매핑을 통해서 DB 에서 검색한 결과를 바로 DTO 객체에 저장시켜줌, 코드 간결해지도록 해줌

- 매핑을 위해서 DB 쪽 테이블의 컬럼명과 DTO 클래스의 필드명이 일치되어야함

+ 즉, 나중에는 form의 name값과 DTO 클래스의 필드명과 DB 테이블의 컬럼명, 총 3개의 이름이 일치해야 연동이 수행됨

- MyBatis 중심으로 설명할 것 (Model 1, Model 2, Spring, SpringBoot 와 모두 연동됨)

- 전자정부 프레임워크에선 MyBatis 주로 사용

- JDBC, DBCP 방식으로 먼저 하고 다음에 ORM 프레임 워크를 사용할 것

- 간단한 테스트 할때는 JDBC 방식 사용

 

JDBC 아키텍처

- 중간에 Driver 가 반드시 필요하다, DB 를 만든 회사 홈페이지에서 구할 수 있다

- 오라클과 연동하려면 오라클용 JDBC Driver 가 필요함, 그게 ojdbc6.jar 파일 (xe 버전)

 

JDBC Driver 환경 설정 (저장 위치)

- 자바 오라클 연동시엔 자바가 설치된 곳에 ojdbc6.jar 에 넣었다

- JSP 오라클 연동시엔 JDBC Driver를 자바가 설치된 곳에 저장해도 되고, 아파치 톰캣이 설치된 곳에 저장해도 되고, 프로젝트의 WebContent/WEB-INF/lib 폴더에 저장해도 된다

- 프로젝트의 WEB-INF/lib 에 저장시 import 시 이 Driver 도 같이 import 되고 export 시 Driver 도 같이 export 되므로 편하다

+ 나중에는 Maven 으로 드라이버 관리

 

JDBC Driver 사용해서 DB 연동

- 자바-오라클 연동과 거의 같다

- 자바코드가 JSP 코드로 바뀐다는 점만 다르다

 

1. 맞는 JDBC Driver 를 프로젝트의 WEB-INF/lib 에 가져온다

- 지금은 클라우드에 있는 오라클용 JDBC Driver 와 mysql 용 JDBC Driver 를 jspproject/WebContent/WEB-INF/lib 에 복붙

 

2. DB 연동 테스트를 위한 파일을 WebContent 폴더에 가져온다

- 클라우드에 있는 DB 연동 테스트 파일 JDBC_Con.jsp 가 있는 JDBC 폴더를 WebContent 폴더에 가져옴

- 지금은 JSP 파일에서 연동 테스트 하지만 나중엔 DAO 클래스에서 테스트

 

3. Oracle 데이터베이스 활성화

 

3-1)

3-2)

 

4. DB 연동 테스트

- JDBC_Con.jsp

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="java.sql.*" %>

<%
  Connection con=null;

  try{

/***************** My-SQL 연결 설정하는 부분 *****************************/
//    String driver = "com.mysql.jdbc.Driver";

//    String jdbcUrl = "jdbc:mysql://localhost:3306/jsptest";
//    String dbId = "jspid";
//    String dbPass = "jsppass";	
/************************************************************************/	


/**************** Oracle 연결 설정하는 부분 *****************************/
    String driver = "oracle.jdbc.driver.OracleDriver";  	

    String jdbcUrl = "jdbc:oracle:thin:@localhost:1521:xe";
    String dbId = "scott";
    String dbPass = "tiger";
/************************************************************************/


	Class.forName(driver);	// JDBC Driver Loading
	con=DriverManager.getConnection(jdbcUrl,dbId ,dbPass );
	
	out.println("제대로 연결되었습니다.");

	} catch(Exception e){ 

		e.printStackTrace();

	}
%>

- DriaverManater 클래스 쓰기 위해 java.sql 패키지 import

- DB 연동시 반드시 예외처리를 해야한다

<MySQL 연결>

- db 인 jsptest 에 id 인 jspid 와 비밀번호인 jsppass 적기

- 주석을 풀어서 MySQL 연동시도시 연동 성공 확인 했다

<Oracle 연결>

- db 인 xe 에 id인 scott 과 비밀번호인 tiger 적기

<그 뒤>

- OracleDriver 라는 바이트코드를 Class.forName() 으로 메모리상으로 로딩

- 접속되면 connection 객체가 생성되고 연결되었다는 메세지 출력

- 로딩이 안되면 catch 로 가서 오류 출력

 

- 여기까지가 DB 연결시 공통적인 코드, 뒤에 select, insert, delete, update 등 작성

- 결과 캡처 (Oracle 연동 성공)

 

- JSP 로 하는 것은 처음이자 마지막, 이후엔 Java 클래스인 DAO 클래스에서 DB 연동

 

JSP-오라클 연동 예제

실습 준비

- 지금은 JSP 파일로 DB 연동할것, 나중에 DAO 클래스에서 DB 연동

- DB 연동하여 insert 등 하기 위해 scott 계정에 테이블 하나를 만들어야한다

create  table  member1( 
	id varchar2(12) primary key,
	passwd varchar2(12) not null,
	name varchar2(10) not null,
	reg_date timestamp not null );

- 이 테이블을 scott 계정에 만들기

- WebContent 폴더에 sql 폴더를 만들고 안에 myoracle.sql 파일 만들기

- myoracle.sql 에서 커넥션 프로파일 설정 후(Oracle_11, New Oracle(scott), xe)

- 이미 생성된 member1 테이블이 없다는 것 확인 후 테이블 생성

- id 는 primary key, 나머지 컬럼은 not null 제약조건

- 나머지는 JSP 파일로 데이터 입력, 수정, 검색, 삭제 할 것

- JSP 로 하는 것은 처음이자 마지막, 이후엔 Java 클래스인 DAO 클래스에서 DB 연동

 

JSP-오라클 연동 예제 1

- insertTestForm.jsp

<%@ page contentType="text/html; charset=euc-kr" %>

<html>
<head><title>레코드 삽입(추가)예제</title>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
	$(document).ready(function(){
		$("form").submit(function(){
			if($("#id").val()==""){
				alert("ID를 입력 하세요");
				$("#id").focus();
				return false;
			}
			if($("#passwd").val()==""){
				alert("비밀번호를 입력 하세요");
				$("#passwd").focus();
				return false;
			}
			if($("#name").val()==""){
				alert("이름을 입력 하세요");
				$("#name").focus();
				return false;
			}
		});
		
	});
</script>
</head>

<body>
  <h2>member1 테이블에 레코드삽입(추가)예제</h2>

  <FORM METHOD="post" ACTION="insertTest.jsp">
    아이디 : <INPUT TYPE="text" NAME="id" id="id"><p>
    패스워드 : <INPUT TYPE="password" NAME="passwd" id="passwd"><p>
    이름:<INPUT TYPE="text" NAME="name" id="name"><p>
    <INPUT TYPE="submit" VALUE="보내기">
  </FORM>

</body>
</html>

- 가장 먼저 실행하는 파일

- 폼을 만들고 유효성 검사를 했다

- 값을 입력후 '보내기' 를 누르면 insertTest.jsp 로 값이 넘어감

 

- insertTest.jsp

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="java.sql.*"%>

<%
  request.setCharacterEncoding("euc-kr");

  String id= request.getParameter("id");
  String passwd= request.getParameter("passwd");
  String name= request.getParameter("name");
  Timestamp register=new Timestamp(System.currentTimeMillis());

  Connection conn=null;
  PreparedStatement pstmt=null;
  int result = 0;
  
  try{
	String jdbcUrl="jdbc:oracle:thin:@localhost:1521:xe";
    String dbId="scott";
    String dbPass="tiger";
	 
	// JDBC 방식
	Class.forName("oracle.jdbc.driver.OracleDriver");
	conn=DriverManager.getConnection(jdbcUrl,dbId ,dbPass );
	
	String sql= "insert into member1 values (?,?,?,sysdate)";
	pstmt=conn.prepareStatement(sql);
	pstmt.setString(1,id);
    pstmt.setString(2,passwd);
	pstmt.setString(3,name);
//	pstmt.setTimestamp(4,register);
	result = pstmt.executeUpdate();

	}catch(Exception e){ 
		e.printStackTrace();
	}finally{
		if(pstmt != null) try{pstmt.close();}catch(SQLException sqle){}
		if(conn != null) try{conn.close();}catch(SQLException sqle){}
	}
%>

<html>
<head><title>레코드 삽입(추가)예제</title></head>
<body>
  
<%
	if(result == 1){
%>    
  		<script>
  			alert("회원가입 성공");
  			location.href="selectTest.jsp";
  		</script>
<% 	}else{%>
   		<script>
			alert("회원가입 실패");
			history.go(-1);
   		</script>
<% 	} %>   
</body>
</html>

- 자바빈 안쓰고 JSP 만으로 파일 작성하고 있으므로, request.getParameter() 로 받고있음

- 나중엔 DAO, DTO 자바 클래스 사용

- 한글값 인코딩과 폼에서 넘어온 값을 getParameter() 로 받고 있다

- result 가 1이면, 즉 insert 를 성공하면 회원가입 성공 메세지를 띄우고 목록인 selectTest.jsp 로 간다

- result 가 1이 아니면, 즉 isnert 실패시 회원가입 실패 메세지를 띄우고 이전페이지인 회원가입 페이지인 insertTestForm.jsp 로 돌아감

ex) 중복아이디로 회원가입 시도시 insert 실패

+ 수정/삽입 부분은 아래에

 

DB 연동 (insertTest.jsp 부분)

  Connection conn=null;
  PreparedStatement pstmt=null;
  int result = 0;
  
  try{
	String jdbcUrl="jdbc:oracle:thin:@localhost:1521:xe";
    String dbId="scott";
    String dbPass="tiger";
	 
	// JDBC 방식
	Class.forName("oracle.jdbc.driver.OracleDriver");
	conn=DriverManager.getConnection(jdbcUrl,dbId ,dbPass );
	
	String sql= "insert into member1 values (?,?,?,sysdate)";
	pstmt=conn.prepareStatement(sql);
	pstmt.setString(1,id);
    pstmt.setString(2,passwd);
	pstmt.setString(3,name);
//	pstmt.setTimestamp(4,register);
	result = pstmt.executeUpdate();

	}catch(Exception e){ 
		e.printStackTrace();
	}finally{
		if(pstmt != null) try{pstmt.close();}catch(SQLException sqle){}
		if(conn != null) try{conn.close();}catch(SQLException sqle){}
	}

- 자바-오라클 연동할떄와 같은 코드

- 필요한 객체를 만들고 try-catch-finally 로 예외처리

+ PreparedStatemet 는 SQL문을 실행시켜주는 역할

- Class.forName() 으로 오라클용 JDBC 로딩, DriverManager.getConnection(url,username,passwd) 으로 connection 객체 생성

- insert sql 문을 사용해서 값을 삽입, 4번째 자리는 sysdate 오라클 함수로 바로 날짜 입력

+ id, passwd, name 의 자료형이 varchar2 이므로 setString() 메소드로 값을 설정

+ sysdate를 대신 사용하므로 위의 Timestamp 객체는 사용되지 않음

+ int result 로 몇개가 삽입 성공했는지 받음, insert 는 1개씩 되므로 성공시 1을 리턴

- finally 에서 close() 로 닫아줌

* DB 연동 절차 설명 아래에

 

- 결과 캡처 (전체 흐름)

- 게시판 형태로 만들어졌으므로 가입 후 목록페이지로 보냄

- 아이디 중복되지 않게 여러명 더 가입시켜보자

- 수정 페이지로 감

- 비밀번호가 맞을때만 수정됨

- 삭제도 마찬가지

+ 수정/삽입 부분은 아래에


DB 연동 절차

1. Class.forName() 으로 JDBC Driver 를 로딩한다

2. Connection 객체로 DB 연결함

- DriverManager 클래스의 getConnection() 으로 객체를 가져옴

3. SQL 문 생성 (객체 생성)

- SQL 문 실행하는 방법은 3 가지이다

- Statement 는 " " 가 복잡했다, PreparedStatement 는 값이 들어갈 위치에 ? 

- 저장프로시저를 실행할때 exe 나 execute 로 실행했지만 자바로 실행할땐 CallableStatement 사용

4. SQL 문 전송 (실행)

- select문은 executeQuery() 사용, 나머지 DML 은 executeUpdate() 사용

 

SQL 문 전송 (실행)

- select 는 검색한 결과를 ResultSet 객체가 저장하고 있다

- insert / update / delete 된 데이터 개수를 반환


JSP-오라클 연동 예제 1 이어서

- selectTest.jsp (목록)

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="java.sql.*"%>

<html>
<head><title>테이블의 레코드를 화면에 표시하는 예제</title></head>
<body>
  <h2>member1 테이블의 레코드를 화면에 표시하는 예제</h2>
  
  <a href="insertTestForm.jsp">회원가입</a>
  <TABLE width="550" border="1">
  <TR>
  	<TD width="100">아이디</TD>
  	<TD width="100">패스워드</TD>
  	<TD width="100">이름</TD>
  	<TD width="250">가입일자</TD>
  	<TD width="100">수정</TD>
  	<TD width="100">삭제</TD>
  </TR>

<%
  Connection conn=null;
  PreparedStatement pstmt=null;
  ResultSet rs=null;
  ResultSet rs01=null;
  int cnt=0;
  
  try{
	String jdbcUrl="jdbc:oracle:thin:@localhost:1521:xe";
    String dbId="scott";
    String dbPass="tiger";
	 
	Class.forName("oracle.jdbc.driver.OracleDriver");
	conn=DriverManager.getConnection(jdbcUrl,dbId ,dbPass );

	pstmt=conn.prepareStatement("select count(*) from member1");
	rs01=pstmt.executeQuery();
	if(rs01.next()){
		cnt = rs01.getInt(1);
//		cnt = rs01.getInt("count(*)");
	}	
	
	String sql= "select * from member1";
	pstmt=conn.prepareStatement(sql);
	rs=pstmt.executeQuery();

	while(rs.next()){
	  String id= rs.getString("id");
      String passwd= rs.getString("passwd");
      String name= rs.getString("name");
      Timestamp register=rs.getTimestamp("reg_date");

%>
     <TR>
  	   <TD width="100"><%=id%></TD>
  	   <TD width="100"><%=passwd%></TD>
  	   <TD width="100"><%=name%></TD>
  	   <TD width="250"><%=register.toString()%></TD>
  	   <TD width="100">
  	   		<a href="updateTestForm.jsp?id=<%=id%>">
  	  		 수정
  	   		</a>  	   
  	   </TD>
  	   <TD width="100">
  	   		<a href="deleteTestForm.jsp?id=<%=id %>">
  	   		 삭제
  	   		</a>
  	   </TD>
    </TR>
<%  } 
  }catch(Exception e){ 
		e.printStackTrace();
  }finally{
	    if(rs != null) try{rs.close();}catch(SQLException sqle){}
		if(pstmt != null) try{pstmt.close();}catch(SQLException sqle){}
		if(conn != null) try{conn.close();}catch(SQLException sqle){}
  }
%>
</TABLE>

총 회원수:<%=cnt %>명


</body>
</html>

- '회원가입' 을 누르면 insertTestForm.jsp 로 넘어간다

- select sql 문을 2개 써서 회원 목록, 총 회원수 를 구하고 있다

- 안에 타이틀을 출력하고 DB 연결해서 검색한 데이터를 뿌려준다

 

<회원수>

- 검색한 총 회원수를 구하기 위해 cnt 변수를 만듬, 그룹함수 count(*) 를 쓰고 결과를 rs01 이라는 ResultSet 객체에 반환

- 결과가 1개이므로 if 문 사용 rs01.next() 와 rs01.getInt(1) 또는 rs01.getInt("count(*)") 을 사용해서 결과 count(*) 를 구해옴

<회원목록>

- 다음으로 회원 목록을 구해오기 위해 select * from member 를 executeQuery() 로 실행

- while 문과 rs.next() 로 하나씩 데이터를 가져와서 출력하고 있다, 출력까지 while문임

- while 문 안에서 데이터를 가져오는 자바코드는 스크립틀릿 태그 안에, 출력하는 html 코드는 스크립틀릿 태그 바깥에 작성, while 문 괄호 잘 보기

- 컬럼의 자료형이 varchar2 이므로 getString() 메소드로 값을 구해옴

+ number 타입이면 getInt() , 즉 컬럼 자료형마다 값을 설정하고 구해오는 메소드가 다름

 

- select sql 문을 2개 쓰므로 ResultSet 객체를 2개 만듬, 전역변수처럼 try 바깥에 선언해야만 finally 에서도 사용가능

+ 날짜 시간을 원하는 포멧으로 바꾸고 싶다면 출력시 Timestamp 와 SimpleDateFormat 사용해야한다

 

'수정' 버튼 눌렀을때 수정폼으로 넘어가기 (selectTest.jsp 부분)

  	   		<a href="updateTestForm.jsp?id=<%=id%>">
  	  		 수정
  	   		</a>

- '수정' 누르면 수정폼인 updateTestForm.jsp 로 하이퍼링크 통해 이동

- 지금은 session 을 쓰지 않고있기 때문에 updateTestForm 으로 id 값을 넘겨줘야함

- get 방식으로 값이 넘어간다, "전달할파일명?변수명=값" 방식으로 값을 넘김

- 이때 값은 DB 에서 가져온 id 이다

- 나중에 이 값을 받으려면 getParameter() 로 받음

 

 

공통코드

	Class.forName("oracle.jdbc.driver.OracleDriver");
	conn=DriverManager.getConnection(jdbcUrl,dbId ,dbPass );

 

- 결과 캡처

 

+ 날짜 시간을 원하는 포멧으로 바꾸기 (selectTest.jsp 수정)

- 년월일시분초 로 출력

- DB 에 저장된 날짜는 어떤 타입이도 상관없다, 출력할때 바꾸어야한다

- Timestamp 와 SimpleDateFormat 사용해야한다

 

+ 나중에 Model 2 에선 SimpleDateFormat 사용불가하므로 JSTL 지원 라이브러리로 처리

+ 페이징 처리 되지 않았으므로 한페이지에 모든 데이터가 나타난다

+ 페이징 처리시 서브쿼리 형태의 인라인 뷰와 rownum 사용

 

- updateTestForm.jsp (수정폼)

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="java.sql.*"%>

<%
  String uid=request.getParameter("id");

  Connection conn=null;
  PreparedStatement pstmt=null;
  ResultSet rs=null; 
  
  try{
	String jdbcUrl="jdbc:oracle:thin:@localhost:1521:xe";
    String dbId="scott";
    String dbPass="tiger";
	 
	Class.forName("oracle.jdbc.driver.OracleDriver");
	conn=DriverManager.getConnection(jdbcUrl,dbId ,dbPass );
	
	String sql= "select * from member1 where id=?";
	pstmt=conn.prepareStatement(sql);
	pstmt.setString(1, uid);
	rs=pstmt.executeQuery();

	if(rs.next()){
	  String id= rs.getString("id");
      String passwd= rs.getString("passwd");
      String name= rs.getString("name");
      Timestamp register=rs.getTimestamp("reg_date");

%>
<html>
<head><title>레코드 수정예제</title></head>

<body>
  <h2>member1 테이블의 레코드 수정예제</h2>

  <FORM METHOD="post" ACTION="updateTest.jsp">
  <input type=hidden name="id" value="<%=id %>">
    아이디 : <%=id %><p>
    패스워드 : <INPUT TYPE="password" NAME="passwd"><p>
    변경할 이름:<INPUT TYPE="text" NAME="name" value="<%=name%>"><p>
    <INPUT TYPE="submit" VALUE="보내기">
  </FORM>

</body>
</html>

<%  } // if end
  }catch(Exception e){ 
		e.printStackTrace();
  }finally{
	    if(rs != null) try{rs.close();}catch(SQLException sqle){}
		if(pstmt != null) try{pstmt.close();}catch(SQLException sqle){}
		if(conn != null) try{conn.close();}catch(SQLException sqle){}
  }
%>

- 목록인 selectTest.jsp 에서 get 방식으로 넘어온 id 변수에 전달된 id 값을 request.getParamter() 로 받는다

- id 값은 DB 에서 비밀번호를 끄집어낼때도 필요하고, 데이터를 수정하기 위해서 where 절에 들어가는 용도로도 필요하다

- id 값은 수정할 수 없도록 보여주기만하고 패스워드, 변경할 이름을 입력

- 변경할 이름 입력창에는 DB 에서 가져온 이름을 나타냄, 그걸 지우고 변경할 이름을 쓰게끔함

- where 절에서 id 를 이용해서 단 한명의 정보를 구해서 구해졌다면 form 을 통해 updateTest.jsp 로 비밀번호, 변경할 이름 전송

- 넘어온 id로 select 를 수행해서 비밀번호를 끄집어내는 select 문과, 비밀번호가 맞는 경우 변경할 이름으로 수정하는 update 문은 다음인 updateTest.jsp 에서 실행함

- 여기선 비밀번호와 변경할 이름을 입력받고 비밀번호, 변경할 이름을 form 을 통해 updateTest.jsp 로 전송함

- 아이디값은 hidden 객체로 updateTest.jsp 로 넘김

- 즉 총 3가지 정보, 아이디, 패스워드, 변경할 이름이 updateTest.jsp 로 넘어감

 

+

    패스워드 : <INPUT TYPE="password" NAME="passwd"><p>

- name 변수인 "passwd" 에 사용자가 입력한 패스워드가 form 을 통해 전달됨

 

hidden 객체로 id 값 넘기기 (updateTestForm.jsp 부분)

- 아이디값은 입력차이 아니므로 넘어가지 않음, 파일끼리 내부적으로 넘기기위해 hidden 객체를 사용해서 넘김

- select 를 수행해서 비밀번호를 끄집어내는 select 문과, 비밀번호가 맞는 경우 변경할 이름으로 수정하는 update 문을 쓰기 위해 id 가 필요하므로 넘겨줘야한다

  <input type=hidden name="id" value="<%=id %>">

 

+ 주의 : 테이블의 이름이 저장되는 공간 크기가 10byte 고 한글 한글자는 3byte 이므로 3 글자까지만 입력 / 수정 가능

 

- updateTest.jsp

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="java.sql.*"%>

<%
  request.setCharacterEncoding("euc-kr");

  String id= request.getParameter("id");
  String passwd= request.getParameter("passwd");
  String name= request.getParameter("name");

  Connection conn=null;
  PreparedStatement pstmt=null;
  ResultSet rs=null;

  try{
	String jdbcUrl="jdbc:oracle:thin:@localhost:1521:xe";
    String dbId="scott";
    String dbPass="tiger";
	 
	Class.forName("oracle.jdbc.driver.OracleDriver");
	conn=DriverManager.getConnection(jdbcUrl,dbId ,dbPass );
	
	String sql= "select id, passwd from member1 where id= ?";
	pstmt=conn.prepareStatement(sql);
    pstmt.setString(1,id);
	rs=pstmt.executeQuery();
    
	if(rs.next()){ // id가 있으면
		String rId=rs.getString("id");
		String rPasswd=rs.getString("passwd");
      if(id.equals(rId) && passwd.equals(rPasswd)){
	    sql= "update member1 set name= ?, reg_date=sysdate  where id= ? ";
	    pstmt=conn.prepareStatement(sql);
	    pstmt.setString(1,name);
	    pstmt.setString(2,id);
	    pstmt.executeUpdate();
	   
%>
		<script>
			alert("회원 정보 수정 성공");
			location.href="selectTest.jsp";
		</script>	
<%
       }else{
 %>
	 <script>
	 	alert("비밀번호가 틀렸습니다");
	 	history.go(-1);
	 </script>
	 	
<% 	 
		}
	 }else{
%>
		<script>
			alert("아이디가 틀렸습니다.");
			history.go(-1);
		</script>
<%
	 }

	}catch(Exception e){ 
		e.printStackTrace();
	}finally{
		if(rs != null) try{rs.close();}catch(SQLException sqle){}
		if(pstmt != null) try{pstmt.close();}catch(SQLException sqle){}
		if(conn != null) try{conn.close();}catch(SQLException sqle){}
	}
%>

- 이름 등에서 한글값이 post 방식으로 넘어가므로 한글 인코딩

- request.getParameter() 로 값을 받아서 updateTestForm.jsp 에서 넘어온 아이디, 패스워드, 변경할 이름값을 변수에 저장

- id는 중복되지 않고, 한명의 정보이므로 if문 사용, if(rs.next()) 에서 id 와 같은 아이디가 DB에 있다면 안의 내용이 실행됨

+ id는 hidden 으로 넘어오므로 id 가 틀릴일은 없다

- 넘어온 아이디값을 where 절에 넣어서 select 문으로 DB의 아이디와 패스워드를 끄집어냄

- 그 후, if 문 안의 if 문에서, 수정폼에서 넘어온 아이디와 DB의 아이디가 같고, 수정폼에서 넘어온 패스워드와 DB의 패스워드가 같으면 update 문 수행 해서 이름, 아이디, 날짜 수정

- 비번 불일치시 if 문안의 else 문에서 "비밀번호가 틀렸습니다" 출력 후 다시 수정폼으로 돌아감

 

- 비밀번호 맞는 경우

- 가입일자도 수정한 시간으로 변경됨

- 비밀번호 틀린 경우

 

- deleteTestForm.jsp (삭제폼)

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="java.sql.*"%>

<%
  String uid=request.getParameter("id");

  Connection conn=null;
  PreparedStatement pstmt=null;
  ResultSet rs=null; 
  
  try{
	String jdbcUrl="jdbc:oracle:thin:@localhost:1521:xe";
    String dbId="scott";
    String dbPass="tiger";
	 
	Class.forName("oracle.jdbc.driver.OracleDriver");
	conn=DriverManager.getConnection(jdbcUrl,dbId ,dbPass );
	
	String sql= "select * from member1 where id=?";
	pstmt=conn.prepareStatement(sql);
	pstmt.setString(1, uid);
	rs=pstmt.executeQuery();

	if(rs.next()){
	  String id= rs.getString("id");
      String passwd= rs.getString("passwd");
      String name= rs.getString("name");
      Timestamp register=rs.getTimestamp("reg_date");

%>
<html>
<head><title>레코드 삭제예제</title></head>

<body>
  <h2>member1 테이블의 레코드 삭제예제</h2>

  <FORM METHOD="post" ACTION="deleteTest.jsp">
  <input type=hidden name="id" value="<%=id %>">
  <%--   아이디 : <%=id %><p> --%>
    패스워드 : <INPUT TYPE="password" NAME="passwd"><p>
   <%--  이름:<%=name%><p> --%>
    <INPUT TYPE="submit" VALUE="삭제">
  </FORM>

</body>
</html>

<%  } // if end
  }catch(Exception e){ 
		e.printStackTrace();
  }finally{
	    if(rs != null) try{rs.close();}catch(SQLException sqle){}
		if(pstmt != null) try{pstmt.close();}catch(SQLException sqle){}
		if(conn != null) try{conn.close();}catch(SQLException sqle){}
  }
%>

- 목록인 selectTest.jsp 파일에서 get 방식으로 넘어온 id 값을 getParameter() 로 받아서 변수 uid 에 저장

- 삭제폼에서 아이디나 이름등을 보여주지 않아도 되므로 수정과 달리 DB 연동하는 코드가 없어도 된다

- 폼을 통해서 hidden 객체로 아이디 값을 전달하고 (<%=id%> 대신 <%=uid%> 도 가능), 사용자가 삭제폼에 입력한 패스워드를 전달함, 즉 2개를 전달함

- 삭제폼에 맞는 비밀번호를 입력했을때 delete sql 문으로 데이터 삭제하는건 다음인 deleteTest.jsp

 

- deleteTest.jsp

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="java.sql.*"%>

<%
  request.setCharacterEncoding("euc-kr");

  String id= request.getParameter("id");
  String passwd= request.getParameter("passwd");

  Connection conn=null;
  PreparedStatement pstmt=null;
  ResultSet rs=null;

  try{
	String jdbcUrl="jdbc:oracle:thin:@localhost:1521:xe";
    String dbId="scott";
    String dbPass="tiger";
	 
	Class.forName("oracle.jdbc.driver.OracleDriver");
	conn=DriverManager.getConnection(jdbcUrl,dbId ,dbPass );
	
	String sql= "select id, passwd from member1 where id= ?";
	pstmt=conn.prepareStatement(sql);
    pstmt.setString(1,id);
	rs=pstmt.executeQuery();
    
	if(rs.next()){ 	 // id가 있으면
		String rId=rs.getString("id");
		String rPasswd=rs.getString("passwd");
      if(id.equals(rId) && passwd.equals(rPasswd)){	// 비번 일치시
	    sql= "delete from member1 where id= ? ";
	    pstmt=conn.prepareStatement(sql);
	    pstmt.setString(1,id);
	    pstmt.executeUpdate();
%>
			<script>
				alert("회원 삭제 성공");
				location.href="selectTest.jsp";
	    	</script>
<%	    
	   }else{	// 비번 불일치시
%>
		  <script>
		  	alert("비밀번호가 틀렸습니다.");
		  	history.go(-1);
		  </script>
<%	   }%>


<% }else{ %>

		<script>
			alert("ID가 틀렸습니다.");
			history.go(-1);
		</script>
		
<%	
	 } 

	}catch(Exception e){ 
		e.printStackTrace();
	}finally{
		if(rs != null) try{rs.close();}catch(SQLException sqle){}
		if(pstmt != null) try{pstmt.close();}catch(SQLException sqle){}
		if(conn != null) try{conn.close();}catch(SQLException sqle){}
	}
%>

- deleteTestForm.jsp 에서 넘어온 아이디와 비밀번호를 getParatmeter() 로 받는다

- 사용자가 입력한 비밀번호값이 DB 의 비밀번호와 일치하는지 확인하기 위해 DB 연결을 하고 select 문 실행

- id 값을 통해 DB 에 저장된 id 와 passwd 를 가져옴

- if(rs.next()) 는 'id 값이 있으면' 이란 의미

- hidden 으로 넘어온 id 와 DB 의 id 가 일치하고, 사용자가 삭제폼에서 입력한 비번과 DB 의 비번이 일치하면 delet 수행

 

 

- 자바를 쓰지 않고 JSP 만으로 오라클 연동하는 처음이자 마지막 예제다

- 그 다음부터는 DAO 클래스로 DB 연동을 처리한다 + DTO 클래스


DAO 클래스

- DB 연동을 처리해주는 클래스가 DAO 클래스이다

- 메소드만으로 구성되어있음

- JSP 파일에서 DAO의 메소드를 호출해서 insert / update / delete 한다

- select 를 DAO 에서 한 후, 검색한 결과를 JSP 파일로 돌려준다

- Model 1, Model 2, Spring 에서 모두 사용

 

DAO 클래스로 DB 연동

+ DTO(자바빈) 클래스와도 연동

- 이미 만들어진 JSP 파일에다가 DAO, DTO 를 추가하여 만들고 연동하기

- 이미 만들어진 JSP 파일들

- 이걸로 DAO, DTO 연습 후 완성된 프로그램으로 넘어갈 것

 

DAO 클래스로 DB 연동 예제 1

1. 실습 준비 및 테이블 생성

+ DAO / DTO 클래스가 없어서 생기는 오류

- JSP 파일들은 다 있고 필요한 아래의 테이블을 먼저 생성해야함

create  table  member2( 
			id varchar2(12) primary key,
			passwd varchar2(12) not null,
			name varchar2(10) not null,
			jumin1 varchar2(6) not null,
			jumin2 varchar2(7) not null,
			email varchar2(30),
			blog varchar2(50),
			reg_date date not null);

- sql/myoracle.sql 에서 테이블 생성 완료

 

- 이제 DAO, DTO 클래스 만들 것

- DAO / DTO 클래스 이 패키지로 만들기

 

2. DTO / DAO 클래스 만들기

JavaBeanMember.register - LogonDataBean.java (DTO)
JavaBeanMember.register - LogonDBBean.java (DAO)

- JavaBeanMember.register 패키지 먼저 생성 후 class 자바 파일 만들기

 

3. DTO 클래스 만들기

- 오라클의 자료형을 자바의 자료형으로 가져온다

- 접근제어자는 private, varchar2 는 String, number 는 int 로, date 는 Date로 변경

- getter setter 메소드 추가

- DTO 클래스 완성

- LogonDataBean.java

// DTO (Data Transfer Object)
package JavaBeanMember.register;
import java.util.Date;

public class LogonDataBean {

	private String id;	// 프로퍼티
	private String passwd;
	private String name;
	private String jumin1;
	private String jumin2;
	private String email;
	private String blog;
	private Date reg_date;
	
	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 getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getBlog() {
		return blog;
	}
	public void setBlog(String blog) {
		this.blog = blog;
	}
	public Date getReg_date() {
		return reg_date;
	}
	public void setReg_date(Date reg_date) {
		this.reg_date = reg_date;
	}
	
}

 

4. DAO 클래스 만들기

- DB 연동은 이제 모두 DAO 클래스에서 처리

- 메소드만으로 구성

- JSP 에서 DAO 의 메소드를 호출해서 sql 문 실행

- Singleton 사용해서 객체 생성 1번만 수행해서 공유함

- 객체를 생성하자

- static 을 붙여서 공유, 외부에서 접근 못하도록 private 설정, 정적메소드인 getInstance() 를 통해서만 접근 가능

- getInstance() 메소드 만들기

- 이제 이 아래에 메소드를 생성함

- 그 메소드를 JSP 에서 호출 (registerPro.jsp 부분)

복습

공유

- Model 2에서 주로 공유 설정할때 request 객체 와 session 객체를 사용한다

 

forward action tag

- 페이지를 이동시켜주는 역할

- 이 태그가 포함된 페이지는 출력되지 않고 바로 포워딩됨

- 계속해서 forwarding 되면 최종적으로 이동한 곳까지가 REQUEST 영역

 

전체 흐름

- 우리가 지금 쓰고 있는 파일들은 Java Servlet 으로 변환된다. 

- 변환된 Java Servlet 을 컴파일 수행하여 바이트코드 만들어서 실행하면

- 실행코드 HTML 로 변환해서 클라이언트의 웹 브라우저가 그걸 출력

 

include action tag vs include directive tag (include 지시어 태그)

- 불러온 파일과 불려진 파일이 따로 따로 Java Servlet 으로 변환되고 <jsp:include > 로 불러옴

- 불러온 파일과 불려진 파일이 한개의 파일로 결합되서 Java Servlet 파일이 1개 만들어짐 include action tag 로 불러옴

 

include action tag

- 다른 문서를 불러온다

- 공통적인 내용을 따로 만들고 모듈화된 내용을 불러서 사용

- 값을 전달할 수도 있다

- include action tag 는 불러온 파일과 불려진 파일이 따로 Servlet 클래스로 만들어짐

- 3가지 형식이 있다

 

1.

<jsp : include page = "포함될 페이지명 " flush = "true | false" />

2.

<jsp : include page = "포함될 페이지명" flush = "true|false" ></jsp : include>

3. 다른 문서를 불러오면서 값을 전달하는 기능이 있다

- 불러온 파일과 불려진 파일이 따로 Servlet 클래스로 만들어지므로 값을 전달하는 게 가능

<jsp : include page = "포함될 페이지명" flush = "true|false">
	<jsp : param name = "paramName1" value = "var1" />
	<jsp : param name = "paramName2" value = "var2" />
</jsp : include>

 

flush 속성

- 포함될 페이지로 이동할 때 현재 페이지가 지금까지 출력 버퍼에 저장된 결과를 어떻게 처리할 것인지 결정

- ture 지정시 포함할 내용 삽입 이전에 현재 페이지가 지금까지 버퍼에 저장한 내용 출력 그 후 포함될 페이지 부름

- 이전에 출력시키지 않겠다는 의미인 false 로 쓰는게 일반적

 

include action tag 예제

실습 준비

- 어제의 forward 와 달리 include는 다른 문서를 불러오는 것이므로 화면에 출력이 된다

 

include action tag 예제 1

- WebContent/include/include1

- includeForm.jsp & includeMain.jsp & includeSub.jsp

- includeForm.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<body>

	<h1>include 액션태그 사용법 예제</h1>

	<form method=post action="includeMain.jsp">
	이름 : <input type="text" name="name"><p>
	<input type="submit" value="보내기">
	</form>	

	</body>
</html>

- form action 인 includeMain.jsp 로 입력한 값인 이름을 전달한다

 

- includeMain.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<body>

	<h1>포함하는 페이지 includeMain.jsp 입니다.</h1>

	<%
		request.setCharacterEncoding("euc-kr");
	%>

	<hr>

	<jsp:include page="includeSub.jsp" flush="false"/>
	includeMain.jsp의 나머지 내용입니다.

	</body>
</html>

- 한글값이 넘어오므로 인코딩 하고 있다

- include action tag 로 인해 불러온 includeSub.jsp 의 내용이 include action tag 가 있는 위치에 출력된다

- forward action tag 와 다르게 inlcude action tag 는 불려진 문서 뿐만 아니라 불러온 현재페이지의 문서도 출력된다

- includeSub.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<%
	String name = request.getParameter("name");
%>

포함되는 페이지 includeSub.jsp 입니다.<p>
<b><%=name%> 님 어서 오세요 !!</b>
<hr>

- 이 페이지에 출력되는 전체 내용이 아까의 includeMain.jsp 파일에 포함되어 출력됨

- forward action tag 와 비슷하게 include action tag 에서도 불려진 문서로 2번 넘어갔지만 form 에서 전달한 값을 request 객체 getParameter() 로 받을 수 있다

 

forward actiont tag vs include action tag

- 공통점 : 페이지가 여러번 넘어가도 form 에서 전달한 값을 request 객체 getParameter() 로 받을 수 있다

- 차이점 : inlcude action tag 는 불려진 문서 뿐만 아니라 불러온 현재페이지의 문서도 출력된다

 

include action tag 예제 2

- WebContent/include/include2

- includeForm2.jsp & includeMain2.jsp & includeSub2.jsp

- includeForm2.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<body>

	<h2>include 액션 태그에서 포함되는 페이지에 값 전달하기</h2>

	<form method=post action="includeMain2.jsp">
	사이트 명 : <input type="text" name="siteName1"><p>
				<input type="submit" value="보내기">
	</form>

	</body>
</html>

- 가장 먼저 실행해야하는 파일

- name 값이 'siteName1' 이다

- '보내기' 를 누르면 action 으로 지정한 페이지 includeMain2.jsp 로 이동하며 전달

 

- includeMain2.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<body>
	
	<h2>includeMain2.jsp 페이지 입니다</h2>

	<%
		request.setCharacterEncoding("euc-kr");
		String siteName1 = request.getParameter("siteName1");
	%>

	<hr>
	<jsp:include page="includeSub2.jsp">
		<jsp:param name="siteName" value="<%=siteName1%>"/>
	</jsp:include>

	includeMain2.jsp 페이지의 나머지 내용입니다.<p>

	</body>
</html>

- 한글 인코딩을 시키고, 아까 form 에서 넘어온 값(사용자 입력값)을 변수 siteName1 변수에 저장

- include action tag 로 다른 문서인 includeSub2.jsp 를 불러오면서 값을 전달하고 있다

- 전달될때 name 값이 siteName

- 전달된 값을 불려지는 문서가 처리가능

- 불러오는 문서와 불려지는 문서가 따로 Servlet 클래스로 만들어지므로 값 전달 가능

+ 우리가 만드는 파일은 전부 확장자가 java 인 Java Servlet 로 변환됨

 

- includeSub2.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<body>

	<%
		String siteName = request.getParameter("siteName");
	%>

	includeSub2.jsp 페이지 입니다.<p>

	<b><%=siteName%></b>
	<hr>

	</body>
</html>

- 전전페이지에서 form 에서 전달된 siteName1 도 getParameter() 로 받을 수 있고 이전의 불러온 페이지에서 전달한 siteName 도 getParameter() 로 받을 수 있다

 

include directive tag (지시어 태그)

- 다른 문서를 불러온다

- 불러올 페이지와 불려지는 페이지가 한개의 파일처럼 동작

- 불러오는 파일과 불려지는 파일끼리 변수를 같이 사용할 수 있다

- 포함태그 = include tag = include directive tag

<%@ include file = "포함될 페이지명" %>

 

include action tag vs include directive tag (지시어 태그)

- include directive tag 는 다른 문서를 불러온다는 점은 include action tag 와 같지만 내부적으로는 다름

- include directive tag 는 불러오는 파일과 불려지는 파일이 1개의 Servlet 클래스(=파일)로 만들어지므로 변수들을 서로 같이 쓸 수 있다

 

include directive tag (지시어 태그) 예제

- WebContent/include/include0

- includer.jsp (불러오는 파일) & includee.jspf (불려지는 파일)

- includer.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<html>
	<head><title>include 디렉티브</title></head>
	<body>

<%
    int number = 10;
%>

<%@ include file="includee.jspf" %>

공통변수 DATAFOLDER = "<%= dataFolder %>"

	</body>
</html>

- 불러올 파일을 includee.jspf 로 지정

+ jspf 의 f 는 fragment 라는 영역을 의미, f를 지우고 includee.jsp 로 바꿔도 된다

- 저 태그가 쓰인 부분에 includee.jsp 를 출력

- 변수 number 는 불러오는 파일에서 정의되었지만 불려지는 파일인 includee.jsp 에서도 사용 가능하다

- 또한 dataFolder 변수는 불려지는 파일에서 정의한 변수이지만 불러오는 파일에서 사용 가능하다

 

- includee.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

includer.jsp에서 지정한 번호: <%= number %>

<p>

<%
    String dataFolder = "c:\\data";
%>

- 불러오는 파일에서 정의한 number 변수를 불려지는 문서에서 쓰고 있다

- 불러오는 파일에서 dataFolder 를 정의하고 불려지는 파일에서 dataFolder 안의 값을 출력하고 있다

 

- 하나의 파일인 것 처럼 동작하므로 불려지는 파일과 불러오는 파일의 변수들을 서로 사용 가능하다

- Java Servlet 으로 변환될때 불려오는 파일과 불러오는 파일이 1개의 Java Servlet 클래스로 만들어짐

 

include action tag vs include directive tag (include 지시어 태그)

- include action tag 로 불러오면 불러온 파일과 불려진 파일이 따로 Java Servlet 으로 변환되고 <jsp:include > 로 불러옴

- include directive tag 로 불러오면 불러온 파일과 불려진 파일이 한개의 파일로 결합되서 Java Servlet 파일이 1개로 만들어짐

 

Java Servlet 파일

- 우리가 작성한 모든 JSP 파일들은 Java Servlet 파일로 내부적으로 변환된다

- 확장자가 java

- 그 변환된 파일들은 workspace 에 있다

C:\Users\admin\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\
work\Catalina\localhost\jspproject\org\apache\jsp

- 여기에 Java Servlet 파일들이 저장되어있다

- 지금껏 작업했던 모든 파일들이 나타남

- 확장자가 JAVA 인 Java Servlet 파일과 바이트코드로 변환된 파일들을 볼 수 있다

 

- 방금 했던 include0 폴더로 들어가보자

- 1개의 Servlet 파일 뿐이다

- 불러오는 파일과 불려지는 파일이 1개 Servlet Class로 동작하는 것이다

- 그러므로 각 파일 안의 변수들을 혼용해서 사용할 수 있다 ( 같은 이름 변수 사용시 충돌가능 )

 

- 방금 했던 include1 폴더로 들어가보자

- include action tag 로 불러온 것은 따로 파일이 만들어짐

- 불러온 파일과 불려진 파일의 Java Servlet 파일이 따로 만들어진다

- 그러므로 include action tag 를 사용할 때는 값을 전달하는 것이 가능하다

- include2 폴더도 include1 폴더와 마찬가지

 

내부 작업

- 작성된 모든 JSP 파일은 내부적으로 Java Servlet 으로 변환됨

- 변환된 파일을 아파치 톰캣이 컴파일해서 바이트 코드로 변환함

- HTML로 변환하여 클라이언트의 웹 브라우저에서 변환된 결과를 실행함

- JSP 파일들을을 서비스할때 시간이 걸리는 이유이다

 

include action tag 사용

- 공통적인 내용을 따로 모듈 파일로 만들고 include action tag 로 불러올때 사용

 

include action tag 사용 예제

실습 준비

 

include action tag 사용 예제 1

- WebContent/template/

- main.jsp & templateTest.jsp

- top.jsp & left.jsp & center.jsp & bottom.jsp

- main.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<jsp:forward page="templateTest.jsp" >
  <jsp:param name="CONTENTPAGE" value="content.jsp"/>
</jsp:forward>

- templateTest.jsp 파일로 포워딩하면서 값을 넘기고 있다, 바로 포워딩

- 넘기는 값은 content.jsp 라는 센터영역에 보여줄 페이지명

- 템플릿 기능임

- main.jsp 를 가장 먼저 실행해야함

- 상단, 좌측, 하단 메뉴는 바뀌지 않고 center 의 내용만 바뀜

- 바뀌지 않는 내용은 따로 파일을 만들어뒀다

 

- templateTest.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<%
   String contentPage = request.getParameter("CONTENTPAGE");
%>

<html>
	<head><title>Template 페이지 연습</title></head>

	<body>

	<table width="600" border="1" cellpadding="2" cellspacing="0" align=center>
		<tr height=80>
			<td colspan="2">
                <!-- 상단 영역 -->
				<jsp:include page="top.jsp" flush="false" />

			</td>
		</tr>
		<tr height=300>
			<td width="150" valign="top">
				<!-- 좌측 영역 -->
				<jsp:include page="left.jsp" flush="false" />

			</td>
			<td width="350" valign="top">
				<!-- 본문 내용 -->
				<jsp:include page="<%= contentPage %>" flush="false" />

			</td>
		</tr>
		<tr height=80>
			<td colspan="2">
				<!-- 하단 영역 -->
				<jsp:include page="bottom.jsp" flush="false" />

		    </td>
		</tr>
	</body>
</html>

- 가장 먼저 request.getParameter() 로 센터영역에 보여줄 페이지명인 content.jsp 를 받아서 변수 contentPage 에 저장

- 표를 작성해서 <tr><td> 안에 모듈화된 상단, 좌측, 센터, 하단 영역 페이지명을 각각 include 해서 불러온다

- center 영역은 고정된 값이 아닌 contentPage 라는 변수에 저장된 값으로 include

 

- top.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

상단 메뉴:
<a href="#">회사소개</a>
<a href="#">제품소개</a>

- 이 내용이 상단 영역에 나타남

 

- left.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

좌측메뉴:<br>
<a href="#">회사소개</a><br>
<a href="#">제품소개</a>

- 이 내용이 좌측 영역에 나타남

 

 

- content.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

하하하하..<br>
내용입니다..

- 이 내용이 center 영역에 나타남

 

 

- bottom.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

하단메뉴: 찾아오시는 길 | 개인보호 정책 | 도움말 | 약관

- 이 내용이 하단 영역에 나타남

 

코드 수정 하기

- '회사소개' 누르면 회사소개 내용이 center 영역에 나타나도록, '제품소개' 누르면 제품소개 내용이 center 영역에 나타나도록 해보자

 

1. top.jsp 파일에서 링크 설정하기

<%@ page contentType = "text/html; charset=euc-kr" %>

상단 메뉴:
<a href="main.jsp">HOME</a>
<a href="comp_forward.jsp">회사소개</a>
<a href="goods_forward.jsp">제품소개</a>

- 'HOME' 을 누르면 초기화면으로 가게끔 main.jsp 를 링크 연결

- '회사소개' 를 누르면 com_forward.jsp 로 가게끔 링크 연결

- '제품소개' 를 누르면 goods_forward.jsp 로 가게끔 링크 연결

- 1개 메뉴당 파일을 2개씩 만들어야한다

 

2. comp_forward.jsp 파일 만들기

- comp_forward.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<jsp:forward page="templateTest.jsp" >
  <jsp:param name="CONTENTPAGE" value="comp.jsp"/>
</jsp:forward>

- main.jsp 파일과 비슷한 형식으로 만든다

- main.jsp 파일을 복붙하고 forwad 로 전달하는 값의 value 가 센터영역에 보여줄 파일명이므로 회사 소개 관련 내용을 보여줄 comp.jsp 로 수정

- 즉, 1개 메뉴당 파일을 2개씩 만들어야한다 ( 보여줄 내용의 파일명을 값으로 전달할 파일 + 실제 보여줄 내용 파일)

- comp_forward.jsp 와 comp.jsp 파일

+ 그럼 templateTest.jsp 에서는 센터 영역에 출력할 파일로 comp.jsp 를 받아서 include 함

 

3. com.jsp 파일 만들기

- comp.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
회사 소개 페이지 입니다. (comp.jsp)
</body>
</html>

- top, left, bottom 은 고정이므로 include 로 불러온다

- 결과 캡처

 

4. goods_forward.jsp 파일 만들기

- goods_forward.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<jsp:forward page="templateTest.jsp" >
  <jsp:param name="CONTENTPAGE" value="goods.jsp"/>
</jsp:forward>

- main.jsp 파일과 비슷한 형식으로 만든다

- main.jsp 파일을 복붙하고 forwad 로 전달하는 값의 value 가 센터영역에 보여줄 파일명이므로 제품 소개 관련 내용을 보여줄 goods.jsp 로 수정

- 즉, 1개 메뉴당 파일을 2개씩 만들어야한다 ( 보여줄 내용의 파일명을 값으로 전달할 파일 + 실제 보여줄 내용 파일)

- goods_forward.jsp 와 goods.jsp 파일

+ 그럼 templateTest.jsp 에서는 센터 영역에 출력할 파일로 goods.jsp 를 받아서 include 함

 

5. goods.jsp 파일 만들기

- goods.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
제품 소개 페이지 입니다. (goods.jsp)
</body>
</html>

 

 

6. main.jsp 실행

- 결과 캡처

- 모듈은 그대로 고정되어있고 center 영역의 내용만 바뀐다

+ 대체할 방법이 많기때문에 꼭 이것만을 사용하지 않아도 된다

 

- 한개 메뉴당 파일을 2개씩 만들었다

- 한개 메뉴당 파일을 1개의 파일로 만들 수 있다

- 다음 예제에서 할 것

 

include action tag 사용 예제 2

실습 준비

 

include action tag 사용 예제 2

- 이전 예제와 다른 점은 하나의 메뉴 당 하나의 파일

- WebContent/temp/

- template.jsp &

- template.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>

<% 
	String pagefile = request.getParameter("page");
	if(pagefile == null){ pagefile = "bestitem";}
%>    
    
<html>
	<head><title>Template Test</title></head>
	<body>
	<table width=960 height=500 border=1 color=gray align=center>
		<tr><td height=43 colspan=3 align=left>
				<jsp:include page="top.jsp" />
			</td>
		</tr>
		<tr><td width=15% align=right valign=top>
				<jsp:include page="left.jsp" />
			</td>
			<td colspan=2 align=center>
				<jsp:include page='<%= pagefile+".jsp" %>'/>
			</td>
		</tr>
		<tr><td width=100% height=40 colspan=3>
				<jsp:include page="bottom.jsp"/>
			</td>
		</tr>
	</table>
	</body>
</html>

- template.jsp 파일을 가장 먼저 실행해야한다

- center 영역만 바뀐다

- page 라는 이름으로 값을 받음 (top.jsp 나 left.jsp 파일로부터 받음)

- 이 template.jsp 는 아래에서도 설명한다

 

 

- top.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>

<a href="template.jsp?page=login">Login</a>
<a href="template.jsp?page=join">Join</a>

- 하이퍼링크를 걸며 값을 전달

- login, join 은 확장자가 생략, 확장자를 빼고 template.jsp 로 전달

ex) Login 클릭시 template.jsp 파일에 page=login 이라는 값을 전달하며 이동

 

- left.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>

<center>
<a href="template.jsp?page=newitem">신상품</a><br><br>
<a href="template.jsp?page=bestitem">인기상품</a><br><br>
</center>

- 하이퍼링크를 걸며 값을 전달

- newitem, bestitem 은 확장자가 생략, 확장자를 빼고 template.jsp 로 전달

ex) '신상품' 클릭시 template.jsp 파일에 page=newitem 이라는 값을 전달하며 이동

 

- template.jsp (다시 돌아가서 보기)

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>

<% 
	String pagefile = request.getParameter("page");
	if(pagefile == null){ pagefile = "bestitem";}
%>    
    
<html>
	<head><title>Template Test</title></head>
	<body>
	<table width=960 height=500 border=1 color=gray align=center>
		<tr><td height=43 colspan=3 align=left>
				<jsp:include page="top.jsp" />
			</td>
		</tr>
		<tr><td width=15% align=right valign=top>
				<jsp:include page="left.jsp" />
			</td>
			<td colspan=2 align=center>
				<jsp:include page='<%= pagefile+".jsp" %>'/>
			</td>
		</tr>
		<tr><td width=100% height=40 colspan=3>
				<jsp:include page="bottom.jsp"/>
			</td>
		</tr>
	</table>
	</body>
</html>

- 아무것도 클릭하지 않았을때 초기 실행시 pagefile = null 이므로 pagefile = "bestitem" 로 함으로서 센터영역에 bestitem.jsp 를 보여줌

-상단, 좌측, 하단에 각각의 모듈을 불러와서 보여줌
- center 영역만 계속 바뀌는데 center 영역에는 top.jsp 나 left.jsp 에서 전달한 값을  pagefile 변수에 저장 후 .jsp 를 붙여서 include 함

ex) top.jsp 에서 login 값을 전달시 login.jsp 를 center 영역에 include

ex) left.jsp 에서 newitem 값을 전달시 newitem.jsp 를 center 영역에 include

 

- newitem.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>

<b>신상품 목록 입니다.</b>

 

include action tag 사용

- 바뀌지 않는 파일을 모듈로 만들고 불러와서 사용

 


자바빈 관련 액션 태그

자바빈 관련 액션 태그

- usebean action tag, setProperty action tag, getProperty action tag

- 자바 클래스와 연동할때 쓰는 액션 태그, 자바빈이라는 클래스와 연동할때 사용

+ 액션 태그 중 forward, include action tag 는 했다

 

자바빈 (JavaBean)

- 자바로 작성된 컴포넌트 클래스를 의미

- Model 1 이지만 자바를 2가지 사용할 것, 그 중 하나

 

자바빈의 장점

1. 폼데이터 처리에 용이하다.

- 폼에서 넘어오는 많은 데이터를 자바빈에 저장하고, 전달할 수 있다.

ex) 회원가입 양식의 수많은 데이터를 받을때 Java Bean(Java Class) 으로 처리시 request 객체의 getParameter() 로 받는 작업을 더는 하지 않아도 됨, 간략한 코드

 

2. 재사용성

- 자바빈은 여러 JSP 파일에서 사용할 수 있다.

- 자바 클래스로 되어있기 떄문에 한번 생성시 재사용이 가능하다는 특징

 

3. 컴포넌트 기반 구현

- JSP, JavaBean(=DTO Class), DAO 클래스가 분리되어서, 각 컴포넌트로 별로 기능을 수행하므로 효율적 처리 가능

 

JSP Model 1 아키텍처

- 브라우저를 통해 클라이언트가 요청 ex) 가입버튼 클릭

- JSP 페이지라는 action 으로 지정된 페이지에서 받음 ex) 값이 넘어감

- JSP 페이지에서 action tag 를 사용함

- Java Bean에서 (=DTO 생성해서) 변수사용, 힙메모리상에서 할당받아 값을 사용

- DB 연동하는 DAO 클래스에서 메소드를 통해 불러옴, 데이터를 처리

 

JavaBean 작성법

 

- 가장 위에 패키지를 만들고 클래스를 만든다

- 필드, 메소드만 있다

1. 필드

- 외부 접근 막기 위해 필드는 주로 private 으로 설정함

- 멤버변수 = 필드 를 Java Bean에서는 property (프로퍼티) 라고 부름

2. 메소드

- 생성자 대신 setter 메소드로 필드값을 설정함

+ 값을 돌려주는것은 getter 메소드로 값을 돌려줌

 

JavaBean 특징 정리

- 즉 JavaBean 에는 필드와 getter, setter 메소드들만 들어간다

- 자바빈에 저장하고, 저장된 값을 가져오고 객체 생성하기위해 action tag 사용, 그게 3가지 액션 태그

- property 는 폼에서 넘어간 내용도 저장하고 DB 에서 검색한 값도 저장하는 중간 저장소 처럼 사용

- 프로퍼티는 JSP 페이지의 내용을 DB 에 저장하거나 DB 에 저장된 내용을 JSP 페이지에 출력할때 중간 데이터 저장소로 사용됨

- 자바빈에서 멤버변수를 property 라고 부른다

- 프로퍼티(property) 는 값을 저장하기 위한 필드로 접근 제어자를 private 으로 선언해서 작성

- 프로퍼티에 값을 저장할 때는 setXX() 메소드 사용, 저장된 값을 사용할 때는 getXX() 메소드 사용

- 하나의 프로퍼티 당 한쌍의 setXX() 메소드와 getXX() 메소드가 존재

- setXX() 메소드와 getXX() 메소드에서는 주로 public 접근 제어자 사용

 

자바빈 관련 액션 태그

1. useBean action tag : 자바빈 객체 생성

2. setProperty action tag : setter 메소드의 매개변수로 값을 전달

3. getProperty action tag : getter 메소드로 리턴된 값을 출력시켜줌

 

자바빈 파일 저장 위치

- 여태까지 JSP 파일은 WebContent 폴더에 넣었었다

- 자바빈 파일은 자바파일이므로 자바빈을 만들떄는 src 폴더 안에 패키지를 만들어서 저장해야함

 

자바빈 예제 1

실습 준비

+ 확장자가 java 파일은 WebContent 폴더에서 정상동작하지 않음, 나중에 src 폴더로 보낼 것

- 확장자가 java 인 SimpleBean.java 가 JavaBean 파일이다

- 이 파일 내용을 src 폴더 안에 새로 만들어서 따라서 작성하자

- 패키지 javaBean 을 주의

 

src 폴더 안에 JavaBean 만들기

- src 폴더 안의 자바빈 클래스를 작성하자

 

자바빈 예제 1

- 자바빈 파일인 SimpleBean.java 파일을 src 폴더에 직접 만들자

- jspproject/src/javaBean/

- SimpleBean.java

// 자바빈, DTO(Data Transfer Object)
package javaBean;

public class SimpleBean {
	
	private String msg;	// 프로퍼티

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}
	
}

- 자바빈 클래스 안에는 프로퍼티(필드), getter 메소드, setter 메소드 이다

- 생성자는 잘 쓰지 않고 setter 메소드로 프로퍼티 값을 설정한다

 

+ 이클립스에서 getter / setter 만들기

 

- 다음으로 WebContent/javabean1/ 으로 돌아오자

- SimpleBeanForm.jsp 먼저 실행

- SimpleBeanForm.jsp

<%@ page contentType="text/html; charset=euc-kr" %>

<html>
	<body>

	<h1>간단한 자바빈 프로그래밍</h1>
	<br>

	<form action="simpleBean.jsp" method="post" >
	<table width="500" border="0" cellspacing="0" cellpadding="3" align="left">
		<tr> 
			<td width="100"> 메시지</td>
			<td width="400"> 
				<input type="text" name="msg" size="20" maxlength="30">
				<input type="submit" name="send" value="보내기">
			</td>
		</tr>
	</table>
	</form>

	</body>
</html>

- form 을 통해 msg 라는 name값으로 사용자의 입력값이 simpleBean.jsp 로 넘어감

- 위 코드는 1번 과정이다

- 지금까지는 1 로 요청을 하면 getParameter() 로 일일히 받았지만 이젠 Java Bean 에 저장 (=힙 메모리상에 저장) 할것

 

- SimpleBean.jsp

<%@ page contentType="text/html; charset=euc-kr" %>
<% request.setCharacterEncoding("euc-kr");%>

<jsp:useBean id="sb" class="javaBean.SimpleBean" />
<jsp:setProperty name="sb" property="msg" />

<html>
	<body>

	<h1>간단한 자바빈 프로그래밍</h1>
	<br>

	메시지: <jsp:getProperty name="sb" property="msg" />

	</body>
</html>

- post 로 넘어온 한글 값이 깨지지 않도록 인코딩 한다

- 각종 자바빈 관련 액션태그들을 사용하고 있다

- 지금까지는 1 로 요청을 하면 getParameter() 로 일일히 받았지만 이젠 액션태그로 Java Bean 으로 처리, 2번 과정

 

useBean action tag

<jsp:useBean id="sb" class="javaBean.SimpleBean" />

- 가장 먼저 써야함

- class 속성에 우리가 사용할 자바빈을 패키지부터 경로를 설정해야함

- 이렇게 경로 설정시 import 하지 않아도 내부적으로 자동 import 함

- 이 자바빈으로 객체를 생성하는 역할을 함
- 앞쪽 form 에서 넘어온 msg 를 저장할 힙메모리 기억공간을 생성하는 것이다

- 객체 명은 id 속성값인 sb 이다

+ 객체를 생성 = 힙메모리에 공간 할당

+ useBean 으로는 객체 생성하며 생성자를 통해 값 전달 안되므로 생성자 대신 setter 메소드를 썼던 것

 

- 아래 코드와 같은 역할을 한다

<%@ page import = "javaBean.SimpleBean" %>
<%
	SimpleBean sb = new SimpleBean();
%>
// useBean action tag 는 이 코드와 같은 역할

 

setProperty action tag

<jsp:setProperty name="sb" property="msg" />

- msg 의 접근제어자가 private 이므로 setter 메소드를 써서 값을 설정

- 접근 제어자가 private 인 프로퍼티에 값을 설정하는 역할

- 객체명 sb 와 property 에 msg 를 쓰면 내부적으로 setMsg() 메소드를 호출해서 값을 sb 객체의 msg 변수에 form 에서 전달된 msg 값을 할당함

- 즉, setProperty action tag 에서 param 속성을 생략하고 property 속성만 지정하면 form 에서 전달받은 매개변수 중 같은 매개변수 값을 자동으로 설정해준다

- 결론적으로 이 msg 라는 넘어온 입력값이 sb 객체의 msg 변수에 할당된다 (아래 주의사항 참고)

 

- 아래 코드와 같은 역할을 한다

	sb.setMsg("안녕");

 

주의 사항

- 앞의 form 에서 넘어오는 name 값 과 자바빈 클래스에서 사용하는 프로퍼티 명이 일치해야함

- 현재는 msg 로 일치한다

 

getProperty action tag

	메시지: <jsp:getProperty name="sb" property="msg" />

- 메모리에 저장되어있는 sb 객체의 msg 프로퍼티 값을 내부적으로 getter 메소드로 불러서 출력까지 시켜준다

- sb 객체의 msg 에 저장된 값을 구해와서 출력함, 즉 이때까지 사용자의 입력값을 메모리에 한번 저장시킨 후 불러온 것

 

- 아래 코드와 같은 역할을 한다

	메세지: <%=sb.getMsg() %>

 

- simpleBeanForm.jsp 실행 결과

+ 환경설정 파일 또는 자바파일 수정시 서버 재시작 해야함

- 폼에서 전달한것을 메모리 상에서 저장했다가 끄집어 내서 출력하고 있다

 

+ 이후 DB 연동 위해선 DAO 클래스까지 만들어야하지만 지금은 DTO 까지의 예시

 

코드 수정 하기

- 이름을 입력하도록 양식에 한 줄 더 추가하자

- 즉 name과 msg 두가지 값을 전달해보자

- simpleBeanForm.jsp (수정)

<%@ page contentType="text/html; charset=euc-kr" %>

<html>
	<body>

	<h1>간단한 자바빈 프로그래밍</h1>
	<br>

	<form action="simpleBean.jsp" method="post" >
	<table width="500" border="0" cellspacing="0" cellpadding="3" align="left">
		<tr>
			<td>이름</td>
			<td><input type=text name="name"></td>
		</tr>
		<tr> 
			<td width="100"> 메시지</td>
			<td width="400"> 
				<input type="text" name="msg" size="20" maxlength="30">
				<input type="submit" name="send" value="보내기">
			</td>
		</tr>
	</table>
	</form>

	</body>
</html>

 

- src/javaBean/SimpleBean.java (수정)

// 자바빈, DTO(Data Transfer Object)
package javaBean;

public class SimpleBean {
	
	private String name;
	private String msg;	// 프로퍼티
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getMsg() {
		return msg;
	}
	public void setMsg(String msg) {
		this.msg = msg;
	}

}

- 이 자바빈의 프로퍼티 값을 가입 양식의 name 값과 일치시켜야한다

 

- simpleBean.jsp

<%@ page contentType="text/html; charset=euc-kr" %>
<% request.setCharacterEncoding("euc-kr");%>
<%@ page import = "javaBean.SimpleBean" %>
<%
	SimpleBean sb1 = new SimpleBean();
//	sb1.msg = "hi";	// 접근 안됨 (private 접근 제어자)
	sb1.setMsg("안녕");
%>

<jsp:useBean id="sb" class="javaBean.SimpleBean" />
<jsp:setProperty name="sb" property="msg" />
<jsp:setProperty name="sb" property="name"/>

<html>
	<body>

	<h1>간단한 자바빈 프로그래밍</h1>
	<br>
	
	메세지: <%=sb.getMsg() %> <br>
	메시지: <jsp:getProperty name="sb" property="msg" />

	</body>
</html>

+ getProperty() 에는 출력시키는 코드도 내장되어있으므로 출력도 시킴

- getProperty() 보다 getXX() 를 더 많이 사용한다

- 이유 : getProperty() 는 확장자가 jsp 인 파일에서만 사용가능하므로 DAO 클래스에서 메모리에 저장된 걸 불러오려면 getProperty() 대신 직접 getXX() 을 더 많이 사용함

 

- 결과 캡처

- 사용자가 입력한 값을 메모리상에 저장하고 저장된 값을 불러와서 출력하고 있다

 

+ setProperty action tag 한줄로 값 설정

- simpleBean.jsp 의 앞 파일의 form 에서 name 과 msg 가 넘어온다

- setProperty action tag 를 두번 사용하고 있다, 두개의 값이 넘어오면 두줄이 필요하다

- 여러개의 값이 넘어오더라도 한줄로 처리할 수 있는 방법이 있다

<jsp:setProperty name="sb" property="*" />

- 이 코드로 인해 여러개가 넘어오더라도 값을 모두 setter 메소드로 설정한다

- form 의 name 과 이름값이 일치하는 자바빈의 property 로 form 에서 넘어온 값들이 자동으로 저장됨

- 이 한줄만으로 request.getParameter() 를 일일히 쓸 필요가 없어짐

- 조건 : 가입하는 양식 form 의 name 값과 자바빈의 property 명이 같아야한다

 

흐름 정리

 

useBean action tag 속성

scope 속성값

- 생성된 객체를 어디까지 사용할건지 사용 범위 지정

- 객체명이 아닌 4가지 영역명 중 하나를 적는다 page, request, session, application

- page : 현재 파일에서만 객체 사용 가능

- session : 세션이 끊어질때까지 Bean 객체 사용 가능

 

setProperty action tag 속성

value 속성

- form 에서 값이 넘어오지 않는 경는 것을 저장하고자 할때 ex) 날짜, 시간은 폼에서 넘어오지 않음

- setter 메소드에 직접 매개변수로 넣을것을 지정가능

 

getProperty action tag 속성

+ DAO 에서 사용될 수 없으므로 나중에는 잘 쓰지 않는 태그

 

자바빈 예제 2

실습 준비

- 자바빈 파일인 MemberInfo.java 파일을 src 폴더에 둬야한다

- MemberInfo.java의 패키지는 madvirus.member

- 이 패키지를 src 안에 생성하고 그 안에 MemberInfo.java 를 복붙하자

 

자바빈 예제 2

- MemberInfo.java

package madvirus.member;

import java.sql.Timestamp;

public class MemberInfo {
    
    private String id;
    private String password;
    private String name;
    private String address;
    private Timestamp registerDate;
    private String email;
    
    public String getId() {
        return id;
    }
    public void setId(String val) {
        this.id = val;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String val) {
        this.password = val;
    }
    public String getName() {
        return name;
    }
    public void setName(String val) {
        this.name = val;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String val) {
        this.address = val;
    }
    public Timestamp getRegisterDate() {
        return registerDate;
    }
    public void setRegisterDate(Timestamp val) {
        this.registerDate = val;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String val) {
        this.email = val;
    }
}

- 6개의 프로퍼티와 각 프로퍼티의 getter / setter 메소드들로 구성되어있다

- 4개는 폼에서 넘어와서 메모리로 저장됨

- password 와 registerDate 는 폼에서 넘어오지 않으므로 setProperty 로 강제로 집어넣을 것

 

- 실행할땐 registerForm.jsp 실행해야한다

- registerForm.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<html>
	<head><title>회원가입 입력 폼</title></head>
	<body>
	
	<form action="register.jsp" method="post">

	<table border="1" cellpadding="0" cellspacing="0">
		<tr><td>아이디</td>
			<td colspan="3"><input type="text" name="id" size="10"></td>
		</tr>
		<tr><td>이름</td>
			<td><input type="text" name="name" size="10"></td>
			<td>이메일</td>
			<td><input type="text" name="email" size="10"></td>
		</tr>
		<tr><td>주소</td>
			<td colspan="3"><input type="text" name="address" size="30"></td>
		</tr>
		<tr><td colspan="4" align="center">
				<input type="submit" value="회원가입">
			</td>
		</tr>
	</table>

	</form>

	</body>
</html>

- form 을 통해 register.jsp 로 값을 전달

- 아이디의 name 값 "id", 이름의 name 값 "name", 이메일의 name 값 "email", 주소의 name 값 "address" 4가지 정보 전달

- 이 4가지 값은 Java Bean Class 에 저장될 것

 

- register.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<%
    request.setCharacterEncoding("euc-kr");
%>

<jsp:useBean id="memberInfo" class="madvirus.member.MemberInfo" />
<jsp:setProperty name="memberInfo" property="*" />
<jsp:setProperty name="memberInfo" property="password"
                 value="<%= memberInfo.getId() %>" />

<html>
		<head><title>가입</title></head>
		<body>

		<table width="400" border="1" cellpadding="0" cellspacing="0">
			<tr><td>아이디</td>
				<td><jsp:getProperty name="memberInfo" property="id" /></td>
				<td>암호</td>
				<td><jsp:getProperty name="memberInfo" property="password" /></td>
			</tr>
			<tr><td>이름</td>
				<td><jsp:getProperty name="memberInfo" property="name" /></td>
				<td>이메일</td>
				<td><jsp:getProperty name="memberInfo" property="email" /></td>
			</tr>
			<tr><td>주소</td>
				<td colspan="3"><jsp:getProperty name="memberInfo" property="address" /></td>
			</tr>
		</table>

		</body>
</html>

+ 한글값이 form 에서 넘어올 수 있으므로 인코딩

- 사용자가 입력한 id 값을 메모리에 저장하고 저장된 값을 불러와서 value 속성으로 강제로 password 값으로 집어넣었음

- 폼에서 4가지 정보만 입력했지만 '암호' 를 포함해서 5가지 정보 출력되게 된다

+ 넘어가는 순서 : registerForm.jsp -> register.jsp -> MemberInfo.java

 

1. useBean action tag 로 Bean 객체 생성 (register.jsp부분)

<jsp:useBean id="memberInfo" class="madvirus.member.MemberInfo" />

- class 값은 패키지부터 해당 클래스명까지 써야한다

- 이렇게 경로 설정하면 import 할 필요 없다

- memberInfo 라는 객체 생성, 그 memberInfo 객체가 id, name, email, address 등을 가리킨다

 

2. setProperty action tag 로 자바빈의 프로퍼티에 값 설정 (register.jsp부분)

<jsp:setProperty name="memberInfo" property="*" />
<jsp:setProperty name="memberInfo" property="password"
                 value="<%= memberInfo.getId() %>" />

<첫 줄 코드>

- 폼에서 넘어온 4가지 정보 id, name, email, address 를 자바빈의 같은 이름 프로퍼티로 저장

<두번째 코드>

- property 속성값으로 password 를 쓰면 내부적으로 setPassword() 의 매개변수로 값을 전달하라는 의미

- 폼에서 넘어오지 않은 password 를 강제로 자바빈 프로퍼티에 넣기 위해 value 속성 자리에 memberInfo.getId() 로 자바빈에 저장된 id 값을 불러와서 자바빈의 password 로 넣고 있다

- 폼에서 넘어오지 않은 값인 password 와 registerDate 를 강제로 자바빈 프로퍼티에 넣기위해 value 속성으로 강제로 집어넣기, 여기선 password 만 넣고 있다

- 그러면 id 값과 password 값이 메모리상에 같은 값으로 저장된다

 

+ 넘어오지 않은 값을 자바빈의 프로퍼티에 저장하고 싶을땐 setProperty action tag 의 value 속성 사용

 

3. getProperty action tag 로 자바빈의 프로퍼티 값 가져와서 출력 (register.jsp부분)

			<tr><td>아이디</td>
				<td><jsp:getProperty name="memberInfo" property="id" /></td>
				<td>암호</td>
				<td><jsp:getProperty name="memberInfo" property="password" /></td>
			</tr>

- 자바빈 객체에 저장된 아이디값을 불러서 출력, 암호를 불러서 출력 하고 있다

- 나머지도 같다

 

- 결과 캡처

- 받은 결과를 메모리상에 저장하고 다시 불러와서 출력하고 있다

- 입력시엔 4가지 정보만 입력하지만

- 암호까지 5가지 정보가 출력됨

- 아이디와 암호가 같은 값으로 나옴

- 입력하지 않았지만 내부적으로 처리

 

+ 코드 수정 하기 1

- 날짜인 registerDate 도 처리하자

- 가입시 날짜를 메모리상에 저장하고 불러서 출력해보자

 

- register.jsp (수정)

<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import="java.sql.Timestamp"%>

<%
    request.setCharacterEncoding("euc-kr");
%>

<jsp:useBean id="memberInfo" class="madvirus.member.MemberInfo" />
<jsp:setProperty name="memberInfo" property="*" />
<jsp:setProperty name="memberInfo" property="password"
                 value="<%= memberInfo.getId() %>" />
<jsp:setProperty name="memberInfo" property="registerDate"
                 value="<%= new Timestamp(System.currentTimeMillis()) %>" />

<html>
		<head><title>가입</title></head>
		<body>

		<table width="400" border="1" cellpadding="0" cellspacing="0">
			<tr><td>아이디</td>
				<td><jsp:getProperty name="memberInfo" property="id" /></td>
				<td>암호</td>
				<td><jsp:getProperty name="memberInfo" property="password" /></td>
			</tr>
			<tr><td>이름</td>
				<td><jsp:getProperty name="memberInfo" property="name" /></td>
				<td>이메일</td>
				<td><jsp:getProperty name="memberInfo" property="email" /></td>
			</tr>
			<tr><td>주소</td>
				<td colspan="3"><jsp:getProperty name="memberInfo" property="address" /></td>
			</tr>
			<tr><td>날자</td>
				<td colspan="3"><jsp:getProperty name="memberInfo" property="registerDate" /></td>
			</tr>
		</table>

		</body>
</html>

- password 뿐 아니라 날짜시간인 registerDate 도 강제로 저장

- 자바빈 클래스에서 날짜시간 registerDate 는 자료형이 Timestamp 이므로 Timestamp 객체를 만들어서 그 객체를 생성자의 매개변수로 넣어야한다, 즉 그 객체를 setProperty 의 value 에 넣어야한다

- Timestamp 클래스를 페이지 지시어 태그로 import 해야한다

 

- 등록 날짜가 찍혀 나온다

 

+ 코드 수정 하기 2

- 날짜 시간을 년월일시분초 로 출력되도록 수정

- 출력하는 곳에 getProperty() 대신 getXX() 메소드로 직접 날짜 시간을 불러와서 SimpleDateFormat 객체 생성해서 패턴 지정하고 적용시켜야함

- register.jsp (수정)

<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import="java.sql.Timestamp"%>
<%@ page import="java.text.SimpleDateFormat"%>

<%
    request.setCharacterEncoding("euc-kr");
%>

<jsp:useBean id="memberInfo" class="madvirus.member.MemberInfo" />
<jsp:setProperty name="memberInfo" property="*" />
<jsp:setProperty name="memberInfo" property="password"
                 value="<%= memberInfo.getId() %>" />
<jsp:setProperty name="memberInfo" property="registerDate"
                 value="<%= new Timestamp(System.currentTimeMillis()) %>" />

<%
	SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEE요일");
%>

<html>
		<head><title>가입</title></head>
		<body>

		<table width="400" border="1" cellpadding="0" cellspacing="0">
			<tr><td>아이디</td>
				<td><jsp:getProperty name="memberInfo" property="id" /></td>
				<td>암호</td>
				<td><jsp:getProperty name="memberInfo" property="password" /></td>
			</tr>
			<tr><td>이름</td>
				<td><jsp:getProperty name="memberInfo" property="name" /></td>
				<td>이메일</td>
				<td><jsp:getProperty name="memberInfo" property="email" /></td>
			</tr>
			<tr><td>주소</td>
				<td colspan="3"><jsp:getProperty name="memberInfo" property="address" /></td>
			</tr>
			<tr><td>날짜</td>
				<td colspan="3"><%=sd.format(memberInfo.getRegisterDate()) %></td>
			</tr>
		</table>

		</body>
</html>

- 출력할때 메모리상에 저장된 날짜시간값을 가져온 후 패턴을 적용한다

- 이때 getProperty 는 불가능하므로 getRegisterDate() 라는 getter 메소드를 직접 사용해서 날짜시간 변수인 registerDate 를 가져옴


+ 메모리상 내용지우고 새로 메모리로 로딩 (빨간줄 삭제)

- Project-Clean..


Model 2

- Controller 클래스 만들때 Java Servlet 으로 만든다

- View 페이지에 출력할때 표현 언어(EL) 사용 

- JSTL 사용자 정의 태그 : 태그를 만들어서 사용 <%@ taglib %>

-> Model 2 전에 Java Servlet, EL(표현언어), JSTL 학습할 것

 

Spring

- Model 2 빠른 개발 위한 프레임 워크

 

내장 객체 메소드 찾아보기

- Java EE 라이브러리의 클래스/인터페이스를 찾아서 내장객체 사용

- Java EE 라이브러리는 Apache Tomcat 에 설치되어있다

ex) JavaEE -> Apache Tomcat lib 폴더의 servlet-api.jar 파일 안에 있다

 


JSP의 영역

- 4가지 영역에 대한 각각의 내장 객체들이 공유 영역 설정

기본  영역 쓰임새
pageContext PAGE (한번의 요청을 처리하는) 하나의 JSP 페이지 내에서 공유될 값을 저장한다
request REQUEST 한번의 요청을 처리하는데 사용되는 모든 JSP 페이지에서 공유될 값을 저장한다
session SESSION 한 사용자와 관련된 정보를 JSP 들이 공유하기 위해서 사용된다
application APPLICATION 모든 사용자와 관련해서 공유할 정보를 저장한다

- PAGE 영역 : 페이지를 벗어나면 공유 불가, 변수에 저장하면 되므로 잘 사용하지 않음

- SESSION 영역 : 회원가입에서 많이 사용, 로그인시 세션 설정, 로그아웃시 세션 끊기

- REQUEST 영역 : 현재 공유설정했으면 이 페이지부터 다음 페이지까지가 공유 영역

- APPLICATION 영역 : 다른 폴더 내에서도 공유 가능

- 모든 객체에서 각 영역에 대해 공유 설정하고 공유 값을 얻어오는 메소드가 같다

ex) setAttribute() 로 공유 설정, getAttribute() 로 공유 값 얻어오기 는 각 객체가 동일

 

pageContext

- 개별적인 page 하나가 PAGE 영역이 됨

 

session

- 세션들마다 아이디를 하나씩 부여해서 서버측 메모리에 저장함

- 한번 세션 연결하면 세션을 연결한 같은 종류의 브라우저끼리는 그 세션 id 를 공유하므로 연결상태 유지가능

- 주로 로그인시 session 을 연결하고 로그아웃시 session 을 끊으므로 그 사이가 범위가 된다

 

request

- REQUEST 영역은 특정 페이지에서 request 객체로 공유 설정하면 그 다음 페이지까지 일반적으로 request 영역

- 뷰페이지에 request 객체로 공유한 값을 뿌려주기 위해서 EL (표현언어) 사용

- 공유한 값들은 Controller 를 통해서 뷰페이지에 뿌려줄때 공유된 값을 쉽게 쓰기 위해서 표현언어 사용

- REQUEST 영역은 PAGE 보다 넓고 SESSION 보다 좁음

- request 객체는 클라이언트의 get/post 요청을 받기도 하지만 영역에 관련된 내장객체이기도 하다

 

JSP의 영역 예제

실습 준비

 

JSP의 영역 예제 1

APPLICATION 영역과 SESSION 영역

- attributeTest1_Form.jsp & attributeTest1.jsp & attributeTest2.jsp & attributeTest3.jsp

- attributeTest1_Form.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<html>
<head>
<title>Attribute Test Form</title>
</head>
<body>
<h2>영역과 속성 테스트</h2>
<form action="attributeTest1.jsp" method="post">
<table border="1">
	<tr><td colspan="2">Application 영역에 저장할 내용들</td></tr>
	<tr>
		<td>이름</td>
		<td><input type="text" name="name"></td>
	</tr>
	<tr>
		<td>아이디</td>
		<td><input type="text" name="id"></td>
	</tr>
	<tr>
		<td colspan="2"><input type="submit" value="전송"></td>
	</tr>
</table>
</form>
</body>
</html>

- Application 영역에 저장할 내용들을 입력

- 가입하는 양식 폼, action 값이 attributeTest1.jsp

- Application 영역에 저장할 값인 이름, 아이디

- get/post 등으로 값을 넘긴게 아니라 공유한 값을 가져와서 뿌린 것이다.

- attributeTest1.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<html>
<head>
<title>Attribute Test</title>
</head>
<body>
<h2>영역과 속성 테스트</h2>
<%
request.setCharacterEncoding("euc-kr");
String name=request.getParameter("name");
String id=request.getParameter("id");
if(name!=null&&id!=null){
	// application 객체로 공유 설정
	application.setAttribute("name",name);
	application.setAttribute("id",id);
}
%>
<h3><%=name %>님 반갑습니다.<br><%=name %>님의 아이디는 <%=id %>입니다.</h3>
<form action="attributeTest2.jsp" method="post">
<table border="1">
	<tr><td colspan="2">Session 영역에 저장할 내용들</td></tr>
	<tr>
		<td>e-mail 주소</td>
		<td><input type="text" name="email"></td>
	</tr>
	<tr>
		<td>집 주소</td>
		<td><input type="text" name="address"></td>
	</tr>
	<tr>
		<td>전화번호</td>
		<td><input type="text" name="tel"></td>
	</tr>
	<tr>
		<td colspan="2"><input type="submit" value="전송"></td>
	</tr>
</table>
</form>
</body>
</html>

<인코딩>

- post 방식으로 한글 값을 받았으므로 한글 인코딩 문제를 해결하기 위해 request.setCharaterEncoding() 으로 인코딩

- 위쪽에서 charset 이 EUC-KR 이므로 EUC-KR 로 값을 인코딩 시킨다

<값 받음>

- name != null && id != null 은 이름과 아이디를 잘 받았다면 이라는 의미

- 이전 파일 attributeTest1_Form.jsp 에서 사용자가 입력한 이름, 아이디를 request.getParameter() 로 값을 받음

- 그리고 받은 값을 화면에 뿌림

<공유 설정>

- 가장 넓은 영역인 APPLICATION 영역에 공유설정, 전체 어플리케이션이 하나의 영역이다

- 그 값들을 application 객체의 setAttribute() 메소드로 APPLICATION 영역 공유 설정함

- 폴더가 달라지더라도 공유한 값을 구해올 수 있는 영역이다, 페이지가 몇단계 넘어가더라도 공유한 값 가져올 수 있다

<입력>

- SESSION 영역에 공유 설정할 값을 입력하는 입력창을 만듬

- 입력받은 값을 post 방식으로 attributeTest2.jsp 파일로 전송

- attributeTest2.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<html>
<head>
<title>Attribute Test</title>
</head>
<body>
<h2>영역과 속성 테스트</h2>
<%
request.setCharacterEncoding("euc-kr");
String email=request.getParameter("email");
String address=request.getParameter("address");
String tel=request.getParameter("tel");

// session 객체로 공유 설정
session.setAttribute("email",email);
session.setAttribute("address",address);
session.setAttribute("tel",tel);

String name=(String)application.getAttribute("name");
%>
<h3><%=name %>님의 정보가 모두 저장되었습니다.</h3>
<a href="attributeTest3.jsp">확인하러 가기</a>
</body>
</html>

- 인코딩 이후 attributeTest1.jsp 파일에서 넘어온 값을 getParameter() 메소드로 받음

- 그 값들을 session 객체의 setAttribute() 메소드로 SESSION 영역에 공유 설정함

- 그리고 APPLICATION 영역에 공유설정되어있던 이름값을 가져오고 뿌린다

- 확인하러 가기 를 클릭시 attributeTest3.jsp 파일로 넘어간다, 값 전달하며 넘어가는 것이 아니라 그냥 하이퍼링크로 넘어간다

- attributeTest3.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@page import="java.util.Enumeration"%>
<html>
<head>
<title>Attribute Test</title>
</head>
<body>
<h2>영역과 속성 테스트</h2>
<table border="1">
	<tr><td colspan="2">Application 영역에 저장된 내용들</td></tr>
	<tr>
		<td>이름</td>
		<td><%=application.getAttribute("name") %></td>
	</tr>
	<tr>
		<td>아이디</td>
		<td><%=application.getAttribute("id") %></td>
	</tr>
</table>
<br>
<table border="1">
	<tr><td colspan="2">Session 영역에 저장된 내용들</td></tr>
<%
Enumeration e=session.getAttributeNames();
while(e.hasMoreElements()){
	String attributeName=(String)e.nextElement();
	String attributeValue=(String)session.getAttribute(attributeName);
	%>
	<tr>
		<td><%=attributeName %></td>
		<td><%=attributeValue %></td>
	</tr>
	<%
}
%>
</table>
</body>
</html>

- 앞에서 application 객체와 session 객체로 공유한 값들을 구해오서 표에서 출력

- 페이지가 계속 넘어가고 값을 전달하지 않았지만 공유가 되기때문에 값을 구해올 수 있다

- APPLICATION 영역의 공유 값을 name, id 라는 속성(네임) 으로 구한다, 언제든지 구해올 수 있는 값이다

+ APPLICATION 영역 공유값은 서로 다른 폴더에서도 구해올 수 있다

- SESSION 영역의 공유 값을 구해올 때는 해당 네임 값을 모르는 경우에 네임과 값을 구해오는 방식이다.

+ 원래는 SESSION 영역의 시간을 정하지만 여기선 설정하지 않았으므로 브라우저를 닫을때 까지이다.

- 페이지가 넘어갈때마다 값을 전달하지 않아도 값을 공유시키면 된다

- 네임 값을 아는 경우 공유 값을 구하는 코드로 바꾸자 (아래 코드)

	<tr>
		<td>email</td>
		<td><%=session.getAttribute("email") %></td>
	</tr>
	<tr>
		<td>tel</td>
		<td><%=session.getAttribute("tel") %></td>
	</tr>
	<tr>
		<td>address</td>
		<td><%=session.getAttribute("address") %></td>
	</tr>
</table>

코드 변경 후 출력
코드 변경 전 출력

 

 

- 전체 출력

1

 

2
3
4

- 현재 get/post 등으로 값을 넘긴게 아니라 공유한 값을 가져와서 뿌린 것이다.

 

JSP의 영역 예제 2

PAGE 영역과 REQUEST영역

- attributeTest4.jsp & requestTest5Result.jsp

- attributeTest4.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<%
pageContext.setAttribute("pageScope", "pageValue");
request.setAttribute("requestScope", "requestValue");
%>

pageValue = <%=pageContext.getAttribute("pageScope") %><br>
requestValue = <%=request.getAttribute("requestScope") %>
</body>
</html>

- pageContext 객체로 PAGE 영역 공유 설정하고 있다

- request 객체로 REQUEST 영역 공유 설정하고 있다

- 아래에서 getAttribute() 메소드로 공유 설정한 각 영역의 공유값들을 구해온다

- PAGE 영역은 하나의 페이지 내에서 공유 가능, 변수를 만들고 변수값을 출력할 수 있는 방법이 있기에 잘 쓰지 않는다

- REQUEST 는 다음 페이지까지 공유 가능 

- PAGE 영역 공유설정시엔 page 객체가 아니라 pageContext 객체로 공유설정을 해야한다

 

- requestTest5.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<%
pageContext.setAttribute("pageScope", "pageValue");
request.setAttribute("requestScope", "requestValue");
%>
<jsp:forward page="requestTest5Result.jsp"></jsp:forward>
</body>
</html>

- 이 문서 실행 시 pageContext 와 request 객체로 공유설정하는 내용은 앞의 예제와 같다
- PAGE 영역과 REQUEST 영역에 공유 설정만 하는 코드

- jsp 의 태그 중 하나인 action 태그인 forward action 태그 이다, 이 태그를 만나면 지정된 페이지로 이동함

- requestTest5Result.jsp 페이지로 바로 이동함

 

- requestTest5Result.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
pageValue = <%=pageContext.getAttribute("pageScope") %><br>
requestValue = <%=request.getAttribute("requestScope") %>
</body>
</html>

- 페이지가 바뀌었으므로 PAGE 영역 범위를 벗어나므로 pageContext 객체로 공유된 값은 사용 불가, null 로 나올 것

- REQUEST 영역은 페이지가 한단계 이동하면 거기까지가 REQUEST 영역이므로 request 객체로 공유한 값 사용 가능

- 즉 이전페이지에서 request 객체로 공유 설정했으므로 한단계 이동한 페이지인 이 페이지까지 유효한 범위임

+ 개별적인 페이지 하나가 PAGE 영역

 

+ 기타 객체

- config 객체 : 환경 설정 파일에 대해서 사용

- exception 객체 : 예외처리시 주로 사용

 

JSP의 영역 예제

실습 준비

 

JSP의 영역 예제 3

- login.jsp & selProduct.jsp

- login.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>login.jsp</title>
</head>
<body>
<center>
	<H2>로그인</H2>
	<form name="form1" method="POST" action="selProduct.jsp">
		<input type="text" name="username"/>
		<input type="submit" value="로그인"/>
	</form>
</center>
</body>
</html>

- '로그인' 버튼 클릭시 selProduct.jsp 로 입력한 id 값을 post 방식 값 전달

 

- selProduct.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>selProduct.jsp</title>
</head>
<%
	// HTML FORM 에서 전달된 데이터의 한글인코딩
	request.setCharacterEncoding("euc-kr");
	
	// session 에 username 이름으로 HTML FORM 의 <input type="text" name="username"/> 에 입력된 값을 저장함. 
	session.setAttribute("username",request.getParameter("username"));
%>
<body>
<center>
	<H2>상품선택</H2>
	<HR>
	<%=session.getAttribute("username") %>님이 로그인 한 상태 입니다.

	${username}
	<HR>
	<form name="form1" method="POST" action="add.jsp">
		<SELECT name="product">
			<option>사과</option>
			<option>귤</option>
			<option>파인애플</option>
			<option>자몽</option>
			<option>레몬</option>
		</SELECT>
		<input type="submit" value="추가"/>
	</form>
	<a href="checkOut.jsp">계산</a>
</center>
</body>
</html>

- 한글값이 username 이라는 네임값이 post 방식으로 전달되므로 한글값 인코딩 처리를 한다

- request.getParameter() 메소드로 네임인 username 을 통해 전달된 값을 받는다

- 받은 그 값을 SESSION 영역에 공유 설정한다, 여기서부터 SESSION 영역이 시작된다

+ 페이지가 바뀌더라도 사용가능

- select-option 에서 값을 선택하고 '추가' 를 누르면 form 을 통해 add.jsp 로 선택값이 넘어감

+ select-option 에서 option 에 value 값이 없을때는 option 태그 안에 쓰인 값이 value 로 넘어감, 즉 select 태그의 name 인 product 변수에 선택된 '사과' 가 저장됨

- '계산' 을 누르면 checkOut.jsp 로 페이지 이동

+ 코드에서 EL(표현언어) 를 통해 한번 더 아이디를 출력하고 있음

- 이게 표현언어이다.

 

- '추가' 시 장바구니에 과일이 담김 (add.jsp)

- 이런식으로 다른 과일들을 몇개 추가

- 장바구니에 담긴 과일들을 보여줌 (checkOut.jsp)

 

- add.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR" import="java.util.ArrayList"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<%	

	// HTML 폼에서 입력된 한글 처리를 위한 부분
	request.setCharacterEncoding("euc-kr");

	// product 속성으로 전달된 파라미터를 읽어옴.
	String productname = request.getParameter("product");

	// session scope 에 저장된 productlist 라는 이름의 ArrayList 객체를 가지고 옴.
	ArrayList list = (ArrayList)session.getAttribute("productlist");

	// 만일 null 인 경우 처음 데이터를 추가한 것이므로 새로운 ArrayList 생성
	if(list == null) {
		list = new ArrayList();
	}

	// ArrayList 에 새로운 데이터 추가
	list.add(productname);
	session.setAttribute("productlist",list);
%>

	<!-- 자바스크립트를 이용해 간단한 메시지 출력  -->
	<script>
		alert("<%=productname %> 이(가)추가 되었습니다.!!");
		history.go(-1);
	</script>
</body>
</html>

- 한글값이 post 방식으로 넘어오므로 euc-kr로 인코딩 처리를 함

- select 의 name 값이었던 product 변수(속성, 네임) 을 통해 getParameter() 로 선택된 값을 구해서 productname 변수에 저장

- 처음에 아무것도 추가하지 않았기 때문에 이 list 는 null 이다, 그래서 null 인 경우 ArrayList 객체를 만들어줌

- 메세지박스로 추가된 과일 알려주고 그 후 상품을 선택할 수 있게끔 이전 파일로 돌아감

 

'추가' 된 과일들을 장바구니에 저장

	// session scope 에 저장된 productlist 라는 이름의 ArrayList 객체를 가지고 옴.
	ArrayList list = (ArrayList)session.getAttribute("productlist");

- 세션에 저장된 값을 구하기 위해 getAttribute("productlist") 사용, 이 productlist 를 세션 영역 공유 설정한 것은 아래 코드

- 처음에 아무것도 추가하지 않았기 때문에 이 list 는 null 이다, 그래서 null 인 경우 ArrayList 객체를 만들어줌

- Object 로 리턴하고 저장된 값이 리스트이므로 ArrayList로 다운캐스팅 하는 것이다

	// ArrayList 에 새로운 데이터 추가
	list.add(productname);
	session.setAttribute("productlist",list);

- 정의된 리스트에 add() 로 추가된 과일을 저장한다

- session.setAttribute("productlist", list); 를 통해 세션에 리스트를 저장함, setAttribute() 에서 두번째 매개변수는 Object 이므로 리스트 또한 들어갈 수 있다

- 사용자가 다시 다른 과일(자몽) 선택후 추가시 위의 코드 getAttribute() 에서 리스트를 구해오고 아래코드로 리스트에 자몽을 추가하고 그 리스트를 세션 영역 공유 설정

+ 세션 영역은 브라우저 창을 닫는 순간 또는 invalidate() 로 세션 전체삭제나 removeAttribute() 로 세션 삭제로 세션을 끊을때까지 유효함

- checkOut.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR" import="java.util.ArrayList"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<center>
<H2>계산</H2>
선택한 상품 목록
<HR>
<%

	// session scope 에 저장된 productlist 라는 이름의 ArrayList 객체를 가져옴.
	ArrayList list = (ArrayList)session.getAttribute("productlist");

	// 선택한 상품이 하나도 없는 경우
	if(list == null) {
		out.println("선택한 상품이 없습니다.!!!");
	}
	else {

		// 선택한 상품이 있을 경우 리스트를 출력함.
		for(Object productname:list) {
			out.println(productname+"<BR>");
		}
	}
%>
</center>
</body>
</html>

- 세션에 공유된 list 를 getAttribute() 로 list 를 구한다, 리스트 객체가 저장되어있으므로 ArrayList 로 다운캐스팅 한다

- '계산' 을 눌렀을 당시 선택한 제품이 하나도 없는 경우 list 는 null

- 선택한 제품이 있을때는 향상된 for 문으로 그 list 에서 하나씩 가져와서 출력한다

 

 

+ request 객체로 영역설정은 Model 2 에서 자주 사용한다

-게시판 쪽의 목록을 가져오기 위한 Service 클래스 에서 View 페이지에서 필요한 값들을 request 객체로 공유 설정

- 사용자가 선택한 page 번호 등을 request 객체로 공유 설정

+ 지금은 getAttribute() 로 값을 가져오는데 나중엔 request.getAttribute(name값) 로 값을 받아와서 다운캐스팅, 언박싱 하는 번거로운 방법 대신 표현 언어(EL) 를 사용해서 ${listcount} 하면 공유값 가져오기부터 출력까지 바로 가능

 

+ session 은 로그인 성공시 session 객체로 공유 설정

+ 자바 클래스에선 session 내장 객체가 없으므로 request.getSession() 으로 받아서 사용


JSP 내장 객체 (이어서)

application 객체

- 가장 넓은 영역에 공유 설정하는 객체

 

application 객체 예제

실습 준비

 

application 객체 예제

- setApplicationAttribute.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>
<%
//    String name = request.getParameter("name");
//    String value = request.getParameter("value");
    
	String name = "test";
	String value = "1234";
	
    if (name != null && value != null) {
        application.setAttribute(name, value);	// 공유 설정
//        application.setAttribute("test", "1234");	// 위와 같다
    }
%>

<html>
<head><title>application 속성 지정</title></head>
<body>
<%
    if (name != null && value != null) {
%>
application 기본 객체의 속성 설정:
 <%= name %>  = <%= value %>
<%
    } else {
%>
application 기본 객체의 속성 설정 안함
<%
    }
%>
</body>
</html>

- application 객체로 APPLICATION 영역에 공유설정되었으므로 폴더가 달라져도 공유한 값을 쓸 수 있다

- 공유되는 name 은 test, 값은 1234

+ 이 파일을 실행해야 APPLICATION 영역에 공유 설정됨

 

- 폴더가 다른 곳에서 공유한 값을 불러오자

- WebContent/index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
처음 작성하는 JSP 프로그램 <br>

application 객체로 공유한 값:
<%=application.getAttribute("test") %>
</body>
</html>

- APPLICATION 영역에 공유설정된 값은 폴더가 달라져도 공유한 값을 쓸 수 있다

+ 영역이 너무 넓기때문에 자주 사용되지는 않는다


JSP 에러처리

 

JSP 에러처리 두가지 방법

1. 각 페이지별로 에러 처리

2. web.xml 파일에 에러 코드(종류)별로 등록

+ web.xml 은 아파치 톰캣 구동시 가장 먼저 실행되는 환경설정 파일

 

1. 각 페이지별로 에러 처리

- 페이지 지시어태그에서 사용할 수 있는 속성 4가지 중 에러 처리 관련 속성이 2가지 있다

 

1) errorPage 속성으로 경로와 에러 페이지명으로 파일을 지정

<%@ page errorPage = "예외발생시보여질JSP지정" %>

2) 그 파일에서 isErrorPage 속성을 true로 지정 (기본값 false)

<% page isErrorPage = "true" %>

- isErrorPage 속성이 true 인 경우 에러 페이지로 지정

 

- errorPage 속성 : JSP 에서 에러처리할때, 에러를 보여줄 페이지명을 지정

- isErrorPage 속성 : 지정된 에러를 보여줄 페이지 안에서 true 로 설정해야함

 

3) 그 후 내장객체 exception 으로 에러 메세지를 구해와서 어떤 원인인지 출력

- exception 기본 객체 : 발생할 예외 객체
- exception.getMessage() : 예외메세지
- exception.printStackTrace() : 예외 추적 메세지 출력

 

2. web.xml 파일에 에러 코드(종류)별로 등록

- 404 에러를 web.xml 파일에 등록하면 404 에러가 발생했을때 하위에 location 으로 지정된 파일이 출력됨(실행됨)

- 500 에러를 web.xml 파일에 등록하면 500 에러가 발생했을때 하위에 location 으로 지정된 파일이 출력됨(실행됨)

- 에러 코드별 뿐만 아니라 에러 종류별로도 등록가능하다 ex) NullPointerException

 

JSP 에러처리 예제

실습 준비

- 'JSP 페이지의 에러 처리' 폴더 안의 내용을 가져옴

 

JSP 에러처리 예제 1
1. 각 페이지별로 에러 처리

- readParameter2.jsp (에러처리 안함) vs readParemeter1.jsp (에러처리 함) & error/viewErrorMessage.jsp (에러페이지)

- readParameter2.jsp

<%@ page contentType = "text/html; charset=utf-8" %>
<html>
<head><title>파라미터 출력</title></head>
<body>

name 파라미터 값: <%= request.getParameter("name").toUpperCase() %>

</body>
</html>

- 에러처리를 하지 않은 파일이다

- name 값을 전달해주는 파일이 없다, 전달되는 값이 없기때문에 500 번 에러 발생

- 500번 오류는 소스코드 상의 오류이다

 

+ 각 에러 상황별 코드가 있다

+ 값이 전달되지 않았는데 받는 경우 500 에러가 나온다

- 어디서 에러가 발생했는지 알려준다

 

에러 처리한 파일

- readParameter.jsp

<%@ page contentType = "text/html; charset=utf-8" %>
<%@ page errorPage = "/error/viewErrorMessage.jsp" %>
<html>
<head><title>파라미터 출력</title></head>
<body>

name 파라미터 값: <%= request.getParameter("name").toUpperCase() %>

</body>
</html>

- 500 번 메세지를 알려주는 창 말고 에러 메세지를 뿌리자

- errorPage 속성에 실제 에러를 보여줄 페이지를 지정한다

- erro 폴더 안의 viewErrorMessage.jsp 파일

- error/viewErrorMessage.jsp

<%@ page contentType = "text/html; charset=utf-8" %>
<%@ page isErrorPage = "true" %>
<html>
<head><title>에러 발생</title></head>
<body>

요청 처리 과정에서 에러가 발생하였습니다.<br>
빠른 시간 내에 문제를 해결하도록 하겠습니다.
<p>
에러 타입: <%= exception.getClass().getName() %> <br>
에러 메시지: <b><%= exception.getMessage() %></b>
</body>
</html>
<!--
만약 에러 페이지의 길이가 512 바이트보다 작다면,
인터넷 익스플로러는 이 페이지가 출력하는 에러 페이지를 출력하지 않고
자체적으로 제공하는 'HTTP 오류 메시지' 화면을 출력한다.
인터넷 익스플로러에서도 에러 페이지 내용을 올바르게 출력하려면
응답 결과에 이 주석과 같은 내용을 포함시켜서
에러 데이터가 512 바이트를 넘도록 해야 한다.
-->

- 지정된 파일인 viewErrorMessage 파일에도 isErrorPage 속성값을 "true" 로 설정해줘야한다
+ isErrorPage 속성 기본값이 false
- errorPage 속성과 isErrorPage 속성을 통해 500 번 오류 발생 대신 지정된 페이지 내용을 출력(실행)

- exception 객체를 이용해서 에러 타입과 에러 메세지를 구해온다.

JSP 에러처리 예제 2

+ 자바처럼 try-catch 구문 사용해서 에러 처리할 수도 있다

- try 문 안에 getParameter() 를 사용하고 catch 안에 파라미터가 올바르지 않습니다 라는 내용 출력

- readParameterWithTry.jsp

<%@ page contentType = "text/html; charset=utf-8" %>
<html>
<head><title>파라미터 출력</title></head>
<body>

name 파라미터 값: 
<% try { %>
<%= request.getParameter("name").toUpperCase() %>
<% } catch(Exception ex) { %>
name 파라미터가 올바르지 않습니다.
<% } %>
</body>
</html>

 

JSP 에러처리 예제 3

1. 각 페이지별로 에러 처리

- bufferOverflow.jsp

- 에러페이지를 error/viewErrorMessage.jsp 로지정

<%@ page contentType = "text/html; charset=utf-8" %>
<%@ page buffer="1kb" %>
<%@ page errorPage = "/error/viewErrorMessage.jsp" %>
<html>
<head><title>버퍼 플러시 이후 에러 발생 결과</title></head>
<body>

<%  for (int i = 0 ; i < 300 ; i++) { out.println(i); }  %>

<%= 1 / 0 %>

</body>
</html>

- buffer 속성값은 기본값이 8kb, buffer 속성으로 크기를 1kb 로 수정

<에러발생>

1. 1 부터 300 까지 출력하기 전에 버퍼 공간이 부족해서 에러가 발생

2. 1을 0 으로 나눌때도 ArithmeticException 에러가 발생

- 에러 메세지를 보여줄 페이지를 viewErrorMessage.jsp 로 지정하고 있다

+ 그 후 viewErrorMessage.jsp 에서 isErrorPage 속성 "true" 로 해야한다

- 실행시

- viewErrorMessage.jsp 의 내용이 출력되고 있다

- 버퍼 공간이 부족해서 300까지 출력하지 못하고 있다

- 1 을 0 으로 나눌때 발생하는 ArithmeticException 예외가 발생했으므로 관련 내용이 여기 출력됨

 

- 첫번재 방법인 페이지마다 지정하는 방법은 페이지마다 errorPage 를 지정해야함

- 각 페이지별로 에러 처리하는 방법은 페이지가 적을때 가능한 페이지이다.


2. web.xml 파일에 에러 코드(종류)별로 등록

- 주로 web.xml 에 에러 코드, 에러 종류를 등록하는 방법을 사용한다

- 에러 코드(404, 500) 등록시 location 에 지정된 파일이 브라우저 창에 나타남

- 에러 종류(java.lang.NullPointException, java.lang.ArithmeticException) 등록시 location 에 지정된 파일이 브라우저 창에 나타남

- 페이지별 처리보다 간결하다

- 단점 : 개발 과정에서는 에러를 쉽게 찾기 힘듬

+ 404 : 주어진 위치에 해당 파일이 없을때 발생하는 에러

 

JSP 에러처리 예제

2. web.xml 파일에 에러 코드(종류)별로 등록

실습 준비

- web.xml 에 이 부분을 복붙

JSP 에러처리 예제 4

2. web.xml 파일에 에러 코드(종류)별로 등록

- web.xml & readParameter2.jsp

- web.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_4_0.xsd"
	id="WebApp_ID" version="4.0">
	<display-name>jspproject</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>

	<error-page>
		<error-code>404</error-code>
		<location>/error/error404.jsp</location>
	</error-page>

	<error-page>
		<error-code>500</error-code>
		<location>/error/error500.jsp</location>
	</error-page>

	<error-page>
		<exception-type>java.lang.NullPointerException</exception-type>
		<location>/error/errorNullPointer.jsp</location>
	</error-page>

</web-app>

- web.xml 파일 : 환경설정 파일, 반드시 WEB-INF 폴더 안에 있어야만 한다

+ Apache Tomcat 이 구동될때 web.xml 의 코드를 가장 먼저 읽어옴

 

+ xml 의 규칙

- 전체를 감싸는 루트 엘리먼트

- 부모 엘리먼트, 자식 엘리먼트는 여러개 쓸 수 있다

 

- readParameter2.jsp 는 에러 처리를 하지 않은 파일이었다

- readParameter2.jsp

<%@ page contentType = "text/html; charset=utf-8" %>
<html>
<head><title>파라미터 출력</title></head>
<body>

name 파라미터 값: <%= request.getParameter("name").toUpperCase() %>

</body>
</html>

- 에러 처리를 하지 않은 파일

- web.xml 에 errorNullPointer 에러를 처리했으므로 readParameter.jsp 실행시 error/errorNullPointer.jsp 가 실행됨

- web.xml 에 에러 등록시 브라우저 창에 에러메세지가 보이지 않으므로 개발과정에서 에러를 찾기 힘들다

- 콘솔창에서는 어떤 에러가 발생했는지 확인 가능


+ 환경설정 파일 수정 후에는 서버 재구동되어야 반영됨


JSP 태그 (이어서)

 

지시어 태그

- 지시어 태그 3가지 태그 중 포함 태그 할 것

1) 페이지 태그 <%@ page %>

2) 포함 태그 <%@ include %>

3) 사용자 정의 태그 <%@ taglib %>

 

액션 태그

- jsp 액션 태그는 6가지 종류 

- 그 중 forward 액션 태그와 include 액션 태그 할 것

- forward action 태그 : 지정된 페이지로 바로 이동시킴 <jsp:forward >

- include action 태그 : 다른 문서를 불러오는 용도로 사용 <jsp:include >

+ plugin action 태그 : 자바 애플릿을 불러오는 용도였는데 지금은 애플릿을 사용하지 않으므로 plugin action 태그사용하지 않음

+ usebean, setProperty, getProperty action 태그 : JAVA DAO/ DTO 클래스와 연결시 사용함

 

지시어 태그의 포함 태그 vs 액션 태그의 include action 태그

+ 다른 문서를 불러온다는 점은 같지만 내부적으로 차이가 있음

- 지시어 태그의 포함 태그 : 불러오는 파일과 불려지는 파일이 한개파일로

- 액션 태그의 include action 태그 : 불러오는 파일과 불려지는 파일이 따로

 

액션 태그 (Action Tag)

- JSP에서 액션(Action Tag)는 스크립트, 주석, 디렉티브와 함께 JSP 페이지를 이루고 있는 요소

- 페이지와 페이지 사이의 제어를 이동시킬 수도 있고, 다른 페이지의 실행결과를 현재의 페이지에 포함시킬 수 있으며, 자바빈을 JSP 페이지에서 사용할 수 있는 기능도 제공

- JSP 지원 액션 태그는 6가지 종류가 있다

forward action tag

- <jsp:forward>

- 다른 페이지로 이동할때 사용되는 태그

- forward action tag 가 포함된 페이지는 브라우저에 출력되지 않고 지정된 페이지로 바로 이동

 

include action tag 

- <jsp:include>

- 다른 모듈 페이지를 불러올때 사용, 즉 다른 페이지를 불러올 때 사용

 

useBean, setProperty, getProperty action tag
- 자비빈 (=DTO 클래스) 사용할때 사용하는 액션태그들


forward action tag

- 현재 페이지에서 다른 페이지로 이동시킬때 사용

- 실행되자마자 지정된 페이지로 이동

- 이 태그가 포함된 페이지는 출력되지 않고 바로 포워딩됨

- 계속해서 forwarding 되면 최종적으로 이동한 곳까지가 REQUEST 영역

- 3가지 형식이 있다

 

1. 간단한 형식

<jsp : forward page = " 이동할 페이지명 " />

2.

<jsp : forward page = " 이동할 페이지명 " > </jsp : forward>

3. 값을 가져가는 경우

<jsp : forward page = " 이동할 페이지명 ">
	<jsp : param name = "paramName1" value = "var1" />
	<jsp : param name = "paramName2" value = "var2" />
</jsp : forward>

- paramName1 이 변수가되고, 이 변수에 전달될 값이 var1 이다

- paramName2 rk 변수가되고, 이 변수에 전달될 값이 var2 이다

 

forward action tag 와 REQUEST 영역

- REQUEST 영역 시작으로부터 forward action tag 로 연결된 페이지들은 REQUEST 영역에 해당

 

forward action tag 예제

실습 준비

 

forward action tag 예제 1

forward action tag 와 REQUEST 영역

forward action tag 3가지 형식 중 첫번째

- WebContent/forward/forward1/

- forwardForm1.jsp & forwardFrom1.jsp & forwardTo1.jsp & forwardTo2.jsp

- 세번 페이지를 전달하고 있고, 순서대로 파일이 넘어감

- forwardForm1.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<body>
	<h1>Forward 사용법 예제</h1>

	<form method=post action="forwardFrom1.jsp">
	아이디 : <input type="text" name="id"><p>
	패스워드 : <INPUT TYPE="password" NAME="password"><p>
			   <input type="submit" value="보내기">
	</form>

	</body>
</html>

- form 으로 다음 페이지로 넘어감

- forwardFrom1.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<body>
	<h2>포워딩하는 페이지: forwardFrom1.jsp</h2>

	<%
		request.setCharacterEncoding("euc-kr");
	%>

   forwardFrom1.jsp의 내용 입니다.<br>
   화면에 절대 표시 안됩니다.

	<%	// request 객체로 공유 설정
		request.setAttribute("name","홍길동");
	%>
	
	<jsp:forward page="forwardTo1.jsp"/>  

	</body>
</html>

- request 객체로 공유 설정 후 페이지를 넘김

- 여기서부터 REQUEST 영역이 시작되고 forward action tag 로 이동하는 곳인 forwardTo1.jsp 와 forwardTo2.jsp 까지가 REQUEST 영역이다

- 여기선 두번 이동하기때문에 REQUEST 영역은 두번 이동한 곳이기때문임

- 일반적으로 1번만 이동하므로 다음 페이지까지 REQUEST 영역이라고 했지만, 사실 계속 해서 이동하면 계속 이동한 곳까지가 REQUEST 영역

- forward action tag 로 이동되어야만 request 객체의 공유값을 사용 가능

- forward action tag 가 있는 페이지인 forwardForm1.jsp 의 내용은 출력되지 않고 forwardTo1.jsp 파일의 내용으로 바로 감

- forward action tag 가 포함된 페이지는 실행은 되지만 출력은 되지 않는다

ex) 한글값 인코딩 코드와 request 객체로 공유 설정하는 코드는 동작하지만 적힌 글은 출력되지 않음

- forwardTo1.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<body>
	<h2>포워딩되는 페이지: forwardTo1.jsp</h2>

	<%
		String id = request.getParameter("id");
		String password = request.getParameter("password");
	%>

	<b><%=id%></b>님의<p>
	패스워드는 <b><%=password%></b>입니다.

	<jsp:forward page="forwardTo2.jsp"/>  

	</body>
</html>

- REQUEST 가 시작된 곳으로 부터 다음 페이지이다

- 가장 첫 페이지인 forwardForm1.jsp의 request 객체에서 form 태그의 action으로 보낸 값을 여기서 getParameter()로 전달된 값을 받고 있다

- request 객체의 form 태그의 action 으로 보낸 값도 forward action tag 로 이어져 있는 다음의 모든 페이지에서 값을 구해올 수 있다

- forward action tag 가 있는 페이지인 forwardTo1.jsp 의 내용은 출력되지 않고 forwardTo2.jsp 파일의 내용으로 바로 감

- forward action tag 가 포함된 페이지는 실행은 되지만 출력은 되지 않는다

- forwardTo2.jsp (최종 페이지)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

    
    ID : <%=request.getParameter("id")%> <br>
    password : <%=request.getParameter("password")%> <br>
    
    request 객체로 공유한 값 출력 <br>
    <%=request.getAttribute("name")%>

- forward action tag 로 연결된 다른 파일들에선 출력이 불가능하므로 최종 페이지인 여기서 출력을 한번 해야한다

- 계속해서 forward action tag 로 이어진 페이지들의 최종 페이지이므로 REQUEST 영역이 여기까지 해당된다

- 그러므로 request 객체 전달값이나 request 객체 공유값을 구해올 수 있다

- request 객체 전달값을 여기서 받고 있다, forward action tag 로 이어진 곳이므로 가능

- request 객체 공유값을 여기서 받고 있다, forward action tag 로 이어진 곳이므로 가능

 

request 객체 공유값 vs request 객체 전달값

request 객체의 역할 두가지

1. request 객체는 REQUEST 영역에서 사용할 수 있는 공유 값을 설정하거나 구해온다

2. request 객체는 form 태그의 action 으로 전달한 값들을 받는 역할을 한다, 클라이언트의 요청 처리

 

- REQUEST 영역은 다음 페이지까지가 아니라 forward action tag 로 이어진 순차적인 모든 페이지 이다

1. request 객체로 공유값을 받아올 때는 forward action tag 로 이어진 순차적인 모든 페이지에서 값을 받아올 수 있다

2. request 객체로 전달값을 구해올 때도 forward action tag 로 이어진 순차적인 모든 페이지에서 값을 구해올 수 있다

 

예제에서의 REQUEST 영역

- forward action tag 로 총 2번 전달하고 있다

- forwardFrom1.jsp -> forwardTo1.jsp -> forwardTo2.jsp

- forwardFrom1.jsp 에서 REQUEST 영역이 시작되었고 REQUEST 영역은 forwardTo1.jsp 뿐만 아니라 forward action tag 로 이어진 forwardTo2.jsp 도 해당

 

request 객체 공유 주의

- forward action 태그로 이동시켜야만 REQUEST 영역 안에 들어가므로 request 객체로 값 공유 가능

- 중간에 location, form-action, meta 등으로 페이지 이동시 REQUEST 영역에서 벗어나므로 request 객체로 값 공유 불가

 

+ forward action tag 작성 주의

- forward action tag 는 이 자체로 태그이므로 스크립틀릿 태그 안에 쓰면 안된다

- HTML 태그처럼 독립된 태그이므로 따로 쓰기

// <% 	<jsp:forward page="forwardTo1.jsp"/>  %> // 틀린 표현
	<jsp:forward page="forwardTo1.jsp"/>

 

forward action tag 예제 2

forward action tag 와 REQUEST 영역

forward action tag 3가지 형식 중 두번째

- WebContent/forward/forward2/

- forwardForm2.jsp & forwardFrom2.jsp

- a.jsp, b.jsp, ab.jsp, o.jsp 는 각 혈액형별 특징들을 알려주는 파일

 

- forwardForm2.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<head>
	<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
	<script>
	
	$(document).ready(function(){
		
		$(":submit").click(function(){
			
			if($("#name").val() == ""){
				alert("이름을 입력 하세요");
				$("#name").focus();
				return false;
			}
			
			if($("#a").is(":checked") == false &&
			   $("#b").is(":checked") == false &&	
			   $("#o").is(":checked") == false &&
			   $("#ab").is(":checked") == false){
				alert("혈액형을 선택 하세요");
				return false;
			}		
			
		});
		
	});	
	
	</script>
	</head>
	<body>

	<h1>포워딩될 페이지에 파라미터값 전달하기 예제</h1>

	<form method=post action="forwardFrom2.jsp">
	이름 : <input type=text id="name" name="name"> <br><br>
	
	당신의 혈액형은?<p> 
	
	<input type="radio" id="a" name="bloodType" value="a">A형<br>
	<input type="radio" id="b" name="bloodType" value="b">B형<br>
	<input type="radio" id="o" name="bloodType" value="o">O형<br>
	<input type="radio" id="ab" name="bloodType" value="ab">AB형<p>
	<input type="submit" value="보내기">
	</form>

	</body>
</html>

- ex) A 형을 선택시 a.jsp 의 내용이 실행됨

- form 태그의 action 을 통해 forwardFrom2.jsp 로 선택값을 전달한다

 

 

- forwardFrom2.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<body>

	<h1>포워딩하는 페이지: forwardFrom2.jsp</h1>

	<%
		request.setCharacterEncoding("euc-kr");

//		String name1 = "Lay";
		String bloodType = request.getParameter("bloodType") + ".jsp";
	
//		String bloodType = "a.jsp";
	%>

	<jsp:forward page="<%=bloodType%>"/>

+ 한글값이 깨지지 않도록 인코딩

- 앞의 forwardForm2.jsp 파일에서 select 박스로 부터 form action 으로 넘어온 값을 받아서 .jsp 를 붙여서 forward 시키는 페이지를 지정한다

ex) 앞에서 A형 선택시 'a' 값을 getParameter() 로 받은 후 .jsp 를 붙여서 a.jsp 를 forward action tag 를 써서 이동시킬 페이지로 지정

 

- a.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<body>

	<h1>포워딩되는 페이지(a.jsp)</h1>

	<%
		String name = request.getParameter("name");
		String bloodType = request.getParameter("bloodType");
	%>

	<b><%=name%></b>님의 혈액형은
	<b><%=bloodType%></b>형이고
	성실하고 신중하며 완벽주의자입니다.

	</body>
</html>

- a.jsp 는 forwardFrom2.jsp 파일과 forward action tag 로 이어져 있는 최종 페이지

- 그러므로 getParameter() 를 통해 forwardForm2.jsp 파일에서 forwardFrom2.jsp 파일로 전송한 값인 name값과 bloodType값. 즉, 이름값과 혈액형 값을 구해올 수 있다

forward action tag 예제 3

forward action tag 와 REQUEST 영역

forward action tag 3가지 형식 중 세번째 : 값을 가져가는 기능

- WebContent/forward/forward3/

- forwardForm3.jsp & forwardFrom3.jsp

- yellow.jsp, blue.jsp, green,jsp, red.jsp 는 선택한 색상에 따라 보여줄 파일

- forwardForm3.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<body>

	<h2>포워딩될 페이지에 파라미터값 전달하기 예제</h2>

	<form method="post" action="forwardFrom3.jsp">
	이름 입력 : <input type="text" name="name"><br><br>
	색 선택: <br>
	<input type="radio" name="color" value="yellow">노랑색<br>
	<input type="radio" name="color" value="green">초록색<br>
	<input type="radio" name="color" value="blue">파랑색<br>
	<input type="radio" name="color" value="red">빨강색<p>
	<input type="submit" value="확인">
	</form>

	</body>
</html>

- form 태그를 통해 입력된 이름과 선택된 색상을 네임값 name 과 네임값 color 에 저장해서 forwardFrom3.jsp 로 전달

 

 

- 선택한 색상 관련 글과 함께 blue.jpg 보여주고 있다

- forwardFrom3.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<html>
	<body>

	<h2>포워딩하는 페이지: forwardTagFrom2.jsp</h2>

<%
   request.setCharacterEncoding("euc-kr");

   String name = request.getParameter("name");
   String selectedColor = request.getParameter("color");
%>

<jsp:forward page="<%=selectedColor+\".jsp\"%>">
    <jsp:param name="selectedColor" value="<%=selectedColor%>"/>
	<jsp:param name="name" value="<%=name%>"/>
</jsp:forward>

- 넘어온 한글값이 깨지지 않도록 인코딩

- 앞에서 넘어온 값을 name, color 네임값을 통해서 구하고 name, selectedColor 변수에 저장한다

- jsp forward action tag 3번째 형식을 사용하면서 값을 전달하고 있다

- selectedColor 는 두곳에 사용하고 있다, 이동할 페이지명 지정과 넘겨줄 값에 사용

- 이렇게 전달된 값들은 request.getParameter() 로 받아야한다!

 

ex) 만약 사용자가 노란색을 클릭해서 color 값이 yellow 라면

- selectedColor 는 "yellow" 가 되고 forward 할 파일은 yellow.jsp 파일

- 전달할 값1은 selectedColor 라는 네임에 해당하는 값인 yellow

- 전달할 값2는 name 이라는 네임에 해당하는 값인 Lay(사용자가 입력한 이름)

 

" " 주의

- 바깥쪽에 " " 를 쓰면 안쪽엔 ' ' 를 써야하는데 JSP 에선 ' ' 를 쓸 수 없다

- 그러므로 .jsp 를 쓰기 위해서 " 앞에 \ 를 붙여준다 -> \".jsp\"

- \ 다음의 특수문자는 그대로 출력한다는 의미

 

- blue.jsp (다른 색상 파일도 마찬가지)

<%@ page contentType="text/html;charset=euc-kr"%>

<%
   String name = request.getParameter("name");
   String selectedColor = request.getParameter("selectedColor");
%>

<h2>포워딩되는 페이지 - <%=selectedColor+".jsp"%></h2>

<b><%=name%></b>님의 좋아하는 색은 "<%=selectedColor%>"이고
자기탐구와 내적성장을 상징하는 색입니다.<br><br>

<img src="<%=selectedColor+".jpg"%>" border="0" width="70" height="30">

- 이 최종 파일에서는 request.getParameter() 를 통해 4가지 값을 구해올 수 있다

1. forwardForm3.jsp 파일의 폼에서의 네임값인 name, color 값들을 가져올 수 있다

2. forwardFrom3.jsp 파일에서 forward action tag 로 전달된 값의 네임값인 name, selectedColor 의 값들을 가져올 수 있다.

- 즉 총 4개의 값을 구해올 수 있다

 

이때 중복된 네임값인 name값은 두가지 값 중 어떤 값을 의미할까?

- 같은 이름일때 가까운 파일의 name값이 출력된다

- 여기선 forward action tag 로 전달된 name값이 출력됨

 

다음 시간

- include action tag

- include 디렉티브 태그

- DTO, DAO 클래스로 자바와 연동

- 자바빈(=DTO 클래스) 연동 위한 action tag

복습

+ Apache Tomcat 을 설치시 선행 설치되어야하는 jre 의 rt.jar 를 통해 자바 라이브러리 사용 가능

+ 출력시 out 객체, 표현식 태그, 표현 언어를 쓰는 방법이 있다

+ Model 1 에선 표현식 태그를 사용하지만 Model 2 에서는 표현식 태그보다 표현언어 ${} 를 사용

 

page  지시어 태그

- 이클립스로 jsp 파일 만들면 1 라인에 자동 생성되는 태그

 

page 지시어 태그 속성

1. contentType : 현재문서의 형식, 텍스트인지 이미지인지, 텍스트라면 text/html 

2. charset : 현재문서를 브라우저로 출력시 어떻게 인코딩 시킬지, 한글은 EUC-KR 또는 UTF-8

+ UTF-8 로 해야 영문 브라우저에서도 한글값 깨지 않음

- 값이 넘어가는것과 관련없다, 현재 문서를 인코딩

3. import : 외부의 클래스등을 사용하려면 import 해야함

4. errorPage / isErrorPage : 페이지 처리시 사용해서 한 페이지에서 에러를 한꺼번에 처리할 수 있게 함

 

주석

1. JSP 주석 : 아무곳이나 기술 가능

2. JSP 스크립트 주석 : 스크립틀릿, 표현식, 선언문 태그 안에서 사용

- JSP 주석과 JSP 스크립트 주석은 웹 브라우저에 전송되지 않음, 소스보기에 표시안됨

+ HTML 주석 : 웹 브라우저에 전송되므로 소스보기에 표시됨

 

내장 객체

- 보통 클래스로 직접 객체를 생성해서 사용해야하지만 Javascript 나 JSP 는 내장객체가 지원됨 

- JSP 는 jre 를 불러왔기 때문에 직접 객체 생성도 가능하고 내장객체도 사용 가능 

- request 객체, response 객체, session 객체, out 객체 등

 

내장 객체의 메소드

- 이 내장객체는 클래스가 아니기 때문에 지원 메소드를 찾기 힘들다

- 메소드를 찾으려면 '실제 타입' 으로 되어있는 해당 클래스나 인터페이스로 찾아야한다

- 여기 들어있는 클래스나 인터페이스의 패키지는 모두 Java EE 이다 (자바시간에 배운건 Java SE)

- 이러한 Java EE 라이브러리 클래스들, 즉 특정 객체의 지원 메소드들은 Apache Tomcat 의 라이브러리를 사용하는 것이다

 

Apache Tomcat 의 라이브러리

- Java EE 라이브러리 클래스들은 Apache Tomcat 의 라이브러리 이다

- 주로 servlet-api.jar 를 많이 사용, 이 파일 안에 request 객체의 메소드들이 있다

 

request 객체

- 클라이언트가 get / post 로 요청하면 그 요청을 받아서 처리해주는 객체

- 가장 사용빈도 높은 객체

 

request 객체 메소드

- 6가지 메소드가 중요

 

request 객체의 메소드

void setCharacterEncoding(String env) 한글 인코딩 처리, post 방식일때 사용
getParameter(String name) name에 해당하는 파라미터 값을 구함
String[] getParameterValues(String name) checkbox 같이 여러 개의 파라미터 값을 구함
String getRemoteAddr() client의 IP주소를 구함
String getRequestURI() 요청 URI를 구함
String getContextPath() 컨텍스트 패스(project명)를 구함

 

request 객체의 setCharacterEncoding() 메소드

- "한글 값" 이 post 방식으로 넘어갈때는 반드시 setCharacterEncoding() 을 통해 인코딩 코드를 위에 추가해야함

+ Model 2 에서 action 값 대신 Controller 로 페이지가 넘어간다는 것 빼고 한글 인코딩 문제는 Model 2 도 같다

 

request 객체의 getParameter() 메소드

- 값 전달시 사용

- name 값이 변수가 되어서 입력양식에서 입력된 값이나 선택양식의 value 값을 구해옴

 

request 객체의 getParameter() 메소드

- 체크박스와 같이 여러개의 값이 넘어갈때 사용

- name 값이 변수가 되어서 입력양식에서 입력된 값이나 선택양식의 value 값을 구해옴

- 리턴으로 String 배열을 리턴해준다

- 첫번째 전달된 값은 0 번방, 두번째 전달된 값은 1번방

 

request 객체의 getRequestURI() 메소드

- 요청 URI 를 구해줌

 

request 객체의 getContextPath() 메소드

- 현재 프로젝트 명을 구해줌

 


JSP 내장 객체 예제 7

request 객체 예제 7

- WebContent/request/board

- HTML 시간에 만든 로그인 폼, 게시판 폼, 회원가입 폼에서 값을 전달하고 출력해보자

- HTML 과 jQuery 시간에 폼 만들기, 유효성 검사했던 내용에 값 전달 기능을 추가해보자

- boardform.html & board.js & board.jsp

- boardform.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 폼</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
	/* $(function(){
		$("form").submit(function(){
			if($.trim($("#writer").val()) == ""){
				alert("작성자명을 입력하세요.");
				$("#writer").focus();
				return false;
			}
			if($.trim($("#passwd").val()) == ""){
				alert("비밀번호를 입력하세요.");
				$("#passwd").focus();
				return false;
			}
			if($("#passwd").val().length <2 || 
			   $("#passwd").val().length >8	){
				alert("비밀번호는 2~8자로 입력하세요");
				$("#passwd").val("").focus();
				return false;
			}
			if($.trim($("#subject").val()) == ""){
				alert("제목을 입력하세요.");
				$("#subject").focus();
				return false;
			}
			if($.trim($("#content").val()) == ""){
				alert("내용을 입력하세요.");
				$("#content").focus();
				return false;
			}
			if($.trim($("#content").val()).length > 200){
				alert("내용은 200자 이내로 입력하세요");
				$("#content").focus();
				return false;
			}
		});		
	});	 */
</script>

<script src="board.js"></script>

</head>
<body>

<form method="post" action="board.jsp">
<table border=1 width=600 align=center>
	<caption>게시판</caption>
	<tr><th>작성자</th>  <!-- th : 가운데 정렬, 찐하게 출력 -->
		<td><input type=text size=30 id="writer" name="writer" 
							         placeholder="작성자명 입력"></td>
	</tr>
	<tr><th>비밀번호</th>
		<td><input type=password size=30 id="passwd" name="passwd" placeholder="2~8자 이내 입력"></td>
	</tr>
	<tr><th>제목</th>
		<td><input type=text size=60 id="subject" name="subject"></td>
	</tr>
	<tr><th>내용</th>
		<td><textarea rows="5" cols="50" id="content" name="content" placeholder="200자 이내로 입력"></textarea></td>
	</tr>
	<tr><th>파일첨부</th>
		<td><input type=file></td>
	</tr>
	<tr><td colspan=2 align=center>
			<input type=submit value="글작성">	 <!-- submit :전송기능 있는 버튼 -->
			<!-- <input type=button value="글작성2">  -->  <!-- button :전송기능 없는 버튼 -->
			<!-- <button>글작성3</button>	 -->			 <!-- 전송기능이 있는 버튼 -->
			<!-- <button type=submit>글작성4</button>  --> <!-- 전송기능이 있는 버튼 -->
			<!-- <button type=button>글작성5</button> -->  <!-- 전송기능이 없는 버튼 --> 
			<input type=reset value="취소">      <!-- 초기화 버튼 -->
		</td>
	</tr>
</table>
</form>

</body>
</html>

- board.jsp 파일 생성하고 작성하기

- board.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
	request.setCharacterEncoding("UTF-8");

	String writer = request.getParameter("writer");
	String passwd = request.getParameter("passwd");
	String subject = request.getParameter("subject");
	String content = request.getParameter("content");

%>

작성자 : <%=writer%> <br>
비밀번호 : <%=passwd %> <br>
제목 : <%=subject %> <br>
내용 : <%=content %> <br>

1. 한글 값 인코딩

2. getParameter() 로 전달된 값 받기

3. 전달된 값을 표현 태그에서 출력

 

- boardform.html 실행 결과

- 내용 textarea 에 두줄을 입력시 두줄로 나오지 않고 한줄로 나온다

 

줄이 바뀐상태로 출력하게 하기 해결 방법 2가지 

1. 표현식태그 좌우에 <pre> </pre> 태그로 감싸기

 

2. 자바의 replace() 함수로 값을 치환

- '내용'을 전달받아서 replace() 함수로 "\n"을 <br> 태그로 치환시켜준다

- textarea 에서 사용자가 값을 입력하면서 Enter 를 누르면 \n 이 입력됨

- 이걸 출력할때 줄을 바꾸려면 <br> 태그가 있어야하므로 <br> 태그로 치환

+ 글꼴, 글자크기 차이가 있지만 CSS 에서 처리할 수 있다

 

- board.jsp (수정)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
	request.setCharacterEncoding("UTF-8");

	String writer = request.getParameter("writer");
	String passwd = request.getParameter("passwd");
	String subject = request.getParameter("subject");
	String content = request.getParameter("content");
	
	// replace("n","<br>") : \n을 <br> 태그로 치환시킨다.
	String contents = request.getParameter("content").replace("\n", "<br>");

%>

작성자 : <%=writer%> <br>
비밀번호 : <%=passwd %> <br>
제목 : <%=subject %> <br>
내용1 : <pre><%=content %></pre> <br>
내용2 : <br>
<%=contents %>

+ 이후엔 DB 연동해서 insert sql 문 실행해서 만들어진 테이블에 insert 할 것

+ 지금은 클라이언트가 요청한 것을 변수로 받아서 출력만 하고 있다

 

- board.js

$(function(){
		$("form").submit(function(){
			if($.trim($("#writer").val()) == ""){
				alert("작성자명을 입력하세요.");
				$("#writer").focus();
				return false;
			}
			if($.trim($("#passwd").val()) == ""){
				alert("비밀번호를 입력하세요.");
				$("#passwd").focus();
				return false;
			}
			if($("#passwd").val().length <2 || 
			   $("#passwd").val().length >8	){
				alert("비밀번호는 2~8자로 입력하세요");
				$("#passwd").val("").focus();
				return false;
			}
			if($.trim($("#subject").val()) == ""){
				alert("제목을 입력하세요.");
				$("#subject").focus();
				return false;
			}
			if($.trim($("#content").val()) == ""){
				alert("내용을 입력하세요.");
				$("#content").focus();
				return false;
			}
			if($.trim($("#content").val()).length > 200){
				alert("내용은 200자 이내로 입력하세요");
				$("#content").focus();
				return false;
			}
		});		
	});

- jQuery 로 유효성 검사를 구현했다

 

+ 에러 500 : 주로 코드 오류

 

JSP 내장 객체 예제 8

request 객체 예제 8

- WebContent/request/member

- HTML 시간에 만든 로그인 폼, 게시판 폼, 회원가입 폼에서 값을 전달하고 출력해보자

- HTML 과 jQuery 시간에 이미 폼 만들기, 유효성 검사 처리 내용에 값 전달 기능을 추가해보자

- memberform.html & member.js & idcheck.jsp & member.jsp

- memberform.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입 폼</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="http://dmaps.daum.net/map_js_init/postcode.v2.js"></script>
<script>
	function openDaumPostcode() {
		new daum.Postcode({
			oncomplete : function(data) {
				// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
				// 우편번호와 주소 정보를 해당 필드에 넣고, 커서를 상세주소 필드로 이동한다.
//				document.getElementById('join_zip1').value = data.postcode1;
				document.getElementById('post').value = data.zonecode;
				document.getElementById('address').value = data.address;				
			}
		}).open();
	}
</script>

<script src="member.js"></script>

<script>

	/* $(document).ready(function(){
	
		// ID중복 검사
		$("#idcheck").click(function(){
			if($("#id").val()==""){
				alert("ID를 입력하세요.");
				$("#id").focus();
				return false;
			}else{
				// window.open("팝업창에 실행될 문서명","윈도우이름","옵션")
				var ref="idcheck.jsp?id="+$("#id").val();
				window.open(ref,"idcheck","width=250, height=150")
			}
		});	
		
		// 주민번호 뒷자리로 포커스 이동
		$("#jumin1").keyup(function(){
			
			if($("#jumin1").val().length == 6)
				$("#jumin2").focus();
		});
		
		
		// 도메인 선택
		$("#email").change(function(){
			if($("#email").val() == ""){		// 직접 입력 선택
				$("#domain").attr("readOnly", false);		// 활성화
				$("#domain").val("").focus();
			}else{								// 도메인 선택
				$("#domain").val($("#email").val());
				$("#domain").attr("readOnly", "readOnly");	// 비활성화
			}			
		});			
		
		// 유효성 검사
		$("form").submit(function(){
			
			if($("#id").val() == ""){
				alert("ID를 입력하세요.");
				$("#id").focus();
				return false;
			}
			if($("#passwd").val() == ""){
				alert("비밀번호를 입력하세요.");
				$("#passwd").focus();
				return false;
			}
			if($("#name").val() == ""){
				alert("이름을 입력하세요.");
				$("#name").focus();
				return false;
			}
			if($("#jumin1").val() == ""){
				alert("주민번호 앞자리를 입력하세요.");
				$("#jumin1").focus();
				return false;
			}
			if($("#jumin1").val().length != 6){
				alert("주민번호 앞자리 6자리를 입력하세요.");
				$("#jumin1").val("").focus();
				return false;
			}
			// isNaN() : 문자가 포함되면 true를 리턴하는 함수
			if(isNaN($("#jumin1").val())){
				alert("숫자만 입력하세요.");
				$("#jumin1").val("").focus();
				return false;
			}
			if($("#jumin2").val() == ""){
				alert("주민번호 뒷자리를 입력하세요.");
				$("#jumin2").focus();
				return false;
			}
			if($("#jumin2").val().length != 7){
				alert("주민번호 앞자리 7자리를 입력하세요.");
				$("#jumin2").val("").focus();
				return false;
			}
			// isNaN() : 문자가 포함되면 true를 리턴하는 함수
			if(isNaN($("#jumin2").val())){
				alert("숫자만 입력하세요.");
				$("#jumin2").val("").focus();
				return false;
			}
			if($("#mailid").val() == ""){
				alert("EMail주소를 입력하세요.");
				$("#mailid").focus();
				return false;
			}
			if($("#domain").val() == ""){
				alert("도메인명을 입력하세요.");
				$("#domain").focus();
				return false;
			}
			if($("#tel1").val() == ""){
				alert("전화번호 앞자리를 입력하세요.");
				$("#tel1").focus();
				return false;
			}
			if(isNaN($("#tel1").val())){
				alert("숫자만 입력하세요.");
				$("#tel1").val("").focus();
				return false;
			}
			if($("#tel2").val() == ""){
				alert("전화번호 중간자리를 입력하세요.");
				$("#tel2").focus();
				return false;
			}
			if(isNaN($("#tel2").val())){
				alert("숫자만 입력하세요.");
				$("#tel2").val("").focus();
				return false;
			}
			if($("#tel3").val() == ""){
				alert("전화번호 끝자리를 입력하세요.");
				$("#tel3").focus();
				return false;
			}
			if(isNaN($("#tel3").val())){
				alert("숫자만 입력하세요.");
				$("#tel3").val("").focus();
				return false;
			}
			if($("#phone1").val() == ""){
				alert("핸드폰  앞자리를 선택하세요.");
				return false;
			}
			if($("#phone2").val() == ""){
				alert("핸드폰 중간자리를 입력하세요.");
				$("#phone2").focus();
				return false;
			}
			if(isNaN($("#phone2").val())){
				alert("숫자만 입력하세요.");
				$("#phone2").val("").focus();
				return false;
			}
			if($("#phone3").val() == ""){
				alert("핸드폰 끝자리를 입력하세요.");
				$("#phone3").focus();
				return false;
			}
			if(isNaN($("#phone3").val())){
				alert("숫자만 입력하세요.");
				$("#phone3").val("").focus();
				return false;
			}
			if($("#post").val() == ""){
				alert("우편번호를 입력하세요.");
				$("#post").focus();
				return false;
			}
			if($("#address").val() == ""){
				alert("주소를 입력하세요.");
				$("#address").focus();
				return false;
			}
			if($("#male").is(":checked") == false &&
			   $("#female").is(":checked") == false ){
				alert("남.여 중에서 1개를 선택 하세요.")
				return false;
			}
			
//			var cnt=0;
//			if($("#h1").is(":checked")) cnt++;
//			if($("#h2").is(":checked")) cnt++;
//			if($("#h3").is(":checked")) cnt++;
//			if($("#h4").is(":checked")) cnt++;
//			if($("#h5").is(":checked")) cnt++;
			
//			if(cnt < 2){
//				alert("취미를 2개 이상 선택 하세요.")
//				return false;
//			}
			
			if($("input:checkbox[name='hobby']:checked").length < 2){
				alert("취미를 2개 이상 선택 하세요.")
				return false;
			}
			
			if($("#intro").val() == ""){
				alert("자기소개를 입력하세요.");
				$("#intro").focus();
				return false;
			}
			
			if($("#intro").val().length > 100){
				alert("자기소개를  100자 이내로 입력하세요.");
				$("#intro").focus();
				return false;
			}
			
		});		
		
	}); */
	
</script>
</head>
<body>

<form method="post" action="member.jsp">
<table border=1 width=600 align=center>
	<caption>회원가입 폼</caption>
	<tr><th>ID</th>
		<td><input type=text autofocus="autofocus" id="id" name="id">
			<input type="button" value="ID중복검사" id="idcheck">
		</td>
	</tr>
	<tr><th>비밀번호</th>
		<td><input type=password id="passwd" name="passwd"></td>
	</tr>
	<tr><th>성명</th>
		<td><input type=text id="name" name="name"></td>
	</tr>
	<tr><th>주민번호</th>
		<td><input type=text size=6 maxlength="6" id="jumin1" name="jumin1">-
		    <input type=text size=7 maxlength="7" id="jumin2" name="jumin2">
		</td>
	</tr>
	<tr><th>EMail</th>
		<td><input type=text size=10 id="mailid" name="mailid">@
			<input type=text size=10 id="domain" name="domain">
			<select id="email">
				<option value="">직접입력</option>
				<option value="naver.com">네이버</option>
				<option value="daum.net">다음</option>
				<option value="nate.com">네이트</option>
				<option value="gmail.com">gmail</option>
			</select>
		</td>
	</tr>
	<tr><th>전화번호</th>
		<td><input type=text size=4 maxlength="4" id="tel1" name="tel1">-
			<input type=text size=4 maxlength="4" id="tel2" name="tel2">-
			<input type=text size=4 maxlength="4" id="tel3" name="tel3">
		</td>
	</tr>
	<tr><th>핸드폰</th>
		<td><select id="phone1" name="phone1">
				<option value="">번호선택</option>
				<option value="010">010</option>
				<option value="011">011</option>
				<option value="016">016</option>
				<option value="018">018</option>
				<option value="019">019</option>
			</select>-
			<input type=text size=4 maxlength="4" id="phone2" name="phone2">-
			<input type=text size=4 maxlength="4" id="phone3" name="phone3">
		</td>
	</tr>
	<tr><th>우편번호</th>
		<td><input type=text size=5 maxlength="5" id="post" name="post">
			<input type="button" value="우편검색" onClick="openDaumPostcode()">
		</td>
	</tr>
	<tr><th>주소</th>
		<td><input type=text size=70 id="address" name="address"></td>
	</tr>
	<tr><th>성별</th>
		<td><input type=radio id="male" name="gender" value="남자">남자
			<input type=radio id="female" name="gender" value="여자">여자
		</td>
	</tr>
	<tr><th>취미</th>
		<td><input type=checkbox id="h1" name="hobby" value="공부">공부
			<input type=checkbox id="h2" name="hobby" value="게임">게임
			<input type=checkbox id="h3" name="hobby" value="등산">등산
			<input type=checkbox id="h4" name="hobby" value="낚시">낚시
			<input type=checkbox id="h5" name="hobby" value="쇼핑">쇼핑
		</td>
	</tr>
	<tr><th>자기소개</th>
		<td><textarea rows="5" cols="50" id="intro" name="intro"
			  placeholder="자기소개를 100자 이내로 입력하세요."></textarea></td>
	</tr>
	<tr><td colspan=2 align=center>
			<input type=submit value="회원가입">
			<input type=reset value="취소">
		</td>
	</tr>
</table>
</form>



</body>
</html>

- member.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<%
	request.setCharacterEncoding("UTF-8");
	
	String id = request.getParameter("id");
	String passwd = request.getParameter("passwd");
	String name = request.getParameter("name");
	String jumin1 = request.getParameter("jumin1");
	String jumin2 = request.getParameter("jumin2");
	String mailid = request.getParameter("mailid");
	String domain = request.getParameter("domain");
	String tel1 = request.getParameter("tel1");
	String tel2 = request.getParameter("tel2");
	String tel3 = request.getParameter("tel3");
	String phone1 = request.getParameter("phone1");
	String phone2 = request.getParameter("phone2");
	String phone3 = request.getParameter("phone3");
	String post = request.getParameter("post");
	String address = request.getParameter("address");
	String gender = request.getParameter("gender");
	
	String[] hobby = request.getParameterValues("hobby");
	String h = "";
	for(String hy : hobby)
		h += hy + "-";
		
	String intro = request.getParameter("intro");	
	String introduce = 
			request.getParameter("intro").replace("\n","<br>");

%>

ID : <%=id %> <br>
비밀번호 : <%=passwd %> <br>
성명 : <%=name %> <br>
주민번호 : <%=jumin1 %>-<%=jumin2 %> <br>
E-Mail : <%=mailid %>@<%=domain %> <br>
전화번호 : <%=tel1 %>-<%=tel2 %>-<%=tel3 %> <br>
핸드폰 : <%=phone1 %>-<%=phone2 %>-<%=phone3 %> <br>
우편번호 : <%=post %> <br>
주소 : <%=address %> <br>
성별 : <%=gender %> <br>
취미 : <%=h %> <br>
자기소개1 : <pre><%=intro %></pre> <br>
자기소개2 : <br>
<%=introduce %> <br>

- String 배열에 hobby 에 저장된 값을 이어서 출력하자, ex) 공부-게임-등산-

- 이어서 출력하기 위해 반복문을 통해 하나의 변수 h 에 누적하고 있다

- Enter 키를 누른 경우 줄을 띄워서 출력하기 위해 replace() 함수로 "\n" 을 "<br>" 로 치환

+ action 태그로 몇줄만에 해결가능, 현재는 action 태그를 사용하지 않고 개별적으로 값을 받고 저장하고 있다

+ 나중엔 Java의 DTO 클래스를 사용하고 action 태그와 결합해서 3줄만에 이 작업을 함

 

+ 취미는 - 를 포함한 형태로 DB에 저장시킨다 ex) 공부-게임-쇼핑-

- 이후 회원 정보 수정등 취미를 조작해야하는 경우에 구분기호를 기준으로 split 해서 사용

 

- 나머지 member.js, idcheck.jsp는 코드 안붙임


response 객체

- 서버에서 클라이언트에 응답할때 사용하는 객체

 

response 객체 사용

1. 응답을 하면서 페이지를 이동하는 경우 많이 사용

2. cookie 발행시 reponse 객체로 응답하며 발행함

- 쿠키 발행시 클라이언트 임시폴더에 파일형태로 쿠키파일이 생성됨

- 나머지 JS 파일은 클라이언트에 쿠키가 저장된 것을 보고 우리 사이트에 접속한 적 있는지 등을 확인 가능

 

언어별 페이지 이동시키는 방법

- HTML : link 걸어서 이동 or meta 태그로 이동시키기, 시간적인 제어 가능 (몇 초 후 실행)

- Javascript : 내장객체 location 의 href 사용해서 이동, 메세지박스를 띄우고 확인버튼 눌렀을때 이동시킬수 있다

- JSP : response 객체로 페이지 이동, 별다른 특징없이 조용히 이동됨

+ 모든 언어에서 페이지 이동시 값을 가지고 갈 수 있다, 이때 폼이 아니므로 get 방식으로만 값 전달 가능하다

 

 

response 객체 메소드

String getCharacterEncoding() 인코딩 타입을 구해오는 역할
void addCookie(Cookie cookie) 쿠키를 발행하는 메소드
발행된 쿠키는 클라이언트의 임시폴더에 파일형태로 저장됨
void sendRidirect(String location) 페이지 이동시 사용하는 메소드
매개변수에는 이동할 페이지명이 들어감, 지정한 URL 로 이동

 

response 객체 정리

- 응답 하면서 쿠키를 발행함

- 응답하면서 페이지도 이동시켜줌

 

response 객체 예제

실습 준비

- 웹상에서 한글 이름을 사용하면 문제 발생, 'response객체' 에서 한글인 '객체' 를 지우기

- 먼저 HTML meta 태그, Javascript location 객체 예제부터 보며 response 객체와 비교할 것

 

JSP 내장 객체 예제 8

response 객체 예제 1

페이지 이동 1

- WebContent/response/response

- HTML meta 태그로 페이지 이동하며 값을 가져가는 예제

- meta.html & first.jsp

- meta.html

<html>
	<head>

	<!-- mata 태그로 페이지 이동 -->
	<meta http-equiv="refresh" content="0;
		url=first.jsp?name=test">

	</head>
	<body>
	</body>
</html>

- HTML meta 태그로 페이지 이동하며 값을 가져가고 있다

- 시간적인 제어 가능하다는 특징

- 쌍따옴표 주의

- 시간적인 제어가 가능하다, content=0 은 바로 이동을 의미

- content=3 으로 설정했다면 3초 뒤 페이지가 이동된다.

- 이동되는 페이지이며, 값이 넘어가는 파일은 first.jsp 이다

- get 방식으로 값이 넘어가므로 "?변수명=값" 으로 값이 넘어간다

- HTML 로 값을 전달할수 있다! 다만 HTML 은 값을 받을 수 없고 전송만 가능하다, JSP 파일에서 값을 받을 수 있다

 

- first.jsp

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

<%

String str = request.getParameter("name");

%>

name : <%=str%>

- get 방식으로 요청이 들어가면 first.jsp 파일에서 name값으로 전달된 값을 받고 있다

- 바로 이동됨

 

+ 2개 이상의 값을 전달할떈 & 로 연결한다

ex)

	<!-- mata 태그로 페이지 이동 -->
	<meta http-equiv="refresh" content="0;
		url=first.jsp?name=test&passwd=1234">

 

+ HTML 에서 페이지를 이동하는 다른 방법이 있다

- 링크를 걸어서 이동하기

- 값이 넘어가는 것이 URL 주소에 노출된다

ex) 네이버에서 링크 클릭해서 페이지 이동시

 

JSP 내장 객체 예제 9

response 객체 예제 2

페이지 이동 2

- WebContent/response/response

- Javascript 에서 location 객체로 페이지 이동하며 값을 가져가는 예제

- location.html & first.jsp

- location.html

<html>
	<head>
	<meta charset="utf-8">
	</head>
	<body>

	<!-- 자바스크립트로 페이지 이동 -->
	<script language="javascript">
		alert("페이지 이동");
		location.href='first.jsp?name=test';
	</script>

	</body>
</html>

- 사용자가 alert 메세지 박스의 확인 버튼을 눌렀을때 location.href 를 사용해서 first.jsp 로 넘어가며 값을 전달

- first.jsp 에서는 name 이라는 변수를 통해 값을 getParameter() 로 받고 있다

- location 객체로 이동하는 방법이 페이지 이동 3가지 방법 중 가장 많이 사용하는 방법

 

JSP 내장 객체 예제 10

response 객체 예제 3

페이지 이동 3

- WebContent/response/response

- JSP 에서 response 객체가 응답을 하면서 페이지 이동

- responseEx.jsp & first.jsp

- responseEx.jsp

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

<h1>Response 예제</h1>
   현재 페이지는  responseEx.jsp 페이지입니다.


<%	// JSP에서 페이지 이동

     response.sendRedirect("first.jsp?name=test");
%>

- sendRedirect() 함수를 통해 first.jsp 로 페이지 이동을 하고 가져가는 값은 name=test

- 마찬가지로 first.jsp 에서는 변수 name 을 통해 값을 받음


out 객체

- 브라우저로 출력할 때, 출력 스트림을 만들어주는 객체

- Model 1에선 JSP 내장객체이므로 바로 사용가능

- Model 2 에선 내장객체가 없으므로 만들어 사용해야함

- 주로 out.println 이나 out.print 로 출력

- 스크립틀릿 태그 안에서 out 객체를 써서 브라우저에 출력

 

out 객체의 메소드

print() 출력 스트림을 브라우저에 출력
println() 출력 스트림을 브라우저에 출력

request 객체의 println() 메소드

- 줄을 바꿔주지 못함, 줄을 안바꿈

- print() 메소드와 거의 같다

+ 줄을 바꾸기 위해선 br 태그나 p 태그를 써야함

 

out 객체 예제

실습 준비

 

JSP 내장 객체 예제 11

out 객체 예제 1

- outEx.jsp

<%@ page contentType="text/html;charset=euc-kr" buffer="5kb"%>

<%
	int totalBuffer = out.getBufferSize();
	int remainBuffer = out.getRemaining();
	int useBuffer = totalBuffer - remainBuffer;
%>

<h1>Out 예제</h1>
<b>현재 페이지의 Buffer 상태</b><p>

출력 Buffer의 전체 크기 : <%=totalBuffer%>byte<p>
현재 Buffer의 사용량 : <%=useBuffer%>byte<p>
남은 Buffer의 크기 : <%=remainBuffer%>byte<p>

- 출력시엔 원래 버퍼라는 임시기억장소에 저장했다가 출력함

 

버퍼 크기 설정 (outEx.jsp 부분)

<%@ page contentType="text/html;charset=euc-kr" buffer="5kb"%>

- 버퍼크기의 기본값은 8kb 이다, 생략시 8kb 로 설정됨

- page 지시어 태그에서 buffer 속성으로 버퍼 크기를 5kb 로 설정

 

- 이때 out 객체를 사용해서 버퍼의 전체 크기, 남은 용량 을 구할 수 있다

 

getBufferSize() 메소드 / 버퍼의 전체 크기 구하기 (outEx.jsp 부분)

<%	int totalBuffer = out.getBufferSize();  %>

 

getRemaining() 메소드 / 버퍼의 남아있는 용량 구하기 (outEx.jsp 부분)

<%	int remainBuffer = out.getRemaining();  %>

 

+ 현재 버퍼의 사용량은 전체 크기 - 남은 용량 으로 구하고 있다

 

- 1kb = 1000byte

 

만약 buffer 크기를 설정하지 않았다면?

- 기본값 8kb

 

JSP 내장 객체 예제 12

out 객체 예제 2

- useOut.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<html>
<head><title>out 기본 객체 사용</title></head>
<body>

<%
    out.println("안녕하세요?");
    out.println("안녕하세요?");
%>
<br>

out 기본 객체를 사용하여 
<%
    out.println("출력한 결과입니다.");
%>

</body>
</html>
</html>

- 자바의 println() 과 다르게 println() 을 사용해도 줄이 바뀌지 않음

 

출력시 줄 바꾸기

- 줄을 바꾸려면 <br> 태그나 <p> 태그를 사용해야함

- 스크립틀릿 태그안에서 <br> 태그를 사용하지 못하므로 out.print() 나 out.println() 메소드 안에 <br> 태그를 써야함!

<%
    out.println("안녕하세요?<br>");
    out.println("안녕하세요?" + "<br>");
    out.println("안녕하세요?");    
%>

- 이렇게 부분 수정


JSP의 영역

JSP의 영역

- 1개의 웹 어플리케이션 개발시 4가지 영역이 만들어짐

- 영역에 관련된 내장객체가 있기떄문에 JSP 영역을 학습

 

1. PAGE 영역

- 가장 좁은 영역

- 1개의 개별적인 페이지가 '페이지 영역'이 됨

 

2. REQUEST 영역

- 공유를 설정하고 그 다음페이지까지가 REQUEST 영역

 

3. SESSION 영역

- session 내장객체는 보통 회원가입 하고 로그인을 성공했을 때 서버와 클라이언트가 session 으로 연결되는데 여기서부터가 SESSION 영역의 시작

- 이후 로그아웃 시 서버와 클라이언트의 연결이 끊어짐, 즉 session 이 끊어짐

- 즉 로그인에 성공한 후부터 로그아웃 할때까지가 SESSION 영역

- 페이지 영역보다는 넓고 애플리케이션 영역보다는 좁다

 

- 브라우저를 통해서 공유를 하게 되는데 로그인 성공 후 부턴 계속 다른 페이지를 이동함, 이동할때마다 자신의 id, 비밀번호 값을 가져가지 않더라도 계속 로그인 상태가 유지됨 이때 공유를 하는 객체가 SESSION 객체

- login ~ logout 까지가 공유되는 영역의 범위

- 페이지가 바뀌더라도 공유한 값들을 쓸 수 있다

 

4. APPLICATION 영역

- 가장 넓은 영역

- 웹 전체가 APPLICATION 영역

application 객체 (정리)

- 영역과 관련된 공유 내장 객체 4개 중 하나

- 가장 넓은 영역의 공유 범위를 가지고 있다

- 애플리케이션 전체가 하나의  APPLICATION 영역

- 같은 종류의 브라우저끼리 공유가 되는 객체

- 폴더가 달라져도 공유가 된다

 

 

- 이 4가지에 대해 공유를 설정할 수 있는 내장 객체들이 있다

 

공유 설정 내장 객체

- pageContext 객체 : PAGE 영역에서 공유 설정

- request 객체 : REQUEST 영역에서 공유 설정, 요청을 처리도 하지만 공유 설정도 가능

- sesssion 객체 : SESSION 영역에 대해 공유 설정

- application 객체 : APPLICATION 영역에 대해 공유 설정

- 객체마다 공유 설정되는 범위가 다르다

 

공유 설정 메소드

- 4개의 객체에 대해 공통적으로 setAttribute() 메소드로 공유 설정함

 

- pageContext.setAttribute() 시 그 페이지 내에서만 공유한 값을 쓰게됨, 페이지가 넘어가면 공유된 값 사용 불가

- 같은 페이지 내에서만 사용가능하고 영역이 너무 좁기에 자주 사용되지 않음

 

- request.setAttribute() 에서 request 로 공유를 설정하고있다, 그 다음 페이지까지가 request 의 영역임, Model 2 에서 많이 사용

 

- session.setAttribute() 에서 session 은 로그인 성공시부터 로그아웃까지의 session 영역이므로 페이지를 넘어가도 공유하는 값은 유지됨, 그래서 로그인 관련은 session 공유 객체 사용

 

- application.setAttribute() 시 너무 영역이 넓어서 자주 사용 않음

- 첫번째 매개변수가 name 값, 즉 키값이고 두번째 매개변수가 value 값이다

- 공유된 값을 구해올때는 getAttribute() 메소드로 구해옴, name 값 즉 키값을 알아야 구해올 수 있다

 

공유 설정과 공유 값 구하기

- 공유 설정하는 메소드는 공통적으로 setAttribute(키,밸류) 이다

- 이렇게 공유되는 값을 setAttribte(키) 를 통해 영역 내에서 불러온다

 


Cookie

Javascript Cookie vs JSP Cookie 용도 차이

Javascript 의 Cookie

- 오늘하루 팝업창 열지 않기 클릭시 쿠키 발행

- 클라이언트의 임시 폴더에 쿠키가 파일형태로 저장되고 하루간 팝업창이 열리지 않음


JSP의 Cookie

- 로그인 상태 유지 체크를 하고 로그인 성공시 쿠키 발행, 그 정보가 컴퓨터에 쿠키 파일로 저장됨, 이때 유효시간을 길게 설정함, 계속 그 쿠키가 존재하므로 다시 접속하더라도 그 쿠키파일을 참조하면서 로그인 상태 유지

 

JSP Cookie

- 일반적으로 사이트에 로그인 시에 쿠키를 발행한다 (로그인 상태 유지 체크하고)

- 서버와 클라이언트 사이의 연결 상태(로그인) 를 유지하기 위해 쿠키 발행

- 쿠키 정보를 불러와서 계속 로그인 상태를 유지하는 것

- 페이지가 이동되어도 쿠키정보를 계속해서 참조하면 되므로 페이지 이동을 하면서 회원 정보를 가지고 가지 않아도 된다

- 유효한 시간이 경과되면 쿠키 정보가 지워짐

 

+ 개인에 대한 정보를 서버측에서 쿠키정보로 구해올 수도 있다

+ 사이트에 따라서는 사이트에 접속만 하더라도 쿠키를 발행하는 경우들이 있다

 

- 보안상 위변조 가능성이 있으므로 위험, 지금은 쿠키를 대신해서 session 을 사용

- session 은 클라이언트의 임시폴더에 저장되지 않고, 브라우저 창을 닫으면 연결이 끊어짐

+ 공공장소에서 로그인 상태 유지 를 체크하고 연결시 쿠키정보가 저장되어 위험함

 

 

- 페이지가 이동되어도 쿠키정보를 계속해서 참조하면 되므로 페이지 이동을 하면서 회원 정보를 가지고 가지 않아도 된다

 

 

Cookie 생성/설정 방법

 

1. Cookie 객체를 먼저 생성

//Cookie cook = new Cookie ( String name, String value )
Cookie cook = new Cookie ( "id", "test" )

- 첫번째 매개변수는 Cookie 의 name 값으로서 변수이고, 두번째 매개변수는 Cookie 의 value 값으로서 변수의 값

- id 변수에 test 란 값을 저장하라는 의미

 

2. response 객체로 쿠키를 발행

response.addCookie( cook );

- response 객체의 addCookie() 메소드로 생성된 쿠키 객체를 통해 클라이언트에게 쿠키 발행

- 발행시 클라이언트의 임시폴더에 쿠키 정보를 파일형태로 저장

 

3. 쿠키 값 변경 (선택사항)

cook.setValue( newValue )

- 생성자 두번째 매개변수에 들어갔던 쿠키 value 를 변경할 수 있다

- setValue() 메소드로 쿠키 값을 수정 가능

 

4. 쿠키 수명(지속시간) 설정

//cook.setMaxAge ( int expiry ); // 단위 : 초
cook.setMaxAge ( 60*60) // 1시간

- 쿠키가 언제까지 유효할지 시간 설정 가능

- setMaxAge() 메소드로 설정하고 매개변수에 들어가는 숫자는 초단위 이다

- 주어진 시간동안 쿠키정보를 가지고 있고 시간이 지나면 발행된 쿠키정보가 지워짐

- 직접 지우는 것도 어렵지만 가능하다

- 시간 설정을 하지 않았을떄는 클라이언트가 브라우저 창을 닫는 순간 자동으로 쿠키 정보가 지워진다

+ 일반적으로는 긴 시간으로 잡고 고객에 대한 정보를 계속 참고해서 로그인 상태 유지

 

5. 쿠키 읽기

Cookie[] cook = request.getCookie();

//쿠키 이름 : cook.getName()
//쿠키 값 : cook.getValue()

- 페이지를 계속 이동시키더라도 발행된 쿠키정보를 읽어와서(참조해서) 로그인 유지

- request 객체의 getCookie() 메소드로 읽어온다

- 여러 쿠키가 있으므로 Cookie 형 1차원 배열로 리턴한다

- 0 번방에 첫번째 쿠키가 있고 1번방에 두번째 쿠키가 있다

- 이때 getName() 메소드로 쿠키 네임을 구해올 수 있고 getValue() 메소드로 쿠키 밸류를 구할 수 있다

 

JSP Cookie 예제

실습 준비

 

JSP Cookie 예제 1

- jspproject/WebContent/Cookie/cookie

- makeCookie.jsp & useCookie.js

- makeCookie.jsp

<%@ page contentType="text/html; charset=euc-kr" %>

<html>
	<head>
		<title>쿠키를 생성하는 예제</title>
	</head>

<%
   String cookieName = "id";
   Cookie cookie = new Cookie(cookieName, "totoro");
   cookie.setMaxAge(10); 		// 단위 : 초
   cookie.setValue("guardian");
   response.addCookie(cookie);	// 쿠키 발행
%>

	<body>
	<h2>쿠키를 생성하는 예제</h2>
	<P>

"<%=cookieName%>" 쿠키가생성 되었습니다.<br>

		<input type="button" value="쿠키의 내용확인" onclick="javascript:window.location='useCookie.jsp'">
	</P>
	</body>
</html>

 

- 가장 먼저 쿠키객체를 생성하고 있다

- id 로 쿠키네임을, totoro 라는 값으로 쿠키값을 설정

- 10초 동안 쿠키를 유지시키도록 하고 있다

- 쿠키 값을 guardian 으로 바꾸고 있다

- response 객체의 addCookie() 로 쿠키 발행하고 있다, 이 코드가 쿠키를 발행하는 쿠키이다

 

- Cookie 클래스는 java.lang 패키지라 import 불필요

 

- 클릭이벤트로 useCookie.js 파일을 연다

- useCookie.js

<%@ page contentType="text/html; charset=euc-kr" %>

<html>
	<head>
		<title>웹 브라우저에 저장된 쿠키를 가져오는 예제</title>
	</head>
	<body>
	<h2>웹 브라우저에 저장된 쿠키를 가져오는 예제</h2>

<%
	Cookie[] cook = request.getCookies();

	if( cook != null ){
		for(int i=0; i<cook.length;++i){
			if(cook[i].getName().equals("id")){
%>

		쿠키의 이름은 "<%=cook[i].getName()%>" 이고 
		쿠키의 값 "<%=cook[i].getValue()%>" 입니다.

<%
			}
		}
	}
%>

	</body>
</html>

- 발행된 쿠키를 getCookies() 로 구해오고 배열에 저장

- 발행된 쿠키의 name 값이 id 가 같다면 getName() 과 getValue()로 쿠키 네임과 밸류를 구해서 출력

 

- makeCookie.jsp 실행

- 10초간 쿠키가 유지되므로 10초 경과 후 쿠키정보 삭제되면 쿠키 참조 불가하므로 새로고침시 정보 사라짐

- 변경된 쿠키값인 guardian 이 나타난다

 

쿠키 정보 확인 방법

- 임시폴더까지 쉽게 들어가기 위해 I.E 사용해야한다

- 브라우저를 I.E 로 변경 후 makeCookie.jsp 실행

- 원래는 히든을 풀어서 이 경로까지 들어가야한다, I.E 에선 쉽게 들어갈 수 있음

- 해당 쿠키 파일 지우면 그런 로그인 유지 기능, 일주일간 열지 않기 기능 등이 해제됨

- 폴더의 파일 전부 지우기

 

+ 쿠키 시간을 300 초로 설정해서 쿠키 형성을 확인해보자

- 300 초간 유지됨

- 300초의 시간이 지나면 파일은 남아있지만 안의 쿠키 정보는 지워버림

- 쿠키 정보가 지워지면 더이상 쿠키정보를 참조할 수 없게 됨

 

+ 쿠키 시간 설정을 하지 않는다면?

- 사용자가 브라우저 창을 닫는 순간 쿠키 정보가 지워짐

 

Cookie 활용 정리

- 쿠키에 저장된 값은 페이지가 넘어갈때 가져갈 필요가 없음

- useCookie.jsp 에서 클라이언트의 쿠키 정보를 구해옴

 

쿠키와 보안

- 클라이언트 임시폴더에 쿠키가 저장되므로 위변조 위험이 있다

- 그래서 지금은 쿠키를 대신해서 세션을 사용한다

 

JSP Cookie 예제 2

- jspproject/WebContent/Cookie/cookie1

- makeCookie.jsp & viewCookies.jsp & modifyCookie.jsp & deleteCookie.jsp

- makeCookie.jsp

쿠키 만들기

<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import = "java.net.URLEncoder" %>

<%  // 쿠키값을 URLEncoder 클래스를 이용해서 인코딩 한다.
    Cookie cookie = new Cookie("name", URLEncoder.encode("최범균"));
    response.addCookie(cookie);
%>

<html>
	<head><title>쿠키생성</title></head>
	<body>

<%= cookie.getName() %> 쿠키의 값 = "<%= cookie.getValue() %>"

	</body>
</html>

- 쿠키 객체 생성, 쿠키 네임값은 name , 쿠키 밸류값은 최범균

- 한글값이 깨지지 않도록 URLEncoder 클래스를 import 하고 encode() 함수로 인코딩 시켜줌

+ 쿠키 밸류값은 한글을 쓰는 것이 좋지 않다

- response 객체로 쿠키를 발행한다

 

- 쿠키 네임값을 getName() 으로, 쿠키 밸류값을 getValue() 로 가져옴

- 쿠키 밸류값이 한글이므로 깨져서 나온다

- 나중에 디코드를 시켜야한다

 

쿠키 보기

- 쿠키를 보는 파일 viewCookies.jsp 을 만들어서 쿠키 정보를 확인하자

- 주의 :

- 쿠키를 보려면 이 브라우저를 닫으면 안된다, 시간설정을 하지 않아서 닫으면 쿠키 정보 지워짐

- viewCookies.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import = "java.net.URLDecoder" %>

<html>
	<head><title>쿠키목록</title></head>
	<body>
	쿠키 목록<br>

<%
    Cookie[] cookies = request.getCookies();

    if (cookies != null && cookies.length > 0) {
        for (int i = 0 ; i < cookies.length ; i++) {
%>

			<!-- 쿠키값을 URLEncoder 클래스를 이용해서 디코딩 한다. -->
			<%= cookies[i].getName() %> = 
			<%= URLDecoder.decode(cookies[i].getValue()) %><br>

<%
        }//for end

    } else {
%>

		쿠키가 존재하지 않습니다.
<%
    }
%>

	</body>
</html>

+ 쿠키 밸류가 한글값이므로 URIDecoder 클래스의 decode() 로 디코드 시키고 있다

 

+ 만약 아까의 그 브라우저를 닫는다면?

- 쿠키가 존재하지 않는다고 뜬다

 

쿠키값 변경하기 2가지 방법

1. 처음 쿠키를 발행하는 것처럼 똑같이 발행

2. setValue() 메소드 사용

 

쿠키값 변경하기

- modifyCookie.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import = "java.net.URLEncoder" %>

<%
    Cookie[] cookies = request.getCookies();

    if (cookies != null && cookies.length > 0) {
        for (int i = 0 ; i < cookies.length ; i++) {

            if (cookies[i].getName().equals("name")) {
                Cookie cookie = new Cookie("name", URLEncoder.encode("JSP프로그래밍"));
                response.addCookie(cookie);
                //cookies[i].setValue(URLEncoder.encode("자바와 JSP"));
                //response.addCookie(cookies[i]);
            }// if end

        }//for end
    }
%>

<html>
	<head><title>값 변경</title></head>
	<body>
		name 쿠키의 값을 변경합니다.
	</body>
</html>

- cookies != null && cookies.length > 0 은 구해온 쿠키가 있다면 이라는 의미

 

1. 처음 쿠키를 발행하는 것처럼 똑같이 발행

- 반복문 안에서 처음 쿠키를 발행하는 것처럼 쿠키 객체를 만듬, 변수명이 똑같기때문에 값이 변하면 쿠키정보를 덮음

2. setValue() 메소드 사용

- setValue() 안에 바꾸고 싶은 값을 넣고 addCookie() 를 사용해서 발행

초기값
변경값

 

또는 두번째 방법을 썼을땐

 

쿠키 삭제

- 쿠키를 바로 삭제하는 함수는 없다

- 다른방법으로 쿠키를 삭제시킴

- deleteCookie.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import = "java.net.URLEncoder" %>

<%
    Cookie[] cookies = request.getCookies();
    if (cookies != null && cookies.length > 0) {
        for (int i = 0 ; i < cookies.length ; i++) {

            if (cookies[i].getName().equals("name")) {
                Cookie cookie = new Cookie("name", "");	// 쿠키 삭제
                cookie.setMaxAge(0);
                response.addCookie(cookie);
            }//if end

        }//for end
    }
%>

<html>
	<head><title>쿠키 삭제</title></head>
	<body>
		name 쿠키를 삭제합니다.
	</body>
</html>

- cookies != null && cookies.length > 0 은 구해온 쿠키가 있다면 이라는 의미, 그런 경우만 안의 내용 실행

- 쿠키 네임값이 'name' 이라면 쿠키를 삭제

 

쿠키를 삭제하는 방법

                Cookie cookie = new Cookie("name", "");	// 쿠키 삭제
                cookie.setMaxAge(0);
                response.addCookie(cookie);

1. 쿠키 네임값을 동일하게 해서 쿠키 밸류값을 null ("") 로 설정

2. 쿠키 시간을 0 초로 설정해서 실행되자마자 바로 삭제되게 함

3. response 객체의 addCookie() 로 쿠키 발행

 

- deleteCookie.jsp 실행해서 쿠키네임값이 name 인 쿠키 삭제

- 이후 viewCookies.jsp 실행해서 쿠키 정보 확인

- 쿠키네임값이 name 이었던 쿠키가 없어졌다

 

JSP Cookie 예제 3

- jspproject/WebContent/Cookie/cookie4

- make1hourCookie.jsp & viewCookies.jsp

- make1hourCookie.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<%
    Cookie cookie = new Cookie("oneh", "1time");
    cookie.setMaxAge(60 * 60); // 60초(1분) * 60 = 1시간
    response.addCookie(cookie);
%>

<html>
	<head><title>쿠키유효시간설정</title></head>
	<body>

	유효시간이 1시간인 oneh 쿠키 생성.

	</body>
</html>

- 1시간짜리 쿠키

- viewCookies.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import = "java.net.URLDecoder" %>

<html>
	<head><title>쿠키목록</title></head>
	<body>
	쿠키 목록<br><br>

<%
    Cookie[] cookies = request.getCookies();
    if (cookies != null && cookies.length > 0) {
        for (int i = 0 ; i < cookies.length ; i++) {
%>

			<%= cookies[i].getName() %> = 
			<%= URLDecoder.decode(cookies[i].getValue()) %><br>

<%
        }//for end
    } else {
%>
		쿠키가 존재하지 않습니다.
<%
    }
%>

	</body>
</html>


session 객체

- 영역과 관련, 공유의 개념과 관련

- 회원관리할때 주로 사용

- 서버와 클라이언트가 연결 상태(로그인) 을 유지하기 위해서 사용되는 개념

- 로그인에 성공시 서버 측에서 session 으로 클라이언트와 연결됨

- 이때, session 을 연결한 클라이언트의 웹 브라우저를 통해서 회원정보를 공유

- 쿠키의 역할을 대체, 클라이언트 임시폴더에 파일이 저장되지 않으므로 위변조 가능성이 없어서 쿠키보다 안전

- session 을 사용하면 공유가 되기때문에 페이지 이동을 하면서 회원정보를 가지고 가지 않아도 된다.

- 로그인했을때 session 이 연결되고 로그 아웃했을때 session 이 끊긴다

 

session 생성/설정 방법

- 공유되는 영역만 다를 뿐 다른 객체와 같은 메소드 사용

 

1. 세션 설정

//session.setAttribute ( java.lang.String name, java.lang.Object value )
session.setAttribute( "id", "guardian23" );

- name 값으로 지정한 이름에 value 값을 할당

- id 란 변수에 guardian23 을 저장하라는 의미

- 로그인에 성공시 주로 세션 설정함

- 같은 브라우저끼리만 공유되고 브라우저가 달라지면 공유가 안됨

2. 세션 사용

//session.getAttribute ( java.lang.String name )
String id = (String) session.getAttribute( "id" );

- 보통 페이지가 바뀌면 값을 가져감

- 하지만 쿠키를 참고하거나 세션을 구해오면 값을 가져갈 필요가 없이 세션의 네임값으로 필요할때마다 세션 밸류값을 가져올 수 있다

- getAttribute() 메소드는 리턴 자료형이 Object 이므로 String 으로 다운캐스팅해서 String 변수에 저장하고 있다

- 저장된 Value 값이 "gardian23" 으로 String 형이었으므로 String 형으로 다운캐스팅 하는 것이다

- 세션 밸류값이 어떤 자료형인지에 따라 다운캐스팅 하는 자료형을 결정

 

3. 세션의 유지시간 설정

session.setMaxInactiveInterval();

- 설정된 시간까지만 세션이 유지된다

- 주어진 시간이 지나면 연결이 끊어진다

ex) 은행 페이지에서 아무 작업하지 않은채 몇분이 지나면 자동으로 로그아웃 되는 기능, 계속 하려면 연장 버튼을 누름

- 시간설정을 하지 않으면 브라우저 창이 닫히면 연결이 끊어짐

 

4. 세션 삭제

- 쿠키는 삭제 메소드가 없었지만 세션은 삭제 메소드가 2개가 있다

//session.removeAttribute ( java.lang.String name );
session.removeAttribute( "id" )

- 세션이 여러개 있는경우 개별적으로 삭제해야할때 removeAttribute() 메소드 사용

- 이 매개변수의 네임값을 가진 세션을 삭제 시켜라는 의미

 

5. 세션 한꺼번에 모든 세션 삭제

session.invalidate();

- invalide() 메소드로 세션 삭제시 모든 세션이 삭제됨

- 로그아웃시, 회원탈퇴시 주로 세션을 삭제한다

 

Cookie vs Session 기능

- Cookie : 로그인 상태 유지 체크하면 브라우저 닫았다가 켰을때도 로그인 유지하는 기능만 쿠키임

- Session : 로그인을 성공했을때 로그인을 유지시켜주는 기능, 쿠키 제외 모든 기능

 

+ session 객체를 알면 나머지 영역 관련 객체들도 비슷하므로 쉽게 이해 가능

 

session 객체 예제

실습 준비

- 폴더명에서 한글인 '객체' 지우기

 

session 객체 예제 1

- WebContent/session/session

- setSession.jsp & viewSession.jsp

- setSession.jsp

<%@ page contentType="text/html; charset=euc-kr" %>

<html>
	<head><title>세션 사용 예제</title>
	</head>
	<body>

<%
	String id = "guardian23";
	String passwd = "1234";

	session.setAttribute("id", id);	// id="guardian23";
	session.setAttribute("passwd", passwd);	// passwd = "1234";
%>

	세션에 id 와 passwd 속성을 설정하였습니다.<br><br>

	<input type="button" value="세션의 설정된 속성확인" onclick="javascript:window.location='viewSession.jsp'">
	</body>
</html>

- 2개의 session 을 설정하고 있다

- session 객체는 내장객체 이므로 정의하지 않고 session 을 바로 사용하고 있다

- id 변수에 "guardian23" 을 passwd 변수에 "1234" 를 저장하고 있다

- 현재는 세션 시간 설정이 안되어있으므로 브라우저를 닫으면 세션 연결이 끊기므로 창을 닫지 않기

- 그 상태에서 버튼 클릭시 클릭이벤트로 viewSession.jsp 로 페이지 이동

- 이 값이 계속 공유되는 것임

- 같은 종류의 브라우저끼리만 공유되는 것임

 

주소값을 복사해서 다른 종류의 브라우저에 URL 를 복붙해보자

- 다른 브라우저에서는 세션이 공유되지 않음

 

- 일반적으로 session name 값을 아는경우 getAttribute() 로 쉽게 구해옴

- 하지만 세션 name 값을 모를때는 아래 방법으로 구하기

 

세션 name 값을 알지 못할때 세션을 보는 방법은?

- 세션 name 값을 먼저 구하고 value 를 구하고 있다

- viewSession.jsp

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="java.util.*" %>

<html>
	<head><title>세션 사용 예제</title></head>
	<body>

<%	// session 의 name값을 모르는 경우에 처리하는 방법
	// 열거형 : "id", "passwd"
	Enumeration attr = session.getAttributeNames();

	while(	attr.hasMoreElements()	){
		String attrName = (String)attr.nextElement();
		String attrValue = (String)session.getAttribute(attrName);
		out.println("세션의 속성명은 " + attrName + " 이고 ");
		out.println("세션의 속성값은 " + attrValue + "이다.<br><br>");
	}
%>

	</body>
</html>

- getAttributeNames() 메소드로 세션을 설정했던 세션 name 값들을 구하고 있다

- 그 값들을 열거형 attr 에 저장하고 hasMoreElemnets() 와 반복문을 통해 구해온 name 값이 없을때까지 루프를 반복하고 있다

- getElement() 메소드로 name 값을 구해오고 attrName 변수에 저장하고, 그 name 값으로 value 를 구해와서 attrValue 변수에 저장한다

- 그리고 그 값들을 출력하면 모든 세션의 네임과 밸류가 출력됨

 

세션 name 값을 알때 처리하는 방법은?

- 위의 코드를 주석으로 막고 세션 name 값을 알고있을때 세션 밸류를 구해보자

<%@ page contentType="text/html; charset=euc-kr" %>
<%@ page import="java.util.*" %>

<html>
	<head><title>세션 사용 예제</title></head>
	<body>

<%--	// session 의 name값을 모르는 경우에 처리하는 방법
	// 열거형 : "id", "passwd"
	Enumeration attr = session.getAttributeNames();

	while(	attr.hasMoreElements()	){
		String attrName = (String)attr.nextElement();
		String attrValue = (String)session.getAttribute(attrName);
		out.println("세션의 속성명은 " + attrName + " 이고 ");
		out.println("세션의 속성값은 " + attrValue + "이다.<br><br>");
	}
--%>
<%
	String id = (String)session.getAttribute("id");
	String passwd = (String)session.getAttribute("passwd");
%>

ID : <%=id %> <br>
비밀번호 : <%=passwd %> <br>

	</body>
</html>

- 세션 name 값으로 쉽게 값을 구해오고 있다

- getAttribute() 는 Object 형으로 리턴하므로 명시적으로 강제형변환을 해야한다

- 이 세션의 밸류값이 String 형이므로 String 형으로 다운캐스팅 하고 있다

- 이렇게 수정 후 setSession.jsp 파일을 실행

- 창이 닫히지 않는 한 이 값이 공유 됨 ( 시간 설정을 안해뒀으므로 ) 

- 같은 종류의 브라우저끼리만 공유됨

 

같은 종류 브라우저인 크롬 브라우저에 URL 복붙

- 공유가 된다

 

다른 종류 브라우저인 마이크로 엣지 브라우저에 URL 복붙

- 공유되지 않음

 

+ 세션을 설정할때도 업캐스팅을 했다

세션 설정

//session.setAttribute ( java.lang.String name, java.lang.Object value )
session.setAttribute( "id", "guardian23" );

- 밸류의 자료형이 Object 로 되어있다

- 우리는 String 형으로 매개변수를 입력했음, 즉 업캐스팅 (자동형변환) 된 것이다

- String 외에도 DTO 클래스 등 직접만든 클래스들이 이 자리에 들어갈 수 있다, Object 가 모든 클래스 조상이므로

 

+ session 은 보통 한개만 설정하는 게 일반적

- 회원의 ID 값이 밸류 자리에 들어감, 회원을 식별하는 고유 정보이기때문에

- id 값만 있으면 p.k 이므로 다른 모든 정보를 구해올 수 있다

 

session 객체 예제 2

- WebContent/session/session2

- closeSession.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<%
    session.invalidate();
%>

<html>
	<head><title>세션 종료</title></head>
	<body>

	<script>
		alert("로그아웃");
		location.href = "../session/viewSession.jsp"
	</script>

	</body>
</html>

- 세션을 삭제함

- 주로 로그아웃시에, 회원탈퇴시에 세션을 삭제한다

- invalidate() 메소드는 모든 세션을 한꺼번에 삭제시켜주는 메소드

- 브라우저 창이 닫히지 않았지만 모든 세션이 삭제됨

- 세선 삭제를 하고 alert 메세지를 띄우고 세션을 확인할 수 있는 viewSession.jsp 로 이동시켜줌

- viewSession.jsp 로의 상대경로인 한폴더 위로 가서 session 폴더의 viewSession.jsp 로 감

- 로그아웃 후, 즉 세션삭제 후 일반적인 흐름대로 <script> 안에 쓴 것

 

- 세션 삭제 확인 가능!

 

session 객체 예제 2

- WebContent/session/sessionLogin

- sessionLogin.jsp & sessionLoginCheck.jsp & sessionLoginForm.jsp & sessionLogout.jsp

- sessionLoginForm.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<html>
	<head><title>로그인폼</title></head>
	<body>

	<form action="<%= request.getContextPath() %>/sessionLogin.jsp" method="post">
		아이디 <input type="text" name="id" size="10">
		암호 <input type="password" name="password" size="10">
			<input type="submit" value="로그인">
	</form>

	</body>
</html>

- '로그인' 버튼 클릭시 sessionLogin.jsp 로 페이지 이동

 

- 찾고자 하는 sessionLogin.jsp 파일을 찾을 수 없다

- 이유 (부분 코드)

- getContextPath() 를 통해 현재 프로젝트명을 구함 -> jspproject

- 프로젝트를 구한 후 sessionLgoin.jsp 파일을 찾아가기 위해선 WebContent 폴더가 기준이 된다

- WebContent 폴더 기준으로부터 session/sessionLogin 을 경로에 추가해야 찾아간다

<form action="<%= request.getContextPath() %>/session/sessionLogin/sessionLogin.jsp" method="post">
</form>

- 로 경로를 수정시 sessionLogin.jsp 파일을 찾아간다

- 하지만 이렇게 절대경로를 쓰는 방식은 복잡하다

 

다른 방법 사용

<form action="sessionLogin.jsp" method="post">
</form>

- 같은 폴더 내에 있으므로 그냥 세션명만 적으면 sessionLogin.jsp 를 잘 찾아간다

- 내부의 id, 비번과 다른 경우 로그인 실패 메세지를 띄우며 이전페이지로 돌아온다 (history 객체 사용)

+ 현재는 DB 연동은 안되어있지만 id 값과 비밀번호 값이 같은 경우 로그인이 성공한다

 

- sessionLogin.jsp (값이 넘어가는 페이지)

<%@ page contentType = "text/html; charset=euc-kr" %>

<%
    String id = request.getParameter("id");
    String password = request.getParameter("password");
    
    if (id.equals(password)) {	// 로그인 성공
        session.setAttribute("MEMBERID", id);	// 세션 설정
%>

		<html>
			<head><title>로그인성공</title></head>
			<body>
			<script>
				alert("로그인 성공");
				location.href="sessionLoginCheck.jsp"
			</script>
			</body>
		</html>

<%
    } else { // 로그인 실패시
%>

		<script>
			alert("로그인에 실패하였습니다.");
//			history.go(-1);	// 이전 파일로 돌아가기
			history.back();	// 이전 파일로 돌아가기
		</script>
<%
    }
%>

- name 값을 통해 값을 구해온다

- 현재는 DB 연동은 안되어있지만 id 값과 비밀번호 값이 같은 경우 로그인이 성공으로 판별

<로그인 성공시>

- 세션을 설정하고 있다, 이때 MEMBERID 라는 변수에 회원이 입력한 id 값(아이디)을 저장

- 그 이후 로그인 성공 메세지 출력하고 확인 클릭시 location 객체로 sessionLoginCheck.jsp 로 넘어감

- location 객체로 페이지 이동시 아무런 값도 가져가지 않았다! -> 브라우저 끼리 창을 닫기 전까지 세션값을 공유하고 있는 것임

- sessionLoginCheck.jsp 파일에서 세션값인 아이디를 써야한다면 세션값을 구해오면 된다

<로그인 실패시>

- 로그인 실패 메세지 출력하고 이전파일로 가기 위해 history 객체의 go(-1) 을 사용하여 이전페이지인 로그인 페이지로 돌아가게함

- go(-1) 대신 back() 메소드를 사용해서 이전파일로 돌아갈 수도 있다

+ sessionLoginForm.jsp 에서 설정했던 name 값이 변수명이 됨

 

- 로그인 성공시 출력

- sessionLoginCheck.jsp 파일로 넘어감, 로그인되었는지 로그아웃되었는지 확인해주는 파일

 

-  로그인 실패시 출력

- 이전 페이지인 로그인 페이지로 돌아옴

 

- location 객체로 페이지 이동시 아무런 값도 가져가지 않았다! -> 브라우저 끼리 창을 닫기 전까지 세션값을 공유하고 있는 것임

- 값 전달 없이 sessionLoginCheck.jsp 파일에서도 세션값을 구해오면 된다

- sessionLoginCheck.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>
<%
    String memberId = (String)session.getAttribute("MEMBERID");

	//조건연산자(3항 연산자)
	// (조건식) ? a : b
	// -> 조건식이 true이면 a가, false면 b가 실행됨

    boolean login = memberId == null ? false : true;
%>

<html>
	<head><title>로그인여부 검사</title></head>
	<body>

<%
    if (login) {	// 로그인 한 경우
%>
		<%= memberId %>님 환영합니다. <br>
		
		<a href="sessionLogout.jsp">로그아웃</a> <br>
		
		정보수정 <br>
<%
    } else {	// 로그인 하지 않은 경우
%>
		로그인하지 않은 상태	<br>
		
		<a href="sessionLoginForm.jsp">로그인</a> <br>
		
		<a href="../../request/member/memberform.html">회원가입</a> <br>
<%
    }
%>

	</body>
</html>

- 위에서 getAttribute() 메소드로 세션의 값을 구해오고 있다, memberId 변수에 저장한다

- 삼항 연산자 사용

- memberId == null 은 공유하는 값이 없다면 이라는 의미

- 그냥 이 파일 sessionLoginCheck.jsp 을 실행하게되면 memberId 값에는 null 값이 들어감

- null 이면 로그인 안한경우이고 false 를 반환 null 이 아니면 로그인을 한 경우 이므로 true 를 반환

- 이 boolean 값으로 if~else 문을 사용해서 로그인 한 경우와 안한 경우를 나눠서 보여줌

 

<로그인 한 경우 = 세션 있는 경우>

- 아이디 표시, 로그아웃 , 정보수정 메뉴가 나타남, 링크걸어주기

- 로그아웃 버튼 클릭시 sessionLogout.jsp 로 가서 거기서 다시 로그인페이지로 보냄

 

<로그인 안한 경우 = 세션 없는 경우>

- 다른 브라우저로 바로 sessionLoginCheck.jsp 실행시 세션이 없으므로 로그인 안한 경우가 됨

- 로그인, 회원가입 메뉴가 나타남, 링크 걸어주기

- 회원가입 을 클릭시 request 폴더의 memberform.html 회원가입 양식으로 가기위해 상대경로를 설정했음

-> "../../request/member/memberform.html"

 

 

- sessionLogout.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<%
    session.invalidate();	// 세션 삭제
%>

<html>
	<head><title>로그아웃</title></head>
	<body>
	<script>
		alert("로그아웃");
		location.href = "sessionLoginForm.jsp";
	</script>
	</body>
</html>

- invalidate() 로 로그아웃을 처리해줌

- 로그아웃 한 후, 로그아웃 메세지를 뿌리고 location 을 통해 로그인 페이지인 sessionLoginForm.jsp 로 이동

 

+ 세션 예시 (네이버)

- 로그인 여부에 따라 다른 화면을 보여줌

1. 로그인 하지 않았을때 = 세션값 없을때

- 로그인 클릭시 로그인 폼으로 넘어감

- 회원가입 클릭시 회원가입 폼으로 넘어감

 

2. 로그인 했을때 = 세션값 있을때

- 로그아웃 클릭시 로그아웃 jsp 파일로 이동되어 세션 연결 끊김

 

+ 페이지 이동해도 언제든 세션값을 가져올 수 있으므로 페이지 이동시에 값전달 할 필요없다

+ 로그인부터 로그아웃까지 세션 영역이므로 그 사이간은 어디서든 세션값을 가져올 수 있다

 


복습

JSP Model 2

- MVC 패턴으로 개발 

- Model 은 DB 처리를 한다, 인터페이스, 상속 등의 개념을 많이 사용 (Service 클래스+ DAO 클래스)

- Controller 클래스를 만들때 Java Servlet 로 만들어진다

- View 는 양식, 결과가 나타나는 페이지
+ Model 2 에서는 표현식 태그보다 표현 언어를 많이 사용

 

Model 2 배우기 전에 배울 것

- Java Servlet : Controller 클래스를 만드는데 사용

- EL (표현 언어) : View 에서 결과를 출력할때 사용

- JSTL

 

Spring

- Model 2 기반으로 개발을 빠르게 하기 위한 자바 프레임워크

+ 프레임워크는 일반적으로 라이브러리 제공

 

Model 1 에서도 자바를 사용

- DTO 클래스

- DAO 클래스 : DB 연동 처리하는 클래스

 

WAS (Web Application Server)

- 웹 프로그램 마다 사용하는 WAS 들이 정해져있다

- JSP : 주로 Apache Tomcat, Jeus, WebLogic, JBoss 등 사용

- ASP (Active Server Page) : IIS 라는 웹 서버가 있어야 ASP 코드 처리 가능

- PHP : 아파치 서버로 PHP 코드 해석하고 서비스


JSP 5대 태그

1. 스크립틀릿 태그 (Scriptlet tag) <%     %>
2. 선언 태그 (Declaration tag) <%!     %>
3. 표현식 태그 (Expression tag) <%=     %>
4. 지시어 태그 (Directive tag)
     1) 페이지 태그 (page tag)
     2) 포함 태그 (include tag)
     3) 사용자 정의 태그 (tag library tag)

<%@ page     %>
<%@ include     %>
<%@ taglib     %>
5. 액션 태그 (action tag) <jsp:usebean   >,   <jsp:setProperty   >
<jsp:getProperty   >,   <jsp: include   >  
<jsp:forward    >,   <jsp:plugin    >

1. 스크립틀릿 태그

- <% %>

-  Java 코드나 JSP 코드가 들어감

- 거의 대부분의 코드가 들어감

 

2. 선언 태그

- <%! %>

- 매서드를 정의할 때는 반드시 선언태그에 쓴다

- 매서드를 만드는 규칙은 JAVA 문법을 따른다, JSP 에서 메서드를 만드는 일은 드뭄

 

3. 표현식 태그

- <%= %>

- 변수나 값을 브라우저에 출력가능

- 출력할 변수나 데이터가 사이에 들어감

- 브라우저에 출력시키는 JSP 3가지 방법 중 1개

 

4. 지시어 태그

- 3가지 종류가 있다

- 공통적으로 <%@ 로 시작

1) 페이지 태그 <%@ page    %>

- JSP 파일을 이클립스로 만들면 자동으로 1라인에 생성되는 태그, 이게 페이지 지시어 태그

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

- 이 페이지에 쓸 수 있는 속성들이 있다

- contentType="text/html; charset=UTF-8" : META 태그에서 현재 문서에 있는 한글값을 브라우저에 출력하기 전에 UTF-8 로 인코딩 시켜라는 뜻, 즉 HTML의 meta 태그에서 하던 역할을 이 페이지 태그에서도 함

2) 포함 태그 <%@ include   %>

+ 부트스트랩에서 외부파일을 불러올때 사용했었다

3) 사용자 정의 태그 <%@taglib   %>

- taglib

 

5. 액션 태그

- <jsp:   > 형태

- 주로 페이지를 이동시킬때 쓰는 액션태그가 있고 자바와 연동할때 쓰는 액션태그가 있다

- include, forward 는 페이지 이동이나 다른 페이지를 이동시킬때 사용하는 액션태그

- usebeen, setProperty, getProperty 는 자바와 연동할때 사용하는 액션태그, Java의 DAO DTO 클래스와 연결할때 사용하는 액션태그

 

+ Java 애플릿 : JAVA Application(내 컴에서만) 형태로 된 것을 웹 상에서 사용될 수 있도록 해줌, 잘 사용되지 않음

 

JSP 5대 태그 예제 1

- tag.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>

<!-- 스크립틀릿 태그 (Scriptlet Tag) -->
<%
	// 기본 자료형 변수
	int i = 30;
	double d = 3.14;
	char c1 = 'A';
	char c2 = '자';
	boolean b1 = true;
	boolean b2 = false;
	
	// 참조형 변수
	// 1. 클래스
	String str1 = "JSP";
	String str2 = new String("JSP");
	
	// 2. 배열
	String[] str = {"자바", "JSP", "오라클", "웹표준", "파이썬"};
	
	for(int j = 0; j < str.length; j++){
		out.println(str[j] + "\t");
	}
	out.println("<br>");
%>

<%	for(String s : str) { %>
		<%=s %> <br>
<% 	}%>

<%
	// 3. 인터페이스 : List
	List list = new ArrayList();	// 업태스팅
	list.add(50);
	list.add(42.195);
	list.add('A');
	list.add(true);
	list.add("JSP");
	
	for(int j = 0; j < list.size() ; j++) {
		out.println(list.get(j) + "\t");
	}
%>
	



<!-- 표현식 태그 (Expression Tag) -->
출력 : <%="출력 성공"%> <br>
연산결과 : <%=1+2+3+4+5+6+7+8+9+10%> <br>
i = <%=i%> <br>
d = <%=d%> <br>
c1 = <%=c1%> <br>
c2 = <%=c2%> <br>
b1 = <%=b1%> <br>
b2 = <%=b2%> <br>
str1 = <%=str1%> <br>
str2 = <%=str2%> <br>

 

 

스크립틀릿 태그 / 기본 자료형 변수 (tag.jsp 부분)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!-- 스크립틀릿 태그 (Scriptlet Tag) -->
<%
	// 기본 자료형 변수
	int i = 30;
	double d = 3.14;
	char c1 = 'A';
	char c2 = '자';
	boolean b1 = true;
	boolean b2 = false;
	
%>

- 일반적인 JAVA 또는 JSP 코드를 쓸때 모두 스크립틀릿 태그안에 쓴다

+ 문법은 JAVA 문법 그대로이다

 

+ JSP에서 참조형 변수의 사용

- 자바의 자료형은 기본자료형 변수가 있고 참조형(클래스, 배열, 인터페이스) 변수가 있다

- JRE를 불러왔기때문에 JRE 라이브러리 안의 내용 사용 가능 

- 자바 문법을 따르므로 java.lang 제외 패키지 안의 클래스, 인터페이스 사용시 import 해야함

 

스크립틀릿 태그 / 참조형 변수 : 클래스 (tag.jsp 부분)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>

<!-- 스크립틀릿 태그 (Scriptlet Tag) -->
<%
	// 참조형 변수
	// 1. 클래스
	String str1 = "JSP";
	String str2 = new String("JSP");
%>

 

- String 은 java.lang 패키지 안의 클래스라 import 하지 않아도 된다

+ 거의 대부분의 코드는 스크립틀릿 태그 안에 쓰인다

 

스크립틀릿 태그 / 참조형 변수 : 배열 (tag.jsp 부분)

<%	
    // 2. 배열
	String[] str = {"자바", "JSP", "오라클", "웹표준", "파이썬"};
	
	for(int j = 0; j < str.length; j++){
		out.println(str[j] + "\t");
	}
	out.println("<br>");
%>

- 배열의 요소들을 반복문을 통해 출력시켜야하는데 표현식 태그를 중첩해서 사용할 수 없다

-> 해결 방법들 중 out 객체로 출력하고 있다

 

+ print() 와 println() 모두 줄이 바뀌지 않는다 -> br 태그 사용

+ br 태그는 태그 바깥에 써도 되고 안에 써도 되지만 안에 쓸떄는 out.println() 안에 써야한다

+ out 객체는 스크립틀릿 태그 안에서 사용해야한다

 

-> 또다른 해결 방법 : 태그를 따로 작성

+ 일반 for문이 아닌 향상된 for 문으로 작성 (tag.jsp 부분)

<%	for(String s : str) { %>
		<%=s %> <br>
<% 	}%>

- 가운데는 표현식 태그로 출력 하고 있다

- 다른 해결방법 중 하나이다, 중첩이 불가능하므로 여는 곳, 닫는 곳 따로 스크립틀릿 태그 안에 넣고 출력하는 부분만 표현식 태그로 출력

 

스크립틀릿 태그 / 참조형 변수 : 인터페이스 (tag.jsp 부분)

<%
	// 3. 인터페이스 : List
	List list = new ArrayList();	// 업태스팅
	list.add(50);
	list.add(42.195);
	list.add('A');
	list.add(true);
	list.add("JSP");
	
	for(int j = 0; j < list.size() ; j++) {
		out.println(list.get(j) + "\t");
	}
%>

- java.util 패키지를 import 하고 리스트를 만들수 있음

- List 객체 만드려면 ArrayList 로 업캐스팅 또는 ArrayList 객체만들기

- List 자료구조의 데이터를 반복문으로 출력, out 객체 사용

* import 하는 방법은 아래에

 

+ import 하는 방법 / 페이지 지시어 태그와 속성 (tag.html 부분)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>

- contentType="text/html; charset=UTF-8" : META 태그에서 현재 문서에 있는 한글값을 브라우저에 출력하기 전에 UTF-8 로 인코딩 시켜라는 뜻, 즉 HTML의 meta 태그에서 하던 역할을 이 페이지 태그에서도 함

- language="java" : 기본값이 java 이므로 생략 가능

- contentType 속성 : 현재 문서의 타입이 텍스트냐 이미지냐 , 현재 문서는 text 란 의미

한글값을 브라우저에 출력시 인코딩을 UTF-8 로 하라는 의미

pageEncoding 도 생략 가능

- import 속성 : import 할때 사용, 추가해서 사용, import="패키지부터 클래스까지의 경로" 로 써야함

- errorPage 속성 : JSP 에서 에러처리할때, 에러를 보여줄 페이지명을 지정, 에러를 보여줄 페이지 안에는 isErrorPage="true"로 설정해야함

- isErrorPage 속성 : 에러를 보여줄 페이지 안에서 true 로 설정해야함

- 그 외는 기본값이 잡혀있으므로 신경쓰지 않아도 된다

 

page 지시어 태그 속성

1. contentType : 현재문서의 형식, 텍스트인지 이미지인지 명시, 텍스트라면 text/html 

2. charset : 현재문서를 브라우저로 출력시 어떻게 인코딩 시킬지, 한글은 EUC-KR 또는 UTF-8

+ UTF-8 로 해야 영문 브라우저에서도 한글값 깨지 않음

- 값이 넘어가는것과 관련없다, 현재 문서를 인코딩

3. import : 외부의 클래스등을 사용하려면 import 해야함

4. errorPage / isErrorPage : 페이지 처리시 사용해서 한 페이지에서 에러를 한꺼번에 처리할 수 있게 함

 

표현식 태그 (tag.jsp 부분)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<!-- 표현식 태그 (Expression Tag) -->
출력 : <%="출력 성공"%> <br>
연산결과 : <%=1+2+3+4+5+6+7+8+9+10%> <br>
i = <%=i%> <br>
d = <%=d%> <br>
c1 = <%=c1%> <br>
c2 = <%=c2%> <br>
b1 = <%=b1%> <br>
b2 = <%=b2%> <br>
str1 = <%=str1%> <br>
str2 = <%=str2%> <br>

- 표현식 태그는 주로 변수명 등을 출력하는 역할

- 표현식 태그 안에 문자열도, 연산식도 들어갈 수 있다

- 연산식의 결과가 출력됨

- 표현식 태그는 문자열, 연산결과, 변수에 저장된 값, 리턴구문에서 돌려받은 값 등을 출력

 

+ 한글 인코딩

- HTML 에서의 한글 인코딩과 JSP 에서의 한글 인코딩이다, 두개가 같은 역할

- 두가지 중 하나는 있어야만 한글이 깨지지 않음

 

JSP 5대 태그 예제 2

선언 태그

- tag1.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!-- 선언태그 -->
<!-- JSP에서 메소드는 반드시 선언태그 안에서 생성해야한다. -->
<%!
	int a = 30;
	public int add(int a, int b) {
		int c = a + b;
		return c;
	}

	public int subtract(int a, int b) {
		int c = a - b;
		return c;
	}
	
	public int multiply(int a, int b) {
		int c = a * b;
		return c;
	}
%>
<%
	int result1 = add(3, 9);	//add 메소드 호출
	int result2 = subtract(3, 9);	//subtract 메소드 호출
	int result3 = multiply(10, 25);	//multiply 메소드 호출
%>

3 + 9 = <%=result1 %> <br>
3 - 9 = <%=result2 %> <br>
10 * 25 = <%=result3 %> <br>
10 * 25 = <%=multiply(10, 25) %> <br>

- JSP에서 메소드는 반드시 선언태그 안에서 생성해야한다

+ 선언 태그안에 변수 선언하는 것도 가능하다

- 메소드를 호출할때는 스크립틀릿 태그, 결과를 출력할때는 표현식 태그를 사용

- 표현식 태그 안에서 함수를 호출하여 리턴받은 결과를 표현식 태그로 바로 출력하는 것도 가능하다

+ 표현식 태그는 문자열, 연산결과, 변수에 저장된 값, 리턴구문에서 돌려받은 값 등을 출력

 

페이지 지시어 태그 속성

1. 자동으로 추가되는 속성

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

- contentType : 현재 문서의 형식

- charset=UTF-8 현재 문서의 한글값을 UTF-8 로 인코딩 시켜라

 

2. 직접 설정

- import

<%@ page import="java.util.Date" %>

- java.lang 외의 패키지의 클래스/인터페이스 사용시엔 반드시 import 필요

- 나중에는 API 가 아닌 직접 만든 클래스를 import

 

+ 날짜 시간 관련 클래스 복습 링크

https://laker99.tistory.com/28

 

JSP 5대 태그 예제 3

import 예제 / 페이지 지시어 태그 1

- 날짜 시간 관련 클래스들 (java.util 패키지)

- import.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="java.util.Date"%>
<%@page import="java.text.SimpleDateFormat"%>
<%@page import="java.sql.Timestamp"%>

<%
	// 1. 날짜, 시간 클래스
	// 1. Date 클래스
//	java.util.Date d = new java.util.Date(); // import 를 안하고 쓸 수 있다
	Date d = new Date();
	SimpleDateFormat sd = 
			new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEE요일");
	
	// 2. TimeStamp 클래스
	Timestamp ts = new Timestamp(System.currentTimeMillis());
%>

현재시간1 : <%=d %> <br>
현재시간2 : <%=sd.format(d) %> <br>
현재시간3 : <%=ts %> <br>
현재시간4 : <%=sd.format(ts) %> <br>

<Date 클래스>

<%@page import="java.util.Date"%>

- Date 클래스를 쓰려면 java.util 을 페이지 지시어 import 속성으로 import 해야함

+ 쉽게 import 하는 법 : Date 를 입력하면서 Ctrl + Space 누르고 선택하면 쉽게 import 가능

- 날짜 시간이 영미권에서 쓰는 형태로 나타난다

 

<SimpleDateFormat 클래스>

<%@page import="java.text.SimpleDateFormat"%>

- 날짜 시간 형식을 한국에서 자주 쓰는 형태로 바꾸기 위해 Java.text.SimpleDateFormat 클래스가 필요

- java.text 패키지 import 

 

<TimeStamp 클래스>

<%@page import="java.sql.Timestamp"%>

- java.security 가 아닌 java.sql 패키지 안의 TimeStamp 클래스를 사용해야한다

- java.sql 패키지를 import

- 이것 역시 포맷을 적용한다

 

JSP 5대 태그 예제 4

import 예제 / 페이지 지시어 태그 2

- 날짜 시간 관련 클래스들 중 Calendar 클래스 (java.util 패키지)

- 날짜 시간 클래스 관련 JAVA 내용은 자바공부할 때 배웠다 https://laker99.tistory.com/28

- import1.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="java.util.Calendar"%>
<%
	// 3. Calendar 클래스
	
	Calendar c = Calendar.getInstance();
	
	int y = c.get(Calendar.YEAR);			// 년
	int m = c.get(Calendar.MONDAY)+1;		// 월(0~11)
	int d = c.get(Calendar.DATE);			// 일
	
	int h1 = c.get(Calendar.HOUR);			// 12시간
	int h2 = c.get(Calendar.HOUR_OF_DAY);	// 24시간
	
	String h = "";
	if(c.get(Calendar.AM_PM) == 0) {	// AM_PM : 0 (오전)
		h = "오전";						// AM_PM : 1 (오후)
	} else {
		h = "오후";
	}
	
	int mm = c.get(Calendar.MINUTE);		// 분
	int s = c.get(Calendar.SECOND);			// 초
	
	// 일(1), 월(2), 화(3), 수(4), 목(5), 금(6), 토(7)
	int week = c.get(Calendar.DAY_OF_WEEK);	// 요일(1~7)
	
	String[] weekend = {"일", "월", "화", "수", "목", "금", "토"};
%>
<%=week %> <br> <!-- 5 : 목 -->

<!-- 12시간제 시간 -->
<%=y%>-<%=m%>-<%=d%> <%=h %> <%=h1 %>:<%=mm %>:<%=s %>
	<%=weekend[week-1] %>요일 <br>

<!-- 24시간제 시간 -->
<%=y%>-<%=m%>-<%=d%> <%=h %> <%=h2 %>:<%=mm %>:<%=s %>
	<%=weekend[week-1] %>요일 <br>

- JAVA 코드는 스크립틀릿 태그, 출력할때는 표현식 태그

+ Calendar 클래스는 new 연산자로 객체생성하지 못함, 정적메소드 getInstance() 사용해서 객체 구함

 

JSP 5대 태그 예제 5

import 예제 / 페이지 지시어 태그 3

- Random 클래스

- Random 클래스 난수발생 내용 JAVA 복습 https://laker99.tistory.com/28

- import2.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.Random"%>

<%
	// 난수 발생
	Random r = new Random();
	
	int r1 = r.nextInt(10);	// 0 ~9
	
	// 1 ~ 45 사이의 난수 발생
	int r2 = r.nextInt(45) + 1;	// 1 ~ 45
%>

난수1 : <%=r1 %> <br>
난수2 : <%=r2 %> <br>

- Random 클래스 메소드 중 nextInt(45) 이면 0 부터 44까지 포함이다

 

JSP의 주석 

- JSP 에선 주석이 크게 2가지로 나눠짐

- 클라이언트 웹 브라우저에 전송하지 않는 부분

- 클라이언트 웹 브라우저에 자체에 전송하지 않기때문에 소스보기 하더라도 결과가 보이지 않음

 

1. JSP 주석

- 아무곳에서나 사용 가능

- 여러줄 기술 가능

<%-- --%>

2. JSP 스크립트 주석

- 스크립틀릿 태그, 표현식 태그, 선언 태그 안에서도 사용 가능

- 단일행 주석과 다중행 주석

//
/* */

 

JSP 주석 주의

<%-- JSP 주석입니다 --%>
<% // 스크립틀릿에 한줄 주석 %>
<% /* 스크립틀릿에 여러줄 주석 %>
<%=name /* 표현식에 주석 사용 %>
<%= /* 표현식에 주석만 있는 경우 컴파일 에러 발생 %>

- 스크립틀릿 태그 안에 사용할 때는 단일행 주석과 다중행 주석 다 가능

- 표현식 태그 안에 사용할때는 다중행 주석만 가능

 

JSP 주석 예제 

실습 준비

- 모두 주석에 대한 예제

 

JSP 주석 예제 1

HTML 주석

- htmlComment.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import = "java.util.Date" %>

<html>
<head><title>HTML 주석</title></head>
<body>

<!-- 처리시간: <%= new Date() %> -->
HTML 주석은 그대로 출력됨.

</body>
</html>

- HTML 주석 <!-- --> 사용

- HTML 주석 안에서 출력하는 표현식 태그 사용하고 있다

- HTML 주석 안 내용은 주석이기 때문에 브라우저에 출력되진 않는다

- 브라우저에 출력되진 않지만 클라이언트 측 언어이기 때문에 웹 브라우저 상에 소스보기 하면 모두 노출됨

브라우저
소스보기

 

+ 소스보기

 

JSP 주석 예제 2

JSP 주석

- jspComment.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<html>
<head><title>JSP 주석</title></head>

<body>

	<%-- JSP 주석입니다. --%>
	주석은 출력 결과에 포함되지 않습니다.

</body>

</html>

- JSP 주석 <%-- --%> 을 사용하고 있다

- 안의 내용은 모두 주석으로 처리됨

- JSP 주석은 아무곳이나 사용 가능하다

- 브라우저 창에 나타나지 않고, 클라이언트 웹 브라우저에도 전송자체를 하지 않은 내용이므로 소스보기 하더라도 보이지 않음

- HTML 주석보다 보안상 더 안전하다

 

JSP 주석 예제 3

JSP 스크립트 주석

- javaComment.jsp

<%@ page contentType = "text/html; charset=euc-kr" %>

<%!
	/**
	 * a와 b의 합을 리턴한다.
	 */
	public int add(int a, int b) {
		return a + b;
	}
%>

<html>
<head><title>자바 주석</title></head>

<body>

<%
	int val1 = 10; // val1에 10을 할당
	int val2 = 20; // val2에 20을 할당
	
	/* va1과 va2의 값을 더한 결과를
	   result에 할당한다. */
	int result = add(val1, val2);
%>

<%= val1 %> + <%= val2 %> = <%= result /* 결과는? */ %>

</body>
</html>

- JSP 스크립트 주석은 JSP 태그 중 스크립틀릿 태그, 표현식 태그, 선언 태그 내에서 사용 가능하다

- JSP 스크립트 주석은 단일행 주석과 다중행 주석이 있다

- 선언 태그 안과 스크립틀릿 태그, 표현식 태그 내에서 주석을 사용하고 있다

- 표현식 태그 안의 주석은 다중행 주석만 가능하고 단일행 주석을 쓰면 오류 발생

- JSP 스크립트 주석은 클라이언트의 웹 브라우저에 전송자체를 하지 않기때문에 소스보기 해도 나타나지 않는다

소스 보기

JSP 주석 예제 4

모든 주석

- comment.jsp

<%@ page contentType="text/html;charset=euc-kr" %>

<html>

<!-- HTML에서 제목을 출력합니다.(html 주석) -->

두 개의 숫자를 더해서 결과를 출력합니다 : <br>

<%-- 계산 결과는 자바 코드로 출력합니다.(jsp 주석) --%>

<body>

<%
/* 두 개의 정수형 변수에
   값을 할당하고 계산합니다. */

int i=1;
int j=2;
i=i+j;

out.println("i+j = " + i); //계산된 결과를 출력합니다.
%>

</body>
</html>

- HTML 주석 : 소스보기에 보임

- JSP 주석 : 소스보기에 보이지 않음

- JSP 스크립트 태그 안 다중행 주석 : 소스보기에 보이지 않음

- JSP 스크립트 태그 안 단일행 주석 : 소스보기에 보이지 않음

 

- 주석은 무엇이든지 브라우저 상에선 안보임, 소스보기시에 HTML 주석은 보인다
- 소스보기에 보이지 않음 = 클라이언트 웹 브라우저로 전달자체가 되지 않았다

 

- HTML 주석은 클라이언트 웹 브라우저에 전송되기 때문에 소스보기 시에 보인다

- 네이버 : HTML 주석은 소스보기로 볼 수 있다

- 보안상 HTML 주석은 좋지 않다

 

JSP 주석 예제 5

모든 주석

- commentEx.jsp

<%@ page contentType="text/html;charset=euc-kr" %>

<html>
	<body>


<h1>Comment Example</h1>

<%
   String name = "Korea";
%>

<!-- html 주석 부분입니다. '소스보기'에서 보이지요. -->

<%-- 
     이 부분은 JSP 페이지에서만 보이고 '소스보기'를 해도 보이지 않습니다.
     브라우저에 보내지 않는 문장입니다. 
--%>

<!-- <%=name%> html주석에서도 동적인 변수 사용(주석 처리되지만 브라우저에서 소스보기로 출력됨) -->

<%-- <%=name%> jsp주석 --%>

<%=name /* 표현식의 주석 부분 입니다*/ %> Fighting!!!

	</body>
</html>

- HTML 주석은 브라우저에 출력되지 않지만 소스보기에서 보임

- JSP 주석은 브라우저에서 출력되지 않고 소스보기에서도 보이지 않음

- HTML 주석 안의 표현식 태그는 소스보기에서 변수 값이 출력됨, 즉 소스보기에서 보임

- JSP 주석 안의 표현식 태그는 소스보기에서 보이지 않음

- 표현식 태그 안의 JSP 스크립트 다중행 주석은 소스코드에서 보이지 않음

- JSP 주석과 JSP 스크립트 주석으로 처리하는게 보안상 안전


JSP 내장 객체

- JSP 에선 9개의 내장 객체가 지원된다

- 따로 정의 없이 사용할 수 있도록 기본적으로 제공됨

- 내장객체를 쓸 수도 있고 직접 클래스로 객체를 만들어서 사용할 수도 있음

기본 객체 실제 타입 설명
request javax.servlet.http.HttpServletRequest 
또는 javax.servlet.ServletRequest
클라이언트의 요청 정보를 저장한다.
respond javax.servlet.http.HttpServletResponse
또는 javax.servlet.ServletResponse
응답 정보를 저장한다
pageContext javax.servlet.jsp.PageContext JSP 페이지에 대한 정보를 저장한다
session javax.servlet.http.HttpSession HTTP 세션 정보를 저장한다
application javax.servlet.ServletContext 웹 어플리케이션에 대한 정보를 저장한다
out javax.servlet.jsp.JspWriter JSP 페이지가 생성하는 결과를 출력할 때 사용되는 출력 스트림이다
config javax.servlet.ServletConfig JSP 페이지에 대한 설정 정보를 저장한다
page java.lang.Object JSP 페이지를 구현한 자바 클래스 인스턴스이다
exception java.lang.Throwable 예외 객체, 에러 페이지에서만 사용된다

- 굵음 적용된 내장객체는 자주 사용되는 객체

 

response 객체

- 서버측에서 응답하는 객체

- 페이지 이동시에 많이 사용하는 객체 (HTML : meta 태그, Javascript : location 객체, JSP : response 객체의 sendRedirect())

- 쿠키 발행시에도 사용하는 객체, 쿠키 발행하면서 응답하면 클라이언트의 임시폴더에 쿠키가 저장됨

 

session 객체

- 서버와 클라이언트 사이 연결을 유지하기 위한 객체

- 주로 회원관리 할때 사용됨

- 회원가입 프로그램에서 로그인에 성공했을 경우 쿠키와 세션을 사용함

- 로그인시 id 비번을 전달해서 가입시의 id 비번과 일치시 세션을 연결하는 것임

- 쿠키 대신 사용

 

out 객체

- 브라우저에 출력시켜주는 객체

- 지원되는 메소드 중 println() 메소드를 통해 출력 가능

- 브라우저에 출력하는 방법 중 1개

 

request 객체

- 클라이언트의 요청 정보를 처리해줌,

- 클라이언트가 get/post 로 요청할때 요청을 처리해주는 객체

- 가입 버튼 클릭시 서버측으로 id, 비번, 이름 등을 서버로 전달함

- 클라이언트가 요청 (form 에서 값 입력후 action 으로 전달) 시 request 객체가 요청을 받음

- 지원되는 메소드 중 getParamenter() 메소드를 통해 넘어온 값을 받을 수 있다

 

request 객체 메소드

+내장객체에서 지원되는 메소드는 자바 스탠다드가 아닌 자바 EE 에서 지원되는 클래스를 찾아야함

javax.servlet.http.HttpServletRequest 또는 javax.servlet.ServletRequest

- 에서 지원 메소드 확인 가능

 

request 객체 예제

실습 준비

- 웹상에서 한글 이름을 사용하면 문제 발생, 'request객체' 에서 한글인 '객체' 를 지우기

 

JSP 내장 객체 예제 1

request 객체 예제 1

- WebContent/request/ex1

- requestExample1.html & requestExample.jsp

- requestExample1.html

<html>
<head>
	<meta charset="UTF-8">
	<title>request객체 연습</title>
	<script src="http://code.jquery.com/jquery-latest.js"></script>
	<script>
	$(document).ready(function(){
		$("form").submit(function(){
			if($("#name").val()==""){
				alert("이름을 입력하세요");
				$("#name").focus();
				return false;
			}
			if($("#studentNum").val()==""){
				alert("학번을 입력하세요");
				$("#studentNum").focus();
				return false;
			}
			if($("#male").is(":checked")==false &&
			   $("#female").is(":checked")==false){
				alert("성별을 선택하세요");
				return false;
			}
			if($("#major").val()=="#"){
				alert("전공을 입력하세요");
				$("#major").focus();
				return false;
			}
		});	
	});	
	</script>
</head>
<body>
<h1>Request 예제1</h1>

<form name=myform method=post action="requestExample1.jsp">
 이름 : <input type="text" name="name" id="name" autofocus="autofocus"><br>
 학번 : <input type="text" name="studentNum" id="studentNum"><br>
 성별 : 남자 <input  type="radio" name="gender"  value="남자" id="male">
        여자 <input type="radio" name="gender" value="여자" id="female"><br>
 전공 : <select name="major" id="major">
			<option value="#">전공을 선택하세요</option>
			<option value="컴퓨터공학">컴퓨터공학</option>
			<option value="영문학과">영문학과</option>
			<option value="수학과">수학과</option>
			<option value="정치학과">정치학과</option>
			<option value="산업디자인과">산업디자인과</option>
		</select><br>
<input type="submit" value="보내기">
<input type="reset" value="취소">
</form>

</body>
</html>

- jQuery 로 유효성 검사 되어있다

- form 태그는 한꺼번에 많은 정보를 저장할때 쓴다

- form 태그의 method 에서 get/post 방식 선택 가능, 보통 보안이 좋은 post 방식 선택

+ get 방식 전송과 post 방식 전송시에 한글 인코딩 문제가 달라짐! (뒤에 설명)

- 나머지(링크걸기, location 으로 이동, meta 태그로 이동) 경우는 get만 가능

- form 의 action 에서 값을 전달할 페이지 지정, 이 자리에는 jsp, php, asp 같은 웹 프로그램 명이 온다

- HTML은 값을 받을 수 없으므로 html 파일이 오지 않음

+ Model 2 는 다르지만 지금은 일단 jsp 파일

- '보내기' 버튼 클릭시 클라이언트에서 사용자가 입력한 정보를 

 

값 전달

- Javascript , jQuery나 CSS 에서는 태그를 구분하기 위해 id 값이 중요하다

- 하지만 JSP 처럼 웹 프로그램과 연동시에는 name 값이 사용자가 입력한 값을 전달하는 변수 역할을 하므로 name 값이 중요하다

- JSP 파일에서 name 값으로 값을 받으므로 태그의 name 값이 중요

- 아래 사진은 받는 측 jsp 파일

jsp 파일측

 

라디오버튼의 값 전달

- 입력양식은 입력한 값이 name 변수에 저장되지만

- 라디오버튼은 입력양식이 아니므로 변수명은 name 값인 'gender' 가 되지만 그 변수 안에 저장된 값은 입력된 값이 아닌 value 속성의 값이다

+ 라디오 버튼은 동일한 name 값을 사용한다, gender 라는 변수명 

- value 값이 한글임을 유심히 보기

 

Select 옵션의 값 전달

- select 도 마찬가지로 선택양식이므로 major 라는 변수에 선택한 값의 value 가 저장된다

 

- requestExample.jsp

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

<%	// 폼파일에서 한글값이 post방식으로 전송될때 utf-8로 인코딩을 시켜주는 역할
	request.setCharacterEncoding("utf-8");
%>

<html>
<h1>Request 객체1</h1>

<%
	String name = request.getParameter("name");
	String studentNum = request.getParameter("studentNum");
	String gender = request.getParameter("gender");
	String major = request.getParameter("major");
/* 
	if(gender.equals("m")){
		gender = "남자";
	}else{
		gender = "여자";
	} */
%>

<body>
성명: <%=name%><p>
학번: <%=studentNum%><p>
성별 : <%=gender%><p>
전공 : <%=major%>
</body>
</html>

 

전달된 값 받기

- request 객체의 getParameter("name 속성값") 메소드로 전달된 값을 받음

- html 파일에서의 name 속성값이 변수명이 되어 그 변수명을 통해 입력된값이나 선택값의 value 값을 받을 수 있음

- 매개변수에는 입력양식과 선택양식의 name 값이 들어감

- 매개변수가 String 형이기때문에 "" 를 해야함

- 리턴형도 String 이기떄문에 String 변수로 받아야함

+ name 값은 대소문자를 구분한다!

 

- 결과 캡처

 

한글 인코딩

만약 post 방식 대신 get 방식으로 값을 전달한다면?

- form 으로 값을 전달하는 경우에는 get / post 선택 가능

+ name값을 통해 넘어가는 값들이 모두 URL 주소 창에 노출된다

- "여자", "컴퓨터공학" 등의 한글값이 깨지지 않고 출력된다

- get 방식으로 전달시 Apache Tomcat 이 자동으로 UTF-8 로 인코딩 해주고 전달하기때문에 크게 신경쓰지 않아도 된다

 

post 방식에서는?

- Apache Tomcat 이 자동으로 인코딩해주지 않음

- 따라서 아래의 코드를 jsp 파일에 넣어야 인코딩 해줌

 

인코딩 코드

<%	// 폼파일에서 한글값이 post방식으로 전송될때 utf-8로 인코딩을 시켜주는 역할
	request.setCharacterEncoding("utf-8");
%>

- 이 코드를 requestExample1.jsp 파일에 넣었기때문에 한글값이 깨지지 않고 잘 출력된다

+ get 방식에선 이 코드가 없어도 Apache Tomcat 에 의해 자동 UTF-8 인코딩 된다

 

- post 방식에선 이 코드가 없다면 한글값이 깨짐

- 이 코드를 request 객체로 값을 받기 전인 위쪽에 써야한다

- 값을 먼저 받은 다음 인코딩을 시키면 깨짐

- 저 부분을 주석처리 했을 경우출력

 

한글 인코딩 정리 & 인코딩 코드 위치

<%	
//한글 인코딩
//1. 폼파일에서 한글값이 get 방식으로 전송될 때는 tomcat 이 자동으로 utf-8 로 인코딩을 시켜준다
//2. 폼파일에서 한글값이 post 방식으로 전송될 떄는  tomcat 이 자동으로 인코딩을 시켜주지 않기 때문에
//	 아래의 코드로 직접 인코딩을 시켜야 한다.
// 폼파일에서 한글값이 post방식으로 전송될때 utf-8로 인코딩을 시켜주는 역할
 	request.setCharacterEncoding("utf-8");
%>

- 이 코드를 request 객체로 요청을 받기 전인 위쪽에 써야한다

 

페이지 지시 태그 vs setCharacterEncoding() 차이

페이지 지시 태그

- 값이 넘어오는 것이 아닌 현재 페이지 문서상의 한글을 인코딩 시켜주는 코드

- 또한 meta 태그의 charset 또한 이 페이지 지시 태그와 같은 의미, 같은 역할

setCharacterEncoding()

- 한글값(value)이 post 방식으로 전송될때 그 넘어온 값을 인코딩 시켜주는 코드

- 이 예제에서는 넘어온 이름값과 성별값과 전공값 을 인코딩시켜주는 코드

 

- 두개를 맞춰야하지만 의미가 다른 코드이다

 

request 객체의 메소드

void setCharacterEncoding(String env) 한글 인코딩 처리
getParameter(String name) name에 해당하는 파라미터 값을 구함
String[] getParameterValues(String name) checkbox 같이 여러 개의 파라미터 값을 구함
String getRemoteAddr() client의 IP주소를 구함
String getRequestURI() 요청 URI를 구함
String getContextPath() 컨텍스트 패스(project명)를 구함

 

내장 객체의 메소드 API 찾기

- 이 내장객체는 클래스가 아니기 때문에 지원 메소드를 찾기 힘들다

- 메소드를 찾으려면 '실제 타입' 으로 되어있는 해당 클래스나 인터페이스로 찾아야한다

- 여기 들어있는 클래스나 인터페이스의 패키지는 모두 Java EE 이다 (자바시간에 배운건 Java SE)

- Java SE (스탠다드 에디션)가 아닌 Java EE 패키지 에서 API를 찾아야한다

- 오라클에서 찾아야함

- request 객체의 getParameter() 메소드를 찾아보자

- java ee api 검색 후 사이트

https://docs.oracle.com/javaee/7/api/toc.htm

 

Java(TM) EE 7 Specification APIs

 

docs.oracle.com

 

- javax.servlet.http 에서 HttpServletRequest 인터페이스 찾기

- javax.servlet.http 에서 HttpServletRequest 인터페이스 에는 getParameter() 메소드가 없다

- 다른 실제 타입에서 찾아보자

- javax.servlet 의 ServletRequest 인터페이스에서 찾아보자

+

 

그 외 request 객체의 메소드

String[] getParameterValues(String name) checkbox 같이 여러 개의 파라미터 값을 구함
String getRemoteAddr() client의 IP주소를 구함
String getRequestURI() 요청 URI를 구함
String getContextPath() 컨텍스트 패스(project명)를 구함

- getParameterValues() : 체크박스 같은 경우 1개의 name 값에 여러개의 value 값이 들어감, 이때 사용

 

+ 일반적으로 값을 받는 name 값과 변수명을 같게 설정

 

id 값 vs name 값

- id 값은 태그를 구해오는데 중요 = jQuery , Javascript , CSS 에서 중요

- name 값은 값을 전달하는데 중요 = JSP 에서 중요

- id 값과 name 값이 같아도 상관없다

 

JSP 내장 객체 예제 2

request 객체 예제 2

- WebContent/request/ex2

- 체크박스를 통해 여러개의 값이 넘어갈때 처리하는 예제

- getParameterValues() 함수 사용

- check01.html & check.jsp

- check01.html

<html>
	<head><title>좋은 사이트 선택</title>	
	<meta charset="utf-8">
	<script src="http://code.jquery.com/jquery-latest.js"></script>
	<script>
	$(document).ready(function(){
//		$("form").submit(function(){
		$("#myform").submit(function(){
			/* var cnt=0;
			if($("#h1").is(":checked"))	cnt++;
			if($("#h2").is(":checked"))	cnt++;
			if($("#h3").is(":checked"))	cnt++;
			if($("#h4").is(":checked"))	cnt++;
			if($("#h5").is(":checked"))	cnt++;
			if($("#h6").is(":checked"))	cnt++;
			if($("#h7").is(":checked"))	cnt++;
			
			if(cnt < 2){
				alert("사이트 2개이상 선택하세요");
				return false;
			} */
			
			if($("input:checkbox[name='site']:checked").length < 2){
				alert("사이트 2개이상 선택하세요");
				return false;
			}			
			
		});
	});	
	</script>
	</head>
<body>

<form id="myform" name=myform  method=post action="check.jsp"> 

	좋은 사이트를 2개 이상 선택하세요<br><br> 
	<input type="checkbox" id="h1" name="site" value="야후">야후<br>
	<input type="checkbox" id="h2" name="site" value="다음">다음<br>
	<input type="checkbox" id="h3" name="site" value="엠파스">엠파스<br>
	<input type="checkbox" id="h4" name="site" value="네이버">네이버<br>
	<input type="checkbox" id="h5" name="site" value="한미르">한미르<br>
	<input type="checkbox" id="h6" name="site" value="네띠앙">네띠앙<br>
	<input type="checkbox" id="h7" name="site" value="라이코스">라이코스<br><br>

	<input type="submit" value="전송">
	<input type="reset" value="취소">

</form> 

</body>
</html>

- name 값이 모두 "site" 로 동일하다, value 값들은 한글값이다

- 전송시 site 라는 변수에 여러개의 value 값이 저장된다(check.jsp 로 post 방식으로 전송된다)

+ 유효성 검사에서 input 값이 checkbox 인 것 중에서 name 값이 site 인 것들 중에서 체크된 체크박스를 구해옴

+ 라디오버튼이나 체크박스는 선택양식이므로 반드시 value 를 지정해야함

- check.jsp

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

<html>
<body>

	<%
		request.setCharacterEncoding("utf-8");

		String[] choice = request.getParameterValues("site");
		String result = "";

		for (int i = 0; i < choice.length; i++) {
			result = result + choice[i] + " ";
		}
	%>

	<center>
		귀하는 <font color=blue><%=result%></font> 를 좋아하시는군요.
	</center>

</body>
</html>

- post 방식으로 전송되었으므로 한글값이 깨지지 않게 하기 위해 인코딩 시켜주는 코드를 위에 넣는다

+ String 배열의 요소들을 반복문을 통해 하나씩 꺼내고 result 변수에 누적시키고 있다

 

인코딩 코드 (check.jsp 부분)

		request.setCharacterEncoding("utf-8");

 

한개의 변수(name값)에 넘어온 여러개의 값 받기 (check.jsp 부분)

		String[] choice = request.getParameterValues("site");

- 한개의 변수(name값)에 넘어온 여러개의 값을 받기 위한 메소드가 따로 있다

- request 객체의 getParameterValues() 메소드로 site 로 전달된 값들을 받아서 String 1차원 배열로 받는다

 

 

JSP 내장 객체 예제 3

request 객체 예제 3

- WebContent/request/ex3

- 라디오 버튼 값 전송

- poll.html & result.jsp

- poll.html

<html>
	<head><title>radio 버튼을 이용한 설문 조사</title>
	<meta charset="utf-8">
	<script src="http://code.jquery.com/jquery-latest.js"></script>
	<script>
	$(function(){
		$("form").submit(function(){
			/* if($("#s1").is(":checked")==false &&
			   $("#s2").is(":checked")==false &&
			   $("#s3").is(":checked")==false &&
			   $("#s4").is(":checked")==false ){
				alert("좋아하는 계절 1개를 선택하세요?");
				return false;
			} */

				if($("input:radio[name='season']:checked").length<1){
					alert("좋아하는 계절 1개를 선택하세요?");
					return false;
				}
		});
	});	
	</script>
	</head>
	<body>
	가장 좋아하는 계절은?
	<p>

	<form name=syberpoll method=post action=result.jsp>
		<input type=radio id="s1" name=season value=봄>봄<br>
		<input type=radio id="s2" name=season value=여름>여름<br>
		<input type=radio id="s3" name=season value=가을>가을<br>
		<input type=radio id="s4" name=season value=겨울>겨울<br>
		<input type=submit value="투표">
	</form>

	</body>
</html>

- 라디오 버튼의 name 값은 동일해야한다, 같은 그룹으로 묶어주는 역할

- season 이라는 name 값에 value 인 봄,여름,가을,겨울 중 하나가 저장되어 넘어감

+ 폼을 통해서 값을 전달할떄 라디오버튼과 체크박스는 value 값을 반드시 설정

+ post 방식이므로 jsp 파일에서 직접 넘어오는 값 한글 인코딩을 해줘야한다

+ 유효성 검사 중에서 input type=radio 중에서 name 속성값이 'season' 이고 그 중 선택된 라디오 박스의 개수(length) 가 0개(1개 미만) 일때 경고 메세지를 띄운다

+ 전송시 form 태그의 action 에 적힌 result.jsp 파일로 전달된다

- result.jsp

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

<html>
	<head><title>설문조사 결과</title>
	</head>
	<body>

	<%
		request.setCharacterEncoding("utf-8");
	
		String choiceseason = request.getParameter("season");
		String result = "";

		/* if(choiceseason.equals("spring")){
			result = "봄";
		} else if(choiceseason.equals("summer")){
			result = "여름";
		} else if(choiceseason.equals("autumn")){
			result = "가을";
		} else if(choiceseason.equals("winter")){
			result = "겨울";
		} */
	%>

		당신이 가장 좋아하는 계절은 <%=choiceseason%> 입니다.
	</body>
</html>

+ post 방식으로 넘어왔으므로 request 객체의 setCharacterEncoding() 메소드로 한글 인코딩을 직접 해준다

- 라디오 버튼의 값은 1개가 넘어오므로 request 객체의 getParameter() 메소드로 전달된 값을 name속성값인 season 을 통해 받고 있다

 

 

JSP 내장 객체 예제 4

request 객체 예제 4

- WebContent/request/ex4

- 그 외 request 객체의 메소드들

- requestInfo.jsp

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

<html>
<head><title>클라이언트 및 서버 정보</title>
<meta charset="utf-8">
</head>
<body>

클라이언트IP = <%= request.getRemoteAddr() %> <br>
요청정보길이 = <%= request.getContentLength() %> <br>
요청정보 인코딩 = <%= request.getCharacterEncoding() %> <br>
요청정보 컨텐트타입 = <%= request.getContentType() %> <br>
요청정보 프로토콜 = <%= request.getProtocol() %> <br>
요청정보 전송방식 = <%= request.getMethod() %> <br>
요청 URI = <%= request.getRequestURI() %> <br>
컨텍스트 경로 = <%= request.getContextPath() %> <br>
서버이름 = <%= request.getServerName() %> <br>
서버포트 = <%= request.getServerPort() %> <br>

</body>
</html>

 

getRemoteAddr() 메소드 (requestInfo.jsp 부분)

클라이언트IP = <%= request.getRemoteAddr() %> <br>

- 클라이언트의 IP 주소를 구해줌

- 어떤 사이트에 방문만 해도 내 IP 주소가 찍혀있는 경우, 이 함수로 내 IP를 구해서 뿌리는 것임

- String 형으로 리턴시켜주므로 String 형 변수에 저장

 

getRequestURI() 메소드 (requestInfo.jsp 부분)

요청 URI = <%= request.getRequestURI() %> <br>

- 요청 URI 를 구해줌

- 현재 파일의 경로값을 보여준다

- 현재 프로젝트 명부터 현재 파일의 경로를 보여줌

- 여기서 jspproject 는 프로젝트 명이고 나머지는 WebContent 를 기준으로 현재 파일의 경로를 보여줌

 

getContextPath() 메소드 (requestInfo.jsp 부분)

컨텍스트 경로 = <%= request.getContextPath() %> <br>

- 현재 프로젝트 명을 구해줌

 

- 전체 출력

- URL 에 localhost 대신 내 ip 주소 적어야 제대로 된 클라이언트 IP 보여줌

- 지금 컴이 서버 IP 이기도 하고 클라이언트 IP 이기도 하므로 똑같이 나옴

- jspproject 는 프로젝트 명이고 나머지는 WebContent 를 기준으로 현재 파일의 경로를 보여줌

 

JSP 내장 객체 예제 5

request 객체 예제 5

- WebContent/request/ex5

- makeTestForm.jsp & viewParameter.jsp

- makeTestForm.jsp

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

<html>
<head><title>폼 생성</title></head>
<body>

폼에 데이터를 입력한 후 '전송' 버튼을 클릭하세요.
<form method="post" action="viewParameter.jsp">
이름: <input type="text" name="name" size="10"> <br>
주소: <input type="text" name="address" size="30"> <br>
좋아하는 동물:
    <input type="checkbox" name="pet" value="dog">강아지
    <input type="checkbox" name="pet" value="cat">고양이
    <input type="checkbox" name="pet" value="pig">돼지
<br>
<input type="submit" value="전송">
</form>
</body>
</html>

- 값 입력하면 그 값을 viewParameter.jsp 로 넘기는 역할

- 변수명이 될 name값을 유심히 보기

- viewParameter.jsp

<%@ page contentType="text/html; charset=utf-8" %>
<%@ page import="java.util.*" %>

<%
    request.setCharacterEncoding("utf-8");
%>

<html>
<head><title>요청 파라미터 출력</title></head>
<body>

<b>request.getParameter() 메소드 사용</b><br>
name 파라미터 = <%= request.getParameter("name") %> <br>
address 파라미터 = <%= request.getParameter("address") %>
<p>

<b>request.getParameterValues() 메소드 사용</b><br>
<%
    String[] values = request.getParameterValues("pet");
    if (values != null) {
    	for (int i = 0 ; i < values.length ; i++) {
%>
			<%= values[i] %>
<%
  		}
  	}
%>
<p>

<b>request.getParameterNames() 메소드 사용</b><br>
<%
    Enumeration num = request.getParameterNames();
    while(num.hasMoreElements()) {
        String name = (String)num.nextElement();
%>
        <%= name %>
<%
    }
%>
<p>

<b>request.getParameterMap() 메소드 사용</b><br>
<%
    Map parameterMap = request.getParameterMap();
    String[] nameParam = (String[])parameterMap.get("name");
    if (nameParam != null) {
%>
name = <%= nameParam[0] %>
<%
	}
%>

</body>
</html>

- 4가지 메소드로 넘어온 값을 받고 있다

- 주로 getParameter() 메소드와 getParameterValues() 메소드 사용

 

getParameter() 메소드로 값 받기 (viewParameter.jsp 부분)

<b>request.getParameter() 메소드 사용</b><br>
name 파라미터 = <%= request.getParameter("name") %> <br>
address 파라미터 = <%= request.getParameter("address") %>
<p>

 

getParameterValues() 메소드로 값 받기 (viewParameter.jsp 부분)

<b>request.getParameterValues() 메소드 사용</b><br>
<%
    String[] values = request.getParameterValues("pet");
    if (values != null) {
    	for (int i = 0 ; i < values.length ; i++) {
%>
			<%= values[i] %>
<%
  		}
  	}
%>
<p>

- 체크박스처럼 여러개의 값이 넘어올때 받는 메소드

 

getParameterNames() 메소드로 값 받기 (viewParameter.jsp 부분)

<b>request.getParameterNames() 메소드 사용</b><br>
<%	// 열거형 : Enumeration num = "name, address, pet"
    Enumeration num = request.getParameterNames();
    while(num.hasMoreElements()) {
        String name = (String)num.nextElement();
%>
        <%= name %>
<%
    }
%>
<p>

- 이 메소드는 name 값을 구해준다

- 이 name 값들을 열거형 변수에 저장하고, num 값이 있다면 nextElement() 로 가져와서 출력

 

getParameterMap() 메소드로 값 받기 (viewParameter.jsp 부분)

<b>request.getParameterMap() 메소드 사용</b><br>
<%
    Map parameterMap = request.getParameterMap();
    String[] nameParam = (String[])parameterMap.get("name");
    if (nameParam != null) {
%>
name = <%= nameParam[0] %>
<%
	}
%>

- Map 의 형태로 값을 돌려준다, 변수에 저장함

- name값이 키가 되고, 사용자가 입력한 이름이 밸류가 됨

- name값을 이용해서 맵에서 밸류를 가져옴

 

 

 

JSP 내장 객체 예제 6

request 객체 예제 6

- WebContent/request/login

- HTML 시간에 만든 로그인 폼, 게시판 폼, 회원가입 폼에서 값을 전달하고 출력해보자

- HTML 과 jQuery 시간에 폼 만들기, 유효성 검사했던 내용에 값 전달 기능을 추가해보자

- loginform.html & login.jsp & login.js

- loginform.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 폼</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
	 /* $(document).ready(function(){
		$("form").submit(function(){
			if($.trim($("#id").val()) == ""){
				alert("ID를 입력하세요.");
				$("#id").focus();
				return false;
			}			
			if($.trim($("#passwd").val()) == ""){
				alert("비밀번호를 입력하세요.");
				$("#passwd").focus();
				return false;
			}			
		});		
	});	  */
</script>

<script src="login.js"></script>

</head>
<body>

<form method="post" action="login.jsp">
<table border=1 width=350 align=center>
	<caption>로그인</caption>
	<tr><th>ID</th>
		<td><input type=text size=30 autofocus="autofocus" id="id" name="id"></td>
	</tr>
	<tr><th>비밀번호</th>
		<td><input type=password size=30 id="passwd" name="passwd"></td>
	</tr>
	<tr><td colspan=2 align=center>
			<input type=submit value="로그인">
			<input type=reset value="취소">
		</td>
	</tr>
</table>
</form>

</body>
</html>

- name 값이 반드시 필요하다

- login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
	request.setCharacterEncoding("UTF-8");

	String id = request.getParameter("id");
	String passwd = request.getParameter("passwd");
%>

ID : <%=id %> <br>
비밀번호 : <%=passwd %>

- post 방식으로 전달되므로 "한글값" 이 깨지지 않도록 인코딩 설정을 위쪽에 하고 있다

- 나중에는 값을 받아 출력하는것 외에도 login.jsp 파일에서 DB 연동을 하고, DB의 아이디, 비밀번호와 맞는지 확인한다

 

- login.jsp

$(document).ready(function(){
		$("form").submit(function(){
			if($.trim($("#id").val()) == ""){
				alert("ID를 입력하세요.");
				$("#id").focus();
				return false;
			}			
			if($.trim($("#passwd").val()) == ""){
				alert("비밀번호를 입력하세요.");
				$("#passwd").focus();
				return false;
			}			
		});		
});

- jQuery 로 유효성 검사를 하고 있다

복습

XML & JSON

- 데이터를 저장하는 포맷 중 하나

 

비동기 요청 함수

ajax()

- 많은 옵션이 있다, 전송방식 선택 가능

- 키:밸류 형태

 

getJSON()

- JSON 데이터를 가져오기 위한 함수

- get 방식 사용

 

getScript()

- 자바스크립트 코드를 return 구문으로 돌려받아서 값을 구해옴

 

get()

- get 방식으로 파일을 요청하고 돌려받음

 

응답을 받은 후

- 결과를 조작해서 원하는 형태로 사용

- XML 파일을 돌려받은 후 언어마다 조작하는 방법은 다르다

 


JSON

- XML 을 대신하기위해 등장, XML 보다 다루기 수월

- 자바의 맵 구조 (키:밸류 형태) 로 되어있다

- 키값을 알면 밸류를 구할 수 있다.

- 가장 바깥쪽엔 [ ] 대괄호가 있고 안엔 { } 중괄호들이 있다

 

JSON 파일 예시

- 아까의 xml 형태의 파일을 json 형태로 바꿔둔 것이다

- item.json

- id가 키고 "1" 이 밸류 값

 

JSON 데이터를 요청하고 결과를 콜백으로 받아서 가져오는 방법

1. getJSON() 함수

2. ajax() 함수로도 가능

 

비동기로 서버에 요청하는 함수

$.getJSON() 함수

	$.getJSON('item.json', function(data, textStatus) {
	 });

- json 데이터를 요청하고 받을 수 있다

- get 방식을 사용한다

getJSON() 매개변수

- 첫번째 매개변수에는 요청할 json 파일명

- 두번째 매개변수에 오는 function 은 콜백함수이다.

function() 매개변수

- data는 item.json 전체 내용을 받음

- textStatus 에서 잘 돌려받으면 success란 문자가 출력됨

 

Ajax 예제 6

 getJSON() 함수 예제 1

1. getJSON() 함수로 json 데이터 가져오기

- example09_05.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSON 이용하기</title>
<style>
td {
  border: 1px solid gray;
}
</style>
<script src="http://code.jquery.com/jquery-1.11.1.js" type="text/javascript"></script>
<script type="text/javascript">
/*  
	- JSON은 JavaScript Object Notation 의 약어로 XML 데이터를 대신하기 위해서 사용된다.
	- JSON은 키와 값을 쌍으로 가지는 구조이다.
	- 배열을 사용할 때는 대괄호([ ])안에 중괄호({ })를 사용하여 조합한다.
	- jQuery에서는 JSON으로 표현한 데이터를 파일에 저장해 두었다가 필요할 때 이를 로드할 수 있는 $.getJSON()함수를 제공한다.

	- 서버로 부터 get방식의 요청을 하고, 응답을 JSON 형식으로 받기 위해서 $.getJSON()함수를 사용한다.
	- $.getJSON()함수의 첫번째 매개변수는 서버의 URL주소를 지정한다. ('item.json')
	- 서버로 요청이 성공적으로 완료되면, 두번째 매개변수로 기술한 콜백함수가 호출된다. (function(data, textStatus))
	  콜백함수의 첫번째 매개변수인 data는 서버에서 돌려받은 JSON 객체 형식의 데이터이고, 두번째 매개변수인 textStatus는 성공일때
	  "success" 라는 문자열이 전달된다.

*/

$(function() {
	
	$.getJSON('item.json', function(data, textStatus) {
//		alert(data);
//		alert(textStatus);		success
        $("#treeData").append(
                 "<tr><td>id</td>" + "<td>name</td>" 
               + "<td>price</td>" + "<td>description</td>" + "</tr>");
        $.each(data, function() {
              $("#treeData").append("<tr>" + "<td>"                 
                      + this.id + "</td>" + "<td>"
                      + this.name + "</td>" + "<td align='right'>"
                      + this.price + "</td>" + "<td>"
                      + this.description + "</td>" + "</tr>");
          });
	 });
	
});

</script>
</head>
<body>
  <table id="treeData"></table>
</body>
</html>

- getJSON() 함수로 item.json 파일을 요청한다

- 그 다음의 function 전체가 두번째 매개변수이고, 이 function 은 콜백함수이다

- each() 함수로 더이상 데이터가 없을때까지 data 를 한개씩 가져와서 반복적인 작업을 함

- each() 함수에서 첫번째로 가져오는건 

- 첫번째 중괄호 {} 안의 내용이다,

- 다음에는 두번째 {} 를 가져온다

- this 는 현재 가져와진 이 {} 데이터를 의미한다

 

밸류 value 가져오기

                      + this.id + "</td>" + "<td>"
                      + this.name + "</td>" + "<td align='right'>"
                      + this.price + "</td>" + "<td>"
                      + this.description + "</td>" + "</tr>");

- 키값 id, name, price, description 으로 밸류를 가져오고 있다

 

+ data와 textStatus

- data는 item.json 전체 내용을 받음

- textStatus 에서 잘 돌려받으면 success란 문자가 출력됨

- 어떤 것인지 alert 로 찍어보기

 

- 결과 출력

 

Ajax 예제 7

ajax() 함수 예제 2

2. 아까의 예제를 getJSON() 대신 ajax() 로 구현하기

- example09_05_02.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSON 이용하기</title>
<style>
td {
  border: 1px solid gray;
}
</style>
<script src="http://code.jquery.com/jquery-1.11.1.js" type="text/javascript"></script>
<script type="text/javascript">
/*
	$.getJSON()함수 대신에 $.ajax()함수를 이용해서 JSON 형식의 데이터를 얻을 수 있다.

*/

$(function() {
    $.ajax({
         url : "item.json",
         dataType : "json",
         success : function(data) {
             $("#treeData").append(
                    "<tr><td>id</td>" + "<td>name</td>" 
                  + "<td>price</td>" + "<td>description</td>" + "</tr>");
             $.each(data, function() {
                 $("#treeData").append("<tr>" + "<td>"                 
                         + this.id + "</td>" + "<td>"
                         + this.name + "</td>" + "<td align='right'>"
                         + this.price + "</td>" + "<td>"
                         + this.description + "</td>" + "</tr>");
             });
         }
    });
});

</script>
</head>
<body>
  <table id="treeData"></table>
</body>
</html>

- $.ajax({}); 함수 안에 모든 것이 들어간다

- url 은 요청할 파일명, 여기서는 item.json 파일이 적혀있다, 나중에는 이 자리에 jsp, spring 파일등이 온다

- function() 콜백함수로 item.json 전체를 돌려받고 data 에 값이 있다

- 콜백함수로 받은 데이터 data를 each() 를 통해 하나씩 {} 단위로 가져오고 있다

+ append() 함수로 테이블에 <tr></tr> 과 <td></td> 를 추가하고 있다

+ get 방식이더라도 페이지가 바뀌지 않기때문에 url 주소창에 뭔가 나타나지는 않고 내부적인 방식이다

 

ajax() 함수 옵션

- url, success 는 생략해선 안된다

- type은 생략가능하고 생략시 type은 get 방식이다

- data 를 가져갈때는 json 데이터를 가져갈 수 있다, 지금은 가져갈 데이터가 없으므로 생략되어있음

- dataType 도 생략 가능하다

- success는 결과(응답)를 잘 돌려받았을때만 실행된다

 

- 결과 출력

- 아까의 예제와 같은 결과이다.

 

비동기로 서버에 요청하는 함수

$.post() 함수

- post 방식으로 비동기로 서버에 요청하는 함수

- 간단한 형식

                $.post(
                 "요청페이지명",
                 "전달될값",        
                  function (msg) {	// 콜백함수
                });

- 매개변수가 3개, 첫번째엔 요청할 페이지명, 두번째는 전달될 값, 세번째는 콜백함수

- 이때 전달될값에서 변수명=변수 로 보내야한다

- 데이터를 전달할 때 문자열 형식의 데이터를 보낸다

 

Ajax 예제 8

ajax() 함수 예제 3 / post() 함수 예제 1

- 같은 내용을 ajax() 로 먼저 구현하고 다음에 post() 부분의 주석을 풀고 설명

1. ajax() 함수로 post 방식 비동기 통신

2. post() 함수로 post 방식 비동기 통신

- example09_08.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>$.ajax로 jsp 파일 로드하기</title>
<style>
td {
  border: 1px solid gray;
}
</style>
<script src="http://code.jquery.com/jquery-1.11.1.js" type="text/javascript"></script>

<script type="text/javascript">
/*
	- $.post() 함수는 post방식으로 서버와 통신하는 jQuery 함수이다.
    - $.post() 함수는 서버의 welcome.jsp 페이지를 post방식으로 요청한다.
*/

$(function() {
    $('#submit').click(function () {
            var username = $('.username').val();	// 서버로 보낼 데이터를 입력창에서 얻어온다.
            var sendData = 'username=' + username;  // 입력창에서 입력받은 데이터를 문자열 형식으로 변환한다.
            
            /* $.post(									// 문자열 형식의 데이터를 welcome.jsp 파일로 보낸다.
                 "welcome.jsp",						// 서버의 welcome.jsp 에서는 받은 데이터를 인사말을 덧붙여서 돌려준다.
                  sendData,        
                  function (msg) {					// 콜백함수는 서버에서 보내온 데이터를 매개변수로 얻어온다.
                	alert(msg);
            	    $('#message').html(msg);			// 서버로부터 받은 데이터를 id가 message인 엘리먼트에 설정한다.
                });    */
            
            	$.ajax({
            		url :"welcome.jsp",
            		type :"post",
            		data : {"username": username},
            		success : function(msg){
            			alert(msg);
            			$('#message').html(msg);
            		} 
            	}); 
            
            return false;      
    });
});

</script>
</head>
<body>
    <form>  
    <label> 이름을 입력하세요 : </label>  
    <input type="text" name="username" class="username"/>  <br/>
    <input type="button" id="submit"  value="전송"/>  
  </form>  
  <div id="message"></div>
</body>
</html>

- 같은 내용이 ajax() 함수로도 구현되어있고, post() 함수로도 구현되어있다, 비교하기

- 요청하는 파일이 welcome.jsp 임

- 사용자 이름을 입력하고 전송버튼을 누르면 지정된 요청을 하는데, 요청하는 페이지가 jsp 페이지이다.

- 요청하면서 사용자가 입력한 이름을 서버측으로 전달한다 

- 전송 버튼을 누르면 페이지가 바뀌지 않고 값을 뿌려준다

+ input type=text 에 class 속성값이 있다 -> 이 태그를 구해올 때 . 으로 구해온다

+ input type=button 이므로 click 이벤트가 발생하므로 click() 을 사용

 

1. ajax() 함수로 post 방식 비동기 통신 (example09_08.html 부분)

            var username = $('.username').val();	// 서버로 보낼 데이터를 입력창에서 얻어온다.
            var sendData = 'username=' + username;  // 입력창에서 입력받은 데이터를 문자열 형식으로 변환한다.
                   	
                $.ajax({
            		url :"welcome.jsp",
            		type :"post",
            		data : {"username": username},
            		success : function(msg){
            			alert(msg);
            			$('#message').html(msg);
            		} 
            	});

- .username으로 input 태그를 구해와서 val() 을 통해 사용자가 입력한 값을 username 변수에 저장

- 서버측에 값을 전달할떄 JSON 형태로 값을 전달해야하기 때문에 username 변수에 따로 저장했다

- url 자리에 요청할 파일명이 들어가는데 여기선 welcome.jsp 라는 JSP 파일이 왔다, 이 welcome.jsp 파일을 요청하겠다는 의미

- data 속성은 서버측으로 값을 가져갈때만 사용되는 속성으로서 JSON 형태, 즉 키:밸류 형태로 값을 가져가야한다

- 그래서 {"username" : username} 라는 JSON 형태로 값을 저달하고 있다

- welcome.jsp 파일에서는 전달된 값을 받을때 JSP의 내장객체 중 클라이언트의 요청을 받는 객체인 request 객체의 getParameter() 로 전달된 값을 받고 표현식 형태 <%= %> 로 출력함, 브라우저에 출력되는 이 내용이 통째로 콜백함수로 돌아가는 것임

- welcome.jsp 파일에서 환영합니다 ~님 을 두번 출력한다, 그 출력하는 값을 function의 msg 매개변수로 받아서 여기서 html()로 id가 message인 태그 사이에 뿌려주는 것

* 아래에 welcome.jsp 파일 설명

 

콜백함수로 돌려받은 값

- alert(msg)로 출력해본 값

- welcome.jsp 파일에서 브라우저에 출력되는 내용들이 통째로 넘어왔음을 알 수 있다

- 이 내용이 msg 변수에 저장된 것

 

welcome.jsp 파일

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<!-- welcome.jsp 파일에서 브라우저에 출력되는 결과를 callback 함수로 돌려준다-->
 환영합니다. <%=request.getParameter("username") %>님  <br>
 환영합니다. ${param.username}님  <br>
 
</body>
</html>

- <%= %> = "표현식 태그" = 브라우저에 출력시킬 값

- ${} = "표현언어"

- username 은 example09_08.html 에서 json 으로 전달되었던 키값

- 이렇게 브라우저에 출력되는 값을 통째로 callback 함수로 돌려주게 되는것

- 위에선 표현식 태그로 한번 출력하고 아래에선 표현 언어로 한번 출력, 여기서 총 출력을 두번하고 있다

 

2. post() 함수로 post 방식 비동기 통신 (example09_08.html 부분)

- 위에서 ajax() 로 구현된 내용을 이번엔 post() 를 사용

- 위의 ajax() 함수와 같은 기능

            var username = $('.username').val();	// 서버로 보낼 데이터를 입력창에서 얻어온다.
            var sendData = 'username=' + username;  // 입력창에서 입력받은 데이터를 문자열 형식으로 변환한다. 
            	
                // $.post("요청페이지명","전달될값","콜백함수");                
                $.post(									// 문자열 형식의 데이터를 welcome.jsp 파일로 보낸다.
                 "welcome.jsp",						// 서버의 welcome.jsp 에서는 받은 데이터를 인사말을 덧붙여서 돌려준다.
                  sendData,        
                  function (msg) {					// 콜백함수는 서버에서 보내온 데이터를 매개변수로 얻어온다.
                	alert(msg);
            	    $('#message').html(msg);			// 서버로부터 받은 데이터를 id가 message인 엘리먼트에 설정한다.
                });

- post 방식으로 welcome.jsp 를 요청하면서 값을 전달하고 있다

- sendData에서 'username=입력받은 이름' 형식으로 값을 전달

- 이렇게 값을 전달하면 jsp 파일에서는 username 이라는 변수명을 통해 값을 받는다

- 브라우저에 출력되는 결과 전체를 콜백함수로 받게 되고 그 값을 msg 변수에 저장

 

- 결과 캡처

 

$.getScript() 함수

- Javascript 파일을 불러온다, 확장자가 js 인 파일을 불러오는 함수이다

- 자바 스크립트 파일을 로드한다

 

Ajax 예제 9

getScript() 예제

- example09_10.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>스크립트 로드하기</title>
<script src="http://code.jquery.com/jquery-1.11.1.js" type="text/javascript"></script>
<script type="text/javascript">
/*
	- 현재파일에서 자바스크립트 파일(test.js)을 get방식으로 요청하는 예제
	- 자바스크립트 파일을 로드하기 위해서 $.getScript() 함수를 사용함.

*/

  $(document).ready(function() {

    $.getScript("test.js");				//자바스크립트 파일(test.js)을 $.getScript()함수로 호출한다.
    $('#submit').click(function() {
    	var msg=call($('.username').val());	// 자바스크립트 파일(test.js)에 정의한 자바스크립트 함수 call()함수를 호출한다.
    	$('#message').html(msg);			// call()함수 호출한 결과를 돌려 받아서 msg변수에 저장한다.
    	 return false;
    });

  });

</script>
</head>
<body>
  <form>  
    <label> 이름을 입력하세요 : </label>  
    <input type="text" name="username" class="username"/>  <br/>
    <input type="button" id="submit" value="전송"/>
    <div id="message"></div> 
  </form>  
</body>
</html>

- $.getScript() 함수로 확장자가 .js 인 파일을 불러온다

- 이 파일을 불러와야만 test.js 안의 함수 call() 을 호출 할 수 있다

- call() 함수를 호출하며 사용자가 입력한 값을 매개변수로 호출한다

- 호출된 call() 에서 return 으로 돌려받은 값을 출력한다

 

- test.js 파일

function call(param){
	return ("Hello, " + param);
}

- 매개변수가 있으므로 이 함수를 호출할 때는 매개변수 param 을 통해서 값을 전달해야함

- 전달될 값을 return 으로 Hello 를 붙여서 돌려줌

 

Ajax 가 자주 사용되는 곳

- ID중복검사에서 팝업창을 띄우지 않고 비동기적인 방식으로 ID중복검사 가능

- war 파일을 import 해서 ID중복검사 구현되어있는 내용을 살펴보자 (자세한 내용은 JSP 를 공부할때)

 

실습준비

1. ajax.war 파일을 이클립스에서 import 하여 ajax 프로젝트 추가

 

2. DB 연동

- 한명이 가입되어있어야만 새로운 ID값으로 중복인지 아닌지 판별 가능하므로 오라클을 활성화시키기

- 계정명 scott

 

3. DB 에 회원 데이터 삽입 (한명 가입시키기)

- DB 연동을 처리해주는 DAO 클래스이다

- DB 연결을 하고 select 문으로 그런 아이디가 있는지 검색해줌

- scott 계정으로 테이블을 만들어야함

- 여기서 테이블을 만들고 강제로 한명을 등록할 것이다

- create 부분을 실행하여 join_member 테이블과 sequence를 생성

- 이 부분을 블럭으로 잡고 실행해서 강제로 데이터를 넣는다

- 그리고 아래의 select 문으로 데이터 삽입 확인하기

- 회원 1명이 등록되었음을 알 수 있다, 아이디는 aaaaa

 

4. ID중복검사 실행

- WebContent/jsp/member/member_join.jsp 을 실행

- member_join.jsp 실행 시

 

1. 중복된 ID를 입력했을때

- 중복된 ID를 입력했을때 1을 전달한다

 

2. 중복이 아닌 ID를 입력했을때

- 중복된 ID를 입력했을때 -1을 전달한다

 

흐름(거꾸로) 설명

 

MemberDAOImpl.java

-id를 매개변수로 받아서 중복된 ID 이면 1 을 리턴하고 중복이 아닌 ID 이면 -1 을 리턴하는 MemberDAOImpl.java의 checkMemberId() 함수가 있다

- DB 와 연동하여 DB에 이미 저장된 ID면 1 을 리턴, 기존에 없는 ID이면 -1 을 리턴

 

member_idcheck.jsp

- 아래의 member.js 파일에서 요청하게되는 파일이다

- member.js 파일에서 전달한 id 값을 키인 memid 로 받고 id 변수에 저장 후 checkMemberId(id) 처럼 매개변수로 넣음

- member_idcheck.jsp 에서 이 checkMemberId() 함수를 호출하며 DB 연결을 하면서 DB 에 ID 가 있는지 없는지 select로 확인 후 return 해준 값을 여기서 받음

 

member.js

- 이 member_idcheck.jsp 파일을 post 방식으로 요청하는 member.js

- 브라우저에 출력되는 값인 <%=re %> 에서 돌려받은 값 re 를 콜백함수 function 의 data 로 받음

- member_idcheck.jsp 를 요청하고 있다

- 전달하는 값인 memid 는 사용자가 입력한 id 값이다

+ success : : 콜백함수로 결과를 잘 돌려받았을때 실행

+ error: :  콜백함수로 결과를 잘 돌려받지 못했을때는 보통 아무것도 안뜨므로 에러를 확인하기 위해 에러 출력하기위해 사용

- 그리고 콜백함수를 통해 data 를 받는다

- 그 data 가 1이라면 중복된 아이디라는 메세지를 띄움

- 그 data 가 -1이라면 사용가능한 아이디라는 메세지를 띄움

+ 이 id_check() 에서 ID 중복검사 버튼을 누르면 ID 중복검사 뿐 아니라 유효성검사까지 해줌

 

member_join.jsp

- 여기서 member.js 를 불러오고 있다

- 그래서 이 member_join.jsp 를 실행하면 된다

- 회원가입할때 실행하는 양식 폼이다

- 버튼을 눌렀을때 member.js 의 id_check() 함수를 실행한다

+ ID 중복검사 버튼을 누르면 ID 중복검사 뿐 아니라 유효성검사까지 해줌

 

+ DB 쪽 테이블 join_member.sql

- 사용자의 아이디는 primary key 즉 기본키이므로 중복되어선 안됨

- 그래서 ID 중복검사를 하는 것

 

흐름 정리

1. member_join.jsp 를 실행시켜 회원가입 폼을 실행함

2. ID중복검사 버튼 클릭 시 onClick 에 의해 member.js의 id_check()가 호출됨

3. member.js 에서의 id_check()가 호출되며 사용자가 input 창에 입력한 id 값을 변수 memid 로 받은 후 member_idcheck.jsp 을 ajax()로 비동기 요청하며 memid 값을 전달함, (나중에 콜백 받음)

4. member_idcheck_jsp 파일에서 키값인 memid 를 통해 값을 받아서 id 변수에 저장한 후 MemberDAOImpl 이라는 DAO 클래스로 객체를 만들고 그 멤버함수인 checkMemberId(id); 를 실행하며 id 를 매개변수로 전달

5. MemberDAOImpl 클래스 멤버함수인 checkMemberId() 에서 DB 연결을 하고, DB select 를 통해 기존의 ID가 있는지 없는지 확인하고 있으면 return 으로 1을 돌려주고, 없으면 -1 을 돌려줌

6. 그럼 4번에서 이 checkMemberId()를 호출했던 member_idcheck.jsp 에서 리턴값을 re 로 받아서 브라우저에 출력한다

7. 이렇게 브라우저에 출력되는 값이 콜백함수로 리턴이 되므로 이 출력된 값 1 또는 -1 이 ajax() 를 썼던 3번의 member.js 로 돌아가서 data 로 값을 받은 후 1이면 중복된 아이디라고 출력하고 -1 이면 사용가능하다고 출력

 

 

+ JSP 파일에서 결과 출력하는 법

- 이렇게 웹 브라우저에 출력되는 값이 callback 함수로 리턴되는 것임!

1. JSP 내장객체 9가지 중 out 객체 사용 out.println(re); 로 출력

2. <%= => 표현식 태그로 출력

3. 표현 언어로 출력

 

+ JSP 파일에서 자바클래스를 쓰기 위해선 import 해야한다

 

+ Ajax 통신시에는 오류시 어디서 잘못되었는지 확인이 힘드므로 값이 어디까지 출력되었는지를 중간에 찍어봐야한다


jQuery 로 맵 출력

- 사이트를 만들때 찾아오는 길 등을 맵으로 보여주게 됨

- 네이버 맵, 다음 맵(카카오), 구글 맵 등을 사용

- 맵 사용을 위해선 회원가입 후 키를 인증받아서 하루동안 맵을 요청할 수 있는 횟수가 정해져있고 그 횟수까지만 맵을 요청할 수 있다

- 브라우저창에 맵을 출력하는 방법을 구글 맵으로 설명할 것

 

실습 준비

- 구글 맵에 대한 인증 파일이 있다 (키 포함)

- 해당사이트로가서 키 인증을 받아야만 사용 가능

 

맵 가져오기 예제 1

- map1.html

<!DOCTYPE html>
<html>
<body>

<h1>My First Google Map</h1>

<div id="googleMap" style="width:100%;height:400px;"></div>

<script>
function myMap() {
var mapProp= {  // 37.4965202,127.0279245
  center:new google.maps.LatLng(37.497975, 127.027506),
  zoom:18,
};
var map = new google.maps.Map(document.getElementById("googleMap"),mapProp);
}
</script>

<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDEM3FEmY5ecJzAkXH9TDRAs1MaXpSWtME&callback=myMap"></script>

</body>
</html>

- myMap() 함수의 mapProp 변수에서는 맵을 출력할 center 의 위치를 위도 경도로 설정하고 zoom 속성으로 맵의 크기 설정

- google.maps.Map(); 으로 map 객체 생성

- getElementById() 로 div 태그를 구해온다, 두번째 매개변수에는 mapProp, 즉 아까의 변수를 넣음

 

키값 불러오기 (map1.html 부분)

<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDEM3FEmY5ecJzAkXH9TDRAs1MaXpSWtME&callback=myMap"></script>

- 해당사이트로가서 키 인증을 받아야만 사용 가능

- 키가 포함되어있으므로 지도가 실행된다

- 마지막 부분에 callback=myMap 으로 되어있다, myMap() 함수를 호출하는 것임

 

 

+ zoom 크기를 줄인다면?

- zoom:10

+ 위도 경도 찾기

- 위도 경도는 Google 지도 등에서 찾는다

+ 네이버, 카카오 맵에서는 위도,경도를 알 수 없음

- URL 주소 창에 위도, 경도가 나온다

https://www.google.co.kr/maps/place/%EC%9D%B4%EB%8C%80%EC%97%AD/data=!4m5!3m4!1s0x357c989a4d840017:0x652b08b73c59c6dd!8m2!3d37.556761!4d126.945857?hl=ko

- 이 위치로 center 를 설정해보자

 

맵 가져오기 예제 2

- map01.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDEM3FEmY5ecJzAkXH9TDRAs1MaXpSWtME"
  type="text/javascript"></script> -->
<script src="http://code.jquery.com/jquery-latest.js"></script>

<script src="http://maps.googleapis.com/maps/api/js"></script>

<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDEM3FEmY5ecJzAkXH9TDRAs1MaXpSWtME"
  type="text/javascript"></script>

<script>
function initialize() {
  var mapProp = {
    center:new google.maps.LatLng(37.497975, 127.027506),
    zoom:18,
    mapTypeId:google.maps.MapTypeId.ROADMAP
  };
  var map=new google.maps.Map(document.getElementById("googleMap"), mapProp);
}
//google.maps.event.addDomListener(window, 'load', initialize);
</script>
<script>
	$(document).ready(function(){
		$("button").click(function(){
//			reload();
			initialize();
		});
	});

</script>

</head>

<body>
<button>지도</button>
<div id="googleMap" style="width:500px;height:380px;"></div>

</body>
</html>

 

- 자동으로 실행되지 않고 클릭을 해야만 맵이 나타나도록 구현했다

- initialize() 함수에서 원하는 위치와 크기를 지정하고 map 객체를 만들고 document.getElementById() 를 통해서 맵을 나타나게할 영역(div)을 지정

- mapTypeId 로 맵의 타입을 설정

 

키값을 인증받는 코드 (map01.html 부분)

<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDEM3FEmY5ecJzAkXH9TDRAs1MaXpSWtME"
  type="text/javascript"></script>

- 그리고 initialize() 함수를 정의하고 있고, 아래쪽에서 버튼을 클릭시 호출할 함수이다

+ 키를 인증받는 이유 : 하루에 조회할 수 있는 횟수에 제약을 걸기위해

+ 이번엔 url에 callback 은 없다

 

- 위,경도를 강남역 기준으로 center 위치를 지정

- 마우스로 드래그시 맵이 움직인다

 

맵 가져오기 예제 3

- 마크 표시 나타나게 하기

- map02.html

<!DOCTYPE html>
<html>
<head>
<script src="http://maps.googleapis.com/maps/api/js">
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDEM3FEmY5ecJzAkXH9TDRAs1MaXpSWtME"
  type="text/javascript"></script>
  
<script>
var myCenter=new google.maps.LatLng(37.497975, 127.027506);

function initialize(){
var mapProp = {
  center:myCenter,
  zoom:18,
  mapTypeId:google.maps.MapTypeId.ROADMAP
  };

var map=new google.maps.Map(document.getElementById("googleMap"),mapProp);

var marker=new google.maps.Marker({
  position:myCenter,
  });

marker.setMap(map);
}

google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>

<body>
<div id="googleMap" style="width:500px;height:380px;"></div>
</body>
</html>

- 특정지역을 가리키는 마크표시를 나타나게 하는 방법이 추가되었다

- myCenter 변수에 위도 경도를 저장해서 center:myCenter 로 간단하게 위치 설정

 

마크 표시 나타나게 하기 (map02.html 부분)

var marker=new google.maps.Marker({
  position:myCenter,
  });

marker.setMap(map);
}

- marker 객체를 만들어서 마크를 만든다

- marker 를 어느위치에 출력할건지 position 에서 설정해야한다, 지금은 강남역으로 설정되었다

- 이후 아래에서 마커객체.setMap(맵객체) 메소드로 map에 marker 를 붙이는 작업을하고 있다

 

+ DOM Level 2 방식의 이벤트 처리 (map02.html 부분)

google.maps.event.addDomListener(window, 'load', initialize);

- 매개변수로 window 객체, 이벤트명, 호출할 함수

- load 이벤트는 현재 문서가 브라우저에 로딩될때 발생

- load 이벤트 발생시 initialize() 함수를 호출하하라는 의미

 

Map 객체 생성 (map02.html 부분)

var map=new google.maps.Map(document.getElementById("googleMap"),mapProp);

- 첫번째 매개변수로 맵을 나타낼 곳의 Element 를 구하고, 두번째 매개변수로 위치나 크기를 지정한 변수명을 넣는다

 

키 인증 코드

<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDEM3FEmY5ecJzAkXH9TDRAs1MaXpSWtME"
  type="text/javascript"></script>

 

 

맵 가져오기 예제 4

- 맵 마커에 애니메이션 주기

- map03.html

<!DOCTYPE html>
<html>
<head>
<script src="http://maps.googleapis.com/maps/api/js">
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDEM3FEmY5ecJzAkXH9TDRAs1MaXpSWtME"
  type="text/javascript"></script>
  
<script>
var myCenter=new google.maps.LatLng(37.497975, 127.027506);
var marker;

function initialize(){
var mapProp = {
  center:myCenter,
  zoom:18,
  mapTypeId:google.maps.MapTypeId.ROADMAP
  };

var map=new google.maps.Map(document.getElementById("googleMap"),mapProp);

var marker=new google.maps.Marker({
  position:myCenter,
  animation:google.maps.Animation.BOUNCE 
  });

marker.setMap(map);
}

google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>

<body>
<div id="googleMap" style="width:500px;height:380px;"></div>
</body>
</html>

- 마커가 바운스로 움직이는 타입으로 되어있다

- 나머지는 이전 예제 map02.html 과 같다

 

마커 바운스로 설정 (map03.html 부분)

var marker=new google.maps.Marker({
  position:myCenter,
  animation:google.maps.Animation.BOUNCE 
  });

- 마커에 대한 애니메이션 기능을 쓰고 있기때문에 마커객체를 만들때 animation 속성을 지정해줌

 

마커가 위아래로 움직이고 있다

 

+ DOM Level 2 방식 대신 onLoad 이벤트 핸들러로 이벤트 처리를 한다면?

<body onLoad="initialize()"></body>

- 이벤트 핸들러 방식으로 이벤트 처리

- 아래의 코드와 같은 기능

google.maps.event.addDomListener(window, 'load', initialize);

 

+ w3schools.com 에도 구글맵 관련 내용이 있다

 

맵 가져오기 예제 5

- map04.html

<!DOCTYPE html>
<html>
<head>
<script src="http://maps.googleapis.com/maps/api/js">
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDEM3FEmY5ecJzAkXH9TDRAs1MaXpSWtME"
  type="text/javascript"></script>
  
<script>
var myCenter=new google.maps.LatLng(37.497975, 127.027506);

function initialize(){
var mapProp = {
  center: myCenter,
  zoom:18,
  mapTypeId: google.maps.MapTypeId.ROADMAP
  };

var map = new google.maps.Map(document.getElementById("googleMap"),mapProp);

var marker = new google.maps.Marker({
  position: myCenter,
  title:'Click to zoom'
  });

marker.setMap(map);

// Zoom to 9 when clicking on marker
google.maps.event.addListener(marker,'click',function() {
  map.setZoom(20);
  map.setCenter(marker.getPosition());
  });
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>

<body>
<div id="googleMap" style="width:500px;height:380px;"></div>

</body>
</html>

- marker 를 클릭시 맵이 확대가 된다

- marker 객체 생성 시 title 속성을 지정했다, 마커에 마우스를 올리면 Click to zoom 이 나타남

 

marker (마커) 클릭 시 줌 하기 (map04.html 부분)

// Zoom to 9 when clicking on marker
google.maps.event.addListener(marker,'click',function() {
  map.setZoom(20);
  map.setCenter(marker.getPosition());
  });
}

- marker 를 클릭하면 클릭이벤트가 발생하고 그 이벤트를 DOM Level 2 방식으로 처리하고 있다

- map 객체에서 setZoom(20); 을 통해 클릭시 크기를 20 으로 확대

- map 객체의 setCenter() 메소드와 marker 객체의 getPosition() 메소드로 확대가 되더라도 marker 의 position 값을 다시 center 로 지정하고 있다

 

 

+ 프로젝트 시에 혼자서 자세히 공부하기, 구글 맵 외에도 카카오 맵으로도 만들어보자

- API 관련 내용도 공부

- 웹과 앱을 따로 인증 받아야함


jQuery UI

- jQuery 에는 기능이 많다, jQuery UI 와 jQuery Mobile 등이 있다

- 이미 다 만들어진 기능들을 가져다 쉽게 쓸 수 있다

 

실습 준비

+ https://jqueryui.com 에도 같은 내용이 있다

 

jQuery UI 예제 1

- index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Chapter 11. jQuery UI</title>
</head>
<body>
	<h1>Chapter 11. jQuery UI</h1>
	<ul>
		<li> <a href="example11_01.html"> 드래그 앤 드랍 기능 구현하기-draggable, droppable      </a> </li>
		<li> <a href="example11_02.html"> 엘리먼트의 크기 변경하기-resizable      </a> </li>
		<li> <a href="example11_03.html"> 엘리먼트를 선택 할 수 있게 하기-selectable         </a> </li>
		<li> <a href="example11_04.html"> 엘리먼트 이동하기-Sortable         </a> </li>
		<li> <a href="example11_05.html"> 헤더는 보이고 클릭했을때 내용이 보이도록 하는 아코디언 컨트롤-accordion         </a> </li>
		<li> <a href="example11_06.html"> 텍스트 박스 자동 완성 기능-Autocomplete         </a> </li>
		<li> <a href="example11_07.html"> 데이터 픽커로 날짜 선택하기-datepicker         </a> </li>
		<li> <a href="example11_08.html"> 탭 컨트롤-tabs                                                                   </a> </li>
	</ul>
</body>
</html>

- jQuery UI 기능 일부를 볼 수 있다

- 여러 예제들이 a 태그로 연결되어있어서 클릭 시 다양한 기능을 볼 수 있다

* jQuery UI 정리 아래에


jQuery UI 정리

* jQuery UI
- jQuery UI는 인터렉티브한 웹을 제공할 수 있도록 하는 인터페이스 개발 도구

- jQuery UI는 애니메이션 효과, 위젯을 쉽게 사용할 수 있도록 있도록 탭을 만들거나 경고 창을 띄우는 등의 효과를 줄 수 있다.

- jQuery UI 관련 웹 사이트
    http://jqueryui.com
 - jQuery UI 데모 사이트
    http://jquery.com/demos

 

- jQuery UI에서 제공하는 기능 (카테고리별)


1. 인터렉션(Interaction)
- Draggable
- Droppable
- Resizable
- Selectable
- Sortable

2. 위젯(Widgets)
- Accordion
- Autocomplate
- Button
- Datepicker
- Dialog
- Progressbar
- Slider
- Tabs

3. 유틸리티(Utilities)
  - Position

4. 이펙트(Effects)
 - Effect
 - Show
 - Hide
 - Toggle
 - Color animation
 - Add class, Remove class, Toggle class, Switch class

 

jqueryui.com 에서 기능 확인

ex) Draggable

 

소스 보기와 기능 적용하는 방법

- jQuery 라이브러리와 jQuery UI 라이브러리를 둘 다 불러와야한다

- 기능이 나타나게 할 태그의 id 값만 적고 draggable() 함수만 적용시 드래그 가능하게 된다

 

ex) Accordion 메뉴

소스 보기와 기능 적용하는 방법

- 내용을 감싼 태그를 가져와서 accordion() 함수만 사용하면 아코디언 메뉴가 적용된다

- jQuery 라이브러리와 jQuery UI 라이브러리를 둘 다 불러오고 있고 CSS 도 불러오고 있다

+ 부트스트랩에서도 아코디언 메뉴 지원함

 

ex) Autocomplete

- 특정 단어 입력시 그 단어 포함하는 단어들 보여줌

- 등록된 단어 중에서만 가능

- availableTags 배열안에 들어간 단어들 중에서 자동완성 가능

- input 태그를 구한 후 autocomplete() 함수만으로 자동완성 가능

- autocomplete() 함수 안에 source: 로 아까의 배열명인 availableTags 를 쓰기

 

ex) Datapicker

- 입력양식 클릭 시 달력모양을 보여줌

+ jquery UI 를 쓰지 않더라도 input type=text 가 아닌 input type=date 로 하면 기본적으로 캘린더가 나타남

* input type=date 사용시 설명 아래

+ 하지만 쓰지못하는 브라우저도 있으므로 어떤 브라우저든 캘린더가 잘 나타나는 jquery UI로 구현

 

 

ex) Tabs

- 먼저 윗부분에서 레이블값들을 출력한다

- 레이블값 태그의 a 태그 #을 통해서 클릭시 어떤 영역을 보여줄지 영역의 id값을 통해서 연결 가능하다 

+ 부트스트랩에서도 지원

 

그 외 효과들

확대

지우기

- 클릭 시 삭제

 

토글


* input type=date 사용시

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

크롬

- 하지만 웹 표준을 잘 지키지 않는 브라우저에서는 잘 나타나지 않는다



jQuery Mobile

실습 준비

- ch12/index.html

- 다양한 기능들이 많다

- ch13/index.html

- ch14/index.html

 

- jQuery UI 처럼 찾아보고 사용하기

- jQuery mobile 사이트 : https://jquerymobile.com

 

jQuery Mobile

Developer Links Seriously cross-platform with HTML5 jQuery Mobile framework takes the "write less, do more" mantra to the next level: Instead of writing unique applications for each mobile device or OS, the jQuery mobile framework allows you to design a si

jquerymobile.com


JSP

JSP

- HTML 로 만들어진 양식에 Javascript 로 유효성 검사를 하고 유효한 값을 전달, 그 값을 JSP 가 받아서 DB 연동 수행

- 게시판, 댓글 게시판, 자료실 등의 기능을 JSP로 처리 가능

 

JSP 방식

- Model1 방식과 Model2 방식이 있다

 

Model1 방식

- JSP 만으로 프로그램 개발, 단, DB 연동을 수행하는 경우엔 자바 클래스를 사용 DTO 클래스와 DAO 클래스를 사용

- 실무에서 많이 사용하지 않음

 

Model2 방식

- JS 파일에는 디자인 적 요소와 프로그램적 요소가 둘 다 있으므로 사이트 규모가 커지거나 사이트가 많아지면 관리가 힘들고 수정시 신경써야할 것이 많다 이런것들을 효율적으로 처리하기 위해 실무에서는 Model2 방식을 많이 사용

- Model2 : 크게 3가지 영역으로 기능을 분리시켜 개발하는 방식 MVC 패턴

- 70% 이상 자바코드로 작성, 인터페이스, 상속, 메소드 오버라이딩 개념 많이 사용

- 우리가 보는 페이지 View 페이지는 디자이너가 개발

- Model 과 Controller 는 개발자가 개발

- 디자인 요소와 개발 요소가 구분

 

학습 방향

- Model 1 먼저 배우고 Model 2 를 배울것

- Model 2 를 빠르게 구현하기 위해서 Spring 이나 Spring 부트를 사용한다

- 그 후 Spring 을 학습할 것, Spring 은 앞의 내용을 모두 알아야한다

 

+ Spring

- 어노테이션, 환경설정 때문에 어렵다

- 코드는 간결하게 처리되는 반면 값이 어떤식으로 리턴되는지 볼수 없다, 이해가 어렵다

+ 파이썬에서 Spring 과 비슷한 역할인 django

+ Springboot 는 환경설정이 자동인 부분이 많아서 쉽다


JSP 기초

- Java Server Pages 의 약자이며, HTML 코드에 JAVA 코드를 넣어 동적 웹페이지를 생성하는 웹어플리케이션 프로그램

- JSP 가 실행되면 작성한 JSP 파일들은 내부적으로는 자바 서블릿(Servlet) 형태로 변환되며, 웹 어플리케이션 서버에서 동작되면서 필요한 기능을 수행하고, 그렇게 생성된 데이터를 웹페이지와 함께 클라이언트로 응답한다.

- "자바" 기반 웹 프로그램

 

JSP 흐름

- 클라이언트측에서 값을 입력하고 서비스를 요청

- JSP를 쓰기 위해서는 아파치 톰캣같은 JSP Container 가 필요하다

- JSP Container 에서 서비스를 하는데 대표적인 Container 는 Apache Tomcat

- JSP 파일 생성시 클라이언트의 요청을 받게되고 내부적으로 JAVA Servlet 으로 변환

- Java Servlet 으로 변환시 확장자가 .java 로 변환

- 이때, 컴파일러를 통해서 바이트 코드로 변환(.class) 이 파일을 tomcat 이 실행함, 자바 서블릿 코드를 이용해서 처리하고 처리된결과를 HTML 로 바꿔서 HTML 로 뿌려줌(= 클라이언트 웹 브라우저에 응답)

 

+ 자바시간에 공부한건 JAVA application(내 컴에서만 실행, 안에 HTML 코드 추가 불가) 이고, JAVA Servlet 은 JAVA 로 만든 웹 프로그램으로서 안엔 HTML, Javascript 코드들이 들어감 

 

Model 1 방식

- 클라이언트가 JSP 로 요청시 대부분의 코드는 JSP만으로 처리

+ 물론 이때도 JavaBean(DTO, DAO 클래스 사용) 즉 일부 자바 사용

- 유지 보수를 쉽게하기 위해 Model 2 방식을 실무에서 많이 사용

 

Model 2

- MVC 패턴으로 분리, Model, View, Controller 로 3가지 영역으로 구분

- Controller 클래스는 Java Servlet 으로 만들고 중간의 흐름을 제어 어떤 서비스 콘텐츠를 넘겨줄건지

- Model 은 DB쪽의 데이터를 처리해줌, Service 클래스와 DAO 클래스가 주로 해당

- View 는 처리한 결과가 나타남

- 70% 이상 Java 코드 (View 페이지 제외 거의 Java 코드)

 

WAS

- 웹 어플리케이션 서버

- 오픈 소스 WAS 중 대표적인게 Apache Tomcat (무료)

 

WAS(Web Application Server) 종류

1. 오픈소스

- Apache Tomcat : 아파치 재단에서 관리하는 WAS

- Jetty : 이클립스 재단에서 관리하며, 임베디드 자바 애플리케이션에서 웹 서비스를 제공한다.

 

2. 상용 소프트웨어

- WebLogic : 오라클에서 관리하는 WAS

- JBoss : 레드헷에서 관리하는 WAS

- Jeus : 티맥스소프트에서 관리하는 제품으로써, 국내에서 많이 사용하고 있다

 

JSP 다운 방법

- 공식사이트 : https://tomcat.apache.org

- 이미 Tomcat 9점대 다운받았다, jre 에서 지원되는 라이브러리를 쓰므로 jre가 설치되어야만 apache tomcat 설치 가능

+ 우리가 쓰는 이클립스 버전이 낮은 버전이라 Tomcat 10점대 지원하지 않음

- 포트번호 설정시 이미 사용하고 있는 포트번호 사용하지 않도록 주의

+ 나는 8080 을 오라클에서 쓰고 있으므로 다른 포트번호 80으로 설정

+ 설치된 위치 알고 있기 

C:\Program Files\Apache Software Foundation\Tomcat 9.0

 

환경 구축 했던 글

https://laker99.tistory.com/86?category=1075935

 

웹브라우저로 접속

- http://localhost:80 로 접속시 C:\Program Files\Apache Software Foundation\Tomcat 9.0\webapps\ROOT\index.jsp 가 실행됨실행

 

개발시 주의

- 이클립스에서 작업시에 이 서비스를 중지시켜야함

- 중지하지 않으면 포트 충돌 발생

 

JSP 실습 준비

- 이미 Tomcat v9.0 설정된 상태다, 저번에 설정했음

- 확장자가 .java 인 자바 파일은 반드시 src 폴더 안에 저장되어야만 정상 동작한다

+ 바이트코드는 build\classes 에 저장됨

- 자바파일을 제외한 나머지 파일은(HTML, CSS, JS, JSP 파일) Content directory 하위에 모든 것을 저장해야 정상 접근 가능하다

- Generate web.xml deployment descriptor 에 체크해서 web.xml 파일 생성

-모든 .java 자바파일은 src 에 나머지 파일은 web.xml 에 저장해야만 정상 동작한다

 

- web.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_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>jspproject</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>
</web-app>

- WebContent 폴더 안의 파일을 찾는 순서이다.
ex) index.html 을 찾고 없으면 index.htm 을 찾고 없으면 index.jsp 를 찾고 없으면 default.html 을 찾는다

- 파일명을 생략하더라도 자동으로 실행되는 파일들의 이름이 적혀있다

- 파일명 생략시 default.jsp 에도 없으면 404 에러를 뿌림

 

- 그래서 첫 페이지는 index 를 파일명으로 주로 적음

- 위의 파일들은 파일명을 생략하더라도 실행이 잘 됨

 

 

+ 네이버 URL

http://www.naver.com/index.html
로 접속해야하지만 포트번호와 파일명을 생략하는 것임

 

JSP 파일 생성

- WebContent 하위에 index.jsp 파일 생성해보자

 

JSP 파일 작성

- index.jsp

- web.xml 파일에 있었으므로 index.jsp 는 생략해도 실행된다

 

URL 분석

http://localhost:80/jspproject/index.jsp

- localhost : 로 요청

- 80 : 포트번호 (80 이므로 생략 가능)

- jspproject : 프로젝트명, 이클립스로 실행할때는 즉 개발상에서는 jspproject 가 경로상에 포함되지만 나중엔빠짐

- index.jsp : 파일명 (index.jsp 이므로 생략 가능)

 

+ 프로젝트는 개발시에 필요한 것

 

환경설정 : 포트번호 설정 방법 2가지

1. Servers/server.xml 에서 포트번호 설정 가능, 현재 80 으로 설정되어있다

2. Servers 뷰에서 하위의 Tomcat 을 더블클릭 후 뜨는 창에서 포트 설정/수정 가능

 

폴더 및 파일 설명

- META-INF 폴더는 DB 접속 방법 중 Connection Pool 이 저장되어있는 폴더이다

- WEB-INF 폴더는 가장 먼저 실행되는 곳이므로 web.xml 은 여기 있어야한다

- WEB-INF 폴더의 lib 폴더에 라이브러리를 저장함, import / export 시 이 lib 파일도 같이 import / export 됨

- 당분간 라이브러리들을 WEB-INF/lib 폴더에 저장할 것

- 나중엔 라이브러리를 Maven 으로 관리할 것 (pom.xml)


JSP 5대 태그 소개

- 자세한 내용은 나중에 학습

- JSP 의 태그는 크게 5가지 종류가 있다

1. 스크립틀릿 태그

- <% %>

-  Java 코드나 JSP 코드가 들어감

- 거의 대부분의 코드가 들어감

 

2. 선언 태그

- <%! %>

- 매서드를 정의할 때는 반드시 선언태그에 쓴다

- 매서드를 만드는 규칙은 JAVA 문법을 따른다, 메서드를 만드는 일은 드뭄

 

3. 표현식 태그

- <%= %>

- 변수나 값을 브라우저에 출력가능

 

4. 지시어 태그

- 3가지 종류가 있다

1) 페이지 태그

2) 포함 태그 <%@ include %>

+ 부트스트랩에서 외부파일을 불러올때 사용했었다

3) 사용자 정의 태그

- taglib

 

5. 액션 태그

- 주로 페이지를 이동시킬때 쓰는 액션태그가 있고 자바와 연동할때 쓰는 액션태그가 있다

include, forward 는 페이지 이동이나 다른 페이지를 이동시킬때 사용하는 액션태그

usebeen, setProperty, getProperty 는 자바와 연동할때 사용하는 액션태그

 

JSP 내장객체

- Javascript 의 내장객체처럼 JSP 에서도 내장객체가 9개 있다

- JSP 에서 기본적으로 정의되기때문에 따로 정의없이 사용가능한 객체

 

 

1. request 객체

- 클라이언트가 get/post 로 요청할때 요청을 처리해주는 객체

- 지원되는 메소드 중 getParamenter() 메소드를 통해 넘어온 값을 받을 수 있다

 

2. response 객체

- 서버측에서 응답하는 객체

- 쿠키를 발행할때 사용하는 객체

 

3. session 객체

- 서버와 클라이언트 사이 연결을 유지하기 위한 객체

- 주로 회원관리 할때 사용됨

 

4. out 객체

- 브라우저에 출력시켜주는 객체

- 지원되는 메소드 중 println() 메소드를 통해 출력 가능

 

앞으로 학습할 것

- JSP

- JSP와 DB 연동

- Model 1 으로 각종 회원가입, 게시판 페이지 만들어볼 것

- Model2에선 MVC 패턴 배울것

- Java Servlet 으로 Container 클래스 만들고 값 전달하는 법

- Model 2 넘어가기 전에 표현언어 EL 공부, JSTL 공부(새로운 태그, 사용자 정의 태그)

- Model 2 로 회원가입, 게시판 등 만들것

 

 

jQuery 예제 52

유효성 검사 예제 직접 작성 3

- 유효성 검사

- ID중복검사에서 팝업창 띄워서 사용자의 아이디값을 전달하는 것을 jQuery 로 구현

- 주민번호 앞자리 6자리 입력하고 손을 떼면 key up 이벤트로 포커스를 뒤로 넘기는 것을 jQuery 로 구현

- E-Mail 입력에서 도메인명을 select 에서 선택하면 그 도메인이 입력양식에 나타나도록 하기

- 우편검색 버튼을 누르면 팝업에서 우편번호 검색이 가능하고 검색 후 회원가입 페이지로 값 가지고 돌아오기(API 사용)

- memberform.html 에 코드 추가

실습 준비

- select 에 id 값 부여, select 태그를 구해와야 하고 select 태그가 여러개이므로 구분이 필요

- 이 라디오버튼의 input 태그를 구해와야하므로 각각 id 값을 다르게 설정

- 각 취미도 input 태그를 구해오기 위해 각각 id 값을 다르게 설정

- 이미지 버튼 주석처리

- ID중복검사 버튼의 id 값 추가

- 취미 체크박스에 초기에 선택된 상태로 나타나지 않게 checked 속성 없애기

 

1. 라이브러리 불러오고 기본 jQuery 함수 쓰기

- 라이브러리 불러오기

- 기본 jQuery 함수 쓰기

- 라이브러리를 잘 불러왔는지 확인

 

2. 아이디 중복검사

0) 먼저 이벤트를 발생시키는 태그인 ID중복검사 버튼 태그의 id값을 구해야함

1) 아이디를 입력하지 않았을때는 입력하라는 메세지를 띄우고

- if~else문으로 아이디를 입력했는지 안했는지 확인 후 분기

2) 아이디를 입력했을때는 팝업창을 띄우기 window.open()

open("팝업창에 실행될 문서명", "윈도우 이름", "옵션"); // window.open

- 팝업창 문서는 idcheck.jsp 

3) 사용자가 입력한 아이디값을 팝업창으로 전달

- get 방식으로만 전달 가능하다

- 값은 ?변수명=값 으로 idcheck.jsp 로 전달됨

- $("#id").val()은 사용자가 입력한 값이고 그걸 'id' 변수에 전달하고 있다

 

+ Javascript 에서는 onClick 등으로 처리를 하거나 요소를 구하려면 getElementById() 사용

+ jQuery 에서는 먼저 이벤트를 발생시키는 태그를 구해야함

 

4) idcheck.jsp 파일 생성

- idcheck.jsp

- 자바나 JSP 를 쓸때는 스크립트 태그인 <% %> 안에 써야한다

- request 객체의 getParameter() 함수로 값을 받는다

- 함수 안의 "id" 는 아까 저장했던 변수명

- 가장 아래코드는 출력할때 코드

+ 나중에 팝업창 부분에서 DB 연동해서 select 해서 중복인지 확인해야함

- 결과 캡처

 

동기적 통신방식 vs 비동기적 통신방식

- 이건 동기적 통신방식이다

- 동기적인 통신 방식 : 한가지 요청이 끝나야 다음 요청 가능

- 동기적인 통신 방식 : 부모창에서 팝업창으로 페이지가 바뀌었다

- AJAX 는 비동기적인 방식

- AJAX에선 팝업창을 띄우지 않고 비동기적인 방식으로 ID중복검사 한다, 콜백함수로 값을 돌려받음

- AJAX에서 페이지를 바꾸지 않고 댓글달면 바로 DB에 insert 되고, 바로 콜백함수로 가져와서 뿌려줌

 

id 중복검사 부분 전체

- memberform.html id 중복검사 부분

- idcheck.jsp

 

3. 주민번호 뒷자리로 포커스 이동

- 주민번호 앞자리 입력한 후 손을 떼면 뒷자리로 포커스 이동

- keyup 이벤트 사용

- 값의 길이값이 정해져있는 경우에만 사용 가능 (ex) 카드번호, 주민등록번호)

 

0) 가장 먼저 이벤트를 발생시킨 태그 구하기

- keyup 이벤트는 주민번호 앞자리 input 태그에서 일어난다

 

1) 이벤트 처리

- 이벤트가 발생하는 태그는 주민번호 앞자리 input 태그

- 키를 눌렀다가 뗐을때 keyup 이벤트 발생

- focus() 통해 뒷자리에 focus 주기

 

2) 주민번호 앞자리 6자리가 모두 입력된 후에 뒷자리로 포커스가 가도록 하기

- 이렇게 if문 쓰지 않으면 한자리만 입력해도 손을 떼게 되므로 뒷자리로 focus가 넘어가버림

- length 속성을 통해 값이 6자리일때만 뒷자리에 focus가 넘어간다

- 이처럼 값의 길이값이 정해져 있는 경우에만 사용 가능

 

주민번호 뒷자리로 포커스 이동 전체

- memberform.html 주민번호 뒷자리로 포커스 이동 부분

 

4. Email 에서 도메인

- 도메인명을 직접입력하는 경우, 도메인명을 선택하는 경우가 있다, 나눠서 처리해야한다

- 직접 입력하는 경우 도메인명을 입력하는 곳에 포커스가 들어가야한다

- select 에서 도메인을 선택시 해당 도메인을 화면에 출력시키기

ex) 구글 선택시 google.com 을 입력양식에 나타나게 하기

 

0) 가장 먼저 이벤트를 발생시키는 태그를 구하기

- 이벤트를 발생시키는 태그는 위의 select 태그이다, select 태그가 여러개 이므로 id값을 통해 구해온다

 

1) change 이벤트로 처리

- 이벤트를 발생시키는 태그인 select 태그를 구해왔다

- select 에서 옵션 선택시 값의 변화가 일어나므로 change 이벤트 발생

 

2) 도메인을 직접 입력하는 경우 ('직접입력' 을 선택한 경우)

- if~else문으로 도메인을 직접 입력하는 경우와 선택하는 경우를 나눠서 처리한다

- select-option 에서 '직접입력'을 선택시 value 는 "" 이된다.

- '직접입력' 선택시 도메인 명을 입력하는 곳의 값을 지우고 focus 해야한다

- 도메인 입력하는 곳의 input 태그 id는 domain, 이 id로 태그를 구해온다

 

3) 도메인을 선택하는 경우

- 구글을 선택하는 경우 google.com 을 도메인 입력양식에 출력해야한다

- 도메인 입력양식 input 태그의 id는 domain

- 그리고 $("#email").val() 을 통해 선택된 옵션의 value 값을 구한 후 그 값을 도메인 입력양식에 설정

 

4) 도메인 영역의 값을 수정하지 못하도록 비활성화

- 도메인명을 선택한 후 이 값이 지워진다

- 도메인 지워지지 않도록 비활성화, readOnly 나 disabled 로 비활성화시키기

- 결과 캡처

- 선택된 도메인이 지워지지 않는다

- 문제는 다시 '직접입력' 을 선택했을때 값은 지워지지만 포커스가 들어가지 않음

- 설정된 readOnly 속성이 해제되지 않았기 때문이다

- 포커스(깜빡임)가 들어가지 않음

- 직접입력 을 선택했을때 readOnly 속성을 해제해줘야한다

- readOnly 속성을 해제해주면 다시 '직접입력' 선택시 포커스가 들어간다

 

+ readOnly (읽기전용) 설정 두가지 방법

+ readOnly (읽기전용) 해제 두가지 방법

 

+ readOnly vs disabled

- readOnly : name 값이 변수가 되어서 사용자가 입력한/선택한 값이 form 태그 action 의 페이지로 넘어감

- disabled : 값이 안넘어감

- 지금은 회원가입 버튼을 통해 이메일 주소값을 넘겨야하므로 readOnly 속성으로 비활성화 시키기

 

주민번호 뒷자리로 포커스 이동 전체

- memberform.html 주민번호 뒷자리로 포커스 이동 부분

 

5. 유효성 검사

0) 이벤트를 발생시키는 태그 구해오기

- 다른 이벤트와 달리 submit 버튼은 submit 버튼이 아니라 form 태그에 이벤트 처리를 해야한다

- 그리고 폼 관련 코드를 안에 넣어야한다

 

1) id, 비밀번호, 이름 유효성 검사

- id 유효성 검사를 한 뒤 나머지는 복사해서 만든다

- id 유효성 검사 완료

- 비밀번호,성명 부분도 복사, id값과 alert 메세지만 바꾸기

 

2) 주민번호 유효성 검사

- 주민번호 앞자리는 3가지를 검사

- 값이 입력되어야함

- 값의 길이값이 6자리 여야함

- 값이 숫자값이어야함

- 유효성 검사에 맞지 않으면 값을 지우고 focus 함

- 결과 캡처

- 주민번호 뒷자리도 복사해서 적용

- alert 메세지나 길이값만 수정

 

3) email 유효성 검사

- id, 비밀번호 유효성 검사와 비슷

- 도메인 부분도 복사해서 비슷하게 작성

 

3) 전화번호 유효성 검사

- 입력되었는지 확인

- 문자인지 숫자인지 확인

+ 숫자만 입력되도록 하기 위해 정규표현식을 쓰는 방법도 있다

- 전화번호 중간자리, 끝자리도 똑같이 처리를 한다

- 결과 캡처

 

 

4) 핸드폰 앞자리 유효성 검사

- 입력되었는지 확인

- 핸드폰 앞자리는 번호를 선택하는 곳

- 번호선택이 나타난 다는 것은 번호를 선택하지 않았다는 의미, 이때 value 가 ""이다

- 이걸 이용해서 유효성 검사를 한다

- 휴대폰 번호 중간자리와 끝자리도 똑같이 작성하고, 중간자리와 끝자리는 숫자인지 문자인지도 검사한다

- 결과 캡처

 

5) 우편검색 기능

- 카카오 API 를 활용해서 팝업창에서 우편번호와 주소를 검색 후 팝업창에서 부모창으로 값 가져오기

- 이전에 만들었던 javascript/member/memberform.html 의 내용을 가져와서 적용

- 이부분을 복사해서 가져오기

- 지금 작업하는 파일에 복붙

- 이 함수 openDaumPostcode() 를 '우편검색' 버튼 누르면 호출해야함

- 이건 자바스크립트로 처리하기, onClick 사용

- 이러면 '우편검색' 버튼 클릭시 함수 실행되며 팝업창이 뜸

 

- 주소 검색 후 클릭시 부모창으로 값이 넘어온다

- 이때 검색한 결과를 받는 함수가 콜백함수 oncomplete : function(data) {}

- 이 콜백함수의 매개변수가 data 이다, 이 data 가 값을 받고 data 통해서 부모창으로 전달

- data 에서 우편번호를 뽑아오는게 zonecode 이고 id값이 post 인 곳의 value 값으로 우편번호를 설정하라는 의미

- data 에서 주소를 뽑아오는게 address 이고 id값이 address 인 곳의 value 값으로 주소를 설정하라는 의미

+ 주석처리된 것은 과거 우편번호가 xx-xxx 였을때 앞자리, 뒷자리 따로 구했던 것

 

6) 우편번호, 주소 유효성 검사

- 기본적인 형식으로 입력값이 없는경우의 유효성 검사를 한다

 

6) 성별 라디오버튼 유효성 검사

- 두 라디오버튼 모두 선택하지 않은 경우

- is() 함수를 사용해서 is(":checked")로 체크가 되었는지 확인 가능

- 선택되었으면 true, 선택되지 않았으면 false 리턴

- 결과 캡처

 

6) 취미 체크박스 유효성 검사

- 두개이상을 선택하도록 한다

- 두가지 방법이 있다

1. 기존 자바스크립트에서 사용했던 방식

- id 값으로 해당 input 태그를 구해오고 is() 함수로 체크 유무를 파악하고 변수값에 +1 증가시켜 누적후 if문으로 확인

+ 사용자가 확인버튼을 눌렀을때 함수를 return false 로 빠져나감

2. 더욱 간결한 방식

- 체크가 되어있는 체크박스를 구해오는 내용이 jQuery 함수 안에 들어감

1. input:checkbox

- :checkbox 필터선택자로 input type=checkbox인 모든 체크박스를 구해옴 (input 태그 중)

2. input:checkbox[name='hobby']

- 체크박스가 다른 곳에도 있을 수 있으므로 체크박수 중 name 값이 hobby 로 되어있는 체크박스만을 모두 구해줌

3. input:checkbox[name='hobby']:checked

- name값이 hobby 인 체크박스 중에서도 :checked 로 체크되어있는 체크박스의 input 태그를 구해오라는 의미

- 그 후 length 속성으로 구해진 체크박스의 개수를 구한다 (가능)

 

7) 자기소개 textarea 유효성 검사

- id 값으로 태그를 구해와도 되고 textarea 태그는 하나이므로 textarea 태그로 구해와도 된다

- 입력되었는지 검사한다

- 100 자 이내여야 한다

- 결과 캡처

 

+ reset 버튼은 이벤트 처리를 하지 않아도 자체적으로 지워주는 기능 있다

 

8) 작성한 내용을 외부파일로 빼기

- .js 파일이어야한다

- member.js 파일 생성

- 자바스크립트에서는 .js 외부파일에 함수단위로 내용이 들어갔지만 제이쿼리에서는 작성한 전체가 들어감

- $(document).ready() 부터 마지막 까지 복사 후 주석 처리

- member.js 파일에 붙여넣기

- 이 member.js 에는 <script></script> 하면 안되고 내용만 들어가야 한다

- memberform.html 에서 외부파일 불러오기

- 결과 캡처

- 외부파일 member.js 를 잘 불러왔음을 알 수 있다

 

위 예제 전체코드

- memberform.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원가입 폼</title>

<script src="http://dmaps.daum.net/map_js_init/postcode.v2.js"></script>
<script>
	function openDaumPostcode() {
		new daum.Postcode({
			oncomplete : function(data) {
				// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
				// 우편번호와 주소 정보를 해당 필드에 넣고, 커서를 상세주소 필드로 이동한다.
//				document.getElementById('join_zip1').value = data.postcode1;
//				document.getElementById('join_zip2').value = data.postcode2;
				document.getElementById('post').value = data.zonecode;
				document.getElementById('address').value = data.address;
				
			}
		}).open();
	}
</script>

<script src="http://code.jquery.com/jquery-latest.js"></script>

<!-- 외부 jQuery 파일 불러오기 -->
<script src="member.js"></script>

<script>
/* 	$(document).ready(function(){

		// ID 중복검사
		$("#idcheck").click(function(){
			
			if($("#id").val() == "") {
				alert("ID를 입력하세요.")
				$("#id").focus();
				return false;
			} else {
				// open("팝업창에 실행될 문서명", "윈도우 이름", "옵션");
				var ref="idcheck.jsp?id="+$("#id").val();
				window.open(ref,"mywin","width=250, height=150");
			}
			
		});
		
		// 주민번호 뒷자리로 포커스 이동
		$("#jumin1").keyup(function(){
			
			if($("#jumin1").val().length == 6)
				$("#jumin2").focus();
		});
		
		// 도메인 선택
		$("#email").change(function(){
			if($("#email").val() == "") {	// '직접입력' 선택
				$("#domain").val("").focus();
				$("#domain").attr("readOnly", false);	//읽기 전용 해제
				// $("#domain").removeAttr("readOnly");	// 위와 같다
			}else {							// '도메인' 선택
				$("#domain").val($("#email").val());
				$("#domain").attr("readOnly", "readOnly");	// 읽기 전용
				// $("#domain").attr("readOnly", true)	// 위와 같다
			}
		});
		
		// 유효성 검사
		$("form").submit(function(){
			
			if($("#id").val() == ""){
				alert("ID를 입력하세요.");
				$("#id").focus();
				return false;
			}
			if($("#passwd").val() == ""){
				alert("비밀번호를 입력하세요.");
				$("#passwd").focus();
				return false;
			}
			if($("#name").val() == ""){
				alert("이름을 입력하세요.");
				$("#name").focus();
				return false;
			}
			if($("#jumin1").val() == ""){
				alert("주민번호 앞자리를 입력하세요.");
				$("#jumin1").focus();
				return false;
			}
			if($("#jumin1").val().length != 6){
				alert("주민번호 앞자리 6자리를 입력하세요.");
				$("#jumin1").val("").focus();
				return false;
			}
			// isNaN() : 문자가 포함되면 true를 리턴
			if(isNaN($("#jumin1").val())){
				alert("숫자만 입력하세요.");
				$("#jumin1").val("").focus();
			}
			if($("#jumin2").val() == ""){
				alert("주민번호 뒷자리를 입력하세요.");
				$("#jumin2").focus();
				return false;
			}
			if($("#jumin2").val().length != 7){
				alert("주민번호 뒷자리 7자리를 입력하세요.");
				$("#jumin2").val("").focus();
				return false;
			}
			// isNaN() : 문자가 포함되면 true를 리턴
			if(isNaN($("#jumin2").val())){
				alert("숫자만 입력하세요.");
				$("#jumin2").val("").focus();
			}
			if($("#mailid").val() == ""){
				alert("EMail 주소를 입력하세요.");
				$("#mailid").focus();
				return false;
			}
			if($("#domain").val() == ""){
				alert("도메인명을 입력하세요.");
				$("#domain").focus();
				return false;
			}
			if($("#tel1").val() == ""){
				alert("전화번호 앞자리를 입력하세요.");
				$("#tel1").focus();
				return false;
			}
			if(isNaN($("#tel1").val())){
				alert("숫자만 입력하세요.");
				$("#tel1").val("").focus();
				return false;
			}
			if($("#tel2").val() == ""){
				alert("전화번호 중간자리를 입력하세요.");
				$("#tel2").focus();
				return false;
			}
			if(isNaN($("#tel2").val())){
				alert("숫자만 입력하세요.");
				$("#tel2").val("").focus();
				return false;
			}
			if($("#tel3").val() == ""){
				alert("전화번호 끝자리를 입력하세요.");
				$("#tel3").focus();
				return false;
			}
			if(isNaN($("#tel3").val())){
				alert("숫자만 입력하세요.");
				$("#tel3").val("").focus();
				return false;
			}
			if($("#phone1").val() == "") {
				alert("핸드폰 번호 앞자리를 선택하세요.");
				$("#phone1").focus();
				return false;
			}
			if($("#phone2").val() == "") {
				alert("핸드폰 번호 중간자리를 선택하세요.");
				$("#phone2").focus();
				return false;
			}
			if(isNaN($("#phone2").val())) {
				alert("숫자만 입력하세요.");
				$("#phone2").val().focus();
				return false;
			}
			if($("#phone3").val() == "") {
				alert("핸드폰 번호 뒷자리를 선택하세요.");
				$("#phone3").focus();
				return false;
			}
			if(isNaN($("#phone3").val())) {
				alert("숫자만 입력하세요.");
				$("#phone3").val().focus();
				return false;
			}
			if($("#post").val() == "") {
				alert("우편번호를 선택하세요.");
				$("#post").focus();
				return false;
			}
			if($("#address").val() == "") {
				alert("주소를 선택하세요.");
				$("#address").focus();
				return false;
			}
			if($("#male").is(":checked") == false &&
				$("#female").is(":checked") == false ){
				alert("성별을 선택하세요.");
				return false;
			}
			
//			var cnt = 0;
//			if($("#h1").is(":checked")) cnt++;
//			if($("#h2").is(":checked")) cnt++;
//			if($("#h3").is(":checked")) cnt++;
//			if($("#h4").is(":checked")) cnt++;
//			if($("#h5").is(":checked")) cnt++;
//			
//			if(cnt < 2) {
//				alert("취미를 2개 이상 선택하세요.");
//				return false;
//			}
			
			if($("input:checkbox[name='hobby']:checked").length < 2){
				alert("취미를 2개 이상 선택하세요.");
				return false;
			}
			
			if($("#intro").val() == "") {
				alert("자기소개를 선택하세요.");
				$("#intro").focus();
				return false;
			}
			if($("#intro").val().length > 100) {
				alert("자기소개를 100자 이내로 입력하세요.");
				$("#intro").focus();
				return false;
			}
			
		});	// submit() end
		
		
	}); */
</script>

</head>
<body>

<form method="post" action="member.jsp">
<table border=1 width=600 align=center>
	<caption>회원 가입폼</caption>
	<tr>
		<th>ID</th>
		<td><input type=text name="id" id="id" autofocus="autofocus">
			<input type="button" value="ID중복검사" id="idcheck">
		</td>
	</tr>
	<tr>
		<th>비밀번호</th>
		<td><input type=password name="passwd" id="passwd">
		</td>
	</tr>
	<tr>
		<th>성명</th>
		<td><input type=text name="name" id="name">
		</td>
	</tr>
	<tr>
		<th>주민번호</th>
		<td><input type=text size=6 maxlength=6 name="jumin1" id="jumin1">-
			<input type=text size=7 maxlength=7 name="jumin2" id="jumin2">
		</td>
	</tr>
	<tr>
		<th>E-Mail</th>
		<td><input type=text size=10 name="mailid" id="mailid">@
			<input type=text size=15 name="domain" id="domain">
			<select id="email">
				<option value="">직접입력</option>
				<option value="naver.com">네이버</option>
				<option value="daum.net">다음</option>
				<option value="nate.com">네이트</option>
				<option value="gmail.com">구글</option>
			</select>
		</td>
	</tr>
	<tr>
		<th>전화번호</th>
		<td>
			<input type=text size=4 maxlength=4 name="tel1" id="tel1">-
			<input type=text size=4 maxlength=4 name="tel2" id="tel2">-
			<input type=text size=4 maxlength=4 name="tel3" id="tel3">
		</td>
	</tr>
	<tr>
		<th>핸드폰</th>
		<td><select name="phone1" id="phone1">
				<option value="">번호선택</option>
				<option value="010">010</option>
				<option value="011">011</option>
				<option value="016">016</option>
				<option value="018">018</option>
				<option value="019">019</option>
			</select>-
			<input type=text size=4 maxlength=4 name="phone2" id="phone2">-
			<input type=text size=4 maxlength=4 name="phone3" id="phone3">
		</td>
	</tr>
	<tr>
		<th>우편번호</th>
		<td><input type=text size=5 maxlenth=5 name="post" id="post">
			<input type="button" value="우편검색" onClick="openDaumPostcode()">
		</td>
	</tr>
	<tr>
		<th>주소</th>
		<td><input type=text size=70 name="address" id="address">
		</td>
	</tr>
	<tr>
		<th>성별</th>
		<td><input type="radio" id="male" name="gender" value="남자">남자
			<input type="radio" id="female" name="gender" value="여자">여자
		</td>
	</tr>
	<tr>
		<th>취미</th>
		<td><input type="checkbox" id="h1" name="hobby" value="공부">공부
			<input type="checkbox" id="h2" name="hobby" value="등산">등산
			<input type="checkbox" id="h3" name="hobby" value="게임">게임
			<input type="checkbox" id="h4" name="hobby" value="낚시">낚시
			<input type="checkbox" id="h5" name="hobby" value="쇼핑">쇼핑
		</td>
	</tr>
	<tr>
		<th>자기소개</th>
		<td><textarea rows="5" cols="70"
				name="intro" id="intro"
				placeholder="자기소개를 100자 이내로 입력하세요"></textarea>
		</td>
	</tr>
	<tr>
		<td colspan=2 align=center>
			<input type="submit" value="회원가입">
			<input type="reset" value="취소">
			
			<!-- 이미지 버튼 : 전송 기능 있음 -->
			<!-- <input type="image" src="img/clock.jpg" width=30> -->
		</td>
	</tr>
</table>
</form>

</body>
</html>

- member.js

	$(document).ready(function(){

		// ID 중복검사
		$("#idcheck").click(function(){
			
			if($("#id").val() == "") {
				alert("ID를 입력하세요.")
				$("#id").focus();
				return false;
			} else {
				// open("팝업창에 실행될 문서명", "윈도우 이름", "옵션");
				var ref="idcheck.jsp?id="+$("#id").val();
				window.open(ref,"mywin","width=250, height=150");
			}
			
		});
		
		// 주민번호 뒷자리로 포커스 이동
		$("#jumin1").keyup(function(){
			
			if($("#jumin1").val().length == 6)
				$("#jumin2").focus();
		});
		
		// 도메인 선택
		$("#email").change(function(){
			if($("#email").val() == "") {	// '직접입력' 선택
				$("#domain").val("").focus();
				$("#domain").attr("readOnly", false);	//읽기 전용 해제
				// $("#domain").removeAttr("readOnly");	// 위와 같다
			}else {							// '도메인' 선택
				$("#domain").val($("#email").val());
				$("#domain").attr("readOnly", "readOnly");	// 읽기 전용
				// $("#domain").attr("readOnly", true)	// 위와 같다
			}
		});
		
		// 유효성 검사
		$("form").submit(function(){
			
			if($("#id").val() == ""){
				alert("ID를 입력하세요.");
				$("#id").focus();
				return false;
			}
			if($("#passwd").val() == ""){
				alert("비밀번호를 입력하세요.");
				$("#passwd").focus();
				return false;
			}
			if($("#name").val() == ""){
				alert("이름을 입력하세요.");
				$("#name").focus();
				return false;
			}
			if($("#jumin1").val() == ""){
				alert("주민번호 앞자리를 입력하세요.");
				$("#jumin1").focus();
				return false;
			}
			if($("#jumin1").val().length != 6){
				alert("주민번호 앞자리 6자리를 입력하세요.");
				$("#jumin1").val("").focus();
				return false;
			}
			// isNaN() : 문자가 포함되면 true를 리턴
			if(isNaN($("#jumin1").val())){
				alert("숫자만 입력하세요.");
				$("#jumin1").val("").focus();
			}
			if($("#jumin2").val() == ""){
				alert("주민번호 뒷자리를 입력하세요.");
				$("#jumin2").focus();
				return false;
			}
			if($("#jumin2").val().length != 7){
				alert("주민번호 뒷자리 7자리를 입력하세요.");
				$("#jumin2").val("").focus();
				return false;
			}
			// isNaN() : 문자가 포함되면 true를 리턴
			if(isNaN($("#jumin2").val())){
				alert("숫자만 입력하세요.");
				$("#jumin2").val("").focus();
			}
			if($("#mailid").val() == ""){
				alert("EMail 주소를 입력하세요.");
				$("#mailid").focus();
				return false;
			}
			if($("#domain").val() == ""){
				alert("도메인명을 입력하세요.");
				$("#domain").focus();
				return false;
			}
			if($("#tel1").val() == ""){
				alert("전화번호 앞자리를 입력하세요.");
				$("#tel1").focus();
				return false;
			}
			if(isNaN($("#tel1").val())){
				alert("숫자만 입력하세요.");
				$("#tel1").val("").focus();
				return false;
			}
			if($("#tel2").val() == ""){
				alert("전화번호 중간자리를 입력하세요.");
				$("#tel2").focus();
				return false;
			}
			if(isNaN($("#tel2").val())){
				alert("숫자만 입력하세요.");
				$("#tel2").val("").focus();
				return false;
			}
			if($("#tel3").val() == ""){
				alert("전화번호 끝자리를 입력하세요.");
				$("#tel3").focus();
				return false;
			}
			if(isNaN($("#tel3").val())){
				alert("숫자만 입력하세요.");
				$("#tel3").val("").focus();
				return false;
			}
			if($("#phone1").val() == "") {
				alert("핸드폰 번호 앞자리를 선택하세요.");
				$("#phone1").focus();
				return false;
			}
			if($("#phone2").val() == "") {
				alert("핸드폰 번호 중간자리를 선택하세요.");
				$("#phone2").focus();
				return false;
			}
			if(isNaN($("#phone2").val())) {
				alert("숫자만 입력하세요.");
				$("#phone2").val().focus();
				return false;
			}
			if($("#phone3").val() == "") {
				alert("핸드폰 번호 뒷자리를 선택하세요.");
				$("#phone3").focus();
				return false;
			}
			if(isNaN($("#phone3").val())) {
				alert("숫자만 입력하세요.");
				$("#phone3").val().focus();
				return false;
			}
			if($("#post").val() == "") {
				alert("우편번호를 선택하세요.");
				$("#post").focus();
				return false;
			}
			if($("#address").val() == "") {
				alert("주소를 선택하세요.");
				$("#address").focus();
				return false;
			}
			if($("#male").is(":checked") == false &&
				$("#female").is(":checked") == false ){
				alert("성별을 선택하세요.");
				return false;
			}
			
//			var cnt = 0;
//			if($("#h1").is(":checked")) cnt++;
//			if($("#h2").is(":checked")) cnt++;
//			if($("#h3").is(":checked")) cnt++;
//			if($("#h4").is(":checked")) cnt++;
//			if($("#h5").is(":checked")) cnt++;
//			
//			if(cnt < 2) {
//				alert("취미를 2개 이상 선택하세요.");
//				return false;
//			}
			
			if($("input:checkbox[name='hobby']:checked").length < 2){
				alert("취미를 2개 이상 선택하세요.");
				return false;
			}
			
			if($("#intro").val() == "") {
				alert("자기소개를 선택하세요.");
				$("#intro").focus();
				return false;
			}
			if($("#intro").val().length > 100) {
				alert("자기소개를 100자 이내로 입력하세요.");
				$("#intro").focus();
				return false;
			}
			
		});	// submit() end
		
		
	});

 

+ '회원가입' 버튼을 누르면 member.jsp 로 값이 넘어가고, 이 양식을 사용해서 JSP 를 공부할때 한다

+ DB의 제약조건에 위배되지 않는 값만 입력되므로 프론트엔드에서 조건에 맞는 값만 전달하도록 하는 것


Ajax

- 비동기적으로 처리하는 통신 기술

- 자주 사용되는 경우가 정해져 있다

ex) ID중복검사 시 팝업창 띄우지 않고 바로 ID중복검사, 댓글달때 페이지를 바꾸지 않고 댓글달기

- ajax.war 파일 다운 후 import 하면 안에 비동기적으로 ID중복검사 하는 것들이 구현되어있음

 

Ajax 정리

- 새로운 언어는 아니다, 자바스크립트가 가진 기본적인 기능

- Asynchronous JavaScript + XML (비동기 자바스크립트와 XML 을 결합한 기술)

- JavaScript와 XML을 이용한 비동기 통신처리를 구현하는 기술

 

동기적 통신 방식

- 클라이언트가 서버측에 요청 후, 서버측에서 응답을 해야만 다음 요청 가능

- 특징 : 페이지가 바뀐다

- action 값으로 지정된 페이지로 post/get 방식으로 요청, 서버측에서는 request 객체로 요청을 받는다(응답), 변수에 저장하고 insert 시킴, 이런 작업이 완전히 끝나야만 다시 요청하고 응답 가능 우리가 쓰고 있는 방법

- 팝업창을 띄우는것도 부모창에서 팝업창으로 페이지가 바뀐 것

 

비동기적 통신 방식

- 클라이언트가 서버에 요청하고, 서버측에서 응답을 하기 전에 (응답이 오기 전에) 클라이언트에서 또 요청을 할 수 있다

- 특징 : 페이지가 바뀌지 않는다

- 페이지를 바꾸지 않고, 콜백함수로 결과를 돌려받아서 사용가능/사용중 메세지 뿌림

 

 

XML

- 클라이언트가 요청하면 서버측에서 결과를 돌려줄때 xml 형태로 결과를 많이 돌려줌

- 일반적인 태그와 다른 점은 태그들을 직접 임의로 만들어 쓸 수 있다는 점

- 지금은 xml 을 대신하는 포멧으로 json 을 많이 쓴다

- xml 과 json은 데이터 포멧, 저장 포멧이다

- 공공데이터는 xml 이나 json 중 하나로 많이 돌려줌

ex) 기상청 날씨정보는 xml 로 많이 돌려준다, 그걸 조작해서 필요한 형태로 바꿔서 사용하는 것

+ 직접 xml 파일을 만드는 경우는 적다, 문법은 공부할 것

 

JSON

- JavaScript Object Notation

- 자바스크립트 객체를 표기하기 위한 표기법 중 한가지, 새로운 언어가 아님

 - JSON은 JavaScript Object Notation 의 약어로 XML 데이터를 대신하기 위해서 사용된다.
- JSON은 키와 값을 쌍으로 가지는 구조이다, 자바의 Map 자료구조와 비슷

- 자바에선 Map, 파이썬에선 딕셔너리, Javascript 에선 JSON
- 배열을 사용할 때는 대괄호([ ])안에 중괄호({ })를 사용하여 조합한다.
- jQuery에서는 JSON으로 표현한 데이터를 파일에 저장해 두었다가 필요할 때 이를 로드할 수 있는  $.getJSON()함수를 제공한다.

- 비동기적으로 서버에 요청하고, 콜백함수를 통해 결과를 돌려받을때 사용

 

jQUery 지원 함수

- 아래 함수 모두 비동기적으로 서버측에 요청을 하는 함수이고 콜백함수를 통해 결과를 받을 수 있는 함수이다

$.ajax() : get 방식으로 요청할지, post 함수로 요청할지 선택 가능
$.get() : get 방식으로 서버측에 비동기로 요청하는 함수 / get 방식으로 Ajax을 수행한다.
$.post() : post 방식으로 서버측에 비동기로 요청하는 함수 / post 방식으로 Ajax을 수행한다.
$.getJSON() : get 방식으로 서버측에 요청하고 (Ajax를 수행하고) JSON 데이터를 가져온다.
$.getScript() : get 방식으로 (Ajax를 수행하고) Script 데이터를 가져온다.
$(selector).load() : Ajax를 수행한 후에 선택한 문서 객체안에 응답받을 파일(문자열)을 불러온다 / load() 안에 쓰인 파일명의 문서를 한꺼번에 불러와서 앞의 선택자 자리에 출력시킴

* Ajax 를 수행 = 서버측에 요청하고 응답을 받음

- 이 함수들로 서버측에 비동기적으로 요청

- 사용 예시

$.ajax({
    url : "전송 페이지",
    type : "전송 방식(get, post방식),
    data : "전송할 데이터(값 가져갈때/json 형태 키밸류형태로 전달)",
    dataType : "요청한 데이터 타입("html","xml","json","text"),
    success : function(result){ 전송 성공하면 실행될 문장; // 응답을 받는 곳 이 함수를 콜백함수라고 함
   }
});

- 콜백함수의 매개변수 result 로 값을 돌려받음

- 이 값을 조작해서 사용해야함
+ React 등 언어가 바뀌더라도 비동기로 처리해야하는 기술들은 익혀야함

 - Ajax 실습 준비

- 다 설명한 후 Ajax(6) 폴더 안의 ajax.war 파일을 다운받아 import 하면 구현 되어있다

 

비동기로 서버에 요청하는 함수

load() 함수

- $("출력시킬 태그").load("요청할 파일명");

- 특정 서버측의 문서를 불러옴, 안에는 특정 파일명이 들어간다

- 서버측에 비동기적으로 요청하고, 서버측의 지정된 파일의 내용을 모두 불러와서 앞의 태그에 결과 출력 시켜주는 역할

 

Ajax 예제 1

load() 함수 예제 1

 

- sample1.html

<!DOCTYPE html>
<html>
<head>
	<title>sample1</title>
	<meta charset="UTF-8">
		
		<script src="http://code.jquery.com/jquery-1.11.1.js">
		</script>

		<script type="text/javascript">

$(function(){
	$("button").click(function(){
		// sample1.txt 파일의 결과를 load 함수로 불러와서 p 태그 사이에 출력
		$("p").load("sample1.txt");
	});
});
		</script>
	</head>
	<body>
		<button>변경</button>
		<p>변경전</p>
	</body>
</html>

sample1.txt 내용

+ jQuery 라이브러리를 불러옴, 버튼이 클릭되어 click 이벤트 발생시 안의 내용 실행

- 페이지를 바꾸지 않고 load() 함수를 이용해서 서버에 sample1.txt 란 파일을 요청을 함

- 그럼 sample1.txt 파일의 내용을 모두 불러와서 앞쪽의 선택한 태그 안에 출력시켜라는 의미

- sample1.txt 가 브라우저에 출력되는 결과(내용)를 load() 로 불러와서 p 태그 안에 출력

- load() 함수 : 서버측의 지정된 파일의 내용을 모두 불러와서 앞의 태그에 결과 출력 시켜주는 역할, 비동기적으로 요청해주는 함수

 

+ 나중엔 sample1.txt 자리에 jsp 파일이나 html 파일 등 들어감

 

Ajax 예제 2

load() 함수 예제 2

- sample09_02.html

- 이전의 예제와 다른 점 : sample1.txt 대신 resource.html 파일을 불러오고 있다

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>서버의 데이터를 대상 엘리먼트에 삽입하기</title>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>

<script type="text/javascript">
$(function() {	
	$('button').click(function() {
		// resource.html 파일의 출력 결과를 load함수로 불러와서 div영역에 출력
		$('#container').load('resource.html');
	});   
});
</script>

</head>
<body>
	<button> 서버로부터 데이터 가져오기 </button>
	<div id="container"> 데이터 가져오기 전 </div>
</body>
</html>

resource.html 내용

- resource.html 을 불러오면 이 resource.html 파일이 브라우저에 출력되는 내용(결과)을 load() 함수로 불러와서 id값이 container인 div 태그 영역에 출력된다.

- load() 함수로 resource.html 의 내용을 불러와서 출력해줌

- 비동기로 요청하거 있으므로 페이지가 바뀌지 않음

 

Ajax 예제 3

load() 함수 예제 3

- 파일 내용 중 특정 태그의 내용만 불러오기

- sample09_03.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>서버의 데이터를 대상 엘리먼트에 삽입하기</title>
<style type="text/css">
div {
  width: 180px;  height: 80px;
  margin: 3px;   float: left;
}
</style>
<script src="http://code.jquery.com/jquery-1.11.1.js" type="text/javascript"></script>
<script type="text/javascript">

/*
	- jQuery에서 제공해주는 load()함수를 사용해서 서버의 menu.html 페이지의 데이터를 가져와서 특정 엘리먼트에 추가한다.
*/

$(function() {	
	   $('#menu1').click(function () {           
		  	 $('#message1').load('menu.html');     // load()함수를 이용해서 menu.html 문서전체를 로드하여 id가 message1인
		  	 return false;						   // 엘리먼트에 추가한다.
		});
	   
	   $('#menu2').click(function () {          
		  	 $('#message2').load('menu.html li'); // load()함수를 이용해서 menu.html 문서의 내용중 li 엘리먼트만 읽어서 id가
			 return false;                        // message2인 엘리먼트에 추가한다.
		});
});
</script>
</head>
<body>
<div>
	<a href="#" id="menu1">메뉴 보기 1</a><p>
	<span id="message1"></span>
</div>
<div>
	<a href="#" id="menu2">메뉴 보기 2</a><p>
	<span id="message2"></span>
</div>	
</body>
</html>

menu.html 내용

- '메뉴 보기1' 과 '메뉴 보기 2' 를 a 태그로 링크를 걸어둠, a 태그 구분을 위해 id 값을 설정

- '메뉴 보기1' 을 클릭시 click() 함수 안에서 load() 함수를 통해 menu.html 전체 내용을 불러와서 id값이 message1 인 span 태그 사이에 출력

		  	 $('#message1').load('menu.html');

- '메뉴 보기2' 을 클릭시 click() 함수 안에서 load() 함수를 통해 menu.html 중에서 li 태그에 있는 내용만 불러와서 id값이 message2 인 span 태그 사이에 출력

		  	 $('#message2').load('menu.html li');

- menu.html 다음 한칸 띄우고 태그명을 쓰면 -> menu.html 내용 중에서 그 태그(li 태그)만 load() 함수로 불러온다

- 한칸 띄운다는 건 자손태그를 의미

+ return false; 를 통해 클릭을 해도 하이퍼링크가 실행되지 않도록 막아줌

- 비동기로 요청하거 있으므로 페이지가 바뀌지 않음

- menu.html 파일의 모든 내용을 불러와서 출력

- menu.html 파일의 내용 중 일부만 불러와서 출력 (li 태그 안의 내용만 불러와서 출력)

- 비동기로 요청하거 있으므로 페이지가 바뀌지 않음

 

비동기로 서버에 요청하는 함수

$.ajax() 함수

- load() 함수와 다르게 많은 옵션들이 있다, 다양한 기능 쓸 수 있다

ex) 옵션들

- ajax() 함수 특징 :  get 방식으로 요청할지 post 방식으로 요청할지 type : 에서 선택 가능

 

 

Ajax 예제 4

ajax() 함수 예제 1

- Ajax 요청 직접 제어하기

- ajax() 함수로 요청 하고 값을 받기

- load() 함수로 처리했던 것과 같은 결과를 ajax() 로 처리

- sample09_04.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>서버의 데이터를 대상 엘리먼트에 삽입하기</title>
<style type="text/css">
div {
  width: 200px;  height: 80px;
  margin: 3px;  float: left;
}
</style>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript">

/*
	- load()를 이용했던 예제를 $.ajax() 함수를 사용해서 구현
	- $.ajax()함수는 Ajax 요청을 설정하고 제어할 수 있도록 jQuery에서 제공하는 유틸리티 함수이다.i

*/

$(function() {	

/*   
	- $.ajax()함수를 실행할 때 옵션으로 URL값(menu.html)을 지정하면 해당 URL서버로 Ajax요청을 한다.
	- success 옵션에 지정한 콜백함수(function(data))는 요청이 성공했을 때 호출된다.
    - 서버로부터 응답받은 데이터는 콜백함수의 매개변수로 전달된다.
	- $.ajax()함수는 서버에서 반환되는 데이터의 형식에 따라 다르게 동작한다.
	  서버측에서 html데이터를 반환하면 html을 받아와 처리하기 위해서 데이터 타입(dateType) 옵션에 html을 지정한다.
*/
	   $('#menu1').click(function () {     
		   $.ajax({								
			    url:'menu.html', // 서버의 불러올 파일명
			    dataType:"html",
			    success: function(data){        // 서버로부터 응답받은 데이터는 콜백함수의 매개변수로 전달된다.
			    	$('#message1').html(data);  // 콜백함수로 전달된 data를 id가 message1인 엘리먼트에 설정한다.
			    }
		   });
		   return false;   
		});
	   
	   $('#menu2').click(function () {   
		   $.ajax({
			    url:'menu.html',
			    dataType:"html",
			    success: function(data){	     // 서버로부터 응답받은 데이터는 콜백함수의 매개변수로 전달된다.	    	
		$('#message2').html($(data).find('li')); // menu.html문서의 내용중 li엘리먼트만 읽어서 id가 message2인
			    }										     // 엘리먼트에 설정한다.
		    });
			return false;   
		});
});
</script>
</head>
<body>
<div>
	<a href="#" id="menu1">메뉴 보기 1</a><p>
	<span id="message1"></span>
</div>
<div>
	<a href="#" id="menu2">메뉴 보기 2</a><p>
	<span id="message2"></span>
</div>	
</body>
</html>

 

ajax 함수 (sample09_04.html '메뉴 보기 1' 부분)

		   $.ajax({								
			    url:'menu.html', // 서버의 불러올 파일명
			    dataType:"html",
			    success: function(data){        // 서버로부터 응답받은 데이터는 콜백함수의 매개변수로 전달된다.
			    	$('#message1').html(data);  // 콜백함수로 전달된 data를 id가 message1인 엘리먼트에 설정한다.
			    }
		   });

- $.ajax({ }); 형태 안에 옵션들을 넣는다

- url 다음에는 서버에 요청할 파일명, 여기선 menu.html 파일을 서버에 요청한다

- dataType 다음에 쓰는 것은 요청할 파일의 확장자가 html 파일이므로 dataType을 html으로 쓴다

- type 에서 어떤 전송 방식을 사용할지 설정

- type 이 생략되면 디폴트는 get 방식

- 서버에 요청을 하고 값(응답)을 잘 받으면 success 다음의 내용이 실행된다

- success 옆의 function 을 callback 함수라고 함, 그리고 매개변수 (임의의 이름) data 로 값을 돌려받음

- 돌려받는 값은 menu.html 파일의 내용 중에 브라우저에 출력되는 값, 즉 전체내용을 콜백함수로 돌려받음

 

콜백함수로부터 값을 잘 돌려받았는지 확인하기위해 alert 코드 추가

- 이 매개변수 data 가 돌려받은 값임

- 결과 캡처

- 이렇게 돌려받은 데이터를 조작해서 뿌려줘야함

- 이떄 뿌려주는 코드는

- 안의 태그를 인식해야하므로 html() 함수를 사용해서 앞의 선택된 태그 영역에 뿌려줌

 

+ html() 함수는 안의 html 태그를 인식하고 <li></li> 를 디스크 모양으로 출력

+ text() 함수는 html 태그 인식불가하고 <li></li>까지 그대로 출력

 

ajax 함수 (sample09_04.html '메뉴 보기 2' 부분)

		   $.ajax({
			    url:'menu.html',
			    dataType:"html",
			    success: function(data){	     // 서버로부터 응답받은 데이터는 콜백함수의 매개변수로 전달된다.
			    	alert(data);
					$('#message2').html($(data).find('li')); 
					// menu.html문서의 내용중 li엘리먼트만 읽어서 id가 message2인 엘리먼트에 설정한다.
			    }										    
		    });

- url : 요청할 파일명, 돌려받는 값은 브라우저에 출력되는 전체 내용을 통째로 콜백함수를 통해 돌려받음

<콜백함수 내부>

- find() 함수 : 특정 태그를 찾는 함수

- data 중에서 즉 menu.html 전체 내용 중에서 li 태그만 찾아서 id값이 message2인 span 태그 사이에 뿌려라는 의미

 

콜백함수로부터 값을 잘 돌려받았는지 확인하기위해 alert 코드 추가

- 이 매개변수 data 가 돌려받은 값임

 

- 결과 캡처

 

- load() 함수로 처리했던 것과 같은 결과를 ajax() 로 처리

 

+ load() 함수로 특정 태그만의 내용을 불러올 때는 load('menu.html li'); 로 불러오기

+ ajax() 함수로 특정 태그만의 내용을 불러올 때는 $(data).find('li') 함수 사용

 

xml 파일 만드는 규칙

- item.xml 파일 열어보기

- 태그들이 정해진 것이 아니라 만들 수 있고 바꿀 수 있다

- xml 파일의 시작

<?xml version="1.0" encoding="UTF-8"?>

- 가장 바깥쪽에 해당되는 태그(엘리먼트)가 반드시 "1개" 있어야한다 = 루트 엘리먼트

- 0개도 2개도 아닌 딱 1개여야 한다

<?xml version="1.0" encoding="UTF-8"?>
<items>
</items>

- 여기선 items 가 루트 엘리먼트

- 그 루트 엘리먼트 안에 부모 엘리먼트인 item 들이 있다

<?xml version="1.0" encoding="UTF-8"?>
<items>
  <item id="1" name="레몬">
    <price>3000</price>
    <description> 레몬에 포함되어 있는 쿠엔산은 피로회복에 좋다. 비타민C도 풍부하다. </description>
   </item>
   
   <item id="2" name="키위">
    <price>2000</price>
    <description> 비타민C가 매우 풍부하다. 다이에트와 미용에도 매우 좋다. </description>
   </item>
</items>

- 그 부모 엘리먼트 안에 child element 들이 있다

- 아이디 값을 구분하기 위해 item id 가 1,2,3,4.. 로 설정되어있다

- web.xml 파일 열어보기 ( 환경설정 파일)

 

- xml 주석기호는 html 주석기호와 같다

- server.xml (아파치톰캣 환경설정 파일) 열어보기

 

xml 파일 사용

- 직접 작성하는 일은 많지 않다

- 공공데이터 요청시 xml 형태로 결과를 돌려준다

ex) 기상청 날씨정보 요청

- 이렇게 xml 파일 형태로 돌려받은 값을 가공, 조작해서 사용해야함 (Javascript, Java, Python 등으로 조작)

 

비동기로 서버에 요청하는 함수

$.get() 함수

- get 방식으로만 요청 가능하다

- 형식 : 

 $.get('item.xml', function(data) {
     });

- 처음 들어가는건 서버에 요청할 파일명

- 두번째 매개변수로 들어가는 function 이 콜백함수이다

 

Ajax 예제 5

get() 함수 예제 1

- XML 파일을 get 방식으로 로드하기

- XML 파일을 요청을 하면 XML 로 결과를 돌려받음

- 요청할 파일명은 item.xml, 이 파일을 콜백함수로 받아서 처리하게됨

- 돌려받은 xml 데이터를 조작해서  필요한 형태로 출력하고 있다

item.xml 내용

- sample09_07.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>XML 파일을 GET 방식으로 로드하기</title>
<style>
td { border: 1px solid gray;
}
</style>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script type="text/javascript">
/*
	- $.get() 함수를 이용해서 item.xml 파일을 불러온다.
    - $.get() 함수의 첫번째 매개변수에는 서버의 URL 주소를 지정한다.
	- $.get() 함수의 두번째 매개변수인 콜백함수를 이용해서 서버에서 보내온 XML 형식의 데이터를 data 로 받늗다.
*/

$(function() {
	 $.get('item.xml', function(data) {
             $("#treeData").append(
                    "<tr><td>id</td>" + "<td>name</td>" 
                  + "<td>price</td>" + "<td>description</td>" + "</tr>");
             $(data).find('item').each(function() {			// 서버에서 얻어온 데이터에서 셀렉터로 item태그를 찾는다.
            	 var $item = $(this);						   // 6개의 item태그중 현재 처리중인 item태그를 this로 접근한후에 이를
                 $("#treeData").append("<tr>" + "<td>"        // this로 접근한 후에 이를 $(this)를 사용하여 jQuery객체를        
                         + $item.attr("id") + "</td>" + "<td>" //생성함  
                         + $item.attr("name") + "</td>" + "<td align='right'>"
                         + $item.find("price").text() + "</td>" + "<td>"
                         + $item.find("description").text() + "</td>" + "</tr>");
             });
    });
});
</script>
</head>
<body>
  <table id="treeData"></table>
</body>
</html>

- 두번째 매개변수는 콜백함수이다

- $.get() 함수를 통해 서버에 서버측의 파일 중 'item.xml' 파일을 요청하고 'item.xml' 파일을 돌려받고 있다

- 콜백함수의 매개변수 data 로 xml 형식의 데이터를 돌려받았다

- body 태그 안에 table 태그 하나뿐, 이 table 태그의 id값만을 가지고 태그를 구해서 tr td 를 만들어서 데이터를 뿌려줄 것

- 테이블 태그를 id값으로 구해와서 append() 함수로 타이틀을 출력, id, name, pirce, descript  추가

- 타이틀이 아닌 돌려받은 데이터의 내용은 가공해야함

 

each() 함수

- 반복적인 작업을 수행하는 함수

- 첫번째 데이터를 가져오고 반복적인 작업을 하고 두번쨰 데이터를 가져오고 반복적인 작업을 하고..

- 더이상 데이터가 없을때까지 가져와서 반복작업 

 

돌려받은 xml 을 원하는 형태로 가공 (sample09_07.html 부분)

             $(data).find('item').each(function() {			// 서버에서 얻어온 데이터에서 셀렉터로 item태그를 찾는다.
            	 var $item = $(this);						   // 6개의 item태그중 현재 처리중인 item태그를 this로 접근한후에 이를
                 $("#treeData").append("<tr>" + "<td>"        // this로 접근한 후에 이를 $(this)를 사용하여 jQuery객체를        
                         + $item.attr("id") + "</td>" + "<td>" //생성함  
                         + $item.attr("name") + "</td>" + "<td align='right'>"
                         + $item.find("price").text() + "</td>" + "<td>"
                         + $item.find("description").text() + "</td>" + "</tr>");
             });

 

 

- 여기서는 $(data).find('item') 이므로 가져온 xml 형식 데이터에서 부모 엘리먼트인 item 태그를 한개씩 계속 구해온다

1. attr() 함수로 속성 가져오기

- 첫번쨰 item 태그인 레몬을 가져와서 $item 변수에 넣고, 그 태그의 속성을 attr() 함수로 가져온다

ex) 먼저 id 속성의 값을 가져옴 -> 1, 다음은 name 속성의 값을 가져옴 -> 레몬

- 이렇게 구해온 값을 <td> 를 열어서 append() 함수로 추가하고 있다

 

2. find() 함수로 태그 찾아서 가져오기

- 세번째로 pirce 란 태그를 구해와야하는데 price는 item 태그의 속성이 아닌 item 안에 있는 자식 Element 임, find() 함수로 price태그를 찾는다

- 이때 찾은 그 자식 태그 사이의 값만 구할땐 text() 로 구해옴

- 네번쨰로 discription 란 태그를 구해야하므로 특정 태그를 찾아주는 find() 함수로 discription 태그를 찾아서 그 안의 값을 가졍괴 위해 text() 로 값을 가져옴

- 이렇게 구해온 값을 <td></td> 안으로 뿌려줌

 

- 다음으로, each() 함수에 의해 다음 item 태그인 키위를 가져와서 $item 변수에 넣고 그 태그의 속성과 자식태그들 사이의  값을 가져오고 다시 <tr> 이 열리며 값을 출력함

- 계속 다음 item 으로 넘어가면서 반복됨

- item 이 없을때까지 반복작업한다

 

- 돌려받은 xml 데이터를 조작해서  필요한 형태로 출력하고 있다

 

each() 함수

- 반복적인 작업을 수행하는 함수

- 첫번째 데이터를 가져오고 반복적인 작업을 하고 두번쨰 데이터를 가져오고 반복적인 작업을 하고..

- 더이상 데이터가 없을때까지 가져와서 반복작업 

 

each() 함수 예제 1

- each01.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>배열을 반복 처리하기</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
  $(function() {
    var list = ['Jessica', 'Tiffany', 'Sunny', 'crystal', 'G.NA']
  
    $.each(list, function(index, value) {
    	alert(index+":"+value);
		$('ol').append('<li>'+value+'</li>');
	});   
    
  });
</script>
</head>
<body>
  <ol>
  </ol>
</body>
</html>

- Javascript 배열 정의하는 방법 var list = [ ] 안에 값을 넣으면 됨 

- 반복문 대신 $.each() 함수로 배열의 값을 차례로 가져와서 출력해보자

$.each(list, function(index, value){});

- index 는 배열 list 에 들어있는 값의 인덱스 번호를 받고

- value 는 이 배열 list 에 들어있는 값을 받음

+ alert 이 우선순위가 높으므로 alert 이 다 출력된 후 해당 목록들을 append 함수로 추가함

- 배열 방번호는 0 번부터 시작하므로 번호가 이렇게 뜸

- alert 이 우선순위가 높으므로 모두 alert 한 후 append 됨

 

each() 함수 예제 2

- each02.html

<!DOCTYPE html>
<html>
<head>
    <script src="http://code.jquery.com/jquery-1.10.2.js"></script>
    <script>
	// each() 메소드 : 매개변수로 입력한 함수를 사용해 for in 반복문처럼 객체나
	//               배열의 요소를 검사하는 메소드

        $(document).ready(function () {
            // 변수를 선언합니다.
            var array = [
                { name: 'Hanbit Media', link: 'http://hanb.co.kr' },
                { name: 'Naver', link: 'http://naver.com' },
                { name: 'Daum', link: 'http://daum.net' },
                { name: 'Paran', link: 'http://paran.com' }
            ];

            // $.each() 메서드를 사용합니다.
            $.each(array, function (index, item) {
                // 변수를 선언합니다.
                var output = '';

                // 문자열을 만듭니다.
                output += '<a href="' + item.link + '">';
                output += '    <h1>' + item.name + '</h1>';
                output += '</a>';

                // 집어넣습니다.
                document.body.innerHTML += output;
            });
        });
    </script>
</head>
<body>

</body>
</html>

- body 태그 안엔 아무 내용이 없다, jQuery 에서 구현할 것

 

+ Javascript 배열 만들기 / json 형태

- 0 번방에 들어갈 값은 {}

- 1 번방에 들어갈 값은 다음 {}

- json 형태로 되어있다

- Javascript 에서 키-밸류 형태 를 json 이라고 한다

- 중괄호 { } 안에 키 : 밸류 형태로 되어있음, 키 값을 알아야만 밸류를 구해올 수 있다

- 키값은 name 과 link

 

each() 로 배열의 값들을 하나씩 처리

- index 란 매개변수는 array 배열의 인덱스번호를 한개씩 전달받음

- item 이란 매개변수는 배열 안의 데이터들을 한개씩 전달받음

- 이게 통째로 item 변수에 들어간다

- 그리고 item.link 와 item.name 을 통해서 데이터를 가져옴

- 즉 키값을 통해서 value 값을 가져온다

- 가져와서 태그로 감싼 후 계속해서 +=로 output 변수에 누적시킨다

- 그 후 innerHTML 속성을 사용해서 output 변수의 값을 누적해서 집어넣음

- document.body.innerHTML 은 Javascript 기능으로서, 앞의 innerHTML 앞에 body 를 쓰면 body 태그 사이에  출력시켜라는 의미이다

 

+ jQuery 식으로 출력하기

- body 태그안에 div 를 만들어서 영역만 만들기

- var output 변수 선언을 each() 함수 바깥 위쪽으로 옮기기

- each() 함수 바깥 아래에서 html() 함수로 output 변수에 누적된 결과를 출력

+ 태그를 인식해야하므로 html() 함수 사용

 

- 그럼 브라우저에는 이렇게 출력된다

- 결과 캡처

 

+ alert()로 output 변수에 어떤 값이 있는지 찍어보면

 

 

JSON 형태 예시

- 이게 json 형태 (키:밸류 형태) 이다

 

공공데이터 데이터 제공 예시

https://www.data.go.kr

 

공공데이터 포털

국가에서 보유하고 있는 다양한 데이터를『공공데이터의 제공 및 이용 활성화에 관한 법률(제11956호)』에 따라 개방하여 국민들이 보다 쉽고 용이하게 공유•활용할 수 있도록 공공데이터(Datase

www.data.go.kr

 

- xml 형태로 되어있다

- json 형태로 되어있다

복습

+ AJAX

- 비동기적으로 요청하고 콜백함수로 값을 받아 처리

- AJAX 는 비동기적으로 통신, 팝업창을 띄우지 않고 ID 중복검사 가능

- 페이지를 바꾸지 않고 댓글을 달면 댓글이 바로 insert 되게함

 

* 동기적 방식= 서버측에 요청시 서버가 응답하고 응답이 끝나야만 그 다음 요청 가능

- 동기적 방식 = 유효성 검사시 팝업창을 띄워서 유효성 검사를 했었다

- 동기적인 방식으로 요청시 주로 페이지가 바뀐다(팝업창으로 페이지가 바뀜)

 

text() 함수 vs val() 함수

- text() : 입력양식 외에도 특정 태그 사이의 값을 구해오거나 설정

- val() : 입력양식 / 선택양식에만 사용 가능

 

focus() 함수 & blur() 함수

- focus() : 포커스를 준다

- blur() : 포커스 아웃되었을때 발생

 

$(this)

- 이벤트를 발생시킨 태그

ex)

$("input").focus(function() {
	$(this).val("").css("color","#000");
});

- 여기서 this 는 focus 이벤트가 발생한 태그

 

필터선택자

- 특정태그만 선택적으로 구해오고 싶을때 사용

 

: input 필터선택자

- 입력 폼 태그 전부 한꺼번에 선택할 수 있는 필터 ex) input, select, textarea, button

 

: text 필터선택자

- input type 속성값이 text 인 input 태그만을 모두 선택하는 필터

 

: password 필터선택자

- input type 속성값이 password 인 input 태그만을 모두 선택하는 필터

 

after() vs append()

- after() : 특정 태그에 요소 추가, 형제 요소로 추가

- append() : 특정 태그에 요소 추가, 자식 요소로 추가

 

remove() 함수

- 선택한 요소(태그)를 HTML 에서 제거

ex)

$( "p" ).remove();

- 선택된 태그인 p 태그가 삭제됨

 

jQuery form 태그 관련 함수 예제

- 폼에서 자주 쓰는 기능들

이미 들어가 있다, 지난시간 내용 이어서


jQuery 예제 35

jQuery form 태그 관련 함수 예제 10

- 라디오 버튼을 선택하는 :radio 필터선택자

- sample12.html

<!DOCTYPE html>
<html>
	<head>
	    <meta charset="UTF-8">
		<title>sample12</title>
		<script src="jquery-1.6.4.min.js"></script>

		<script type="text/javascript">

$(function(){
	// :radio 는 input type=radio 버튼을 모두 구해오는 필터 선택자
	$(":radio").click(function(){
		$("label").css("font-weight","");
		$("label[for='"+$(this).attr("id")+"']").css("font-weight","bold");
	});

	$("label").click(function(){
		$("label").css("font-weight","");
		$(this).css("font-weight","bold");
	});

});

		</script>
	</head>
	<body>
		성별:
		<input type="radio" name="gender" 
		value="남자" id="gender_man" />
		<label for="gender_man">남자</label>

		<input type="radio" name="gender" 
		value="여자" id="gender_woman" />
		<label for="gender_woman">여자</label>

	</body>
</html>

- input type 속성값이 radio 인 모든 태그만을 구해온다.

- 라디오 버튼을 클릭시 click 이벤트가 발생한다

- 라디오 버튼을 클릭시 모든 label 을 구해와서 font-weight 를 ""로 설정한다, 즉 기존에 bold 되어있던 것을 해제하는 것

- 라디오 버튼의 id 값과 label 태그의 for 값은 같은 값이어야 한다

+ radio 버튼은 name 값이 동일해야하고, id 값은 서로 다르게 설정해야함

- 또한 버튼이 아닌 레이블 태그를 선택해도 해당 레이블에 bold 를 적용시킨다

 

사용자가 선택한 라디오 버튼에 해당하는 레이블 구하기 (sample12.html 부분)

	$("label[for='"+$(this).attr("id")+"']").css("font-weight","bold");

 

-  label 태그의 for 속성을 불러오는데, for 속성값이 $(this).attr("id") 인, 즉 "gender_man" 인 label 태그를 구해옴

- 이때, $(this) 는 '남자' 에 해당하는 input 태그를 의미하고, attr("id")를 통해 그 input 태그의 id 속성을 구하면 "gender_man" 이다

- 그 label 태그에 대해 bold 를 적용하고 있다

- 라디오 버튼의 id 값과 label 태그의 for 값이 같은 값이어야 가능하고 보통 같은값으로 설정

 

+ $("요소 선택[속성=값]") 는 속성 선택자 중 하나, 해당 요소 중 어떤 속성의 값이 특정값일때만 그 태그를 구해온다.

 

- 또한 버튼대신 레이블을 눌러도 똑같이 레이블이 bold 가 됨

 

 

+ 라디오 버튼에도 change 이벤트 발생

 

jQuery 예제 36

jQuery form 태그 관련 함수 예제 11

-  체크박스를 모두 구해오는 :checkbox 필터선택자

- input type=reset 인 모든 태그를 구해오는 :reset 필터선택자

- sample14.html

<!DOCTYPE html>
<html>
	<head>
	    <meta charset="UTF-8">
		<title>sample14</title>
		<script src="jquery-1.6.4.min.js"></script>

		<script type="text/javascript">
// :checkbox 는 input type=checkbox 로 되어있는 태그를 모두 구해오는 필터 선택자

$(function(){

	$("button").click(function(){	// '전부체크' 버튼
		$(":checkbox").attr("checked","checked");
	});

// :rest 은 input type=reset 로 되어있는 태그를 모두 구해오는 필터 선택자
	$(":reset").click(function(){	// '전부해제' 버튼
		$(":checkbox").attr("checked",false);
	});

});

		</script>
	</head>
	<body>
스킬:
<input type="checkbox" name="xhtml" value="XHTML" id="xhtml"/>
<label for="xhtml">XHTML</label>

<input type="checkbox" name="css" value="CSS" id="css" />
<label for="css">CSS</label>

<input type="checkbox" name="javascript"
value="JavaScript" id="javascript" />
<label for="javascript">JavaScript</label>

<input type="checkbox" name="php" value="PHP" id="php" />
<label for="php">PHP</label>

<p><button> 전부체크</button></p>
   <input type="reset" value="전부 해제">

	</body>
</html>

<'전부체크' 버튼>

- :checkbox 는 input type 속성값이 checkbox 인 태그만을 모두 구해오는 필터선택자

- 모두 동의하기 누르면 모든 체크박스에 체크가 되게 하는 기능등에 활용 가능.

- 이때, 모든 input type = checkbox 태그를 구해와야함

- :checkbox 로 모든 체크박스를 구해오고 attr() 을 통해 checked 속성값을 checked 로 설정한다

- input type = "checkbox 에서 checked = "checked" 시 체크되므로 그럼 모든 체크박스가 효율적으로 선택됨

<'전부해제' 버튼>

- :reset 은 input type 속성값이 reset 인 태그를 모두 구해오라는 필터선택자

- input type=reset 인 태그를 구해와서 click 이벤트를 처리

- 클릭시 모든 checkbox 를 구해와서 attr() 로 checked=false 로 설정함으로서 모든 체크박스의 체크가 해제됨

 

+ jQuery 에서 전부해제 하는 이벤트를 처리하고 있으므로 input type=reset 일 필요는 없다, 속성값이 button 이어도 가능, 그럼 id 값이나 다른 방법으로 태그를 구해와서 체크해제 이벤트를 처리하면 된다

+ CSS 적용을 위해 라디오 input 태그의 id값과 label 태그의 for 값을 같은값으로 설정한다

 

 

jQuery 예제 37

jQuery form 태그 관련 함수 예제 12

- sample14.html 와 같은 기능이지만 다른 방법 코드

- removeAttr() 함수 : 속성을 제거해줌

- sample14-1.html 중 sample14.html 과 다른 부분만

	$(":reset").click(function(){
//		$(":checkbox").attr("checked",false);
		$(":checkbox").removeAttr("checked");
	});

- '전부해제' 기능을 다르게 구현

- attr() 을 통해 checked 속성을 false로 설정한게 첫번째 방법이고, 여기선 removeAttr() 함수를 사용해서 checked 란 속성(attribute) 을 제거해줌

 

- 사진 없음 (sample14.html 와 같은 기능)

 

jQuery 예제 38

jQuery form 태그 관련 함수 예제 13

- 전송버튼을 모두 구해오는 :submit 필터선택자

- sample15.html

<!DOCTYPE html>
<html>
	<head>
	    <meta charset="UTF-8">
		<title>sample15</title>
		<script src="jquery-1.6.4.min.js"></script>

		<script type="text/javascript">
// :submit 은 input type=submit 으로 되어있는 태그를 구해오는 필터 선택자

$(function(){

	$(":submit").mouseover(function(){
		$(this).after("<p>입력한 내용을 서버로 전송합니다.</p>");
	}).mouseout(function(){
		$("p").remove();
	});

});

		</script>
	</head>
	<body>
<dl>
<dt>이름<em>(필수)</em></dt>
<dd><input type="text" name="name" /></dd>

<dt>코멘트</dt>
<dd>
<textarea name="comment"></textarea>
</dd>

<dd><input type="submit" value="전송" /></dd>
</dl>

	</body>
</html>

- :submit 는 input type 속성값이 submit 인 태그만을, 즉 전송버튼을 모두 구해오는 필터선택자

- 모든 전송버튼을 구해와서 mouseover 이벤트와 mouseout 이벤트를 처리하고 있다

- mouseover() 에서 해당 버튼에 마우스 오버시 after() 함수를 통해 안의 내용(태그)을 형제요소로 추가하고 있다

 

 

jQuery 예제 39

jQuery form 태그 관련 함수 예제 14

- 이미지를 구해오는 :image 필터선택자

- sample16.html

<!DOCTYPE html>
<html>
	<head>
	    <meta charset="UTF-8">
		<title>sample16</title>
		<script src="jquery-1.6.4.min.js"></script>

		<script type="text/javascript">
// :image 은 input type=image 로 되어있는 태그를 구해오는 필터 선택자

$(function(){

	$(":image").mouseover(function(){
		$(this).attr("src","button_on.jpg");
	}).mouseout(function(){
		$(this).attr("src","button.jpg");
	});

});

		</script>
	</head>
	<body>
<dl>
        <dt>이름<em>(필수)</em></dt>
        <dd><input type="text" name="name" /></dd>
        <dt>코멘트</dt>
        <dd>
                <textarea name="comment"></textarea>
        </dd>
        <dd><input type="image" src="button.jpg" alt="전송" /></dd>
</dl>

	</body>
</html>

- :image는 input type 속성값이 image인 태그만을 모두 구해오는 필터선택자

- 여기선 이미지버튼을 만들어서, mouseover 와 mouseout 시 다른 이미지를 src 속성값으로 설정하고 있다

+ 초기 상태 버튼은 눌려져있지 않은 짙은 회색 버튼 이미지인 button.jpg 이다

- :image 를 통해 모든 input type=image 를 불러오지만 그 중에서도 $(this)를 통해 이벤트가 발생한 그 이미지만 불러올 수 있다

+ 이미지가 여러개 있다고 하더라도 $(this) 를 통해 마우스 오버가 된 그 이미지 태그를 구해옴

 

- 마우스 포인터가 올라왔을때, 내려왔을때 다른 이미지 적용

 

jQuery 예제 40

jQuery form 태그 관련 함수 예제 15

- 리셋버튼을 선택하는 :reset 필터선택자

- sample17.html

<!DOCTYPE html>
<html>
	<head>
	    <meta charset="UTF-8">
		<title>sample17</title>
		<script src="jquery-1.6.4.min.js"></script>

		<script type="text/javascript">

$(function(){

	$(":reset").one("click",function(){
//	$(":reset").click(function(){
		$(this).after("<p>입력 내용을 초기화 합니다.</p>");
	});

});

		</script>
	</head>
	<body>
<form action="">
	<dl>
		<dt>이름<em>(필수)</em></dt>
		<dd><input type="text" name="name" /></dd>

		<dt>코멘트</dt>
		<dd>
			<textarea name="comment"></textarea>
		</dd>
		<dd><input type="reset" value="재설정" /></dd>
	</dl>
</form>
	</body>
</html>

- :reset는 input type 속성값이 reset인 태그만을 모두 구해오는 필터선택자

- :reset 으로 모든 리셋버튼을 가져온 뒤, $(this) 를 통해 그 중 클릭된 리셋버튼에 대해 after() 를 실행

- one() 함수를 통해 괄호 안의 click 이벤트를 한번만 수행하게 한다

- one() 함수를 쓰지 않고 바로 click() 을 썼다면, '재설정' 버튼을 누를때마다 같은 내용을 여러번 덧붙임

 

 

+ one() 함수를 쓰지 않고 바로 click() 을 썼다면

- one() 함수를 쓰지 않고 바로 click() 을 썼다면, '재설정' 버튼을 누를때마다 같은 내용을 여러번 덧붙임

 

jQuery 예제 41

jQuery form 태그 관련 함수 예제 16

- 유효성 검사 내용

- sample18.html

<!DOCTYPE html>
<html>
	<head>
	    <meta charset="UTF-8">
		<title>sample18</title>
		<script src="jquery-1.6.4.min.js"></script>

		<script type="text/javascript">

$(function(){

	$("button").click(function(){

		if($("#mail").val() == ""){
			alert("메일 주소를 입력하세요");
			$("#mail").focus();
			return false;
		}
		if($("#check").val()==""){
			alert("메일주소확인을 입력 하세요");
			$("#check").focus();
			return false;
		}
		if($("#mail").val() != $("#check").val()){
//			 $("em").text("메일 주소가 동일하지 않습니다.");
			alert("메일주소가 동일 하지 않습니다.");
			$("#check").val("");
			$("#check").focus();
			return false;
		}
	});

});

		</script>
	</head>
	<body>
	<form action="check.html">
	<dl>
	<dt>메일주소</dt>
	<dd><input type="text" name="mail" id="mail"/></dd>

	<dt>메일주소<em>(확인)</em></dt>
	<dd><input type="text" name="check" id="check" /></dd>
	<dd><button> 확인</button>
		<input type=reset value="취소"></dd>
	</dl>
	</form>

	</body>
</html>

- 확인 버튼을 'button' 으로 구해와서 click 시 유효성 검사를 실행한다

- val() 함수를 통해 입력양식에서 입력된 값을 구해와서 유효성 검사를 한다

- input type=reset 은 따로 이벤트를 쓰지 않더라도 기본적으로 지워주는 기능이 내장되어있다

 

+ <button></button> 태그는 전송기능이 있는 태그이다!

+ button 태그는 전송기능이 있는 버튼 태그지만 click 이벤트로 처리해도 처리가 된다

 

+ jQuery 에서 함수들을 . 으로 계속 연결 가능하다

$("#check").val("").focus();

- 아래의 코드와 같다

$("#check").val("");
#("#check").focus();

 

jQuery 예제 42

jQuery form 태그 관련 함수 예제 17

- 파일선택 폼을 선택하는 :file 필터선택자

- sample19.html

<!DOCTYPE html>
<html>
	<head>
	    <meta charset="UTF-8">
		<title>sample19</title>
		<script src="jquery-1.6.4.min.js"></script>

		<script type="text/javascript">
// :file 은 input type=file 로 되어있는 태그를 구해오는 필터 선택자

$(function(){

	$(":file").mouseover(function(){
		$(this).after("<p>업로드 가능한 파일은 300kb까지 입니다</p>")
	}).mouseout(function(){
		$("p").remove();
	});

});

		</script>
	</head>
	<body>
		사진:<input type="file"><br>
			  <input type="file">
	</body>
</html>

- :file 은 input type 속성값이 file 인 태그만을 모두 구해오는 필터선택자

- :file 로 두 파일선택 버튼 태그를 불러오고, $(this) 는 두개의 태그 중에 사용자가 마우스 오버한 태그를 불러와서, after() 를 통해 그 태그 다음에 p 태그를 추가

- 이후 mouseout 시 추가된 p 태그를 remove() 로 삭제

 

+ after() 은 요소를 형제로 추가, 선택된 태그 바로 다음에 추가됨

 

jQuery 예제 43

jQuery form 태그 관련 함수 예제 18

- 라디오버튼이나 체크박스에서 체크상태인 태그를 구해오는 :checked 필터선택자

- each() 함수

- sample20.html

<!DOCTYPE html>
<html>
	<head>
	    <meta charset="UTF-8">
		<title>sample20</title>
		<script src="jquery-1.6.4.min.js"></script>

		<script type="text/javascript">
// :checked는 라디오 버튼이나 체크박스에서 체크 상태인 태그를 
//  선택하도록 해준다. 

// label 태그 혹은 체크 박스가 클릭될 때 체크 상태인 체크박스와 
//  쌍을 이루는 label 태그의 배경색을 회색으로 변경함.

$(function(){

	$("label,:checkbox").click(function(){
		$("label").css("background","");
		$(":checked").each(function(){
			$("label[for='"+$(this).attr("id")+"']").css("background","#CCC");
		});
	});

});

		</script>
	</head>
	<body>
		스킬:
		<input type="checkbox" name="xhtml" value="XHTML" id="xhtml" />
		<label for="xhtml">XHTML</label>

		<input type="checkbox" name="css" value="CSS" id="css" />
		<label for="css">CSS</label>

		<input type="checkbox" name="javascript"value="JavaScript" id="javascript" />
		<label for="javascript">JavaScript</label>

		<input type="checkbox" name="php" value="PHP" id="php" />
		<label for="php">PHP</label>

	</body>
</html>

- 선택자가 , 로 연결시 , 양쪽에 있는 태그 둘 다 구해옴

- 여기서 $(label,:checkbox) 는 label 태그도 불러오고 모든 input type=checkbox 도 불러옴

- 그러므로 체크박스를 클릭하거나 레이블을 클릭시 안의 내용이 실행됨

- click() 안에서 레이블 태그를 모두 불러온 후 css() 로 배경색을 모두 지움

 

- 라디오버튼이나 체크박스에서 체크상태인 태그를 모두 구해오는 :checked 필터선택자

- 그리고 :checked 태그로 체크상태인 태그를 모두 구해옴

- each() 함수 : 반복문처럼 반복적인 작업을 수행해주는 함수

- $(":checked").each() 는 구해진 더이상 체크된 체크박스가 없을때까지 실행하라는 의미

- 루프를 돌리듯이 하나씩 구해진 클릭된 체크박스를 가져와서 클릭한 체크박스의 id 속성값과 for 속성값이 같은 label 태그만 css() 로 배경색을 회색으로 설정

 

+ 여기서 체크된 체크상자에 다시 체크(클릭)을 해도 이 click() 이 실행되는 것, 그러므로 한번더 클릭해서 체크 해제시 배경색을 지워줌

 

ex) 만약 XHTML 을 체크했다면

$(":checked").each(function(){});

- 에서 체크된 모든 체크박스를 하나씩 구해오는데 이때 XTML 체크박스도 해당하게 되므로 안의 내용이 실행됨

$(this).attr("id") 는 'xhtml'

- 을 의미한다

$("label[for='"+$(this).attr("id")+"']")

- 은 label 태그 중 for 속성값이 'xtml' 인 label 태그를 의미한다

 

- 체크박스 체크시 옆의 텍스트의 background 색이 바뀐다, 레이블을 클릭시에도 동일

- 한번더 클릭시 다시 click() 이 다시 실행되어서 클릭되어 해제된 체크박스의 레이블이 회색이 아니게 됨

 

+ 주의 : label 태그의 for 값과 input type=checkbox 의 id 값이 같아야한다

 

jQuery 예제 44

jQuery form 태그 관련 함수 예제 19

- select-option 에서 선택되어있는 option 태그를 구해오는 :selected 필터선택자

- sample21.html

<!DOCTYPE html>
<html>
	<head>
	    <meta charset="UTF-8">
		<title>sample21</title>
		<script src="jquery-1.6.4.min.js"></script>

		<script type="text/javascript">
// 연령을 "10대" 로 선택하면 "좋아하는 술" 입력란이 입력 불가 상태가 됨
// :selected 는 선택된 option 태그를 구해오는 필터 선택자

$(function(){

	$("select").change(function(){
//		if($(":selected").attr("value")=="10 대"){	// '10대' 선택, 아래와 똑같다
		if($("select").val() == "10 대") {	// 더 간단한 방법
			$("input").attr("disabled", "disabled");
//			$("input").attr("disabled", true); 위와 똑같다
//			$("input").attr("readOnly", "readOnly"); readOnly 로 비활성화
//			$("input").attr("readOnly", true); 위와 똑같다

		}else{	// 나머지 연령대 선택
			$("input").removeAttr("disabled");
//			$("input").attr("disabled", false); 위와 똑같다
//			$("input").attr("readOnly", false); readOnly 로 비활성화
//			$("input").removeAttr("readOnly"); 위와 똑같다
		}
	});

});

		</script>
	</head>
	<body>
<p> 나이:
<select name="age">
<option value=" 선택해주세요"> 선택해주세요</option>
<option value="10 대">10 대</option>
<option value="20 대">20 대</option>
<option value="30 대">30 대</option>
<option value="40 대이상">40 대이상</option>
</select></p>
<p> 좋아하는 술:<input type="text" /></p>

	</body>
</html>

- select-option 에서 선택되어있는 option 태그를 구해오는 :selected 필터선택자

- select-option 에서 어떤 값을 선택시 change 이벤트 발생, 이때 select 태그가 이벤트를 발생시키는 태그가 된다

- select-option 중 특정 태그만 구해오려면 if~else 문으로 나눠서 change 이벤트를 처리해야한다

- $(":selected").attr("value") == '10 대' 는 선택된 옵션의 value 속성값이 '10 대' 일때 를 의미한다, 즉 '10 대가 선택되었으면' 을 의미함

 

- 10 대가 선택되었을때 attr() 함수로 input 태그의 disabled 속성을 "disabled" 로 설정하여 input 태그를 비활성화 시킴

- 그리고 나머지의 경우는 else에서 removeAttr() 함수를 통해 disabled 속성을 삭제함, 또는 attr() 함수로 "disabled" 를 false로 설정해서도 똑같이 구현 가능

			$("input").removeAttr("disabled");
//			$("input").attr("disabled", false); 위와 똑같다

 

+ select 에서 아무것도 선택하지 않으면 가장 첫번째가 선택된 상태임 (주로 선택해주세요 메세지)

+ 이때 option 태그에 selected="selected" 속성을 추가시 초기부터 선택된 채로 나타남

 

$(":selected").attr("value") 대신 다른 간단한 방법으로 구해오기

//		if($(":selected").attr("value")=="10 대"){}	// '10대' 선택
		if($("select").val() == "10 대") {}	// 간단한 방법

- 그냥 $("select").val() 을 통해서도 select 에서 선택된 옵션의 값을 구해올 수 있다

- val() 함수로 입력양식 / 선택양식의 값을 구해오거나 설정할 수 있다

+ 여기선 select 가 1개이므로 그냥 태그선택자로 가져옴

 

- select 에서 10대를 선택시 입력창을 비활성화 시킴

 

+ $("input").attr("disabled",true); 는?

- disabled 해제되어 입력 가능해짐

			$("input").attr("disabled", "disabled");
//			$("input").attr("disabled", true); 위와 똑같다

 

 

+ 비활성화 시키는 방법 2가지 중 disabled 대신 readonly 도 될까?

- 마찬가지로 비활성화 잘 된다

//			$("input").attr("disabled", "disabled");
//			$("input").attr("disabled", true); 위와 똑같다
			$("input").attr("readOnly", "readOnly"); readOnly // readOnly 로 비활성화

 

비활성화 시키는 코드

			$("input").attr("disabled", "disabled");
//			$("input").attr("disabled", true); 위와 똑같다
//			$("input").attr("readOnly", "readOnly"); readOnly 로 비활성화
//			$("input").attr("readOnly", true); 위와 똑같다

 

비활성화 푸는 코드 (활성화)

			$("input").removeAttr("disabled");
//			$("input").attr("disabled", false); 위와 똑같다
//			$("input").attr("readOnly", false); readOnly 로 비활성화
//			$("input").removeAttr("readOnly"); 위와 똑같다

 

+ AJAX 에서 each() 함수 쓴다, AJAX 할때 자세히 공부

 

jQuery 예제 45

유효성 검사 예제 1

- jQuery 는 유효성 검사를 할때 가장 많이 사용

- jQuery01.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jQuery연습</title>

<!-- <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> -->
<script src="jquery-1.9.1.min.js" type="text/javascript"></script>

<script>

$(document).ready(function(){	
	
//    $("form").submit(function(){
	  $("#myform").submit(function(){	

//	function check() {
		var id = $.trim($("#id").val());//jQuery를 이용하여 앞뒤 공백 제거 
		if (id == "") {
//		if($.trim($("#id").val()) == ""){
			alert("ID를 입력 하세요?");
			$("#id").focus();
			return false;
		}
//	}

	}); // submit() end
}); // ready() end

</script>

</head>
<body>
	<form id=myform name=myform method=post action=send.jsp>
		<table border=1 align=center>
			<tr>
				<td>ID</td>
				<td><input type=text id="id" name="id" size=20></td>
			</tr>
			<tr>
				<td align=center colspan=2>
				<input type=submit value="가입"></td>
			</tr>
		</table>
	</form>
</body>
</html>

+ submit 버튼이므로 form 태그에 대해 submit 이벤트를 등록한다, 나머지 내용은 모두 그 안에 넣음

- id 값이 id 로 되어있는 태그를 구해서 안의 값을 구해서 var id 에 저장한다

- 그 id 변수가 null 이면 경고창을 띄우고 태그에 focus() 로 focus 를 준다

 

trim() 함수

- 문자열 좌측과 우측의 공백을 없애줌

- 주의 : 그냥 trim() 이 아니라 $.trim() 형태로 써야함

 

 

jQuery 예제 46

유효성 검사 예제 2

- jQuery01-1.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
	<title>jQuery연습</title>
	<script src="jquery-1.9.1.min.js" type="text/javascript"></script>
	<script>

//function sendGuest() {

$(document).ready(function(){

 $("form").submit(function(){

	var name=$.trim($("#name").val());
	var content=$.trim($("#content").val());
	
	if(name == "") {
		alert("이름 !!");
		$("#name").focus();
		return false;
	}

	if(content == "") {
		alert("내용 !!");
		$("#content").focus();
		return false;
	}
	
 }); // submit();

});  // ready();

//}

</script>

</head>
<body>
<!--
<form onSubmit="return sendGuest()" name=myform method=post action=send.jsp>
-->
<form method=post action=send.jsp>
<table width="500" border="1" align=center>
	<tr height="50">
		<td align="center"><b>방명록</b></td>
	</tr>
</table>
<br>
<table width="500" border="1" align=center>
	<tr height="25">
		<td align="center" width="100">작성자</td>
		<td align="left">
		    <input type="text" id="name" name="name">
		</td>
	</tr>
	<tr height="70">
		<td align="center" width="100">내용</td>
		<td align="left">
		    <textarea rows="6" cols="50" id="content" name="content"></textarea>
		</td>
	</tr>
</table>
<table width="500" border="0" align=center>
	<tr height="25">
		<td align="center">
		<input type="submit" value="등록하기">
		<input type=reset value="취소">
		</td>
	</tr>
</table>

</form>
</body>
</html>

- form 태그에 submit 이벤트를 처리함

- 작성자 입력양식의 id값과 내용 입력양식의 id값을 이용해서 불러온 후 val() 로 값을 구하고,$.trim() 후 각각 변수에 저장해서 유효성 검사를 하고 있다

- name=="" 일때 경고창과 포커스 처리를 한 후 return false 로 함수를 완전히 빠져나간다

- 함수를 빠져나갔으므로 이름을 입력하라는 경고창만 띄우고 내용을 입력하라는 경고창은 띄우지 않음

 

 

 

+ return false 가 없다면?

- 경고창이 이중으로 뜬다

 

jQuery 예제 47

유효성 검사 예제 3

- 이전 예제와 비슷
- mem_insert.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원가입 폼</title>
<script src="jquery-1.9.1.min.js"></script>
<script>

$(document).ready(function(){

   $("form").submit(function(){

// function check(){
	 if($.trim($("#id").val())==""){
		 alert("아이디를 입력하세요!");
		 $("#id").val("").focus();
		 return false;
	 }	
	 if($.trim($("#pwd").val())==""){
		 alert("비밀번호를 입력하세요!");
		 $("#pwd").val("").focus();
		 return false;
	 }
	 if($.trim($("#name").val())==""){
		 alert("이름을 입력하세요!");
		 $("#name").val("").focus();
		 return false;
	 }
	 if($.trim($("#addr").val())==""){
		 alert("주소를 입력하세요!");
		 $("#addr").val("").focus();
		 return false;
	 }
	 if($.trim($("#intro").val()) == ""){
		 alert("자기 소개를 입력 하세요!");
		 $("#intro").focus();
		 return false;
	 }
// }
	
   }); // submit() end

}); // ready() end

</script>
</head>
<body>
<!--
 <form method="post" action="mem_ok.jsp" 
	   onsubmit="return check()">
-->
<form method="post" action="mem_ok.jsp">
  <table align="center" border="1">
    <tr>
     <th>아이디</th>
     <td><input name="id" id="id" size="14" /></td>
    </tr>
    
    <tr>
      <th>비밀번호</th>
      <td><input type="password" name="pwd"			id="pwd" size="14" /></td>
    </tr>
    
    <tr>
      <th>회원이름</th>
      <td>
       <input name="name" id="name" size="20" />
      </td>
    </tr>
    
    <tr>
      <th>회원주소</th>
      <td>
       <input name="addr" id="addr" size="30" />
      </td>
    </tr>

	<tr>
      <th>자기소개</th>
      <td>
       <textarea name="intro" rows=5 cols=25 id="intro"></textarea>
      </td>
    </tr>
    
    <tr>
     <th colspan="2">
     <input type="submit" value="저장" />&nbsp;
     <input type="reset" value="취소" onclick="$('#id').focus()" />
     </th>
    </tr>
  </table>
 </form>
</body>
</html>

- 입력양식들의 id 값을 다르게 설정하여 구분한다

- 전송 버튼 클릭시 값이 전달될 파일은 mem_ok.jsp 파일

- 리셋버튼 태그에 onClick 속성에서 함수이름 대신 바로 함수를 사용하고 있다

- 계속해서 아래쪽의 내용이 실행되지 않도록 return false; 를 추가한다

- 나머지는 이전의 예제들과 비슷하다

 

포커스

 

jQuery 예제 48

유효성 검사 예제 4

- 패턴 지정해서 정규 표현식 검사

- jQuery02.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> jQuery 폼체크 예제 </title> 
<script src="jquery-1.9.1.min.js"></script> 
<script type="text/javascript"> 
 
//function form_check() { 
$(document).ready(function(){

	$("form").submit(function(){

   // 체크 패턴 
// var pattern = /^[a-zA-Z]+[a-z0-9_]$/; 
// var num = /^[0-9]+$/; 

   var pattern = /^[a-z]+[a-z0-9_]+[a-z0-9_]$/; 
   var num = /^[0-9]+$/;    
   
   // 아이디 체크 
   var id = $.trim($('#id').val());//jQuery를 이용하여 앞뒤 공백 제거 
   if(id=="") { 	// 유효성 검사
      alert("아이디를 입력하세요!"); 
      $('#id').focus(); 
      return false; 
      
   } else { 		// 정규 표현식 검사
      if(!pattern.test(id)) { // test():pattern에 맞지 않으면 - false 리턴
         alert("아이디는 영문소문자로 시작하고\r\n영문소문자, 숫자, 언더바(_)만 사용하실 수 있습니다! "); 
 //      $('#id').select(); 

//		 $("#id").val("");
//		 $("#id").focus();

		 $("#id").val("").focus();
         return false; 
      } 
   } 
   
   // 비밀번호 체크 
   var pss = $.trim($('#pss').val());//jQuery를 이용하여 앞뒤 공백 제거 
   if(pss=="") { 		// 유효성 검사
      alert("비밀번호를 입력하세요!"); 
      $('#pss').focus();	  
      return false; 
      
   } else { 			// 정규 표현식 검사
      if(!num.test(pss)) { 	// test():pattern에 맞지 않으면 - false 리턴
         alert("비밀번호는 숫자만 가능합니다!");
//		 $('#pss:text').attr('value', '');
		 $("#pss").val("");
		 $('#pss').focus();
 //      $('#pss').select(); 
         return false; 
      } 
   } 
	}); // submit() end

});	// ready() end
//} 

</script> 
</head> 
<body> 
<!--
<form method="post" action="send.jsp" onSubmit="return form_check()"> 
-->
<form method="post" action="send.jsp">
ID : <input type="text" id="id" name="post_id"> <br>
비밀번호 : <input type="text" id="pss" name="post_pss"> <br><br>
<input type="submit" id="join_button" value="폼체크"> 
</form> 
</body> 
</html>  

<!-- 
 test() 함수
	test() 함수는 정규식과 비교하여 포함되면 true 반환, 포함되지 않으면 false 반환
	pattern에 맞으면 - true
    pattern에 맞지 않으면 - false -->

- 아이디값은 소문자 a-z , 숫자 0-9, _(언더바) 가능하고 나머지는 불가능

- 비밀번호는 0-9 숫자만 가능

 

- 유효성 검사보다는 정규 표현식 검사이다, 지정된 정규 표현식과 다른 경우 alert

- 주로 이메일처럼 아이디@g.com 처럼 형식이 정해져있을때, 사용자의 입력이 정규표현식과 일치하는지 확인

 

패턴 지정 (jQuery02.html 부분)

   // 체크 패턴 
// var pattern = /^[a-zA-Z]+[a-z0-9_]$/; 
// var num = /^[0-9]+$/; 

   var pattern = /^[a-z]+[a-z0-9_]+[a-z0-9_]$/; 
   var num = /^[0-9]+$/;

- 패턴 지정시 시작을 알리는 ^ 기호, 끝을 알리는 $ 기호

- 대괄호안의 문자만 사용가능하다는 의미

pattern 변수

- 아이디의 패턴 지정

- 3가지 []가 + 로 연결된 것은 순차적으로 연결된 것

- [a-z] 는 영문 소문자 a 부터 z 까지 가능하다는 의미이고 [a-z] 로 시작해야함

- 그 뒤로 a-z 0-9 _ 가 가능하고, 끝나는 문자는 a-z 0-9 _ 가 가능하다 즉 아이디는 최소 3글자 임

- 가운데 있는 [a-z0-9_] 는 없어도 비슷하다

num 변수

- num 변수는 비밀번호의 패턴 지정

- [0-9] 로 0 부터 9까지의 숫자들만 비밀번호로 가능

 

id 유효성 검사 (jQuery02.html 부분)

   // 아이디 체크 
   var id = $.trim($('#id').val());//jQuery를 이용하여 앞뒤 공백 제거 
   if(id=="") { 	// 유효성 검사
      alert("아이디를 입력하세요!"); 
      $('#id').focus(); 
      return false; 
      
   } else { 		// 정규 표현식 검사
      if(!pattern.test(id)) { // test():pattern에 맞지 않으면 - false 리턴
         alert("아이디는 영문소문자로 시작하고\r\n영문소문자, 숫자, 언더바(_)만 사용하실 수 있습니다! "); 
 //      $('#id').select(); 

//		 $("#id").val("");
//		 $("#id").focus();

		 $("#id").val("").focus();
         return false; 
      } 
   }

- if문에서 유효성 검사를 하고 유효성 검사를 통과했다면(즉 값이 써져있다면) else문에서 정규 표현식 검사를 한다

- 정규 표현식 검사는 아래에서 

 

id 정규 표현식 검사 (jQuery02.html 부분)

      if(!pattern.test(id)) { // test():pattern에 맞지 않으면 - false 리턴
         alert("아이디는 영문소문자로 시작하고\r\n영문소문자, 숫자, 언더바(_)만 사용하실 수 있습니다! "); 
 //      $('#id').select(); 

//		 $("#id").val("");
//		 $("#id").focus();

		 $("#id").val("").focus();
         return false;

- test() 함수 : 입력했던 패턴과 사용자가 입력한 값이 맞는지 확인해줌

- 패턴을저장한변수명.test(사용자입력양식) 으로 사용

- 맞으면 true 리턴, 맞지 않으면 false 리턴

- 우리는 맞지 않을 경우 처리를 알림창을 띄우는 등의 처리를 해야하므로 !pattern.test(id) 를 if() 안에 넣었다

- 정규 표현식에 맞지 않으면 알람창을 띄우고, 아이디 입력양식을 비우고 focus 함

 

비밀번호 정규 표현식 검사 (jQuery02.html 부분)

      if(!num.test(pss)) { 	// test():pattern에 맞지 않으면 - false 리턴
         alert("비밀번호는 숫자만 가능합니다!");
//		 $('#pss:text').attr('value', '');
		 $("#pss").val("");
		 $('#pss').focus();
 //      $('#pss').select(); 
         return false; 
      }

- id 정규 표현식 검사와 유사

 

test() 함수

- 입력했던 패턴과 사용자가 입력한 값이 맞는지 확인해줌

- 패턴을저장한변수명.test(사용자입력양식) 으로 사용

- 정규식과 비교하여 포함되면 true 반환, 포함되지 않으면 false 반환
- pattern에 맞으면 true, pattern에 맞지 않으면 false

 

- 형식에 맞는값을 입력해야만 사용 가능

 

jQuery 예제 49

유효성 검사 예제 5

- 유효성 검사 + 정규 표현식 검사

- join.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jQuery 회원가입</title>
<style type="text/css">
	#jointable table{width:600px;}
	#jointable th{text-align: right;								  background-color:orange;}
	#jointable td input {border:1px solid seagreen;}
</style>

<script type="text/javascript" src="jquery-1.9.1.min.js"></script>
<script type="text/javascript">

$(document).ready(function() {

    $("form").submit(function() {
        
            var tel1_pattern = /(^01[016789]$)/; //정규식
            
            if ($("#id").val() == "") {
                alert("아이디를 입력하세요!");
                $("#id").focus();
				return false;
            } else if ($("#pwd").val() == "") {
                alert("비밀번호를 입력하세요!");
                $("#pwd").focus();
				return false;
            } else if ($("#pwd2").val() == "") {
                alert("비밀번호확인 을  입력하세요!");
                $("#pwd2").focus();
				return false;
            } else if ($("#pwd").val() != $("#pwd2").val()) {
                alert("비밀번호와 비밀번호 확인이 일치하지않습니다.");
                $("#pwd").val("");
                $("#pwd2").val("");
                $("#pwd").focus();
				return false;
            } else if ($("#name").val() == "") {
                alert("이름을  입력하세요!");
                $("#name").focus();
				return false;
            } else if ($("#tel1").val() == "") {
                alert("전화번호 첫번째자리 입력하세요!");
                $("#tel1").focus();
				return false;
            } else if ($("#tel1").val().length != 3) {
                alert("전화1을 3개의 숫자로 입력하세요!");
                $("#tel1").val("");
                $("#tel1").focus();
				return false;
            } else if (isNaN($("#tel1").val())) {
                alert("전화1을 3개의 숫자로  입력하세요!");
                $("#tel1").val("");
                $("#tel1").focus();	
				return false;
// var tel1_pattern = /(^01[016789]$)/;  pattern에 맞지 않으면 - false
            } else if (!tel1_pattern.test($("#tel1").val())) {
                alert("010, 011, 016, 017, 018, 019만 가능합니다.")
                $("#tel1").val("")
                $("#tel1").focus();
				return false;
            } else if ($("#tel2").val() == "") {
                alert("전화번호 두번째자리를 입력하세요!");
                $("#tel2").focus();
				return false;
            } else if ($("#tel2").val().length != 4) {
                alert("전화1을 4개의 숫자로 입력하세요!");
                $("#tel2").val("");
                $("#tel2").focus();
				return false;
            } else if (isNaN($("#tel2").val())) {
                alert("전화2을 3~4개의 숫자로 입력하세요!");
                $("#tel2").val("");
                $("#tel2").focus();
				return false;
            } 
/*			
			else if($("#tel2").val() == "" || 
					  $("#tel2").val().length > 4 ||				       isNaN($("#tel2").val())) {


//                alert("okkkkkkk");
/*
                var pattern = /(^01[016789]$)/; //정규식 슬래쉬(/)로 시작해서, 슬래쉬(/)로 끝났다.
                var tel1 = $("#tel2").val();
                if (!pattern.test(tel1)) {
                    //틀리면
                    alert("010, 011, 016, 017, 018, 019,o19만 가능합니다.")
                    $("#te2").val("")
                    $("#te2").focus();

                }
*/
//            }

            else if ($("#tel3").val() == "") {
                alert("전화번호 세번째자리를 입력하세요!");
                $("#tel3").focus();
				return false;
			}else if ($("#tel3").val().length != 4) {
                alert("전화1을 4개의 숫자로 입력하세요!");
                $("#tel3").val("");
                $("#tel3").focus();
				return false;
            } else if (isNaN($("#tel3").val())) {
                alert("전화2을 3~4개의 숫자로  입력하세요!");
                $("#tel3").val("");
                $("#tel3").focus();			
				return false;
            } else if ($("#addr").val() == "") {
                alert("주소를  입력하세요!");
                $("#addr").focus();
				return false;
            } else if ($("#job").val() == "") {
                alert("직업을  선택하세요!");
                $("#job").focus();
				return false;
            } else if ($("#man").is(':checked') == false &&	
            		   $("#woman").is(':checked') == false) {
                alert("남자또는 여자를  선택하세요!");
				return false;
            } else if ($("#email").val() == "") {
                alert("이메일을 입력하세요!");
                $("#email").focus();
				return false;
            } else if ($("#intro").val() == "") {
                alert("자기소개를  입력하세요!");
                $("#intro").focus();
				return false;
            } else {
                alert("ok");

//				$("form").submit();
            }

        }); // click() end

}); // ready() end
	
</script>
</head>

<body>
<h1>회원 가입</h1>

<form action="send.jsp" method=post>

<table id="jointable">
	<tr>
		<th>아이디</th>
		<td><input type="text" name="id" id="id" size="12" maxlength="12" /></td>
	</tr>
	<tr>
		<th>비밀번호</th>
		<td><input type="password" name="pwd" id="pwd" size="12" maxlength="12" /></td>
	</tr>
	<tr>
		<th>비밀번호확인</th>
		<td><input type="password" name="pwd2" id="pwd2" size="12" maxlength="12" /></td>
	</tr>
	<tr>
		<th>이름</th>
		<td><input type="text" name="name" id="name" size="12" maxlength="12" /></td>
	</tr>
	<tr>
		<th>전화번호</th>
		<td>
		<input type="text" name="tel1" id="tel1" size="3" maxlength="3" />-
		<input type="text" name="tel2" id="tel2" size="4" maxlength="4" />-
		<input type="text" name="tel3" id="tel3" size="4" maxlength="4"/>
		</td>
	</tr>
	<tr>
		<th>주소</th>
		<td><input type="text" name="addr" id="addr" maxlength="100" /></td>
	</tr>	
	<tr>
		<th>직업</th>
		<td>

			<select id = "job">
				<option value="">------
				<option value="학생">학생
				<option value="직장인">직장인
				<option value="자영업">자영업
				<option value="주부">주부
			</select>
		
		</td>
	</tr>
	<tr>
		<th>성별</th>
		<td>
			<input type="radio" id="man" name="gender" value="M">남자
			<input type="radio" id="woman" name="gender" value="W">여자
		</td>
	</tr>
	<tr>
		<th>이메일</th>
		<td><input type="text" name="email" id="email"	size="50" maxlength="50" /></td>
	</tr>
	<tr>
		<th>자기소개</th>
		<td>
			<textarea rows="5" cols="40" id="intro"	name="intro"></textarea>
		</td>
	</tr>
	<tr>		
		<td colspan="2" align=center>
			<input type="submit" id="btn_join" value="가입">
			<input type="reset" id="btn_cancel" value="취소">	
		</td>
	</tr>
</table>


</form>

</body>
</html>

<!--

1. isNaN() 함수
	isNaN() 함수는 숫자인지 아닌지를 판단하고 true/false 를 리턴함.
	isNaN('a') -- true 리턴.(문자)
	isNaN('123') --- false 리턴.(숫자)
	cf.isNaN 은 Not a Number 의 약자. 

	if(isNaN(document.myform.tel1.value){
		alert("숫자만 입력 하세요");
	}
    if(isNaN($("#tel1").val())){
		alert("숫자만 입력 하세요");
	}

2. test() 함수
	test() 함수는 정규식과 비교하여 포함되면 true 반환, 포함되지 않으면 false 반환
	pattern에 맞으면 - true
    pattern에 맞지 않으면 - false

3. is() 함수
   is() 함수는 값의 유형을 검사하고 그 결과에 따라 true 또는 false를 반환함
   
   라디오 버튼이나 체크박스가 체크되면 true를 반환하고, 체크되지 않으면 false를 반환함.

-->

- 테이블의 id 값인 jointable 으로 <style> 에서 CSS 를 적용하고 있다

- 가장바깥에 $(document).ready() 가 오고 그 다음 form 에 대해 submit 이벤트 처리를 하고 있다, 나머지 내용은 모두 그 안에 들어간다

 

패턴 지정(join.html 부분)

            var tel1_pattern = /(^01[016789]$)/; //정규식

- tel1_pattern 변수에 정규표현식 설정

- 01 로 시작해서 [] 안의 값중 한개가 들어가야함

+- [] 는 그 안의 값 중 하나를 의미, 여러개가 올 수 있다

 

패턴 적용 (join.html 부분)

 

사용된 함수

1. isNaN() 함수

- 숫자인지 아닌지를 판단,숫자가 아니면(문자이면) true 리턴, 숫자이면 false 리턴

 

2. test() 함수
- 정규식과 비교하여 포함되면 true 반환, 포함되지 않으면 false 반환
- pattern에 맞으면 true, pattern에 맞지 않으면 false 리턴

 

3. is() 함수

- 라디오버튼이나 체크박스에 체크가 되었는지 판별, 체크가 되었으면 true 리턴, 체크되지 않았을땐 false 리턴

 

부분 코드 (순차적)

유효성 검사 1 (join.html 부분)

- 아이디, 비밀번호, 비밀번호 확인은 유효성 검사를 한다

 

유효성 검사 2 (join.html 부분)

- 일치하지 않는 경우 비밀번호도 지우고 비밀번호 확인 도 지우고 비밀번호에 focus

 

유효성 검사 3 (join.html 부분)

- val() 을 이용하여 전화번호 첫번째 부분에 대한 유효성 검사를 하고 있다

- length 속성과 isNaN() 함수로 유효성 검사

- 전화번호 첫번째 부분 유효성 검사 : 입력이 되어야하고, 입력된 값이 3자리 여야하며, 숫자여야 한다

 

정규 표현식 검사 1 (join.html 부분)

- 전화번호 첫번째 부분에 대한 정규 표현식 검사를 하고 있다

- test() 를 통해 기존에 지정해둔 패턴과 맞는지 확인하고 있다

- 맞지않을때 false를 리턴하고 ! 를 사용했으므로 위는 정규 표현식에 맞지 않으면 실행되는 코드이다

- 01 로 시작해야하고 다음 자리는 0,1,6,7,8 또는 9 이어야한다

 

+ 그 다음의 전화번호 두째자리, 세번째 자리도 첫번째 자리에서 했던 것과 유사하게 유효성 검사와 정규표현식 검사를 한다

+ 이름, 자기소개의 유효성 검사도 앞과 비슷하게 처리한다

 

select 유효성 검사 (join.html 부분)

 

- select 에서 아무것도 선택하지 않았을때의 기본 option 의 value 가 "" 이므로 이렇게 select-option 유효성 검사 가능하다

 

라디오박스 유효성 검사 (join.html 부분)

- is() 함수를 통해 해당 라디오박스가 체크되었는지 is(':checked') 로 확인한다, 체크시에 true 반환

- 즉 남자도 선택되지 않았고 (&&) 여자도 선택되지 않았을때 alert 메세지를 띄운다

 

모든 유효성 검사와 정규 표현식 검사 통과 후 마지막 else 구문 (join.html 부분)

- 앞의 if, else if 에 걸리지 않으면 모든 유효성 검사와 정규 표현식 검사를 통과한 것이다.

- 모든 유효성 검사와 정규 표현식 검사를 통과시 alert 창으로 "ok" 를 출력

 

 

jQuery 예제 50

유효성 검사 예제 직접 작성 1

- 유효성 검사 + 정규 표현식 검사

실습 준비

- 폴더 생성 후, HTML 시간에 만들었던 양식폼 html 파일을 각 폴더로 가져오기

- loginform.html

- requred 속성에 의해 메세지를 출력, 우리가 원하는 메세지를 출력할 수 없으므로 지우자

- method="get" 에서 "post" 로 수정

 

- 현재는 유효성 검사가 안되어있으므로 '로그인' 버튼 클릭시 바로 넘어감

- 직접 차례로 유효성 검사를 하자

- loginform.html 에 코드 추가

 

1. jQuery 사용을 위해 라이브러리 구해오기

<script src="http://code.jquery.com/jquery-Latest.js"></script>

- head 태그 내에서 CDN 방식으로 최신 라이브러리 불러오기

 

2. <script></script> 사이에 jQuery 코드 쓰기

- $(document).ready(); 문서를 불러오고 준비가 완료되면 이라는 의미

- jQuery 기본적인 형태, 안의 내용은 코드 실행이 되자마자 실행됨

 

3. '로그인' 버튼은 input type=submit 이므로 form 태그에 대해 submit 이벤트 처리

- 폼과 관련된 나머지 내용은 모두 이 submit 함수에 들어가야한다

 

4. id와 비밀번호 유효성 검사

- 입력이 되지 않은 경우의 유효성 검사를 하고 있다

- return false 를 이용해서 바로 위의 함수인 submit() 함수를 완전히 빠져나감

- 실행 확인 캡처

 

5. 작성한 jQuery 코드를 외부 파일로 빼기

- 외부파일로 뺄때는 확장자를 .js 로 해야한다

- Javascript 에선 함수단위로 들어갔지만 jQuery 에는 $(document).ready() 부터 안의 내용이 모두 들어가야함

- 해당 부분을 복사 후 주석처리 한다

- login.js 안에 복사한다

- loginform.html 파일로 돌아와서 <script> 로 외부 파일을 불러온다

- 결과 캡처

- 이전에 만들어둔 login.jsp 파일이 있으므로 넘어가서 id와 비밀번호가 출력됨

 

위 예제 전체코드

- loginform.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 폼</title>

<script src="http://code.jquery.com/jquery-Latest.js"></script>

<!-- 외부 jQuery 파일 불러오기 -->
<script src="login.js"></script>

<script>
/* 	$(document).ready(function(){
		$("form").submit(function(){
			
			// id 유효성 검사
			if($.trim($("#id").val()) == "") {	// id 입력안하면				
				alert("ID를 입력하세요.");
				$("#id").focus();
				return false;
			}
			
			// 비밀번호 유효성 검사
			if($.trim($("#passwd").val()) == "") {	// 비밀번호 입력안하면				
				alert("비밀번호를 입력하세요.");
				$("#passwd").focus();
				return false;
			}
			
		});
	});  */
</script>

</head>
<body>

<!-- 
method : 값을 전달하는 방식을 설정 : get, post
action : 값이 전달될 파일을 설정
-->

<form method="post" action="login.jsp">
<table border=1 width=350 align=center>
	<caption>로그인</caption>
	<tr>
		<td>ID</td>
		<td><input type=text size=20
							 maxlength=10
							 autofocus="autofocus"
							 name="id"
							 id="id">
		</td>
	</tr>
	<tr>
		<td>비밀번호</td>
		<td><input type=password size=20
								 name="passwd"
								 id="passwd"></td>
	</tr>
	<tr>
		<td colspan=2 align=center>
			<input type=submit value="로그인"><!-- 전송기능이 있는 버튼 -->
			<input type=reset value="취소"><!-- 초기화 버튼 -->
		</td>
	</tr>
</table>
</form>

</body>
</html>

- login.js

$(document).ready(function(){
	$("form").submit(function(){
		
		// id 유효성 검사
		if($.trim($("#id").val()) == "") {	// id 입력안하면				
			alert("ID를 입력하세요.");
			$("#id").focus();
			return false;
		}
		
		// 비밀번호 유효성 검사
		if($.trim($("#passwd").val()) == "") {	// 비밀번호 입력안하면				
			alert("비밀번호를 입력하세요.");
			$("#passwd").focus();
			return false;
		}
		
	});
});

 

jQuery 예제 51

유효성 검사 예제 직접 작성 2

- 유효성 검사

- boardform.html 에 코드 추가

실습 준비

- submit 버튼과 reset 버튼만 남기고 주석처리 또는 지우기

- 초기값으로 나오는 value 삭제

- 유효성 검사를 위해 내용안에 들어간 내용 삭제

- textarea 는 저 태그 안의 값이 value 가 되고 val() 로 구해지는 값이기 때문에

 

1. boardform.html 에 코드 추가, 기본

 

2. 작성자명과 비밀번호 유효성 검사

+ 만약 .trim() 을 사용한다면 $.trim($("#passwd").val()) 처럼 val() 까지 안에 들어가야함

+ 반복문은 break 로 빠져나가고 함수는 return false; 로 빠져나가야 한다

- id 를 입력하지 않았을때 return false; 로 submit() 함수를 빠져나감

- 따라서 id 유효성 검사에서 걸린 후 함수를 빠져나가면 "비밀번호를 입력하세요" alert 창은 뜨지 않는다

 

3. 비밀번호 정규 표현식 검사

- 비밀번호 값은 2자리부터 8자리까지만 입력 가능하다

- OR 연산자 || 로 인해 둘 중 하나만 만족하여도 참이된다.

- 결과 캡처

 

4. 제목과 내용 유효성 검사

- 값이 입력되었는지와 값의 길이를 유효성 검사한다

- 제목은 50자 이내, 내용은 200자 이내로 입력해야한다

- 제목 길이가 적절하지 않으면 경고창을 띄우고 "" 로 지우고 focus 한다

- 내용 길이가 적절하지 않으면 경고창을 띄우고 focus 만 한다

 

+ 내용 textarea 태그의 경우엔 value 속성이 없지만, 그 태그 사이의 내용이 value 가 되어 val() 할때 나타난다

- 즉, val()=="" 이란 의미는 내용을 입력하지 않음 의 의미

- 결과 캡처

 

4. 첨부파일 유효성 검사

- 첨부파일 선택하지 않았을때 메세지를 뿌리는 유효성 검사

- 일반적인 양식과 비슷하게 처리

- 꼭 첨부파일이 필요한 경우에 유효성 검사

 

+ 첨부파일은 일반적인 텍스트 전달과 다르다

+ JSP 에서 첨부파일 처리위한 라이브러리로 파일을 서버측으로 전달 가능

 

4. 작성한 코드를 외부파일로 만들기

- 작성한 코드를 외부파일 board.js 로 빼기

- $(document).ready() 부터의 모든 내용을 복사 후 주석처리

- 해당 내용을 복사 후 주석처리

- board.js 파일에 붙여넣기

- 다시 boardform.html 에서 외부 jQuery 파일 불러오기

 

- 결과 출력

 

+ 외부파일 board.js 는 재사용 가능한 파일이 됨

 

위 예제 전체코드

- boardform.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판</title>

<script src="http://code.jquery.com/jquery-latest.js"></script>

<!-- 외부 jQuery 파일 불러오기 -->
<script src="board.js"></script>
<script>
/* 	$(document).ready(function(){
		$("form").submit(function(){
			if($("#writer").val() ==""){
			alert("작성자 명을 입력하세요");
			$("#writer").focus();
			return false;
			}
		
			if($("#passwd").val() ==""){
			alert("비밀번호를 입력하세요");
			$("#passwd").focus();
			return false;
			}
	
			if($("#passwd").val().length < 2 ||
				$("#passwd").val().length > 8 ) {
				alert("비밀번호는 2 ~ 8 자 이내로 입력하세요");
				$("#passwd").val("").focus();
				return false;
			}
			
			if($("#subject").val() ==""){
				alert("제목을 입력하세요.");
				$("#subject").focus();
				return false;
				}
			if($("#subject").val().length > 50) {
				alert("제목을 50자 이내로 입력하세요.");
				$("#subject").val("").focus();
				return false;
			}
			if($("#content").val() ==""){
				alert("내용을 입력하세요.");
				$("#content").focus();
				return false;
				}
			if($("#content").val().length > 200) {
				alert("내용을 200자 이내로 입력하세요.");
				$("#content").focus();
				return false;
			}
			if($("#myfile").val() == ""){
				alert("첨부파일을 선택하세요.");
				return false;
			}
		
		});	// submit() end
	})	// $(document) end */
</script>
</head>
<body>

<form method="post" action="board.jsp">
<table border=1 width=500 align=center>
	<caption>게시판</caption>
	<tr>
		<th>작성자</th>
		<td><input type=text size=20 name="writer"
									 id="writer"
									 placeholder="작성자명 입력">
		</td>
	</tr>
	<tr>
		<th>비밀번호</th>
		<td><input type=password size=20 name="passwd"
									     id="passwd"
									     placeholder="2~8자 이내 입력">
		</td>
	</tr>
	<tr>
		<th>제목</th>
		<td><input type=text size=50 name="subject"
									 id="subject"
									 placeholder="50자 이내로 입력">
		</td>
	</tr>
	<tr>
		<th>내용</th>
		<td><textarea rows="5" cols="50" name="content"
				id="content" placeholder="200자 이내로 입력"></textarea>
		</td>
	</tr>
	<tr>
		<th>파일첨부</th>
		<td><input type=file name="myfile" id="myfile">
		</td>
	</tr>
	<tr>
		<td colspan=2 align=center>
			<input type="submit" value="글작성1"><!-- 전송기능 있는 버튼 -->
			<!-- <input type="button" value="글작성2">전송기능 없는 버튼 -->
			
			<!-- <button>글작성3</button>전송기능 있는 버튼 -->
			<!-- <button type="submit">글작성4</button>전송기능 있는 버튼 --> 
			<!-- <button type="button">글작성5</button>전송기능 없는 버튼 -->
			
			<input type="reset" value="취소"><!-- 초기화 버튼 -->
			<!-- <button type="reset">초기화</button>초기화 버튼 -->
		</td>
	</tr>
</table>
</form>

</body>
</html>

- board.js

	$(document).ready(function(){
		$("form").submit(function(){
			if($("#writer").val() ==""){
			alert("작성자 명을 입력하세요");
			$("#writer").focus();
			return false;
			}
		
			if($("#passwd").val() ==""){
			alert("비밀번호를 입력하세요");
			$("#passwd").focus();
			return false;
			}
	
			if($("#passwd").val().length < 2 ||
				$("#passwd").val().length > 8 ) {
				alert("비밀번호는 2 ~ 8 자 이내로 입력하세요");
				$("#passwd").val("").focus();
				return false;
			}
			
			if($("#subject").val() ==""){
				alert("제목을 입력하세요.");
				$("#subject").focus();
				return false;
				}
			if($("#subject").val().length > 50) {
				alert("제목을 50자 이내로 입력하세요.");
				$("#subject").val("").focus();
				return false;
			}
			if($("#content").val() ==""){
				alert("내용을 입력하세요.");
				$("#content").focus();
				return false;
				}
			if($("#content").val().length > 200) {
				alert("내용을 200자 이내로 입력하세요.");
				$("#content").focus();
				return false;
			}
			if($("#myfile").val() == ""){
				alert("첨부파일을 선택하세요.");
				return false;
			}
		
		});	// submit() end
	})	// $(document) end

+ Recent posts