1. append/appendTo, prepend/prependTo

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>메소드 연습 예제</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
    // 마지막에 새로운 요소 추가
    $(".box1 ul").append("<li>C/C++</li>");
    $("<li>HTML 5</li>").appendTo(".box2 ul");

    // 첫 번째에 새로운 요소 추가
    $(".box3 ul").prepend("<li>JSP/Servlet</li>");
    $("<li>ORACLE</li>").prependTo(".box4 ul");
})

</script>

</head>
<body>

<h3>조작(Manipulation)</h3>

<div class="box box1">
    <ul>
        <li>자바</li>
        <li>스프링</li>
    </ul>
</div>

<div class="box box2">
    <ul>
        <li>javascript</li>
        <li>css</li>
    </ul>
</div>

<div class="box box3">
    <ul>
        <li>ASP.NET</li>
        <li>PHP</li>
    </ul>
</div>

<div class="box box4">
    <ul>
        <li>MariaDB</li>
        <li>MySQL</li>
    </ul>
</div>    

</body>
</html>

2. before, after

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>메소드 연습 예제</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
    var a = 0, b = 0;

    $(".btn1").click(function () {
        $("p.p2").before("<p>앞-"+(++a)+"번째 문장 추가</p>");
    });

    $(".btn2").click(function () {
       $("p.p2").after("<p>뒤-"+(++b)+"번째 문장 추가</p>"); 
    });

});

</script>

</head>
<body>

<h3>조작(Manipulation)</h3>

<div style="margin: 20px;">
    <button type="button" class="btn btn1"> Node.js 앞에 추가 </button>
    <button type="button" class="btn btn2"> Node.js 뒤에 추가 </button>
</div>
<hr>

<p class="p1">자바스크립트</p>
<p class="p2">Node.js</p>
<p class="p3">vue.js</p>

</body>
</html>

3. wrap, wrapAll, wrapInner

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>메소드 연습 예제</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<style type="text/css">
*{
    padding: 0; margin: 0;
}

body {
    font-size:14px;
    font-family:"맑은 고딕", 나눔고딕, 돋움, sans-serif;
}

a {
    color: #000;
    text-decoration: none;
}
a:hover, a:active {
    color: tomato;
    text-decoration: underline;
}

.btn{
    color:#333;
    font-weight:500;
    border:1px solid #ccc;
    background-color:#fff;
    text-align:center;
    cursor:pointer;
    padding:3px 10px 5px;
    border-radius:4px;
}

ul {
    list-style: none;
}
li{
    padding: 0;
}

h3{
    margin: 30px;
}

.box{
    box-sizing: border-box;
    width: 350px;
    min-height: 50px;
    margin: 20px auto;
    border: 3px dotted gray;
    padding: 15px; 
}

label {
    background: yellow;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
   // p태그를 각각 새로운 div로 감싸기
   $(".btn1").click(function () {
       $("p").wrap("<div class='box'></div>");
   });

   // 모든 ul을 하나의 div로 감싸기. ul 사이에 p태그 등이 존재하면 모든 ul은 묶고 p 태그는 아래로 간다.
   $(".btn2").click(function () {
       $("ul").wrapAll("<div class='box'></div>");
   });

   // 선택한 요소 안을 감싸기
   $(".btn3").click(function () {
      $("p").wrapInner("<label></label>"); 
   });
});

</script>

</head>
<body>

<h3>조작(Manipulation)</h3>

<div style="margin: 20px;">
    <button type="button" class="btn btn1"> p 태그를 각 div로 감싸기 </button>
    <button type="button" class="btn btn2"> 모든 ul태그를 하나의 div로 감싸기 </button>
    <button type="button" class="btn btn3"> p 태그 안에 label 태그 추가 </button>
</div>
<hr>

<p>자바스크립트</p>
<p>CSS</p>
<hr>

<ul>
    <li>자바</li>
    <li>스프링</li>
</ul>

<h4>데이터베이스</h4>

<ul>
    <li>오라클</li>
    <li>MYSQL</li>
</ul>

</body>
</html>

4. clone

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>메소드 연습 예제</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
    $("ul li").click(function() {
		alert($(this).text());
	});
	
	$(".btn").click(function() {
		// box1의 ul을 복사하여 box2에 추가. 
		$(".box1 ul").clone().appendTo(".box2"); 
		// 이벤트는 복제되지 않음. 실행순서가 늦어서..
		
		// box3의 ul을 복사하여 box4에 추가. 이벤트도 복제
		$(".box3 ul").clone(true).appendTo(".box4");
	});
});

</script>

</head>
<body>
<h3>조작(Manipulation)</h3>
<div style="margin: 20px;">
    <button type="button" class="btn"> 복사하기 </button>
</div>
<hr>

<div class="box box1">
    <ul>
        <li>자바</li>
        <li>스프링</li>
        <li>파이썬</li>
    </ul>
</div>
<div class="box box2"></div>

<div class="box box3">
    <ul>
        <li>HTML</li>
        <li>javascript</li>
        <li>css</li>
    </ul>
</div>
<div class="box box4"></div>


</body>
</html>

 

Selector

DOM의 요소( element )를 선택.

 

DOM(Document Object Model)

- HTML 문서의 요소를 제어하기 위해 웹 브라우저에서 처음 지원

- DOM은 동적으로 문서의 내용, 구조, 스타일에 접근하고 변경하기 위한 방법

- 브라우저별로 DOM 구현이 호환되지 않음에 따라, W3C에서 DOM 표준 규격을 작성

 

기본 셀렉터

#id : 지정된 아이디를 가지는 엘리먼트와 일치하는 셀렉터.

element : 모든 <element> 엘리먼트와 일치하는 셀럭터(태그 등)

.class : 지정된 클래스명을 가지는 요소를 선택.

* : 모든 엘리먼트를 선택한다.

 

예제

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<style type="text/css">
* {
	padding: 0; margin: 0; box-sizing: border-box;
}
body {
	font-style: 14px;
	font-family: 맑은 고딕, 나눔고딕, 돋움, sans-serif;
}
a {
	color: #000; text-decoration: none;
}
a:hover, a:acrive {
	color: tomato; text-decoration: underline;
}
h3 {
	margin: 10px;
}

span, label {
	display: block;
}
.box {
	width: 350px; min-height: 50px; margin: 20px auto; padding: 15px;
	border: 3px dotted gray; 
}
</style>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">

