ch13-ajax
생성하고 table.sql
생성CREATE TABLE people(
id VARCHAR2(10) PRIMARY KEY,
name VARCHAR2(30) NOT NULL,
job VARCHAR2(30) NOT NULL,
address VARCHAR2(60) NOT NULL,
blood_type VARCHAR2(2) NOT NULL
);
INSERT INTO people VALUES ('test', '실험', '학생', '서울시', 'A'); -- 중복 체크용 초기 데이터
COMMIT;
ch11-jdbc
폴더에서 dbinfo.jspf
복사하여 ch13-ajax
폴더에 붙여넣기하고, 첫 행의 contentType 속성 값을 text/plain
으로 변경confirmId.jsp
생성<%@ page language="java" contentType="text/plain; charset=UTF-8"
pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ 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" %> <%-- include된 파일과 contentType이 불일치하면 에러 --%>
<%
// 전송된 데이터 인코딩 처리
request.setCharacterEncoding("UTF-8");
// 전송된 데이터 반환
String id = request.getParameter("id");
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
try {
// JDBC 수행 1단계 : 드라이버 로드
Class.forName(driverName);
// JDBC 수행 2단계 : Connection 객체 생성
conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);
// SQL문 작성
sql = "SELECT id FROM people WHERE id=?";
// JDBC 수행 3단계 : PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setString(1, id);
// JDBC 수행 4단계 : SQL문을 실행해서 결과 행을 Resultset에 담아 반환
rs = pstmt.executeQuery();
if(rs.next()) { // ID 중복
%>
{"result":"idDuplicated"} <%-- JSON 데이터 --%>
<%
}
else { // ID 중복되지 않음
%>
{"result":"idNotFound"} <%-- JSON 데이터 --%>
<%
}
}
catch(Exception e) {
e.printStackTrace();
%>
{"result":"failure"} <%-- JSON 데이터 --%>
<%
}
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) {}
}
%>
main.html
생성<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>아이디 중복 체크</title>
<style type="text/css">
ul {
padding: 0;
margin: 0;
list-style: none;
}
ul li {
padding: 0;
margin: 0 0 10px 0;
}
label {
width: 100px;
float: left;
}
</style>
<script type="text/javascript" src="../js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
// 아이디 중복 체크 결과
var count = 0; // 0: 아이디 중복 체크하지 않았거나 중복, 1: 아이디 중복되지 않음
$('#confirmId').click(function() {
if($('#id').val().trim()=='') {
alert('아이디를 입력하세요!');
$('#id').focus();
$('#id').val(''); // 공백 제거
return; // 함수를 빠져나감
} // end of if
// 서버 프로그램과 통신
$.ajax({
url:'confirmId.jsp', // 요청 URL
type:'post', // 클라이언트의 데이터 전송 방식
data:{id:$('#id').val()}, // 서버로 전송할 데이터
dataType:'json', // 서버로부터 전송받는 데이터의 타입
cache:false, // 캐시를 사용하지 않음
timeout:30000, // 전송 또는 서버 상황이 좋지 않아 응답이 지연되는 경우, 실패로 간주하는 대기 시간; 밀리초 단위이며 정상적인 경우 통신에 1-2초 정도 소요
success:function(param) { // JSON 데이터를 정상적으로 전송받았을 때; catch 블럭의 {"result":"failure"}도 success에 해당
if(param.result=='idDuplicated') {
count = 0;
$('#id_signed').text('이미 등록된 아이디').css('color', 'red');
$('#id').val('').focus();
}
else if(param.result=='idNotFound') {
count = 1;
$('#id_signed').text('사용 가능한 아이디').css('color', 'black');
}
else {
count = 0;
alert('아이디 중복 체크시 오류 발생!')
}
},
error:function() { // JSON 데이터가 아닌 에러 페이지 등을 전송받았을 때
count = 0;
alert('네트워크 오류 발생!');
}
}); // end of ajax
}); // end of click
$('#insert_form #id').keyup(function() {
$('#id_signed').text('');
count = 0;
}); // end of keyup
$('#insert_form').submit(function() {
if($('#id').val().trim()=='') {
alert('아이디를 입력하세요!');
$('#id').val('').focus();
return false;
}
if(count==0) {
alert('아이디 중복 체크는 필수입니다!');
$('#confirmId').focus();
return false;
}
else {
alert('아이디가 중복되지 않습니다.');
return false;
}
}); // end of submit
});
</script>
</head>
<body>
<div>
<form id="insert_form" method="post"> <!-- action을 지정하지 않으면 자기 자신을 호출 -->
<fieldset>
<legend>회원 가입</legend>
<ul>
<li>
<label for="id">아이디</label>
<input type="text" name="id" id="id">
<input type="button" id="confirmId" value="중복 체크">
<span id="id_signed"></span> <!-- 중복 체크 결과를 표시하기 위한 빈 태그 -->
</li>
<li>
<input type="submit" value="전송">
</li>
</ul>
</fieldset>
</form>
</div>
</body>
</html>
ch14-ajax
생성하고 새 JSP 파일 insertPerson.jsp
생성<%@ page language="java" contentType="text/plain; charset=UTF-8"
pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page import="java.sql.SQLException" %>
<%@ include file="/ch13-ajax/dbinfo.jspf" %> <%-- 첫 /는 컨텍스트 루트를 의미 --%>
<%
// 전송된 데이터 인코딩 처리
request.setCharacterEncoding("UTF-8");
// 전송된 데이터 반환
String id = request.getParameter("id");
String name = request.getParameter("name");
String job = request.getParameter("job");
String address = request.getParameter("address");
String blood_type = request.getParameter("blood_type");
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try {
// JDBC 수행 1단계 : 드라이버 로드
Class.forName(driverName);
// JDBC 수행 2단계 : Connection 객체 생성
conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);
// SQL문 작성
sql = "INSERT INTO people (id, name, job, address, blood_type) "
+ "VALUES (?, ?, ?, ?, ?)";
// JDBC 수행 3단계 : PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setString(1, id);
pstmt.setString(2, name);
pstmt.setString(3, job);
pstmt.setString(4, address);
pstmt.setString(5, blood_type);
// JDBC 수행 4단계 : SQL문 실행
pstmt.executeUpdate();
%>
{"result":"success"}
<%
}
catch(Exception e) {
e.printStackTrace();
%>
{"result":"failure"}
<%
}
finally {
// 자원 정리
if(pstmt!=null) try {pstmt.close();} catch(SQLException e) {}
if(conn!=null) try {conn.close();} catch(SQLException e) {}
}
%>
main.html
생성
.jsp
를 클릭하면 JavaScript와 서버가 주고받은 요청 및 응답의 헤더나 서버에서 응답한 JSON 데이터 등을 확인 가능<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 정보</title>
<style type="text/css">
form {
width: 500px;
margin: 10px auto;
}
ul {
padding: 0;
margin: 0;
list-style: none;
}
ul li {
padding: 0;
margin: 0 0 10px 0;
}
label {
width: 150px;
float: left;
}
table {
border: solid 1px gray;
width: 500px;
margin: 0 auto;
border-collapse: collapse;
}
td {
border: solid 1px gray;
}
</style>
<script type="text/javascript" src="../js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
// 목록
function selectData() {
// <table>의 내부 내용 제거(초기화)
$('#output').empty();
// 서버에 데이터 요청
$.ajax({
url:'getPeopleJSON.jsp',
dataType:'json',
cache:false,
timeout:30000,
success:function(param) {
$(param).each(function(index, item) { // 배열로 처리
var output = '';
output += '<tr>';
output += '<td>' + item.id + '</td>';
output += '<td>' + item.name + '</td>';
output += '<td>' + item.job + '</td>';
output += '<td>' + item.address + '</td>';
output += '<td>' + item.blood_type + '</td>';
output += '</tr>';
// 테이블에 생성한 태그를 추가
$('#output').append(output);
}); // end of each
},
error:function() {
alert('네트워크 오류 발생!');
}
}) // end of ajax
} // end of selectData
// 이벤트 연결
$('#insert_form').submit(function name(event) {
// 입력 양식의 내용을 요청 매개 변수 문자열로 만듦; GET 방식처럼 파라미터명과 값의 쌍을 연결하고 인코딩 처리
var input_data = $(this).serialize();
// 서버에 데이터 전송
$.ajax({
url:'insertPerson.jsp',
type:'post',
data:input_data,
dataType:'json', // 서버로부터 받을 데이터의 형식
cache:false,
timeout:30000, // 응답이 30초 이상 지연되면 에러 처리
success:function(param) {
if(param.result=='success') {
alert('회원 가입 성공');
// 초기화
$('#insert_form input[type="text"]').val('');
// 목록 호출
selectData();
}
else {
alert('회원 가입시 오류 발생!');
}
},
error:function() { // (에러 페이지 등) 형식에 맞지 않는 데이터를 받은 경우
alert('네트워크 오류 발생!');
}
}); // end of ajax
// 기본 이벤트 제거
event.preventDefault();
}); // end of submit
// 초기 화면에 데이터를 표시
selectData();
});
</script>
</head>
<body>
<div>
<form id="insert_form" method="post">
<fieldset>
<legend>회원 가입</legend>
<ul>
<li>
<label for="id">아이디</label>
<input type="text" name="id" id="id">
</li>
<li>
<label for="name">이름</label>
<input type="text" name="name" id="name">
</li>
<li>
<label for="job">직업</label>
<input type="text" name="job" id="job">
</li>
<li>
<label for="address">주소</label>
<input type="text" name="address" id="address">
</li>
<li>
<label for="blood_type">혈액형</label>
<input type="text" name="blood_type" id="blood_type">
</li>
</ul>
<div align="center">
<input type="submit" value="추가">
</div>
</fieldset>
</form>
</div>
<table id="output"></table>
</body>
</html>
getPeopleJSON.jsp
생성<%@ page language="java" contentType="text/plain; charset=UTF-8"
pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ 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="/ch13-ajax/dbinfo.jspf" %>
<%-- 배열 안에 스크립트릿 사용 --%>
[<%
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql= null;
try {
// JDBC 수행 1단계 : 드라이버 로드
Class.forName(driverName);
// JDBC 수행 2단계 : Connection 객체 생성
conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);
// SQL문 작성
sql = "SELECT * FROM people ORDER BY id DESC";
// JDBC 수행 3단계 : PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// JDBC 수행 4단계
rs = pstmt.executeQuery();
while(rs.next()) {
String id = rs.getString("id");
String name = rs.getString("name");
String job = rs.getString("job");
String address = rs.getString("address");
String blood_type = rs.getString("blood_type");
if(rs.getRow()>1) { // 첫 번째 행을 제외하고
out.print(","); // 쉼표 삽입
}
%>
{
"id":"<%= id %>",
"name":"<%= name %>",
"job":"<%= job %>",
"address":"<%= address %>",
"blood_type":"<%= blood_type %>"
}
<%
} // end of while
} // end of try
catch(Exception e) { // 예외 발생시 형식에 맞지 않는 데이터(에러 페이지)가 전송되도록 별도의 JSON 데이터를 만들지 않음
e.printStackTrace();
}
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) {}
}
%>]
ch15-ajax
생성하고 ch11-jdbc
폴더에서 table.sql
을 복사하여 ch15-ajax
폴더에 붙여넣기ch13-ajax
폴더에서 dbinfo.jspf
를 복사하여 ch15-ajax
폴더에 붙여넣기하고, 첫 행의 contentType 속성 값을 text/xml
으로 변경getProductList.jsp
생성<%@ page language="java" contentType="text/xml; charset=UTF-8"
pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ 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" %>
<?xml version="1.0" encoding="UTF-8"?>
<product>
<%
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
try {
// JDBC 수행 1단계 : 드라이버 로드
Class.forName(driverName);
// JDBC 수행 2단계 : Connection 객체 생성
conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);
// SQL문 작성
sql = "SELECT * FROM product ORDER BY num DESC";
// JDBC 수행 3단계 : PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// JDBC 수행 4단계 : SQL문을 실행하고 결과 행들을 ResultSet에 담아 반환
rs = pstmt.executeQuery();
while(rs.next()) {
%>
<item>
<num><%= rs.getInt("num") %></num>
<name><%= rs.getString("name") %></name>
<price><%= rs.getInt("price") %></price>
<stock><%= rs.getInt("stock") %></stock>
<origin><%= rs.getString("origin") %></origin>
<reg_date><%= rs.getDate("reg_date") %></reg_date>
</item>
<%
}
}
catch(Exception e) {
e.printStackTrace();
}
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) {}
}
%>
</product>
main.html
생성<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>XML 데이터 처리</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
#wrap {
overflow: hidden;
}
.item {
margin: 5px;
padding: 5px;
width: 200px;
height: 150px;
float: left; /* 반응형처럼 동작함 */
border-width: 3px;
border-style: solid;
border-color: gray;
border-radius: 10px;
}
</style>
<script type="text/javascript" src="../js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
function selectData() {
$.ajax({
url:'getProductList.jsp',
dataType:'xml',
success:function(param) {
// 화면 초기화
$('#wrap').empty();
$(param).find('item').each(function() {
var output = '<div class="item">';
output += '<p>상품 번호 : ' + $(this).find('num').text() + '</p>';
output += '<p>상품명 : ' + $(this).find('name').text() + '</p>';
output += '<p>가격 : ' + $(this).find('price').text() + '</p>';
output += '<p>재고 : ' + $(this).find('stock').text() + '</p>';
output += '<p>원산지 : ' + $(this).find('origin').text() + '</p>';
output += '<p>등록일 : ' + $(this).find('reg_date').text() + '</p>';
output += '</div>';
// 문서 객체 추가
$('#wrap').append(output);
}); // end of each
},
error:function() {
alert('네트워크 오류 발생!');
}
}); // end of ajax
} // end of selectData
// 초기 화면 데이터 처리
selectData();
});
</script>
</head>
<body>
<div id="wrap"></div>
</body>
</html>