Study Web Development

1월 6일

이전으로

Servlet & JSP

3. JSP

3-3 기본 객체

request
  1. 새 JSP 파일 s05_gugudanForm.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>실습</title>
</head>
<body>
<h2>구구단</h2>
<form id="myForm" action="s06_gugudan.jsp" method="post">
	<label title="2부터 9 사이의 숫자만 입력 가능합니다">단을 입력하세요 : <input type="text" name="dan" id="dan"></label>
	<input type="submit" value="보기" id="btn">
</form>
<script type="text/javascript">
	let dan = document.getElementById('dan');

	dan.onkeyup = function() {
		let num = Number(dan.value);
		if(!Number.isInteger(num) || num>9 || num<2) { // isNaN(dan.value)도 가능
			reset();
			return;
		}
		document.getElementById('btn').value = num + '단 보기';
	}
	
	document.getElementById('myForm').onsubmit = function() {
		dan.value = dan.value.trim(); // 4    처럼 공백을 포함하여 전송하는 경우 대비
		if(!dan.value) {
			reset();
			alert('단을 입력하세요!')
			return false;
		}
	}
	
	function reset() {
		dan.value = '';
		document.getElementById('btn').value = '보기';
		dan.focus();
	}
</script>
</body>
</html>
  1. 새 JSP 파일 s06_gugudan.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<% request.setCharacterEncoding("UTF-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>실습</title>
</head>
<body>
<% int dan = Integer.parseInt(request.getParameter("dan")); %>
<h2>구구단 : <%= dan %></h2>
<% for(int i=1;i<=9;i++) { %>
	<%= dan %> * <%= i %> = <%= dan * i %><br>
<% } %>
</body>
</html>
  1. 새 JSP 파일 s07_registerForm.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>실습</title>
</head>
<body>
<!-- 이름(name), 아이디(id)와 비밀번호(password), 전화번호(phone), 취미(hobby: 영화보기, 음악 감상, 등산, 낚시, 춤), 자기 소개(content) -->
<form action="s08_register.jsp" method="get" id="myForm">
	<label>이름 : <input type="text" name="name" id="name" size="10"></label><br> <!-- name은 서버용 식별자, id 및 class는 CSS와 JavaScript용 식별자 -->
	<label>아이디 : <input type="text" name="id" id="id" size="30"></label><br>
	<label>비밀번호 : <input type="password" name="password" id="password" size="30"></label><br>
	
	<label>전화번호 : <select name="phone" id="area_code">
		<option>010</option><option>070</option>
		<option>02</option><option>031</option><option>032</option>
		<option>직접 입력</option>
	</select>
	- <input type="text" name="phone" size="4">
	- <input type="text" name="phone" size="4"></label><br>
	<!-- <label>전화번호 : <input type="text" name="phone" id="phone" size="30"></label><br> -->
	
	취미 : 
	<label><input type="checkbox" name="hobby" class="hobby" value="영화 보기">영화 보기</label>
	<label><input type="checkbox" name="hobby" class="hobby" value="음악 감상">음악 감상</label>
	<label><input type="checkbox" name="hobby" class="hobby" value="게임">게임</label>
	<label><input type="checkbox" name="hobby" class="hobby" value="독서">독서</label>
	<label><input type="checkbox" name="hobby" class="hobby" value="그림 그리기">그림 그리기</label><br>
	
	<label>자기 소개 : <br><textarea rows="5" cols="50" name="content" id="content"></textarea></label><br>
	
	<input type="submit" value="전송">
</form>
<script type="text/javascript">
	let area_code = document.getElementById('area_code');
	area_code.onchange = function() {
		if(this.value=='직접 입력') { // 동적으로 태그 생성
			let area_code_text = document.createElement("input");
			area_code_text.type = 'text';
			area_code_text.name = 'phone'; // 서버 전송용 식별자 부여
			area_code_text.size = 3; // 국번이므로 길이를 3자로 제한
			area_code_text.onkeyup = checkPhone; // 유효성 검사 이벤트 핸들러 연결
			this.parentNode.insertBefore(area_code_text, this.nextSibling);
		}
		else if(this.nextSibling.size==3) { // 동적으로 태그 삭제
			this.nextSibling.remove();
		}
	}
	
	let phones = area_code.parentNode.getElementsByTagName('input'); // 국번의 부모 <label> 태그의 자식 <input> 태그들을 선택
	for(let i=0;i<phones.length;i++) {
		phones[i].onkeyup = checkPhone; // 유효성 검사 이벤트 핸들러 연결
	}
	
	function checkPhone() {
		this.value = this.value.trim(); // 공백 제거
		if(!Number.isInteger(Number(this.value))) {
			let num = parseInt(this.value);
			if(isNaN(num)) this.value = ''; // 입력 값이 숫자가 아닌 문자로 시작하는 경우 전부 삭제
			else this.value = num; // 입력 값이 숫자로 시작하다 문자가 섞인 경우 문자 부분을 잘라냄
		}
		if(this.value.length>this.size) {
			this.value = this.value.substring(0, this.size); // 길이 제한
		}
	}
	
	myForm.onsubmit = function() {
		let inputs = document.getElementsByTagName('input'); // <textarea> 태그를 제외한 입력 칸들 얻기
		for(let i=0;i<inputs.length;i++) {
			if(!inputs[i].value.trim()) { // value가 지정되어 있는 체크박스와 전송 버튼은 항상 else로 빠짐
				inputs[i].value = '';
				inputs[i].focus();
				alert(inputs[i].parentNode.innerText.split(':')[0].trim() + '을/를 입력하세요!'); // split('\n')[0]은 첫 줄을 반환; <label> 태그로 <input> 태그들을 감싸두지 않으면 원하는 문자열이 추출되지 않으므로 주의
				return false;
			}
		}
	}
</script>
</body>
</html>
  1. 새 JSP 파일 s08_register.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<% request.setCharacterEncoding("UTF-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>실습</title>
</head>
<body>
이름 : <%= request.getParameter("name") %><br>
아이디 : <%= request.getParameter("id") %><br>
비밀번호 : <%= request.getParameter("password") %><br>
전화번호 : 
<%
	String[] phones = request.getParameterValues("phone");
	String phone = "";
	for(int i=0;i<phones.length;i++) {
		if(phones.length==4 && i==0) continue;
		phone += phones[i];
		if(i<phones.length - 1) phone += " - ";
	}
%>
<%= phone %><br>
취미 :
<%
	String[] hobbies = request.getParameterValues("hobby");
	String hobby = "";
	if(hobbies!=null) {
		for(int i=0;i<hobbies.length;i++) {
			hobby += hobbies[i];
			if(i<hobbies.length-1) hobby += ", ";
		}
	}
%>
<%= hobby %><br>
자기 소개 : <br>
<textarea rows="5" cols="50" readonly><%= request.getParameter("content") %></textarea><br>
</body>
</html>
  1. 새 JSP 파일 s18_orderForm.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>실습</title>
<style type="text/css">
	.goods {display: flex; flex-direction: column;}
	.row {display: flex; flex-direction: row;}
	.row div,.row label {margin: 5px 15px; width: 75px;}
	h3 small {color: gray; font-style: italic; font-weight: normal; font-size: 0.8rem;
	}
</style>
</head>
<body>
<!-- 
[실습 문제] 이름(name), 날짜(order_date), 상품(item: 가방, 신발, 옷, 식사권)
가방(20만원), 신발(10만원), 옷(5만원), 식사권(15만원)
30만원 미만 배송비 5천원 추가
 -->
<h2>상품 구매</h2>
<form action="s19_order.jsp" method=get id="myForm">
	<label>이름 <input type="text" name="name" id="name"></label><br>
	<label>날짜 <input type="date" name="order_date" id="order_date"></label><br>
	<h3>상품 목록<small>(30만원 미만 배송비 5천원 추가)</small></h3>
	<div class="goods">
		<div class="row">
			<label><input type="checkbox" name="item" value="가방">가방</label>
			<label><input type="checkbox" name="item" value="신발">신발</label>
			<label><input type="checkbox" name="item" value="옷"></label>
			<label><input type="checkbox" name="item" value="식사권">식사권</label><br>
		</div>
		<div class="row">
			<div class="price">20만원</div>
			<div class="price">10만원</div>
			<div class="price">5만원</div>
			<div class="price">15만원</div>
		</div>
	</div>
	<input type="submit" value="구입">
</form>
<script type="text/javascript">
	document.getElementById('myForm').onsubmit = function(event) {
		let name = document.getElementById('name');
		name.value = name.value.trim(); // 공백 제거
		if(!name.value) {
			alert('이름을 입력하세요!');
			name.focus();
			return false;
		}
		
		let order_date = document.getElementById('order_date');
		if(!order_date.value) {
			alert('날짜를 입력하세요!');
			order_date.focus(); // <input type="date"> 경우 focus되는 위치(연도 대신 picker ) 지정할  없기 때문에 생략해도 무방
			return false;
		}
		
		let items = document.getElementsByName('item');
		let check = false;
		for(let i=0;i<items.length;i++) {
			if(items[i].checked) check = true;
		}
		if(!check) {
			alert('상품을 하나 이상 선택하세요!');
			return false;
		}
		
		/*
		let items = document.getElementsByName('item');
		let prices = document.getElementsByClassName('price');
		for(let i=0;i<items.length;i++) {
			if(items[i].checked) { // 선택된 상품에 대응하는 가격을 값으로 갖는 <input> 태그 동적 생성
				let price_out = document.createElement("input");
				price_out.type = 'number';
				price_out.name = 'price'; // 서버 전송용 식별자 부여
				price_out.value = parseInt(prices[i].textContent)*10000;
				price_out.style.display = 'none';
				prices[i].parentNode.insertBefore(price_out, prices[i].nextSibling);
			}
		}
		*/
	}
</script>
</body>
</html>
  1. 새 JSP 파일 s19_order.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.HashMap" %>
<% request.setCharacterEncoding("UTF-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>실습</title>
</head>
<body>
<!-- 
구매 금액이 30만원 미만이면 배송비 5천원 추가
[출력 예시]
이름 : 
주문 날짜 : 
구입 내용 : 
배송비 : 
총 구매 비용(배송비 포함):  
 -->
<h2>구매 내역</h2>
이름 : <%= request.getParameter("name") %><br>
주문 날짜 : <%= request.getParameter("order_date") %><br>
<%
	// 가격 정보
	HashMap<String, Integer> map = new HashMap<String, Integer>();
	map.put("가방", 200000);
	map.put("신발", 100000);
	map.put("옷", 50000);
	map.put("식사권", 150000);
	
	// 배송비
	int delivery_fee = 5000;
 %>
구입 내용 : 
<%
	String[] items = request.getParameterValues("item");
	int sum = 0;
	if(items!=null) {
		for(int i=0;i<items.length;i++) {
			// 구매 비용 누적
			sum += map.get(items[i]);
			if(i>0) out.println(",");
%>
			<%= items[i] %>
<%
		} // end of for
		if(sum<300000) sum += delivery_fee;
		else delivery_fee = 0;
%>
		<br>
		배송비 : <%= String.format("%,d원", delivery_fee) %><br> <%-- String의 format() 메서드를 이용해 세 자리마다 쉼표 찍기 --%>
		총 구매 비용(배송비 포함) : <%= String.format("%,d원", sum) %><br>
<%
	} // end of if
%>
</body>
</html>
response
  1. 새 JSP 파일 s09_responseA.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 리다이렉트시 생략 가능한 영역 시작 --%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>response.sendRedirect() 테스트</title>
</head>
<body>
현재 페이지는 s09_responseA.jsp 입니다. 화면에 보여지지 않습니다.
</body>
</html>
<%-- 리다이렉트시 생략 가능한 영역 끝 --%>
<%
	// response.sendRedirect("/jspMain/ch03-nestedObject/s10_responseB.jsp"); // 이동할 페이지의 경로를 Context Root부터 명시
	response.sendRedirect("s10_responseB.jsp"); // 이동할 페이지가 같은 경로에 있으면 파일명만 명시 가능
%>
  1. 새 JSP 파일 s10_responseB.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>s10_responseB.jsp</title>
</head>
<body>
현재 페이지는 s10_responseB.jsp 입니다.
</body>
</html>

3-1 디렉티브

출력 버퍼와 응답
  1. 새 JSP 파일 s11_autoFlushFalse.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page buffer="1kb" autoFlush="false" %> <%-- java.io.IOException 발생(JSP 버퍼 오버플로우) --%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>autoFlush 속성값 false 예제</title>
</head>
<body>
<%
	for(int i=0;i<1000;i++) {
%>
1234
<%
	}
%>
</body>
</html>
  1. 새 JSP 파일 s12_autoFlushTrue.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page buffer="1kb" autoFlush="true" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>autoFlush 속성값 true 예제</title>
</head>
<body>
<%
	for(int i=0;i<1000;i++) {
%>
1234
<%
	}
%>
</body>
</html>

3-3 기본 객체

out
  1. s13_bufferInfo.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>버퍼 정보</title>
</head>
<body>
버퍼 크기 : <%= out.getBufferSize() %><br>
남은 버퍼 크기 : <%= out.getRemaining() %><br> <%-- getRemaining() 메서드는 메서드가 호출된 시점에서의 남은 버퍼 크기를 반환 --%>
autoFlush : <%= out.isAutoFlush() %><br>
남은 버퍼 크기 : <%= out.getRemaining() %>
</body>
</html>
pageContext
application
exception

3-4 기본 객체와 영역

기본 객체 영역
pageContext 하나의 JSP 페이지를 처리할 때 사용되는 영역
request 하나의 HTTP 요청을 처리할 때 사용되는 영역
session 하나의 웹 브라우저와 관련된 영역
application 하나의 웹 어플리케이션과 관련된 영역
  1. 새 JSP 파일 s14_scopeA.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSP 4개 기본 객체와 영역</title>
</head>
<body>
<%
	pageContext.setAttribute("msg1", "봄"); // setAttribute() 메서드에 속성명과 값을 인자로 전달하면 객체에 해당 속성을 저장
	request.setAttribute("msg2", "여름");
	session.setAttribute("msg3", "가을");
%>
page 영역 msg1 = <%= pageContext.getAttribute("msg1") %><br> <%-- getAttribute() 메서드에 속성명을 인자로 전달하면 값을 반환 --%>
request 영역 msg2 = <%= request.getAttribute("msg2") %><br>
session 영역 msg3 = <%= session.getAttribute("msg3") %>
</body>
</html>
  1. 새 JSP 파일 s15_scopeB.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSP 4개 기본 객체와 영역</title>
</head>
<body>
page 영역 msg1 = <%= pageContext.getAttribute("msg1") %><br> <%-- pageContext의 영역은 하나의 JSP 페이지와 일대일 대응; s14_scopeA와 별개의 페이지이므로 속성이 공유되지 않아 null 반환 --%>
request 영역 msg2 = <%= request.getAttribute("msg2") %><br> <%-- request의 영역은 하나의 JSP 페이지와 일대일 대응; s14_scopeA와 별개의 HTTP 요청이므로 속성이 공유되지 않아 null 반환; include, forward 액션 태그를 사용해서 영역 확장 가능 --%>
session 영역 msg3 = <%= session.getAttribute("msg3") %><br> <%-- session의 영역은 하나의 클라이언트(=브라우저)와 일대일 대응; s14_scopeA를 실행했던 브라우저가 종료되기 전까지는 속성이 공유되어 값을 반환; 브라우저 종료 후 재시작시 클라이언트가 변경된 것으로 인식됨 --%>
</body>
</html>
  1. 새 JSP 파일 s16_setApplication.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>application 속성 지정</title>
</head>
<body>
<%
	application.setAttribute("user_id", "star");
%>
application에 속성 저장 완료!
</body>
</html>
  1. 새 JSP 파일 s17_getApplication.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.Enumeration" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>application 기본 객체 속성 보기</title>
</head>
<body>
<%
	// application의 모든 속성명 구하기
	Enumeration attrEnum = application.getAttributeNames();
	while(attrEnum.hasMoreElements()) {
		// 속성명 구하기
		String name = (String)attrEnum.nextElement();
		// 값 구하기
		Object value = application.getAttribute(name);
%>
		application 속성 : <b><%= name %></b> = <%= value %><br> <%-- 웹 어플리케이션 하나당 application 객체가 1개 생성되며, 공유 범위가 가장 넓음; 서버가 종료되기 전까지 객체가 유지됨 --%>
<%
	}
%>
</body>
</html>

다음으로