// 실행 안됨. DOM이 준비 되지 않았으므로
// $("p").css("border", "1px solid #777");
	
// DOM이 로딩 되었을 때 실행
$(function() {
	// 모든 요소
	$("*").css({color:"#333", "font-size":"13px"}); 
	// {}는 자바스크립트에서 객체
	
	// 태그 선택자
	$("p").css("border","2px dashed #333");
	
	// id 선택자
	$("#layout1").css({width:'300px', padding:'10px', border:'2px solid green'});
	
	// class 선택자
	$(".red").css("color", "red");
	
	// AND
	$("label.underline").css("text-decoration", "underline");
	
	// 바로 아래 자식 하나
	$("div > label").css("color", "tomato");
	
	// 모든 자식(손자도 포함)
	$("div label").css("background", "#ff0");
	
	// 인접 형제. 바로 다음 형제 하나
	$("label + span").css("border", "1px dashed red")
	
	// 다음에 나오는 일반 형제
	$("label ~ span").attr("title", "과목");
	
});

</script>

</head>
<body>

<h3> selector</h3>

<div class="box">
	<div id="layout1">
		<label>프로그래밍</label>
		<span class="red">자바</span>
		<span>C언어</span>
		<span class="underline">코틀린</span>
		<p>
			<label class="red underline">데이터베이스</label>
			<span>오라클</span>
			<span>MySQL</span>
			<span>빅데이터</span>
		</p>
	</div>
	<div id="layout2">
		<label>웹</label>
		<span>HTML</span>
		<span>CSS</span>
		<span>JavaScript</span>
		<p>
			<label>웹프로그래밍</label>
			<span>JSP</span>
			<span>PHP</span>
			<span>ASP.NET</span>
		</p>
		<p>
			<span>React</span>
			<label>기타</label>
			<span>jQuery</span>
		</p>
	</div>
	
</div>
</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<style type="text/css">
* {
	padding: 0; margin: 0; box-sizing: border-box;
}
body {
	font-style: 14px;
	font-family: 맑은 고딕, 나눔고딕, 돋움, sans-serif;
}
a {
	color: #000; text-decoration: none;
}
a:hover, a:acrive {
	color: tomato; text-decoration: underline;
}
h3 {
	margin: 10px;
}

.box {
	width: 350px; min-height: 50px; margin: 20px auto; padding: 15px;
	border: 3px dotted gray; 
}

.box span, .box label {
	display: block;
}

</style>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">

// 실행 안됨. DOM이 준비 되지 않았으므로
// $("p").css("border", "1px solid #777");
	
// DOM이 로딩 되었을 때 실행
$(function() {
	// span 태그의 글자색을 tomato로
	$("span").css("color", "tomato");
	
	// span 태그와 label 태그의 글자에 밑줄
	$("span, label").css("text-decoration", "underline");
	
	// div1 아이디의 글자색을 blue
	$("#div1").css("color", "blue");
	
	// div2 아이디의 글자를 진하게
	$("#div2").css("font-weight", "700");
	
	// c1 클래스의 배경색을 yellow로
	$(".c1").css("background", "yellow");
	
	// input 요소 중 name=subject인 요소
	$("input[name=subject]").css("background", "#eee");
	
	// form의 input 요소 중 name 속성을 가진 요소
	$("form input[name]").css("border", "none");
	
	// form의 input 요소 중 type=text와 type=password인 요소
	$("form input[type=text], form input[type=password]").css("border-bottom", "1px solid blue");
	
	// form의 input 요소 중 name 속성 값이 'a'로 시작하는 요소
	$("form input[name^=a]").css("border-right", "3px solid red");
	
	// form의 input 요소 중 title 속성 값이 '버튼'으로 끝나는 요소
	$("form input[title$='버튼']").css("border-left", "3px solid black");
	
	// form의 input 요소 중 name 속성 값이 'x'가 포함된 요소
	$("form input[name*=x]").css("border-left", "3px solid black");
	
	// form의 input 요소 중 title 속성 값에 '내용'이라는 단어(띄어쓰기 구분)가 들어간 요소
	$("form input[title~='내용']").css("background", "yellow");
	
	
});

</script>

</head>
<body>

<h3> selector</h3>

<div class="box">
	<div id="div1">테스트 1</div>	
	<div id="div2" class="c1">테스트 2</div>
	<span>테스트 3</span>
	<span>테스트 4</span>
	<div id="div3" class="c1">테스트 5</div>
	<span class="c1">테스트 6</span>
	<span class="c2">테스트 7</span>
</div>
<hr>

<div class="box">
	<p> <input type="text" name="subject" title="과목 입력"> </p>
	<form>
		<p> <input type="text" name="subject" title="과목 입력"> </p>
		<p> <input type="text" name="ax1" title="1장 제목 입력"> </p>
		<p> <input type="text" name="as2" title="1장 내용 입력"> </p>
		<p> <input type="text" name="bs1" title="2장 제목 입력"> </p>
		<p> <input type="text" name="bx2" title="2장 내용 입력"> </p>
		<p> <input type="password" name="pwd" title="패스워드 입력"> </p>
		<p> <input type="file" name="selectFile"> </p>
		<p>
			<input type="button" value="입력완료" title="입력 버튼">
			<input type="reset" value="다시입력" title="리셋 버튼">
		</p>
	</form>
</div>

</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<style type="text/css">
*{
	padding: 0; margin: 0;
}

body {
    font-size:14px;
	font-family:"맑은 고딕", 나눔고딕, 돋움, sans-serif;
}

a {
	color: #000;
	text-decoration: none;
}
a:hover, a:active {
	color: tomato;
	text-decoration: underline;
}

h3 {
	margin: 10px;
}

.btn {
	color:#333;
	font-weight:500;
	border:1px solid #ccc;
	background-color:#fff;
	text-align:center;
	cursor:pointer;
	padding:3px 10px 5px;
	border-radius:4px;
	font-family:"Malgun Gothic", "맑은 고딕", NanumGothic, 나눔고딕, 돋움, sans-serif;
}
.btn:active, .btn:focus, .btn:hover {
	background-color:#e6e6e6;
	border-color: #adadad;
	color: #333;
}

textarea:focus, input:focus{
	outline: none;
}
.boxTF {
	border:1px solid #999;
	padding:3px 5px 5px;
	border-radius:4px;
	background-color:#fff;
	font-family:"Malgun Gothic", "맑은 고딕", NanumGothic, 나눔고딕, 돋움, sans-serif;
}

