Study Web Development

1월 12일

이전으로

Servlet & JSP

5. JSP와 DB 연동

5-1 JDBC

다이나믹 웹 프로젝트의 이름 변경
  1. 이클립스 하단의 Servers 탭에서 현재 작동 중인 서버를 오른쪽 클릭하여 Stop 선택
  2. 중단된 서버를 오른쪽 클릭하고 Add and Remove-Remove All-Finish 선택
    • Configured 항목에 있는 프로젝트들은 Tomcat과 연동 중이므로, Tomcat의 정보를 지워야 프로젝트명 변경 가능
  3. 프로젝트를 오른쪽 클릭하여 Refactor-Rename 선택
실습
  1. 새 JSP 파일 detailTest.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page import="java.sql.ResultSet" %>
<%@ page import="java.sql.Date" %>
<%@ page import="java.sql.SQLException" %>
<%@ include file="dbinfo.jspf" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 상세 정보</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<% 
	int num = Integer.parseInt(request.getParameter("num"));

	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	String sql = null;
	
	try {
		Class.forName(driverName);
		conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);
		sql = "SELECT * FROM product WHERE num=?";
		pstmt = conn.prepareStatement(sql);
		pstmt.setInt(1, num);
		rs = pstmt.executeQuery();
		if(rs.next()) {
%>
<div class="page-main">
	<h2 class="align-center">상품 상세 정보</h2>
	<hr style="border-style: solid; color: gray;"> <!-- <hr> 태그의 align, noshade, size, width 속성은 HTML5에서는 더 이상 지원되지 않으며, CSS로 제어됨 -->
	<ul>
		<li>상품 번호 : <%= num %></li>
		<li>상품명 : <%= rs.getString("name") %></li>
		<li>가격 : <%= String.format("%,d원", rs.getInt("price")) %></li>
		<li>재고 : <%= String.format("%,d개", rs.getInt("stock")) %></li>
		<li>원산지 : <%= rs.getString("origin") %></li>
		<li>등록일 : <span title="<%= rs.getString("reg_date") %>"><%= rs.getDate("reg_date") %></span></li>
	</ul>
	<hr style="border-style: solid; color: gray;">
	<div class="align-right">
		<input type="button" value="수정" onclick="location.href = 'updateTestForm.jsp?num=<%= num %>';">
		<input type="button" value="삭제" onclick="location.href = 'deleteTestForm.jsp?num=<%= num %>';">
		<input type="button" value="목록" onclick="location.href = 'selectTest.jsp';">
	</div>
</div>
<%
		}
		else {
%>
<div class="result-display">
	<div class="align-center">
		조회하려는 상품이 존재하지 않습니다!<br>
		<input type="button" value="이전 페이지" onclick="history.go(-1);">
		<input type="button" value="상품 목록" onclick="location.href = 'selectTest.jsp';">
	</div>
</div>
<%
		}
	}
	catch(Exception e) {
		e.printStackTrace();
%>
<div class="result-display">
	<div class="align-center">
		상품 상세 정보 조회에 실패했습니다!<br>
		3초 후 상품 목록 페이지로 이동합니다.
	</div>
</div>
<script type="text/javascript">
	setTimeout(function() {location.href = 'selectTest.jsp';}, 3000);
</script>
<%
	}
	finally {
		if(rs!=null) try {rs.close();} catch(SQLException e) {}
		if(pstmt!=null) try {pstmt.close();} catch(SQLException e) {}
		if(conn!=null) try {conn.close();} catch(SQLException e) {}
	}
%>
</body>
</html>
  1. 새 JSP 파일 updateTestForm.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page import="java.sql.ResultSet" %>
