BackEnd/JSP
[JSP] JSP를 이용한 간단한 CRUD 구현(여행 예약 프로그램) ② / C 구현
나루나른
2024. 4. 14. 18:56
Oracle DB와 JavaIDE를 이용한 간단한 CRUD 구현의 두번째 게시글이다. 첫번째 게시글과 마찬가지로 이런 형태로 구현하는 방법은 정말 구닥다리이므로 기본적인 개념에 대한 참고용으로만 간단히 봐주길 바란다.
로그인 및 회원가입 등 세션이 필요한 내용은 존재하지 않으며 데이터 입력에 대한 간단한 유효성 검사만 있는 CRUD 구현이다.
예약 등록 페이지에 직접 데이터를 insert 하기 위한 travleBook.jsp 페이지의 코드이다. 유효성 검사는 JSP 페이지 내에서 직접 script로 추가하면 내용이 너무 길어지기 때문에 .js 파일의 형태로 따로 구현했다.
travel.jsp(tbl_reserve_01/예약 등록 테이블에 직접 데이터를 삽입하는 페이지)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="../js/validate.js"></script>
<title>travelBook.jsp</title>
<style>
header {background: blue; color: white; text-align : center; }
nav {background: lightblue;}
footer {background: blue; color: white; text-align: center;}
</style>
</head>
<body>
<header>
<h1>여행 예약 프로그램 ver.2018-12</h1>
</header>
<nav>
<div>
<!-- jsp:include 태그를 사용해 mainmenu.jsp 파일을 현제 페이지에 포함시켜서 메인메뉴를 추가함 -->
<jsp:include page="mainmenu.jsp"></jsp:include>
</div>
</nav>
<section>
<h3>예약 등록</h3>
<!-- 예시이지만, 주민 번호 등 예민한 정보들이 들어가므로, post 방식을 통해 trvaelBookProc.jsp 페이지로 데이터를 전송 -->
<form name="travelfrm" id="travelfrm" method="post" action="travelBookProc.jsp" onsubmit="return validate()" >
<table class="table table-bordered">
<tr>
<th>예약번호</th>
<td>
<input type="text" name="rno" id="rno" size="8" maxlength="8" required><!-- required는 필수 데이터라는 의미 -->
</td>
</tr>
<tr>
<th>상품코드</th>
<td>
<select name="tcode" id="tcode">
<option value="">상품선택</option>
<%
//Oracle DB 연결 및 행 추가 --------------------------
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
//오라클 DB 서버 연결 관련 정보
String url = "jdbc:oracle:thin:@localhost:1521:xe";
String user = "system";
String password = "1234";
String driver = "oracle.jdbc.driver.OracleDriver";
//드라이버 로딩(지정된 드라이버 클래스를 메모리에 로드)
Class.forName(driver);
//오라클 DB 연결 (DriverManager를 사용하여 데이터베이스에 연결)
con = DriverManager.getConnection(url, user, password);
//out.println("오라클 DB 서버 연결 성공");
//상품에 대한 코드를 가져오는 SQL문
//SQL 쿼리 문자열을 구성하기 위한 StringBulider 인스턴스 생성
StringBuilder sql = new StringBuilder();
sql.append("select tcode, ");
// 상품 코드와 관련된 지역 정보 및 출발 날짜를 포맷팅하여 문자열로 결합
sql.append(" '[ '|| tcode|| '] ' || tarea ");
sql.append(" || to_char(to_date(tdate, 'YYYY-MM-DD'), 'YYYY-MM-DD') ");
sql.append(" || ' 출발' as tname ");//포멧팅한 결과를 tname으로 명명함
sql.append(" from tbl_tourcode_02 ");
sql.append(" order by tcode ");
// 준비된 SQL 쿼리를 사용하여 PreparedStatement 객체 생성
pstmt = con.prepareStatement(sql.toString());
// 쿼리 실행: 실행 결과로 ResultSet 객체 반환
rs = pstmt.executeQuery();
//rs(ResultSet에서 데이터를 읽음)
if(rs.next()){//커서를 통해 첫번째 행에 데이터가 존재하는지 확인 후 출력
do{
// 옵션 태그 생성하여 상품 코드를 값으로, 상품 이름을 표시로 사용
out.println("<option value='" + rs.getString("tcode") + "'>");
out.println(rs.getString("tname"));
out.println("</option>");
} while(rs.next());//그 다음 데이터를 지목하는 커서가 존재하면 옮겨다니면서 출력한다.
}//if end
} catch (Exception e) {
out.println("오라클 DB 연결실패 : " + e);
}finally{//자원 반납 순서를 주의해야한다.(선언된 후순위부터 닫아야함)
try{
if(rs!=null) {
rs.close();
}
}catch(Exception e){}
try{
if(pstmt != null){
pstmt.close();
}
}catch(Exception e){}
try{
if(con!=null){
con.close();
}
}catch(Exception e){}
}//finally end
%>
</select>
</td>
</tr>
<tr>
<th>주민번호</th>
<td>
<input type="text" name="rjumin1" id="rjumin1" size="6" maxlength="6" required>
-
<input type="text" name="rjumin2" id="rjumin2" size="7" maxlength="7" required>
</td>
</tr>
<tr>
<th>성명</th>
<td>
<input type="text" name="rname" id="rname" size="20" maxlength="20" required>
</td>
</tr>
<tr>
<th>전화번호</th>
<td>
<input type="text" name="rphone1" id="rphone1" size="3" maxlength="3" required>
-
<input type="text" name="rphone2" id="rphone2" size="4" maxlength="4" required>
-
<input type="text" name="rphone3" id="rphone3" size="4" maxlength="4" required>
</td>
</tr>
<tr>
<th>이메일</th>
<td>
<input type="text" name="remail" id="remail" size="30" maxlength="30" required>
</td>
</tr>
<tr>
<th>결제상태</th>
<td>
<input type="radio" name="rstat" id="rstat" value="1" checked>미납
<input type="radio" name="rstat" id="rstat" value="2">완납
</td>
</tr>
<tr>
<td colspan="2">
<!-- submit 버튼을 누르면 form의 action을 통해 다른페이지로 데이터가 전송됨. -->
<input type="submit" value="예약">
<input type="reset" value="취소" onclick="alert('정보를 지우고 처음부터 다시 입력합니다.');">
</td>
</tr>
</table>
</form>
</section>
<footer>
<p>
HRDKOREA Copyright©2018 All rights reserved.
Human Resources Development Service of Korea
</p>
</footer>
</body>
</html>
유효성 검사에 대한 파트이다. jsp 페이지에서는 validate.js 파일에 대한 경로를 지정해서 유효성 검사를 함.
validate.js(유효성 검사)
function validate(){//유효성 검사
//유효성 검사에서 .focus() 함수는 각각의 id속성의 값을 선택해, 해당 값이 활성화되어서
//값을 입력받을 준비가 되었는지를 의미하는데 해당 함수를 호출하면 페이지를 로드하거나, 특정한 이벤트가 발생하면
//해당 입력 필드에 입력을 시작할 수 있다.
//1. 예약 번호의 글자 갯수가 8글자인지 확인
let rno = $("#rno").val().trim();
//rno(예약번호)가 8글자가 아니라면 경고창을 출력함
if(rno.length != 8){
alert("8글자를 입력해 주세요.");
$("#rno").focus();
return false;//조건이 거짓일 경우 false를 리턴해서 서버로의 전송을 막음.
}
//2. 상품코드를 선택했는지 확인
let tcode = $("#tcode").val(); //상품코드의 id가 'tcode'라고 가정
if(!tcode){//tcode가 선택되지 않았다면 경고창을 출력함
alert("상품코드를 선택해 주세요.");
$("#tcode").focus();
return false;
}
//3. 주민번호가 맞는지 확인 각각 앞자리가 6글자, 뒷자리가 7글자, 숫자형으로 입력되었는지 확인
let rjumin1 = $("#rjumin1").val().trim();
//각 자릿수와 isNaN()을 통해 입력받은 데이터가 숫자형으로 입력되었는지를 판단함
if(rjumin1.length != 6 || isNaN(rjumin1) ){
alert("주민번호 앞자리를 입력해주세요");
$("#rjumin1").focus();
return false;
}
let rjumin2 = $("#rjumin2").val().trim();
if(rjumin2.length != 7 || isNaN(rjumin2) ){
alert("주민번호 뒷자리를 제대로 입력해주세요");
$("#rjumin2").focus();
return false;
}
//번외 이름 유효성 검사
let rname = $("#rname").val().trim();
//rname의 길이를 비교해 2~30글자 이내로만 입력하도록 경고창을 출력한다.
if(rname.length < 2 || rname.length > 30){
alert("이름을 2 ~ 30글자 이내로 입력해주세요");
$("#rname").focus();
return false;
}
//4. 예약자 전화가 각각 3글자, 4글자 4글자 숫자형으로 입력되었는지 확인
let rphone1 = $("#rphone1").val().trim();
let rphone2 = $("#rphone2").val().trim();
let rphone3 = $("#rphone3").val().trim();
//각 전화번호의 자릿수와 isNaN()을 통해 입력받은 데이터가 숫자형으로 입력되었는지를 판단함
if(rphone1.length != 3 || isNaN(rphone1)){
alert("전화번호 첫 번째 부분을 제대로 입력해주세요");
$("#rphone1").focus();
return false;
}
if(rphone2.length != 4 || isNaN(rphone2)){
alert("전화번호 두 번째 부분을 제대로 입력해주세요");
$("#rphone2").focus();
return false;
}
if(rphone3.length != 4 || isNaN(rphone3)){
alert("전화번호 세 번째 부분을 제대로 입력해주세요");
$("#rphone3").focus();
return false;
}
//5. 고객 이메일에 @문자가 존재하는지 확인
let remail = $("#remail").val().trim();
// 이메일에서 @의 위치를 찾는다.
let atPosition = remail.indexOf("@");
// @가 이메일에 없거나, @가 맨 처음이나 끝에 위치하는 경우 유효성 검사에 실패함.
if (atPosition < 1 || atPosition === remail.length - 1) {
alert("올바른 이메일 주소를 입력해주세요.");
$("#remail").focus();
return false;
} else {
// @ 기호 뒤의 문자열(도메인 부분)을 추출한다.
let domainPart = remail.substring(atPosition + 1);
// 도메인 부분에 .이 있는지 확인한다.
// 도메인 파트의 처음부터, 끝 부분까지 .문자열이 존재하는지 확인함.
if (domainPart.indexOf(".") < 1 || domainPart.lastIndexOf(".") === domainPart.length - 1) {
alert("이메일 주소의 도메인이 올바르지 않습니다.");
$("#remail").focus();
return false;
}
}
//모든 유효성 검사를 통과하면(모든값이 true라면)
//사용자가 입력한 데이터를 서버로 전송한다.
return true;
}//validate end;
모든 유효성 검사를 통과하면 travelBookProc.jsp 페이지를 통해 DB에 해당 데이터들이 삽입된다.
travelBookProc.jsp (travleBook에서 사용자가 입력한 데이터가 해당 페이지를 통해 DB에 저장됨)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>travelBookProc.jsp</title>
</head>
<body>
<%
//한글 인코딩
request.setCharacterEncoding("UTF-8");
//사용자가 입력한 정보를 가져와서 변수에 담고, trim()을 이용해 공백을 제거함.
String rno = request.getParameter("rno").trim();//예약번호
String tcode = request.getParameter("tcode");//상품코드
String rjumin1 = request.getParameter("rjumin1").trim();//주민번호 앞자리
String rjumin2 = request.getParameter("rjumin2").trim();//주민번호 뒷자리
//주민번호 앞, 뒷자리를 하나로 연결함
String rjumin = rjumin1 + rjumin2;
String rname = request.getParameter("rname").trim();//예약자 이름
String rphone1 = request.getParameter("rphone1").trim();//전화번호 첫번째
String rphone2 = request.getParameter("rphone2").trim();//전화번호 두번째
String rphone3 = request.getParameter("rphone3").trim();//전화번호 세번째 부분
String remail = request.getParameter("remail").trim();//이메일 주소
String rstat = request.getParameter("rstat");//결제 상태
Connection con = null;
PreparedStatement pstmt = null;
try {
//오라클 DB 서버 연결 관련 정보
String url = "jdbc:oracle:thin:@localhost:1521:xe";
String user = "system";
String password = "1234";
String driver = "oracle.jdbc.driver.OracleDriver";
//드라이버 로딩
Class.forName(driver);
//오라클 DB 서버 연결
con = DriverManager.getConnection(url, user, password);
//out.println("오라클 DB 서버 연결 성공");
//SQL문 작성
StringBuilder sql = new StringBuilder();
// 데이터 삽입을 위한 SQL 명령어 작성. tbl_reserve_01 테이블에 데이터를 삽입.
// VALUES 절에서는 각 필드에 대응하는 값을 ?로 표시한다. ?는 매개변수로 대체될 자리 표시자이다.
sql.append(" INSERT INTO tbl_reserve_01 (rno, rjumin, rname, rphone1, rphone2, rphone3, remail, rstat, tcode) ");
sql.append(" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
//sql 형식으로 변환 PreparedStatement : 변수를 문자열로 변환해주는 명령어
pstmt = con.prepareStatement(sql.toString());
// 각 자리 표시자에 해당하는 값을 설정
pstmt.setString(1, rno); // 예약번호
pstmt.setString(2, rjumin); // 사용자의 주민등록번호
pstmt.setString(3, rname); // 사용자의 이름
pstmt.setString(4, rphone1); // 전화번호의 첫 번째 부분
pstmt.setString(5, rphone2); // 전화번호의 두 번째 부분
pstmt.setString(6, rphone3); // 전화번호의 세 번째 부분
pstmt.setString(7, remail); // 이메일 주소
pstmt.setString(8, rstat); // 결제 상태 (미납, 완납 등)
pstmt.setString(9, tcode); // 상품 코드
//// SQL 쿼리 실행 및 결과 처리
int cnt = pstmt.executeUpdate();
//cnt == 0 : 만약에 업데이트된 데이터가 없다면
if(cnt==0){
//예약 실패 메시지 출력
out.println("<p>에약에 실패하였습니다.</p>");
out.println("<p><a href='javascript:history.back()'>[다시시도]</a></p>");
}else{
// 예약 성공 시, 알림 및 페이지 이동하는 스크립트
out.println("<script>");
out.println(" alert('예약이 완료되었습니다.');");
out.println(" location.href='travelList.jsp';");//리스트 페이지로 이동
out.println("</script>");
}
} catch (Exception e) {
out.println("오라클 DB 서버 연결 및 행 추가 : "+e);
}finally{//자원 반납의 순서 주의(후순위부터 닫기)
try{
if(pstmt != null){pstmt.close();}
}catch(Exception e){}
try{
if(con!=null){con.close();}
}catch(Exception e){}
}//finally end
%>
</body>
</html>
모든 부분이 만족해야 서버로 데이터가 전송되는 것을 볼 수 있다.