.box{
	box-sizing: border-box;
	width: 500px;
	min-height: 50px;
	margin: 20px auto;
	border: 3px dotted gray;
	padding: 15px; 
}
</style>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
	$("form input + span").hide();
	$("form input[type=text]").css("border", "1px solid #aaa");
	
	// focus 이벤트. button 제외
	$("form input").not($(":button")).focus(function() {
		$(this).css("border", "1px solid #f28011");
		// 이벤트를 발생시킨 바로 다음 형제중 span 태그
		$(this).next("span").show();
	});
	
	// blur 이벤트. button 제외
	$("form input").not($(":button")).blur(function() {
		$(this).css("border", "1px solid #aaa");
		// 이벤트를 발생시킨 바로 다음 형제중 span 태그
		$(this).next("span").hide();
	});
});

</script>

</head>
<body>

<h3>selectors 예제</h3>

<div class="box">
<form>
	<p>
		<input type="text" name="id">
	    <span>아이디 입력.</span>
	    <span>5~10자 이내</span>
	</p>
	<p>
		<input type="text" name="name">
		<span>이름 입력.</span>
	</p>
	<p>
		<input type="text" name="age">
		<span>나이 입력.</span>
	</p>
	<p>
		<input type="text" name="birth">
		<span>생년월일 입력.</span>
	</p>
	<p style="padding: 5px;">
	<!-- 
		<button type="button" class="btn"> 등록하기 </button>
		<button type="button" class="btn"> 등록취소 </button>
	-->
		<input type="button" class="btn" value="등록하기">		
		<input type="button" class="btn" value="등록취소">		
	</p>
</form>
</div>

</body>
</html>

focus 이벤트에서 button을 제외

blur이벤트에서 button을 제외

 

이외 filter 가 여러가지 있음. 

 

선택된 요소 접근 메소드

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<style type="text/css">
*{
	padding: 0; margin: 0;
}

body {
    font-size:14px;
	font-family:"맑은 고딕", 나눔고딕, 돋움, sans-serif;
}

a {
	color: #000;
	text-decoration: none;
}
a:hover, a:active {
	color: tomato;
	text-decoration: underline;
}

.btn{
    color:#333;
    font-weight:500;
    border:1px solid #ccc;
    background-color:#fff;
    text-align:center;
    cursor:pointer;
    padding:3px 10px 5px;
    border-radius:4px;
}

ul {
	list-style: none;
}
li{
	padding: 0;
}

h3{
	margin: 30px;
}

.box{
	box-sizing: border-box;
	width: 350px;
	min-height: 50px;
	margin: 20px auto;
	border: 3px dotted gray;
	padding: 15px; 
}
</style>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
	$(".btnOk").click(function() {
		// var name = $(".std").html(); // html 소스 반환(innerHTML 속성)
		var name = $(".std").text(); // 텍스트만 반환
		
		// 속성값 가져오기
		var num = $(".std").attr("data-num");
		
		// document.getElementById("score").value = 90;
		$("#score").val(90); // value 속성에 값 설정
		
		// value 속성 값 가져오기
		var subject = $("#subject").val();
		var score = $("#score").val();
		
		var s = "<p>학번 : <b>" + num + "</b></p>";
		s +="<p>이름 : <b>" + name + "</b></p>";
		s +="<p>과목 : <b>" + subject + "</b></p>";
		s +="<p>점수 : <b>" + score + "</b></p>";
		
		// 텍스트 설정
		// $("#layout").text(s);
		
		// html 콘텐츠 설정
		$("#layout").html(s);
		
	});
	
})

/*
-- 선택된 요소 접근 
  .html() : 해당 요소의 HTML 콘텐츠를 반환하거나 설정한다.
  .text() : 해당 요소의 텍스트 콘텐츠를 반환하거나 설정한다.
  .val() : <form>요소의 값을 반환하거나 설정한다
  .attr() : 해당 요소의 명시된 속성의 속성값을 반환하거나 설정한다.
  .width() : 선택한 요소 중에서 첫 번째 요소의 너비를 픽셀 단위의 정수로 반환하거나 설정한다.
  .height() : 선택한 요소 중에서 첫 번째 요소의 높이를 픽셀 단위의 정수로 반환하거나 설정한다.
  .position() : 선택한 요소 중에서 첫 번째 요소에 대해 특정 위치에 존재하는 객체를 반환한다.(getter 메소드)

-- 메소드 체이닝(method chaining)
  여러 개의 메소드가 연속으로 호출되는 것
  예 : $("ul").find("li").eq(1).append("자바");
*/
</script>

</head>
<body>

<h3>선택된 요소 접근</h3>
<div style="margin: 20px;">
	<button type="button" class="btn btnOk"> 확인 </button>
</div>
<hr>

<div class="box">
	<p>
		<!-- data-* : 개발자에 의해 만들어진 속성 -->
	    <span class="std" data-num="1"><b>홍길동</b></span>
	</p>
	<p> <input type="text" id="subject" value="자바"> </p>
	<p> <input type="text" id="score"> </p>
</div>

<div class="box">
	<p>결과</p>
	<div id="layout"></div>
</div>

</body>
</html>

jQeury 개요

- jQuery는 빠르고 간결한 JavaScript Library 이다.

- HTML document traversing(탐색), 이벤트 처리, 애니메이션, AJAX를 단순화하여 빠른 웹 개발을 가능하게 한다.

- 다양한 브라우저 지원

- 경량 파일(90kb 수준의 파일크기)

- CSS3 규격 지원

- 존 레식에 의해 개발

 

jQuery를 사용하기 위한 라이브러리 포함

<script type="text/javascript" src="jquery-1.12.4.min.js"></script> 

 

CDN(Content Delivery Network)을 이용 jQuery 라이브러리 포함

<script src="http://code.jquery.com/jquery-3.6.0.min.js"></script>

 

core 예제

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

<script type="text/javascript">
// DOM이 로드 될 때 실행
/*
// 이벤트 핸들러 프로퍼티 방식
// 테스트-2 만 실행
window.onload = function() {
	console.log("테스트-1");
};

window.onload = function() {
	console.log("테스트-2");
};
*/