<%@ page import="java.sql.SQLException" %>
<%@ include file="dbinfo.jspf" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 정보 수정</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<%
	int num = Integer.parseInt(request.getParameter("num"));

	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	String sql = null;
	
	try {
		Class.forName(driverName);
		conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);
		sql = "SELECT * FROM product WHERE num=?";
		pstmt = conn.prepareStatement(sql);
		pstmt.setInt(1, num);
		rs = pstmt.executeQuery();
		if(rs.next()) {
%>
<div class="page-main">
	<h2 class="align-center">상품 정보 수정</h2>
	<form id="myForm" action="updateTest.jsp" method="post">
		<input type="hidden" name="num" value="<%= num %>">
		<ul>
			<li>
				<label for="name">상품명</label>
				<input type="text" name="name" id="name" value="<%= rs.getString("name") %>">
			</li>
			<li>
				<label for="price">가격</label>
				<input type="number" name="price" id="price" value="<%= rs.getInt("price") %>" min="1" placeholder="1 ~ 999,999,999">
			</li>
			<li>
				<label for="stock">재고</label>
				<input type="number" name="stock" id="stock" value="<%= rs.getInt("stock") %>" min="0" placeholder="0 ~ 999,999,999">
			</li>
			<li>
				<label for="origin">원산지</label>
				<input type="text" name="origin" id="origin" value="<%= rs.getString("origin") %>">
			</li>
		</ul>
		<div class="align-center">
			<input type="submit" value="수정">
			<input type="button" value="목록" onclick="location.href = 'selectTest.jsp';">
		</div>
	</form>
</div>
<script type="text/javascript" src="validateLength.js"></script>
<%
		}
		else {
%>
<div class="result-display">
	<div class="align-center">
		수정하려는 상품이 존재하지 않습니다!<br>
		<input type="button" value="이전 페이지" onclick="history.go(-1);">
		<input type="button" value="상품 목록" onclick="location.href = 'selectTest.jsp';">
	</div>
</div>
<%
		}
	}
	catch(Exception e) {
		e.printStackTrace();
%>
<div class="result-display">
	<div class="align-center">
		상품 수정에 실패했습니다!<br>
		3초 후 이전 페이지로 이동합니다.
	</div>
</div>
<script type="text/javascript">
	setTimeout(function() {history.go(-1);}, 3000);
</script>
<%
	}
	finally {
		if(rs!=null) try {rs.close();} catch(SQLException e) {}
		if(pstmt!=null) try {pstmt.close();} catch(SQLException e) {}
		if(conn!=null) try {conn.close();} catch(SQLException e) {}
	}
%>
</body>
</html>
  1. 새 JSP 파일 updateTest.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page import="java.sql.SQLException" %>
<%@ include file="dbinfo.jspf" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 정보 수정 처리</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<%
	request.setCharacterEncoding("UTF-8");

	Connection conn = null;
	PreparedStatement pstmt = null;
	String sql = null;
	
	try {
		Class.forName(driverName);
		conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);
		sql = "UPDATE product SET name=?, price=?, stock=?, origin=?, reg_date=SYSDATE WHERE num=?";
		pstmt = conn.prepareStatement(sql);
		pstmt.setString(1, request.getParameter("name"));
		pstmt.setInt(2, Integer.parseInt(request.getParameter("price")));
		pstmt.setInt(3, Integer.parseInt(request.getParameter("stock")));
		pstmt.setString(4, request.getParameter("origin"));
		pstmt.setInt(5, Integer.parseInt(request.getParameter("num")));
		pstmt.executeUpdate();
%>
<div class="result-display">
	<div class="align-center">
		상품 정보 수정에 성공했습니다!<br>
		<input type="button" value="상품 목록" onclick="location.href = 'selectTest.jsp';">
	</div>
</div>
<%
	}
	catch(Exception e) {
		e.printStackTrace();
%>
<div class="result-display">
	<div class="align-center">
		상품 정보 수정에 실패했습니다!<br>
		3초 후 상품 정보 수정 페이지로 이동합니다.
	</div>
</div>
<script type="text/javascript">
	setTimeout(function() {location.href = 'updateTestForm.jsp?num=<%= request.getParameter("num") %>';}, 3000);
</script>
<%
	}
	finally {
		if(pstmt!=null) try {pstmt.close();} catch(SQLException e) {}
		if(conn!=null) try {conn.close();} catch(SQLException e) {}
	}
%>
</body>
</html>
  1. 새 JSP 파일 deleteTestForm.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page import="java.sql.ResultSet" %>