/*
// addEventListener
// 둘 다 실행
window.addEventListener("load", function() {
	console.log("테스트-1");
});
window.addEventListener("load", function() {
	console.log("테스트-2");
});
*/
/*
// jquery를 이용한 실행
// 둘 다 실행
jQuery(document).ready(function() {
	console.log("테스트-1")
});
jQuery(document).ready(function() {
	console.log("테스트-2")
});
*/
/*
// jQuery(document).ready(function(){}); 의 짧은 표현
jQuery(function(){
	console.log("테스트-1");
});
jQuery(function(){
	console.log("테스트-2");
});
*/
/*
// jQuery === $
$(function(){
	console.log("테스트-1");
});
$(function(){
	console.log("테스트-2");
});
*/
/*
$(document).ready(function() {
	// DOM 객체만 로드 되면 바로 실행
	console.log("테스트-1");
});
$(window).on("load", function() {
	// 해당 페이지의 모든 외부 리소스(이미지, css 등)가 로드 된 후 실행
	// $(function(){}); 보다 느림
	console.log("테스트-2");
})
*/

$(function() {
	$(document.body).css("background", "#eee");
});
</script>

</head>
<body>

<h3> jQuery Core 예제</h3>
<p>
  jQuery( elements ), $( elements )
</p>

<p>
  $() = $(document).ready() = jQuery() = jQuery(document).ready()
</p>

</body>
</html>

 

 

파일업로드를 위한 <form> 태그

<form> 태그의 enctype 속성

- <form> 태그 안에 정의된 요청 파라미터를 클라이언트에서 서버로 전송할 때 인코딩 방법을 지정한다.

- HTTP 헤더의 Content-Type 을 지정하여 서버에 어떤 종류의 데이터가 전송되는지를 전달한다.

- method="post"인 경우에만 이 속성은 유효하다.

- 속성 값

1) application/x-www-form-urlencoded

기본 enctype 속성으로 요청 파라미터는 key1=value1&key2=value2 형태로 나열된다.

공백은 +, 영숫자가 아닌 문자는 %HH(문자코드의 16진수 2자리)로 인코딩하여 전송한다.

이 content type은 바이너리 데이터(파일 등) 전송에서는 사용할 수 없다.

2) multipart/form-data

문자 인코딩을 하지 않고 전송되며, 파일을 전송할 때 사용한다.

여러 형태의 데이터 (파일 내용, 텍스트 입력 값 등)가 동시에 전달되며 각 데이터는 boumdary=...(경계정보) 뒤에 붙은 문자열을 이용하여 구분한다.

3) text/plain 

공백이 +문자로 변환되며 특수 문자를 인코딩 하지 않는다.

 

예제 (ch09)

더보기

ex01

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>파일 업로드</h3>
<%--
  - form 태그에서 enctype을 생략하면 기본이 application/x-www-form-urlencoded
  - application/x-www-form-urlencoded 속성 값은 파라미터를 주소형식으로 인코딩하여 전송
    파라미터는 "이름1=값1&이름=값2" 형태로 body영역에 실어서 전송된다.
  - application/x-www-form-urlencoded 속성 값에서 파일을 서버로 전송하면 파일 이름만 전송 된다.
  - enctype 속성은 method가 post인 경우만 유효
 --%>

<form action="ex01_ok.jsp" method="post" >
<p> 제목 : <input type="text" name="subject"> </p>
<p> 파일 : <input type="file" name="selectFile"> </p>
<p>
	<button type="submit">등록하기</button>
</p>

</form>

</body>
</html>

ex01_ok

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
	request.setCharacterEncoding("utf-8");
	
	// request.getParameter()는 문자열만 전달 받는다.
	String subject = request.getParameter("subject");
	// 파일은 enctype="application/x-www-form-urlencoded" 에서는 이름만 전송 받는다.
	String selectFile = request.getParameter("selectFile");
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>요청 받은 정보</h3>

<p>제목 : <%= subject %> </p>
<p>파일 : <%=selectFile %> </p>

</body>
</html>

 위 예제를 통해서 파일을 전달 받지 못하는 것을 알 수 있다. 파일의 이름만을 받았음.

 

ex02

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>파일 업로드</h3>
<%--
  * form 태그에서 enctype이 multipart/form-data인 경우
    - 문자 인코딩을 하지 않고 전송하며, 파일을 전송할 때 사용
    - 피일의 내용도 전송된다.
  * enctype 속성은 method가 post인 경우만 유효
  
 --%>

<form action="ex02_ok.jsp" method="post" enctype="multipart/form-data">
<p> 제목 : <input type="text" name="subject"> </p>
<p> 파일 : <input type="file" name="selectFile"> </p>
<p>
	<button type="submit">등록하기</button>
</p>

</form>

</body>
</html>

ex02_ok

<%@page import="java.net.URLDecoder"%>
<%@page import="java.io.InputStream"%>
<%@page import="java.util.Enumeration"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
	request.setCharacterEncoding("utf-8");
	
	// enctype="multipart/form-data"로 넘어온 파라미터는 request.getParameter()로 받을 수 없다.
	// String subject = request.getParameter("subject");
	// String selectFile = request.getParameter("selectFile");
	
	
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>요청 받은 정보</h3>

<%
	String contentType = request.getContentType();
	out.print("<p>contentType : " + contentType + "</p>");
	out.print("<hr>");
	
	out.print("<h3>[[헤더 정보들]]....</h3>");
	Enumeration<String> e = request.getHeaderNames();
	while(e.hasMoreElements()) {
		String name = e.nextElement();
		String value = request.getHeader(name);
		out.print("<p>" + name + " : " + value + "</p>");
	}
	out.print("<hr>");
	
	out.print("<h3>[[request Body 영역으로 넘어온 데이터]]</h3>");
	
	InputStream is = request.getInputStream();
	byte[] buf = new byte[2048];
	int size;
	String str;
	while( (size = is.read(buf)) != -1) {
		// enctype = "application/x-www-form-urlencoded" 인 경우
		// str = new String(buf, 0, size);
		// str = URLDecoder.decode(str, "utf-8");
		
		// enctype = "nultipart/form-data" 인 경우
		str = new String(buf, 0, size, "utf-8");
				
		out.print("<p>" + str + "</p>");
	}
	out.print("<hr>");
	
%>

</body>
</html>

파일이 넘어왔음을 알 수 있다.

 

cos.jar을 이용한 업로드 (권장하지 않음)

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>파일 업로드</h3>
<%--
  * cos.jar를 이용한 업로드
    http://servlets.com 
 --%>

<form action="ex03_ok.jsp" method="post" enctype="multipart/form-data">
<p> 제목 : <input type="text" name="subject"> </p>
<p> 파일 : <input type="file" name="selectFile"> </p>
<p>
	<button type="submit">등록하기</button>
</p>

</form>

</body>
</html>
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@page import="java.io.File"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
	request.setCharacterEncoding("utf-8");

	// String root = pageContext.getServletContext().getRealPath("/"); 도 가능
	String root = session.getServletContext().getRealPath("/");
	String pathname = root + "uploads" + File.separator + "pds";
	File f= new File(pathname);
	if(! f.exists() ) {
		f.mkdirs();	
	}
	
	String encType = "utf-8"; // 클라이언트가 보낸 정보의 인코딩
	int maxFileSize = 5*1024*1024; // 최대 업로드 용량(5MB)
	
	MultipartRequest mreq = null;
				// request, 파일저장경로, 파일최대크기, 인코딩, 중복파일명보호
	mreq = new MultipartRequest(request, pathname, maxFileSize, encType, 
			new DefaultFileRenamePolicy() );
	
	// 제목 
	String subject = mreq.getParameter("subject");
	
	// 서버에 저장된 파일 이름
	String saveFilename = mreq.getFilesystemName("selectFile");
	
	// 클라이언트가 올린 파일 이름
	String originalFilename = mreq.getOriginalFileName("selectFile");
	
	// 파일 크기
	long fileSize = 0;
	File file = mreq.getFile("selectFile"); // 업로드된 파일에 대한 File 객체
	if(file != null) {
		fileSize = file.length();
	}
	

%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>파일 업로드 결과 : cos.jar</h3>

<p> 제목 : <%=subject%> </p>
<p> 클라이언트가 올린 파일 이름 : <%=originalFilename %></p>
<p> 서버에 저장된 파일 이름 : <%=saveFilename %></p>
<p> 파일 크기 : <%=fileSize %>byte.</p>


</body>
</html>

 

세션이란 ? 

- 둘 이상의 page request에서 사용자를 식별하거나, 웹 사이트를 방문하고 해당 사용자에 대한 정보를 저장하는 방법을 제공한다.

- Servlet container는 HttpSession을 사용하여 Http client - HTTP server간의 세션을 생성한다.

- 세션은 한 명의 사용자에 해당한다. (브라우저 당 하나의 세션 객체가 생성된다.)

- 서버는 Cookie, rewriting URL과 같은 방법으로 세션을 유지하면서 관리할 수 있다.

- 객체를 세션에 바인딩하여 사용자 정보를 유지할 수 있다.

 

톰캣의 세션 동작 원리

- session.isNew() 메소드는 세션이 생성된 곳에서 아직 클라이언트가 세션 ID를 모르는 상태(최초 접속 상태)의 경우 "true"를 반환한다.

- 이 경우 아직 클라이언트 정보가 서버에 유지되지 않기 때문에, 서버는 Response Headers에 JSESSIONID 이라는 이름으로 쿠키 정보를 client로 전달한다.

- session.isNew() 메소드는 "false"를 반환하면 이미 세션이 설정되어있는 경우이며, 이 경우 client브라우저는 로컬에 저장되어 있는 JSESSIONID 쿠키 값을 request header에 담아 서버로 전송한다.

- 서버는 client로 부터 JSESSJIONID 쿠키 값을 전달 받으면 response로 JSESSIONIS 쿠키 값을 client로 보내지 않는다.

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3> 세션 동작 원리 </h3>

<!-- isNew() :  클라이언트가 세션 ID를 모르는 상태(최초 접속)인 경우 true를 반환 --%>
<!-- isNew()가 true를 반환하면 클라이언트 정보가 서버에 저장되지 않은 상태이다. -->
<p> isNew() : <%= session.isNew() %></p>
<hr>

<h4>쿠키 내용</h4>
<%
	Cookie[] cc = request.getCookies();
	if(cc != null) {
		for(Cookie c : cc) {
			String name = c.getName();
			String value = c.getValue();
			out.print("<p>"+name+" : "+ value + "</p>");
		}
	}
%>

</body>
</html>

 

쿠키를 사용하지 않는 세션 ID의 관리

- 휴대 기기 등 모든 단말이 쿠키를 사용할 수 있는 것은 아니다.

- 쿠키를 사용할 수 없는 경우 URL에 직접 세션 ID를 작성하여 세션 ID를 클라이언트 측에 유지시킨다.

구체적으로는 HttpServletResponse의 encodeURL (String url) 메소드를 사용한다.

PrintWriter writer = response.getWriter();

String link = "/main";

link = response.encodeURL(link);

writer.println("<a href = '"+link+"'>메인</a>");

encodeURL() 메소드를 사용하면 지정된 인수에 대해 다음의 값을 추가하며, 쿠키를 사용 못해도 클라이언트측에서 세션 ID를 보유할 수 있다.

jsessionid = 세션id

 

예제

더보기

sessionEx2

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>session : 클라이언트의 정보를 서버에 저장</h3>
<!-- 세션은 일반적으로 로그인 처리 등에서 이용된다. -->

<p>
  <a href="sessionSet.jsp">세션 설정</a> |
  <a href="sessionInfo.jsp">세션 확인</a> |
  <a href="sessionRemove.jsp">세션 제거</a>
</p>
</body>
</html>

sessionSet

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
	// session : 세션을 나타내는 JSP 내장 객체(HttpSession)
	// 서블릿에서 세션 객체 구하기 : HttpSession sess = request.getSession();
	// EL에서의 세션 객체 : sessionScope
	
	// 세션 유지시간 설정(톰캣 기본 세션 유지시간 : 30분)
	session.setMaxInactiveInterval(60*20); // 단위 : 초
	
	session.setAttribute("name", "홍자바");
	session.setAttribute("age", 20);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>session 설정</h3>

<p>
	<a href="sessionEx2.jsp">돌아가기</a>
</p>

</body>
</html>

sessionInfo

<%@page import="java.util.Date"%>
<%@page import="java.text.SimpleDateFormat"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
	String name = "";
	int age = 0;
	
	try {
		// 세션에 설정한 값 가져오기
		name = (String)session.getAttribute("name");
		age = (Integer)session.getAttribute("age");
	} catch(Exception e) {
	}
	
	// 세션 유지시간
	int interval = session.getMaxInactiveInterval();
	
	// 세션 아이디
	String id = session.getId();
	
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
	
	// 세션 생성 시간
	Date date1 = new Date(session.getCreationTime());
	String create_date = sdf.format(date1);
	
	// 세션 마지막 접속 시간
	Date date2 = new Date(session.getLastAccessedTime());
	String last_date = sdf.format(date2);
	
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>session 정보</h3>