<%@ page import="java.sql.SQLException" %>
<%@ include file="dbinfo.jspf" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 삭제</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<%
	int num = Integer.parseInt(request.getParameter("num"));

	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	String sql = null;
	try {
		Class.forName(driverName);
		conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);
		sql = "SELECT name FROM product WHERE num=?";
		pstmt = conn.prepareStatement(sql);
		pstmt.setInt(1, num);
		rs = pstmt.executeQuery();
		if(rs.next()) {
%>
<div class="page-main align-center">
	<h2>상품 삭제</h2>
	상품 번호 <%= num %>, <b><%= rs.getString("name") %></b> 정말 삭제하시겠습니까?<br>
	<form action="deleteTest.jsp" method="post">
		<input type="hidden" name="num" value="<%= num %>">
		<input type="submit" value="삭제">
		<input type="button" value="목록" onclick="location.href = 'selectTest.jsp';">
	</form>
</div>
<script type="text/javascript">
	let word = document.querySelector('b');
	let last = word.textContent.charCodeAt(word.textContent.length-1); // 마지막 글자의 유니코드 값
	let post;
	if(last<44032 || last>55203) { // 마지막 글자가 한글이 아닌 경우
		post = '을/를';
	}
	else {
		post = ((last - 44032) % 28) > 0 ? '' : '';
	}
	word.parentNode.insertBefore(document.createTextNode(post), word.nextSibling);
</script>
<%
		}
		else {
%>
<div class="result-display">
	<div class="align-center">
		삭제하려는 상품이 존재하지 않습니다!<br>
		<input type="button" value="이전 페이지" onclick="history.go(-1);">
		<input type="button" value="상품 목록" onclick="location.href = 'selectTest.jsp';">
	</div>
</div>
<%
		}
	}
	catch(Exception e) {
		e.printStackTrace();
%>
<div class="result-display">
	<div class="align-center">
		상품 삭제에 실패했습니다!<br>
		3초 후 목록 페이지로 이동합니다.
	</div>
</div>
<script type="text/javascript">
	setTimeout(function() {location.href = 'selectTest.jsp';}, 3000);
</script>
<%
	}
	finally {
		if(rs!=null) try {rs.close();} catch(SQLException e) {}
		if(pstmt!=null) try {pstmt.close();} catch(SQLException e) {}
		if(conn!=null) try {conn.close();} catch(SQLException e) {}
	}
%>
</body>
</html>
  1. 새 JSP 파일 deleteTest.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page import="java.sql.SQLException" %>
<%@ include file="dbinfo.jspf" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 삭제 처리</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<%	
	Connection conn = null;
	PreparedStatement pstmt = null;
	String sql = null;
	
	try {
		Class.forName(driverName);
		conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);
		sql = "DELETE FROM product WHERE num=?";
		pstmt = conn.prepareStatement(sql);
		pstmt.setInt(1, Integer.parseInt(request.getParameter("num")));
		pstmt.executeUpdate();
%>
<div class="result-display">
	<div class="align-center">
		상품 삭제에 성공했습니다!<br>
		<input type="button" value="상품 목록" onclick="location.href = 'selectTest.jsp';">
	</div>
</div>
<%
	}
	catch(Exception e) {
		e.printStackTrace();
%>
<div class="result-display">
	<div class="align-center">
		상품 삭제에 실패했습니다!<br>
		3초 후 목록 페이지로 이동합니다.
	</div>
</div>
<script type="text/javascript">
	setTimeout(function() {location.href = 'selectTest.jsp';}, 3000);
</script>
<%
	}
	finally {
		if(pstmt!=null) try {pstmt.close();} catch(SQLException e) {}
		if(conn!=null) try {conn.close();} catch(SQLException e) {}
	}
%>
</body>
</html>

jQuery

6. Ajax(Asynchronous JavaScript and XML)

6-1 Ajax 개요

  1. webapp 폴더 오른쪽 클릭하고 새 폴더 js 생성 후 jquery-3.6.0.min.js 파일을 해당 폴더로 이동

6-2 jQuery Ajax 메서드

  1. 새 폴더 ch12-ajax 생성하고 새 HTML 파일 s01_ajax.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jQuery를 이용한 비동기 통신 구현</title>
<script type="text/javascript" src="../js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
	$(function() {
		// text 정보 읽어오기
		$.ajax({
			url:'myString.jsp',
			success:function(param) { // 서버의 응답이 성공했을 때 호출; ajax() 메서드는 서버에서 데이터를 받으면 인자 param에 전달
				// 전송받은 text를 body에 표시
				$('body').append(param);
			}
		});
	});