<p> 이름과 나이 : <%=name%>, <%=age%> </p>
<p> EL을 이용하여 세션 값 가져오기 : ${sessionScope.name}, ${sessionScope.age}</p>
<p> 세션 최대 유지시간 : <%=interval / 60 %>분 </p>
<p> 세션 아이디 : <%=id%></p>
<p> 세션 생성 시간 : <%=create_date %></p>
<p> 세션 마지막 접속 시간 : <%=last_date %></p>
<hr>

<p>
	<a href="sessionEx2.jsp">돌아가기</a>
</p>

</body>
</html>

sessionRemove

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
	// 세션에 저장된 속성값 지우기
	session.removeAttribute("name");
	session.removeAttribute("age");
	
	// 세션에 저장된 모든 속성값을 지우고 세션을 초기화
	session.invalidate();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3> session 지우기</h3>

<p>
	<a href="sessionEx2.jsp">돌아가기</a>
</p>

</body>
</html>

 

 

 

쿠키란?

- 쿠키는 클라이언트에 대한 정보를 클라이언트의 하드디스크에 저장한 text파일

- 쿠키는 텍스트 형태로 저장되기 때문에 변조, 복사 가능하여 보안성이 없다.

- 쿠키는 서버에서 사용자에게 편리한 기능을 제공하기 위해 많이 사용되고, 웹 브라우저에 의해 관리된다.

- 일반적으로 브라우저는 각 웹 서버 당 20개의 쿠키와 총 300개의 쿠키를 지원하며 쿠키 크기는 각각 4kb로 제한될 수 있다.

- 쿠키 정보는 javax.servlet.http.Cookie클래에 의해 관리 된다.

 

쿠키 설정하기

1) Cookie 객체를 생성한다. 생성자에 문자열로 쿠키이름과 값을 설정한다.

- 형식

 Cookie cookie = ew Cookie("key", "value");

- 이름과 값은 영수자와. 공백이나 다음 문자를 포함할 수 있다.

[] () = , " / ? @ : ;

2) setMaxAge(초) 메소드를 이용하여 쿠키 유효 기간을 초단위로 설정한다.

- 유료 기간을 설정하지 않으면 브라우저가 종료될 때까지 쿠키가 지속됨을 나타내는 -1 이다.

- 다음은 쿠키 유효시간을 24시간으로 설정한 예이다.

cookie.setMaxAge(60*60*24);

3) HTTP응답 헤더에 쿠키를 보낸다.

- HttpServletResponse 인터페이스의 addCookie() 메소드에 의해 HTTP 응답 헤더에 쿠키를 보낸다.

- JSP에서 쿠키를 설정하는 방법은 다음과 같다.

response.addCookie(cookie);

 

Cookie 유효 시간 설정

- setMaxAge(int expiry)메소드를 이요하여 유효시간 초 단위로 설정한다.

- expiry

음수 : 브라우저가 종료되면 쿠키가 제거된다.

0: 생성과 동시에 제거

양수 : 초 단위로 해당 시간만큼 유지된다.

설정하지 않은 경우 : 디폴트로 -1이 설정되어 브라우저가 종료할 때 까지 유효하다.

 

Cookie 설정 시 주의 사항

- 쿠키의 이름이나 값에 한글 등이 포함되는 경우 다음과 같이 java.net 패키지의 URLEncoder.encode()메소드를 이용하여 주소 형식으로 인코딩해야한다.

Cookie cookie = new Cookie("key", URLEncoder.encode("값", "utf-8");

- Cookie의 유효범위를 설정하지 않는 경우. 쿠키를 설정하는 페이지의 경로와 하위 경로에서만 접근가능하다. 

따라서 모든 경로에서 쿠키의 값을 반환 받을 경우에는 다음과 같이 유효 범위를 "/"로 설정한다.

cookie.setPath("/");

 

Cookie 가져오기 및 제거

- Cookie 가져오기

1) 쿠키를 가져오기 위해서는 HttpServletRequest 인터페이스의 getCookies()메소드를 이용해서 가져온다.

- getCookies() 메소드는 javax.servlet.http.Cookie객체의 배열을 반환한다.

- JSP 에서 쿠키 가져오기

Cookie []ck = request.getCookies();

2) 반환 받은 Cookie객체의 getName() 과 getValue() 메소드를 이용하여 쿠키를 가져 온다.

String name, value;
	if( ck!=null) {
		for(Cookie c : ck) {
			name = c.getName();
			value = c.getValue();
            			:
		}
	}

 

- Cookie 제거하기

쿠키 값을 제거하기 위해서는 쿠키에 대한 값을 지우고 유효기간을 만료시킨다.

JSP 에서 쿠키 제거 방법

Cookie cookie = new Cookie("제거할쿠키이름",null) // 쿠키 값 지우기

cookie.setMaxAge(0); // 유효시간 만료

response.addCookie(cookie): // HTTP 응답 헤더에 제거할 쿠키를 보낸다.

 

확인용 예제

더보기

cookieEx

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>cookie 예제</h3>

<p>
	<a href="setCookie.jsp">쿠키설정</a>
	<a href="getCookie.jsp">쿠키확인</a>
	<a href="removeCookie.jsp">쿠키제거</a>
</p>

</body>
</html>

setCookie

<%@page import="java.net.URLEncoder"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
	// 쿠키 설정 : 서버가 클라이언트 컴퓨터에 정보를 저장
	// 쿠키의 유효시간을 설정하지 않으면(life cycle), 브라우저가 종료되면 쿠키도 제거된다.
	Cookie c1 = new Cookie("subject", "java"); // 쿠키이름, 쿠키값 생성자를 이용해서 객체생성. 쿠키는 String만 가능
	response.addCookie(c1);
	
	Cookie c2 = new Cookie("subject2", "spring");
	c2.setMaxAge(60 * 60); // 1시간 : 쿠키 유효시간(단위 : 초)
	response.addCookie(c2);
	
	// 한글을 쿠키로 설정할 경우에는 반드시 인코딩
	Cookie c3 = new Cookie("subject3", URLEncoder.encode("오라클", "utf-8") );
	c3.setMaxAge(-1); // -1 : 브라우저가 종료되면 쿠키도 제거
	response.addCookie(c3);
	
	// 쿠키는 기본적으로 쿠키를 설정한 경로에서만 접근할 수 있다.
	Cookie c4 = new Cookie("tel", "010-1111-1111");
	c4.setPath("/"); // 모든 경로에서 쿠키를 접근 할 수 있도록 설정
	response.addCookie(c4);
	
	Cookie c5 = new Cookie("age", "20"); // 쿠키는 문자열만 가능하다. 숫자도 따옴표형식으로 넣어야함.
	c5.setMaxAge(0); // 쿠키 생성과 동시에 제거(일반적으로 쿠키를 제거할 때 사용)
	response.addCookie(c5);
	
	
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3> 쿠키 설정 </h3>
<p>
	<a href="cookieEx.jsp">돌아가기</a>
</p>

</body>
</html>

getCookie

<%@page import="java.net.URLDecoder"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>쿠키 가져오기 : 클라이언트 컴퓨터에 저장된 쿠키를 서버로 가져오기</h3>
<%
	Cookie[] cc = request.getCookies(); // 쿠키는 배열로 가져올 수 있따.
	if( cc != null ) {
		for(Cookie c:cc){
			String name = c.getName(); // 쿠키 이름
			String value = c.getValue(); // 쿠키 값
			if(name.equals("subject3")) {
				value = URLDecoder.decode(value, "utf-8");
			}
			
			out.print("<p>" + name + " : " + value + "</p>");
		}
	}
%>
<hr>

<p>
	<a href="cookieEx.jsp">돌아가기</a>
</p>

</body>
</html>

 

p1

<%@page import="java.net.URLEncoder"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
	Cookie c = new Cookie("sname1", URLEncoder.encode("컴퓨터", "utf-8") );
	response.addCookie(c);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>컴퓨터</h3>
<p> 컴퓨터중 최고의 성능</p>
<p> 제조사 : 삼성 </p>
<p> 가격 : 1,000,000 </p>
<hr>
<p><a href="shop.jsp">돌아가기</a></p>
</body>
</html>

p2

<%@page import="java.net.URLEncoder"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
	Cookie c = new Cookie("sname2", URLEncoder.encode("핸드폰", "utf-8") );
	response.addCookie(c);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>핸드폰</h3>
<p> 핸드폰중 최고의 성능</p>
<p> 제조사 : 삼성 </p>
<p> 가격 : 1,200,000 </p>
<hr>
<p><a href="shop.jsp">돌아가기</a></p>
</body>
</html>

p3

<%@page import="java.net.URLEncoder"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
	Cookie c = new Cookie("sname3", URLEncoder.encode("노트북", "utf-8") );
	response.addCookie(c);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>노트북</h3>
<p> 노트북중 최고의 성능</p>
<p> 제조사 : 삼성 </p>
<p> 가격 : 1,500,000 </p>
<hr>
<p><a href="shop.jsp">돌아가기</a></p>
</body>
</html>

게시판 URI 및 JSP 생각하기

 

1. URI 및 JSP
  1) 리스트
 uri : /cp/bbs/list.do
 jsp : /WEB-INF/views/bbs/list.jsp
 
  2) 글쓰기 폼
 uri : /cp/bbs/write.do
 jsp : /WEB-INF/views/bbs/write.jsp

  3) 글쓰기 완료
 uri : /cp/bbs/write_ok.do -> list.do 로 리다이렉트

  4) 글보기
 uri : /cp/bbs/article.do
 jsp : /WEB-INF/views/bbs/article.jsp
 
  5) 글수정 폼
 uri : /cp/bbs/update.do
 jsp : /WEB-INF/views/bbs/write.jsp  

  6) 글수정 완료
 uri : /cp/bbs/update_ok.do -> list.do 로 리다이렉트

  7) 글삭제
 uri : /cp/bbs/delete.do -> list.do 로 리다이렉트

 

2. 흐름도와 파라미터(클라이언트가 서버에 보내는 값)
  1) 리스트

- 리스트 --> 리스트 : 페이지번호클릭(페이지번호[, 검색컬럼, 검색값])
- 리스트 --> 리스트 : 검색(검색컬럼, 검색값)
- 리스트 --> 리스트 : 초기화(검색 해제)
- 리스트 --> 글쓰기폼 : 등록하기 버튼
- 리스트 --> 글보기 : 제목클릭(글번호, 페이지번호[, 검색컬럼, 검색값])

  2) 글쓰기폼
- 글쓰기폼 --> 등록하기 : 글저장 --> 리스트로 리다이렉트
                |
           (폼 데이터 : 제목, 작성자, 내용, 패스워드)
- 글쓰기폼 --> 등록취소 : 리스트로 가기

  3) 글보기
- 글보기 --> 리스트 : 리스트버튼(페이지번호[, 검색컬럼, 검색값])
- 글보기 --> 글보기 : 이전글/다음글(이전글/다음글번호, 페이지번호[, 검색컬럼, 검색값])
- 글보기 --> 수정폼 : 수정버튼(글번호, 페이지번호)
- 글보기 --> 글삭제 : 삭제버튼(페이지번호[, 검색컬럼, 검색값])

  4) 글수정폼
- 글수정폼 --> 수정완료 : 글수정버튼--> 리스트로 리다이렉트(글보기로 리다이렉트)
                |
         (폼 데이터 : 제목, 작성자, 내용, 패스워드, 글번호, 페이지번호) // 수정할게시글번호!!
- 글수정폼 --> 수정취소 : 리스트로 가기

  5) 글삭제 --> 리스트로 리다이렉트(페이지번호[, 검색컬럼, 검색값])

 

 

자유게시판으로 사용할 DB table

더보기

-- 게시판 테이블
CREATE TABLE bbs (
num NUMBER NOT NULL,
name VARCHAR2(30) NOT NULL,
pwd VARCHAR2(50) NOT NULL,
subject VARCHAR2(255) NOT NULL,
content VARCHAR2(4000) NOT NULL, -- 1300자 이상 저장을 위해서는 CLOB
ipAddr VARCHAR2(50) NOT NULL,
hitCount NUMBER DEFAULT 0,
reg_date DATE DEFAULT SYSDATE,
CONSTRAINT pk_bbs_num PRIMARY KEY(num)
);

-- 게시판 시퀀스
CREATE SEQUENCE bbs_seq
INCREMENT BY 1;
START WITH 1
NOMAXVALUE
NOCYCLE
NOCACHE;

 

페이징 처리에 사용하는 쿼리 Query

더보기