</script>
</head>
<body>

</body>
</html>
  1. 새 JSP 파일 myString.jsp 생성
<%@ page language="java" contentType="text/plain; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%> <%-- 서버에서 HTML을 전송하지 않으므로 contentType 값 변경; trimDirectiveWhitespaces를 true로 지정하면 서블릿 변환 과정에서 발생하는 불필요한 공백이 제거됨 --%>
Hello JSP!
  1. 새 JSP 파일 myParam.jsp 생성
<%@ page language="java" contentType="text/plain; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%
	String name = request.getParameter("name");
	String age = request.getParameter("age");
%>
이름은 <%= name %>이고 나이는 <%= age %>살입니다.
  1. 새 HTML 파일 s02_ajax.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jQuery를 이용한 비동기 통신 구현</title>
<script type="text/javascript" src="../js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
	$(function() {
		// text 정보 읽어오기
		$.ajax({
			url:'myParam.jsp', // 요청 URL
			data:{ // 서버에 전송할 데이터
				name:'dororong',
				age:21
			},
			success:function(param) { // 서버의 응답이 성공했을 때 호출
				$('body').append(param);
			}
		});
	});
</script>
</head>
<body>

</body>
</html>
XML
  1. 새 JSP 파일 myXML.jsp 생성
    • XML 문서는 실행시 브라우저에서 트리 구조로 인식되면 에러 없는 것
<%@ page language="java" contentType="text/xml; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<?xml version="1.0" encoding="UTF-8"?> <!-- XML 프롤로그; 현재 문서가 XML 문서임을 명시 -->
<people> <!-- XML 문서는 단 하나의 루트 요소를 가져야 함 -->
	<person>
		<name>박문대</name>
		<job>아이돌</job>
		<age>29</age>
	</person>
	<person>
		<name>강예나</name>
		<job>헌터</job>
		<age>30</age>
	</person>
</people>
  1. 새 HTML 파일 s03_ajax.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jQuery를 이용한 비동기 통신 구현</title>
<script type="text/javascript" src="../js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
	$(function() {
		// XML 데이터 읽어오기
		$.ajax({
			url:'myXML.jsp',
			success:function(param) {
				$(param).find('person').each(function() { // <person> 태그를 배열 형태로 인식하여 each() 메서드로 처리
					var name = '<li>' + $(this).find('name').text() + '</li>'; // $(this)는 <person> 태그의 jQuery 객체를 가리킴; text() 메서드는 선택된 <name> 태그 내의 내용을 반환
					var job = '<li>' + $(this).find('job').text() + '</li>';
					var age = '<li>' + $(this).find('age').text() + '</li>';
					
					// body에 가공한 데이터를 추가
					$('body').append('<ul>' + name + job + age + '</ul>');
				});
			}
		});
	});
</script>
</head>
<body>

</body>
</html>
JSON
  1. 새 JSP 파일 myJSON.jsp 생성
<%@ page language="java" contentType="text/plain; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%-- JSON 데이터; XML보다 용량에서 이점이 있어 웹에서 많이 사용됨 --%>
[{
	"name":"바닐프티", <%-- key와 value 모두 문자열은 큰따옴표로 감싸야 함 --%>
	"job":"포켓몬",
	"age":5
},{
	"name":"너굴",
	"job":"자영업자",
	"age":"20"
}]
  1. 새 HTML 파일 s04_ajax.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jQuery를 이용한 비동기 통신 구현</title>
<script type="text/javascript" src="../js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
	$(function() {
		// JSON(JavaScript Object Notation) 데이터 읽어오기
		$.ajax({
			url:'myJSON.jsp',
			dataType:'json', // 서버로부터 전송받은 데이터의 타입
			success:function(param) {
				$(param).each(function(index, item) { // param은 배열이므로 each() 메서드로 처리; index는 배열의 인덱스, item은 배열 요소의 값(객체)
					var output = '';
					output += '<div>';
					output += '<h1>' + item.name + '</h1>';
					output += '<p>' + item.job + '</p>';
					output += '<p>' + item.age + '</p>';
					output += '</div>';
					
					// 가공된 데이터를 div에 추가
					$('#output').append(output);
				});
			}
		});
	});
</script>
</head>
<body>
	<div id="output"></div>
</body>
</html>

다음으로