-- ORACLE :

 

아래 쿼리는 오라클에서 성능이 우수함
SELECT * FROM (
    SELECT ROWNUM rnum, tb.* FROM (
        SELECT num, name, subject, hitCount, 
            TO_CHAR(reg_date, 'YYYY-MM-DD') reg_date
        FROM bbs
        ORDER BY num DESC
    ) tb WHERE ROWNUM <= 끝
) WHERE rnum >= 시작;
-- 수정/삭제가 빈번히 일어나는 경우 index의 성능이 좋지 않음.

-- ORACLE 12C 이상 : 위 쿼리보다 성능이 좋지 않음
SELECT num, name, subject, hitCount,
    TO_CHAR(reg_date, 'YYYY-MM-DD') reg_date
FROM bbs
ORDER BY num DESC
OFFSET 30 ROWS FETCH FIRST 10 ROWS ONLY;
---------------------------------
-- MySQL
SELECT num, name, subject, hitCount,
    DATE_FORMAT(reg_date, '%Y-%m-%d') AS reg_date
FROM bbs
ORDER BY num DESC
LIMIT 건너뛸개수, 가져올개수;

 

페이징 처리 로직

 

Example

페이지당 게시글 10개

전체 데이터 개수 965개

-> 전체 페이지 개수는 97개

페이지당 게시글 10개

전체 데이터 개수 960개

-> 전체 페이지 개수는 96개

 

즉, (전체 데이터 개수 / 페이지당 게시글) 에서 소수점이하가 없으면 ( 나머지가 없으면) 몫만큼의 개수가 전체페이지 개수이고, 그렇지 않을경우는 +1을 해줘야 한다.

 

전체데이터개수/페이지당게시글 + (전체데이터개수%페이지당게시글== 0 ? 0 : 1);

// 자바에서 int는 정수형만 취급하므로 나누었을 때 소수가 표현되지 않음.

 

1페이지에는 1~10까지의 자료가 나온다.

2페이지는 11~20

3페이지는 21~30

:

n페이지 1+(n-1*10)~n*10 

 

package com.util;

public class MyUtil {
	/**
	 * 전체 페이지수 구하기
	 * @param rows			한화면에 출력할 목록 수
	 * @param dataCount		총 데이터 수
	 * @return				전체 페이지 수
	 */
	public int pageCount(int rows, int dataCount) {
		if(dataCount <= 0) {
			return 0;
		}
		
		return dataCount / rows +(dataCount % rows > 0 ? 1 : 0);
	}
	
	/**
	 * 페이징 처리(GET 방식)
	 * @param current_page	현재 표시되는 페이지 번호
	 * @param total_page	전체 페이지 수
	 * @param list_url		링크를 설정할 주소
	 * @return				페이지 처리 결과
	 */
	public String paging(int current_page, int total_page, String list_url) {
		StringBuilder sb = new StringBuilder();
		
		int numPerBlock = 10;
		int currentPageSetup;
		int n, page;
		
		if(current_page < 1 || total_page < 1) {
			return "";
		} // 데이터가 없으면 설정할 필요가 없음
		
		if(list_url.indexOf("?") != -1) {
			list_url += "&";
		} else {
			list_url += "?";
		}
		
		// currentPageSetup : 표시할 첫 페이지-1
		currentPageSetup = (current_page / numPerBlock) * numPerBlock;
		if(current_page % numPerBlock == 0) {
			currentPageSetup = currentPageSetup - numPerBlock;
		}
		
		sb.append("<div class='paginate'>");
		
		// 처음페이지, 이전(10페이지 전)
		n = current_page - numPerBlock;
		if(total_page > numPerBlock && currentPageSetup > 0) {
			sb.append("<a href='"+list_url+"page=1'>처음</a>");
			sb.append("<a href='"+list_url+"page="+n+"'>이전</a>");
		}
		
		// 페이징 처리
		page = currentPageSetup + 1;
		while(page <= total_page && page <= (currentPageSetup+numPerBlock)) {
			if(page == current_page) {
				sb.append("<span>"+page+"</span>");
			} else {
				sb.append("<a href='"+list_url+"page="+page+"'>"+page+"</a>");				
			}
			page++;
		}
		
		// 다음(10페이지 후), 마지막페이지
		n = current_page + numPerBlock;
		if(n > total_page) n = total_page;
		if(total_page - currentPageSetup > numPerBlock) {
			sb.append("<a href='"+list_url+"page="+n+"'>다음</a>");
			sb.append("<a href='"+list_url+"page="+total_page+"'>끝</a>");
		}
		
		sb.append("</div>");
		
		return sb.toString();
	}
	
}

 

 

테스트

더보기
<%@page import="com.util.MyUtil"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
	request.setCharacterEncoding("utf-8");

	// 파라미터로 넘어온 페이지번호(JSP에서 page는 예약어로 변수명으로 사용 불가)
	String pageNum = request.getParameter("page");
	int current_page = 1;
	if(pageNum != null) {
		current_page = Integer.parseInt(pageNum);
	}
	
	MyUtil util = new MyUtil();
	
	int dataCount = 965;
	int rows = 10;
	int total_page = util.pageCount(rows, dataCount);
	if(current_page > total_page) {
		current_page = total_page;
	}
	
	String listUrl = "list.jsp";
	String paging = util.paging(current_page, total_page, listUrl);
	
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<style type="text/css">
* {
	margin: 0; padding: 0;
	box-sizing: border-box;
}

body {
	font-size: 14px;
	font-family: 맑은 고딕, 나눔고딕, 돋움, sans-serif;
}

.paginate {
	text-align: center;
	font-size: 14px;
}

.paginate a {
	border: 1px solid #ccc;
	color: #000;
	font-weight: 600;
	text-decoration: none;
	padding: 3px 7px;
	margin-left: 3px;
	vertical-align: middle;
}

.paginate a:hover, .paginate a:active {
	color: #6771ff;
}

.paginate span {
	border: 1px solid #e28d8d;
	color: #cb3536;
	font-weight: 600;
	padding: 3px 7px;
	margin-left: 3px;
	vertical-align: middle;
}

.paginate :first-child {
	margin-left: 0;
}

.container {
	width: 700px;
	margin: 30px auto;
}

</style>


</head>
<body>

<div class="container">
	<h3>페이징 처리 테스트</h3>
	
	<div style="padding-top: 10px;">
		<%= paging %>
	</div>
</div>


</body>
</html>

+ Recent posts