[JSP/Servlet] JSP Model1 방식을 활용한 회원 가입 CRUD 홈페이지 제작기 | With JavaBeans, 커스텀 태그 라이브러리, 커넥션 풀

Re_Go·2024년 8월 13일
0

JSP&Servlet

목록 보기
18/19
post-thumbnail

1. 서론

이번에도 마찬가지로 서블릿을 이용해 이전에 제작했던 홈페이지를 개선해 보았는데요. 때문에 이번 섹션을 먼저 보시기 전에 먼저 이전 제작 홈페이지의 로직을 한 번 보시고 오시는 것을 추천 드립니다.

아무튼 이번에는 저번에 사용하지 않았던 자바빈즈(특정 역할을 대체하는 자바 객체 혹은 클래스)와 표현하기 힘들었던 스크립틀릿을 좀 더 편하게 사용할 수 있게 해주는 커스텀 태그 라이브러리, DB를 좀 더 편하게 접촉하게 할 수 있는 커넥션 풀을 사용해 보았습니다.

이번 홈페이지 로직에 사용된 JSP 모델 1 그림과 설명

  1. 사용자가 JSP 페이지에 요청을 보냄
  2. JSP에서 DB를 중계하는 자바빈즈(DAO)에 사용자의 요청 정보를 전달하면 해당 자바빈즈는 이를 토대로 DB에서 해당 정보를 커넥션 풀을 이용하여 쿼리문을 실행
  3. 쿼리 실행(사용자의 정보 저장, 혹은 조회) 후에 결과를 받아온 뒤 서버 측에 해당 사용자의 정보들을 자바 객체로 임시 저장하기 위한 자바빈즈(VO)에 임시 저장하거나 반대로 DB에 업데이트 된 경우 해당 반환 값 (정상 반영 값인 정수값을 반환 받음)을 받은 뒤 VO 객체, 혹은 정수 반환 값을 JSP 페이지에 전달
  4. 결과값을 전달 받은 JSP는 해당 결과값을 토대로 JSP 페이지에 사용자의 요청을 화면에 출력(VIEW)으로 응답(response)함.

2. 프로젝트 파일 구성

우선 라이브러리 파일들은 다음과 같이 구성되어 있으며, DB 연동을 위한 ojdbc, 커넥션 풀 사용을 위한 아파치 커넥션풀 라이브러리들, 외부 커스텀 태그 라이브러리와 해당 태그에 EL 표현식을 쓰기 위한 taglibs 라이브러리들을 다운받은 뒤 빌드 패스에 추가해 주었습니다.

그 다음 JSP 페이지 입니다. 이전에 사용했던 프로젝트의 페이지들을 활용해 주었습니다.

마지막으로 자바빈즈 파일입니다. 이곳에는 이전 프로젝트에서 사용자가 JSP 페이지마다 DB를 일일이 연결해서 쿼리를 던져주어야만 했던 수고를 덜하기 위해 커넥션 풀을 자체적으로 연동한 뒤 사용자의 호출이 있을 때마다 정의한 각 DML문을 실행하는 메서드를 호출하여 그 결과값을 반환해 주는 DAO(Data Access Object) 객체 하나와

해당 DB의 테이블과 똑같은 데이터 타입과 이름으로 칼럼들이 정의되어 있어 서버 영역에서 DB의 결과값, 혹은 전달값으로 편하게 받고 전달해줄 VO(Value Object) 객체를 하나 만들어 줍니다.

3. 추가 개념글

특히 이번 섹션에서는 제 블로그에 소개를 드리지 않은 자바빈즈와 커스텀 태그 라이브러리, 커넥션 풀을 간단히 알아볼 수 있는 블로그 글들을 좀 소개해 드리고자 하는데요.

우선 자바빈즈의 경우 ORM이나 스프링으로 자동 연결 및 관리가 가능하기 때문에 그냥 어떻게 만드는지에 대한 개념이나 방법 정도를 아래의 블로그에서 파악하시는 것으로도 충분합니다.

(https://ccomccomhan.tistory.com/37)

또한 커스텀 태그 라이브러리의 경우 클래스 기반 커스텀 태그는 거의 사장되다시피 한 반면 태그 기반 커스텀 태그는 유지 보수 측면에서 종종 사용되는 상황 (그마저도 요즘 웹페이지 동작은 SPA가 대세라 MPA는 외면 받는 상태라 리액트가 JSP를 대체하긴 하지만...)인지라 이것도 마찬가지로 아래의 아래의 블로그에서 그냥 이런게 있구나 하는 정도로만 파악하시는 것으로도 충분합니다.

(https://blog.naver.com/yunwoosup/222045402611)

마지막으로 커넥션 풀 또한 사용자가 일일이 연결하지 않아도 된다는 장점이 있으나, 이는 JPA는 물론 마이바티스에서도 훨씬 편하게 가능하기 때문에 이마저도 아래의 블로그에서 참고하시면 좋을듯 합니다.

(https://velog.io/@jaemin05/%EC%BB%A4%EB%84%A5%EC%85%98-%ED%92%80%EC%9D%84-%EC%99%9C-%EC%95%8C%EC%95%84%EC%95%BC%ED%95%A0%EA%B9%8C)

4. 오라클 DB 테이블 구성

오라클 DB의 경우 green 테이블을 다음과 같은 구조로 생성했습니다.

CREATE TABLE users (
    idx        NUMBER PRIMARY KEY,               
    id         VARCHAR2(20) NOT NULL,            
    pw         VARCHAR2(20) NOT NULL,            
    name       VARCHAR2(20) NOT NULL,            
    age        NUMBER NOT NULL,                  
    addr       VARCHAR2(50),                     
    reg_date   DATE                              
);

create sequence green_seq start with 1 increment by 1;

5. 전체 로직 설명

index.js

가장 기본적인 메인 페이지이며, 이전의 프로젝트와 달라진점이 없는 페이지 입니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
// 스타일
<style type="text/css">
	table {
		margin: 0 auto;
		border:  1px solid lightseagreen;
	}
	thead {
		background-color: lightseagreen;
		color: white;
	}
	tfoot{
		background-color: lightseagreen;
	}
	td{
		text-align: center;
		padding: 3px;
	}
	th{
		height: 30px;
		padding: 5px;
	}
	input[type=button], input[type=reset]{
		background-color: lightseagreen;
		border: 1px solid white;
		padding: 5px;
		color: white;
	}
	input[type=button]:hover {
		background-color: white;
		color: lightseagreen;
		font-weight: bold;
		cursor: pointer;
	}
</style>
<script type="text/javascript" defer>
	function view_all(){
		location.href = "view_all.jsp";
	}

// 예외 처리
	function view_one(f){
		let regId = /^[0-9a-zA-Z]{8,16}$/;
		if (!regId.exec(f.id.value)) {
		    alert("대소문자와 소문자를 혼합한 8~16자의 아이디를 입력해 주세요.");
		    f.id.value = "";
		    f.id.focus();
		    return;
		}
		f.action = "view_one.jsp";
		f.submit();
	}

	function insert_one(f){
		let regId = /^[0-9a-zA-Z]{8,16}$/;
		if (!regId.exec(f.id.value)) {
		    alert("대소문자와 소문자를 혼합한 8~16자의 아이디를 입력해 주세요.");
		    f.id.value = "";
		    f.id.focus();
		    return;
		}
		let regPw = /^[0-9a-zA-Z]{8,16}$/;
		if (!regPw.exec(f.pw.value)) {
		    alert("대소문자와 소문자를 혼합한 8~16자의 비밀번호를 입력해 주세요.");
		    f.pw.value = "";
		    f.pw.focus();
		    return;
		}
		let koreanRegName = /^[가-힣]{2,6}$/;
	    if (!koreanRegName.exec(f.name.value)) {
		    alert("올바른 이름을 입력해 주세요.");
		    f.name.value = "";
		    f.name.focus();
		    return;
	    }
	    let regAge = /^[0-9]{1,3}$/;
	    if (!regAge.exec(f.age.value)) {
		    alert("올바른 나이를 입력해 주세요.");
		    f.age.value = "";
		    f.age.focus();
		    return;
	    }
	    let regAddr = /^[가-힣0-9\s]{5,30}$/;
	    if (!regAddr.exec(f.addr.value)) {
		    alert("올바른 주소를 5자 이상 입력해 주세요");
		    f.addr.value = "";
		    f.addr.focus();
		    return;
	    }
		f.action = "insert_one.jsp";
		f.submit();
	}

	function remove_one(f){
		let regId = /^[0-9a-zA-Z]{8,16}$/;
		if (!regId.exec(f.id.value)) {
		    alert("대소문자와 소문자를 혼합한 8~16자의 아이디를 입력해 주세요.");
		    f.id.value = "";
		    f.id.focus();
		    return;
		}
		let regPw = /^[0-9a-zA-Z]{8,16}$/;
		if (!regPw.exec(f.pw.value)) {
		    alert("대소문자와 소문자를 혼합한 8~16자의 비밀번호를 입력해 주세요.");
		    f.pw.value = "";
		    f.pw.focus();
		    return;
		}
		f.action = "remove_one.jsp";
		f.submit();
	}

	function update_one(f){
		let regId = /^[0-9a-zA-Z]{8,16}$/;
		if (!regId.exec(f.id.value)) {
		    alert("대소문자와 소문자를 혼합한 8~16자의 아이디를 입력해 주세요.");
		    f.id.value = "";
		    f.id.focus();
		    return;
		}
		let regPw = /^[0-9a-zA-Z]{8,16}$/;
		if (!regPw.exec(f.pw.value)) {
		    alert("대소문자와 소문자를 혼합한 8~16자의 비밀번호를 입력해 주세요.");
		    f.pw.value = "";
		    f.pw.focus();
		    return;
		}
		f.action = "update_one.jsp";
		f.submit();
	}
</script>
</head>
HTML 코드
<body>
	<form method="post">
		<table>
			<thead>
				<tr>
					<th colspan="2">회원 정보 관리</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td>아이디</td>
					<td><input type="text" name="id"></td>
				</tr>
				<tr>
					<td>비밀번호</td>
					<td><input type="password" name="pw"></td>
				</tr>
				<tr>
					<td>이름</td>
					<td><input type="text" name="name"></td>
				</tr>
				<tr>
					<td>나이</td>
					<td><input type="number" name="age"></td>
				</tr>
				<tr>
					<td>주소</td>
					<td><input type="text" name="addr"></td>
				</tr>
			</tbody>
			<tfoot>
				<tr>
					<th colspan="2">
						<input type="button" value="전체보기" onclick="view_all()">&nbsp;&nbsp;
						<input type="button" value="검색" onclick="view_one(this.form)">&nbsp;&nbsp;
						<input type="button" value="삽입" onclick="insert_one(this.form)">&nbsp;&nbsp;
						<input type="button" value="삭제" onclick="remove_one(this.form)">&nbsp;&nbsp;
						<input type="button" value="수정" onclick="update_one(this.form)">&nbsp;&nbsp;
						<input type="reset" value="다시 작성">
					</th>
				</tr>
			</tfoot>
		</table>
	</form>
</body>
</html>

전체 출력 영역(view_all.jsp, getAllList)

DB의 모든 사용자를 조회하여 페이지를 출력하는 코드 부분입니다. 특히 이번 JSP 페이지들은 에서 DB 처리는 DAO에서 직접 처리를 해줄것이기 때문에 해당 DAO 객체의 메서드를 호출하고 전달할 값으로 VO 객체에 세팅해 두었던 인스턴스를 전달해 주었으며,

페이징 처리의 경우 이전에 사용하던 스크립틀릿 방식에서 벗어나 자바 코드의 로직 동작이 가능하도록 아파치 측에서 제공하고 있는 커스텀 태그 라이브러리와 EL 조합으로 페이지를 처리해 주었습니다.

  1. view_all.jsp
<%@page import="org.joonzis.ex.GreenVO"%>
<%@page import="java.util.List"%>
<%@page import="org.joonzis.ex.GreenDao"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <!-- 
    ① dao 객체를 얻어와 해당 객체에 정의되어 있는 getAllList 메서드를 호출하면서
    사용자에게 미리 세팅해놓은 파라미터를 던져줍니다. 단 view_all 페이지 에서는
    모든 사용자의 값을 받을 것이기 때문에 파라미터가 없어도 되므로 던질 매개변수는 없으며
    받는 결과값은 List 형태의 GreenVO 객체 집합(나중에 설명할 예정)을 받으므로
    GreenVO 타입의 List의 변수를 하나 선언하여 결과값을 받은 뒤
    해당 페이지 컨텍스트에 속성으로 세팅을 해줍니다.
    -->
 <%
 	GreenDao dao = GreenDao.getInstance();
 	List<GreenVO> list = dao.getAllList();
 	pageContext.setAttribute("list", list);
 %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<jsp:include page="index.jsp"/>

	<br> <hr> <br>
	
	<h1 style = "text-align:center" >member 테이블의 전체 데이터</h1>
	<table>
		<thead>
			<tr>
				<th>회원번호</th> 
				<th>아이디</th> 
				<th>비밀번호</th> 
				<th>이름</th> 
				<th>나이</th> 
				<th>주소</th> 
				<th>가입일</th> 
			</tr>
		</thead>
		<tbody>
        <!-- 
        ② taglib으로 대표적으로 사용되는 라이브러리는 c 태그이며, 
        이 라이브러리는 for문과 if조건문이 대표적으로 사용되기 때문에 
        여기서는 대표적으로 choose(when, otherwise를 포함하는 범위)와
        when(if, else if문 역할), otherwise(else문 역할), 
        forEach(for문 및 forEach 메서드 역할)를 사용하여 List에 담긴
        사용자의 값들을 출력하는 역할로 사용하였습니다.
        -->
			<c:choose>
				<c:when test="${list.size() > 0}">
					<c:forEach var = "vo" items = "${list}">
						<tr>
	<!-- 
    ③ DAO의 DB 관련 메서드를 거치면서 vo에 세팅 된 각 로우(행)들의 
    값들을 차례대로 forEach 구문을 사용하면서 꺼내옵니다. 
    단 단일 행만 출력할 경우 forEach는 사용하지 않아도 됩니다. 
    -->
							<td>${vo.getIdx()}</td> 
							<td>${vo.getId()}</td>
							<%-- 필드처럼 쓰려면 필드명대로 써야함 (private 이지만 필드를 쓰면 컴파일러는 getter로 자동 인식) --%>
							<td>${vo.pw}</td> 
							<td>${vo.getName()}</td> 
							<td>${vo.getAge()}</td> 
							<td>${vo.getAddr()}</td> 
							<td>${vo.getReg_date()}</td> 
						</tr>
					</c:forEach>
				</c:when>
				<c:otherwise>
					<tr> 
						<td colspan="7">회원이 존재하지 않습니다.</td>
					</tr>
				</c:otherwise>
			</c:choose>
		</tbody>
	</table>
</body>
</html>
  1. getAllList 메서드
public class GreenDao {
	// DB 연결 을 위한 커넥션 API
	private Connection conn = null;
    // 쿼리 실행 준비를 위한 API
	private PreparedStatement ps = null;
    // 쿼리 실행 결과 순회하며 순차적으로 가져오는 대표적인 API
	private ResultSet rs = null;
    //실행할 쿼리문을 담을 변수
	private String sql = "";

	public GreenDao() {}
    // 무분별한 GreenDao 인스턴스 생성 방지를 위해 공유 가능한 하나의 인스턴스만을 미리 생성
	private static GreenDao dao = new GreenDao();

	// 생성한 인스턴스를 반환해주는 메서드
	public static GreenDao getInstance() {
		return dao;
	}

    // 커넥션 풀을 관리하는 객체(DataSource)
	private static DataSource ds;
	static {
		try {
        	// JNDI (Java Naming and Directory Interface) 환경을 초기화하고, 데이터베이스 연결과 같은 리소스를 검색하거나 바인딩 할 수 있는 기본적인 설정을 완료 (그냥 해당 어플리케이션의 DB를 찾기 위한 준비단계라고 생각하시면 편합니다.)
			Context context = new InitialContext();
            // JNDI 환경에서 DataSource 객체를 검색하여 데이터베이스 연결을 관리하기 위한 참조를 얻는 과정
			ds = (DataSource)context.lookup("java:comp/env/jdbc/oracle");
		} catch (NamingException e) {
			e.printStackTrace();
		}	
	}

    // 조회해서 받아올 값들은 하나 하나의 GreenVO(사용자의 전체 정보 한 줄) 그룹이기 때문에
   // List 배열로 받아 사용
	public List<GreenVO> getAllList() {
		List<GreenVO> list = new ArrayList<>();

		try {
        	// dataSource를 사용하여 DB에 연결을 요청
			conn = ds.getConnection();
            // 쿼리문 작성
			String sql = "select * from green order by idx";
            //쿼리문 실행 준비
			ps = conn.prepareStatement(sql);
            // 실행 된 쿼리의 결과값을 반환 받음
			rs = ps.executeQuery();
			// resultSet의 next 메서드를 이용해 결과 집합을 순차적으로 접근
			while(rs.next()) {
            	// vo 객체를 만들고 해당 객체에 컬럼의 순서대로 순차적으로 값을 세팅(setter)한 뒤
                // List(GreenVO 타입)에 저장
				GreenVO vo = new GreenVO();
				vo.setIdx(rs.getInt(1));
				vo.setId(rs.getString(2));
				vo.setPw(rs.getString(3));
				vo.setName(rs.getString(4));
				vo.setAge(rs.getInt(5));
				vo.setAddr(rs.getString(6));
				vo.setReg_date(rs.getDate(7));
				list.add(vo);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if(rs != null) {rs.close();}
				if(ps != null) {ps.close();}
				if(conn != null) {ps.close();}
			}catch(Exception e2) {
				e2.printStackTrace();
			}
		}
		// 작업이 rs.next 작업이 끝나면 list를 반환
		return list;
	}
ㆍ
ㆍ
ㆍ
(중략)

회원 가입(삽입) 영역 (insert_one.jsp, getInsert 메서드)

위의 view_all.jsp 페이지와 마찬가지로 이전 프로젝트에서 insert_one.jsp에서 요청을 받은 뒤 VO 객체에 세팅한 후 DAO의 getInsert에 전달하고 난 결과값을 토대로 다음과 같이 페이징 처리를 해줄 것입니다.

  1. insert_one.jsp
<%@page import="org.joonzis.ex.GreenVO"%>
<%@page import="org.joonzis.ex.GreenDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 <!-- 
 받은 요청 정보들을 VO에 세팅하는 영역
 -->
 <%
 request.setCharacterEncoding("utf-8");
 String id = request.getParameter("id");
 String pw = request.getParameter("pw");
 String name = request.getParameter("name");
 String age = request.getParameter("age");
 String addr = request.getParameter("addr");

 GreenVO vo = new GreenVO();

 vo.setId(id);
 vo.setPw(pw);
 vo.setName(name);
 vo.setAge(Integer.parseInt(age));
 vo.setAddr(addr);

 <!-- 
 view_all.jsp와 마찬가지로 dao의 인스턴스를 얻어와 getInsert 메서드 호출 후 결과값을 이용
 -->
 GreenDao dao = GreenDao.getInstance();
 int result = dao.getInsert(vo);
 pageContext.setAttribute("result", result);

 // 이전 사용 방법
 //response.sendRedirect("view_all.jsp");
 %>

 <!-- 
 스크립틀릿보다 원활한 조건문 작성이 가능하기 때문에, 커스텀 태그를 이용하여 조건문에 따른 페이징 처리를 자바스크립트 태그와 병행해서 처리
 -->
 <c:choose> 
 	<c:when test="${result >= 0}">
		<script type="text/javascript">
			location.href = "view_all.jsp"
		</script> 			
 	</c:when>
 	<c:otherwise>
 		<script type="text/javascript">
 			alert("회원 가입에 실패했습니다.")
			location.href = "view_all.jsp"
		</script>
 	</c:otherwise>
 </c:choose>
  1. getInsert 메서드 (이전 프로젝트의 getInsert와 크게 다르지 않습니다.)
public int getInsert(GreenVO vo) {
		int result = 0;

		try {
			conn = ds.getConnection();

			sql = "insert into green(idx, id, pw, name, age, addr, reg_date)" + 
						 "values(green_seq.nextval, ?, ?, ?, ?, ?, sysdate)";

			ps = conn.prepareStatement(sql);
			conn.setAutoCommit(true);
			ps.setString(1, vo.getId());
			ps.setString(2, vo.getPw());
			ps.setString(3, vo.getName());
			ps.setInt(4, vo.getAge());
			ps.setString(5, vo.getAddr());
			result = ps.executeUpdate();
			if(result > 0) {
				System.err.println("데이터 추가 완료");
			}else {
				System.out.println("데이터 추가 실패");
			}
		} catch (Exception e) {
			e.printStackTrace();	
		}finally {
			try {
				if(ps != null) {ps.close();}
				if(conn != null) {conn.close();}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}

		return result;
	}

회원 삭제 영역 (delete_one.jsp, getRemove 메서드)

설명은 위 영역의 삽입 영역과 거의 동일하기 때문에 생략하도록 하겠습니다.

  1. delete_one.jsp
<%@page import="org.joonzis.ex.GreenDao"%>
<%@page import="org.joonzis.ex.GreenVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 <%
 request.setCharacterEncoding("utf-8");
 String id = request.getParameter("id");
 String pw = request.getParameter("pw"); 

 GreenVO vo = new GreenVO();

 vo.setId(id);
 vo.setPw(pw);

 GreenDao dao = GreenDao.getInstance();
 int result = dao.getRemove(vo);
 pageContext.setAttribute("result", result);

 //response.sendRedirect("view_all.jsp");
 %>

 <c:choose> 
 	<c:when test="${result >= 0}">
		<script type="text/javascript">
			location.href = "view_all.jsp"
		</script> 			
 	</c:when>
 	<c:otherwise>
 		<script type="text/javascript">
 			alert("정보 삭제에 실패했습니다.")
			location.href = "view_all.jsp"
		</script>
 	</c:otherwise>
 </c:choose>
  1. getRemove 메서드
public int getRemove(GreenVO vo) {
		int result = 0;

		try {
			conn = ds.getConnection();
			
			sql = "delete from green where id = ? and pw = ?"; 
			
			ps = conn.prepareStatement(sql);
			conn.setAutoCommit(true);
			ps.setString(1, vo.getId());
			ps.setString(2, vo.getPw());
			result = ps.executeUpdate();
			if(result > 0) {
				System.err.println("데이터 삭제 완료");
			}else {
				System.out.println("데이터 삭제 실패");
			}
		} catch (Exception e) {
			e.printStackTrace();	
		}finally {
			try {
				if(ps != null) {ps.close();}
				if(conn != null) {conn.close();}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}

		return result;
	}

회원 업데이트 영역 1-1 (update_one.jsp, getUpdateView 메서드)

로직은 이전에 다루었던 프로젝트의 로직을 따르고 있기 때문에 설명이 필요하다고 판단되는 부분은 간단한 주석 정도로만 코드를 설명하겠습니다.

  1. update_one.jsp
<%@page import="org.joonzis.ex.GreenVO"%>
<%@page import="org.joonzis.ex.GreenDao"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="java.sql.Connection"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<script type="text/javascript">
	function update(f){
		if(f.pw.value == '' || !f.name.value || f.age.value === null || f.addr.value === null){
			alert("정보가 비어있습니다. 확인해 주세요.")
			return;
		}
		f.action = "update.jsp";
		f.submit();
	}
</script>
<body>
	<jsp:include page="index.jsp"/>

	<br> <hr> <br>
	
	<%
	request.setCharacterEncoding("utf-8");
	response.setContentType("text/html; charset=UTF-8");
	String id = request.getParameter("id");
	String pw = request.getParameter("pw");

	GreenDao dao = GreenDao.getInstance();
	GreenVO vo = dao.getUpdateView(id, pw);
	pageContext.setAttribute("vo", vo);	
	%>

	<h1 style = "text-align:center">${vo.getId()} 회원의 데이터</h1>
	<form method = "post">
		<table>
			<thead>
				<tr>
					<th>회원번호</th> 
					<th>아이디</th> 
					<th>비밀번호</th> 
					<th>이름</th> 
					<th>나이</th> 
					<th>주소</th> 
					<th>가입일</th> 
				</tr>
			</thead>
			<tbody>
		 			<c:choose>
                    	<!-- 
                        태그 라이브러리의 경우 비교 연산자를 기호가 아닌 특정 문구로
                        비교하는 것이 가능하기 때문에 다음과 같이 vo가 비어있는지를
                        판단하기 위해 empty 구문을 사용했습니다. (비어있지 않다면
                        not empty를 사용)
                        -->
		 				<c:when test="${empty vo}">
		 					<tr>
		 						<td colspan="7">member 데이터가 없습니다.</td>
	 						</tr>	
		 				</c:when>
		 				<c:otherwise>
		 					<tr>
		 						<td>
		 							${vo.getIdx()}
		 							<input type = "hidden" name = "idx" value = "${vo.getIdx()}">  
		 						</td>			
		 						<td>
		 							${vo.getId()}
		 						</td>			
		 						<td>
		 							<input type = "password" name = "pw" value = "${vo.getPw()}"> 
		 						</td>			
		 						<td>
		 							<input type = "text" name = "name" value = "${vo.getName()}">
		 						</td>			
		 						<td>
		 							<input type = "number" name = "age" value = "${vo.getAge()}"> 
		 						</td>			
		 						<td>
		 							<input type = "text" name = "addr" value = "${vo.getAddr()}">
		 						</td>			
		 						<td>
		 							<input type = "text" name = "reg_date" value = "${vo.getReg_date()}" readonly> 
		 						</td>			
		 					</tr>	
		 				</c:otherwise>
		 			</c:choose>
			</tbody>
			<tfoot>
				<tr>
					<td colspan = "7">
						<input type = button value = "수정" onclick = "update(this.form)">
					</td>
				</tr>
			</tfoot>
		</table>
	</form>
</body>
</html>
  1. getUpdateView 메서드
public GreenVO getUpdateView(String id, String pw){
		GreenVO vo = new GreenVO(); 

		try {
			conn = ds.getConnection();
			String sql = "select * from green where id = ? and pw = ?";
			ps = conn.prepareStatement(sql);
			ps.setString(1, id);
			ps.setString(2, pw);
			rs = ps.executeQuery();
			if(rs.next()) {
				vo.setIdx(rs.getInt(1));
				vo.setId(rs.getString(2));
				vo.setPw(rs.getString(3));
				vo.setName(rs.getString(4));
				vo.setAge(rs.getInt(5));
				vo.setAddr(rs.getString(6));
				vo.setReg_date(rs.getDate(7));
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if(rs != null) {rs.close();}
				if(ps != null) {ps.close();}
				if(conn != null) {ps.close();}
			}catch(Exception e2) {
				e2.printStackTrace();
			}
		}

		return vo;
	} 

회원 업데이트 영역 1-2 (update.jsp, getUpdate 메서드)

로직은 이전에 다루었던 프로젝트의 로직을 따르고 있기 때문에 설명이 필요하다고 판단되는 부분은 간단한 주석 정도로만 코드를 설명하겠습니다.

  1. update.jsp
<%@page import="org.joonzis.ex.GreenDao"%>
<%@page import="org.joonzis.ex.GreenVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
	request.setCharacterEncoding("UTF-8");
	response.setContentType("text/html; charset=UTF-8");

	String pw = request.getParameter("pw");
	String name = request.getParameter("name");
	int age = Integer.parseInt(request.getParameter("age"));
	String addr = request.getParameter("addr");
	int idx = Integer.parseInt(request.getParameter("idx"));

	GreenVO vo = new GreenVO();
	vo.setPw(pw);
	vo.setName(name);
	vo.setAge(age);
	vo.setAddr(addr);
	vo.setIdx(idx);

	GreenDao dao =GreenDao.getInstance();
	int result = dao.getUpdate(vo);
	pageContext.setAttribute("result", result);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<c:choose>
		<c:when test="${result > 0}">
			<script type="text/javascript">
				location.href = "view_all.jsp";
			</script>
		</c:when>
		<c:otherwise>
			<script type="text/javascript">
				alert("정보 수정에 실패했습니다.")
				location.href = "view_all.jsp";
			</script>
		</c:otherwise>
	</c:choose>
</body>
</html>
  1. getUpdate 메서드
public int getUpdate(GreenVO vo) {
		int result = 0;
		
		try {
			conn = ds.getConnection();
				
			sql = "update green set pw = ?, name = ?, age = ?, addr = ? where idx = ?"; 
			ps = conn.prepareStatement(sql);
			conn.setAutoCommit(true);
			ps.setString(1, vo.getPw());
			ps.setString(2, vo.getName());
			ps.setInt(3, vo.getAge());
			ps.setString(4, vo.getAddr());
			ps.setInt(5, vo.getIdx());
			result = ps.executeUpdate();
			if(result > 0) {
				System.err.println("데이터 수정 완료");
			}else {
				System.out.println("데이터 수정 실패");
			}
		} catch (Exception e) {
			e.printStackTrace();	
		}finally {
			try {
				if(ps != null) {ps.close();}
				if(conn != null) {conn.close();}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	
		return result;
	}

특정 사용자 조회 영역 (view_one.jsp, getUserInfoById 메서드)

로직은 이전에 다루었던 프로젝트의 로직을 따르고 있기 때문에 설명이 필요하다고 판단되는 부분은 간단한 주석 정도로만 코드를 설명하겠습니다.

  1. view_one.jsp
<%@page import="org.joonzis.ex.GreenDao"%>
<%@page import="org.joonzis.ex.GreenVO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 <%
 request.setCharacterEncoding("utf-8");
 String id = request.getParameter("id");

 GreenDao dao = GreenDao.getInstance();
 GreenVO result = dao.getUserInfoById(id);
 pageContext.setAttribute("vo", result);

 // 이전에 사용했던 방법
 //response.sendRedirect("view_all.jsp");
 %>

 <body>
    <jsp:include page="index.jsp"/>
   
    <br> <hr> <br>

    <h1 style="text-align:center">green 테이블의 전체 데이터</h1>
    <table>
        <thead>
           <tr>
	           <th>번호</th>
	           <th>아이디</th>
	           <th>비밀번호</th>
	           <th>이름</th>
	           <th>나이</th>
	           <th>주소</th>
	           <th>가입일</th>
           </tr>
        </thead>
        <tbody>
            <c:choose>
                <c:when test="${not empty vo}">
                        <tr>
                            <th>${vo.getIdx()}</th>
                            <th>${vo.getId()}</th>
                            <th>${vo.getPw()}</th>
                            <th>${vo.getName()}</th>
                            <th>${vo.getAge()}</th>
                            <th>${vo.getAddr()}</th>
                            <th>${vo.getReg_date()}</th>
                        </tr>
                </c:when>
                <c:otherwise>
                	<tr>
                		<td colspan="7">정보 조회에 실패했습니다 </td>
                	</tr>
                </c:otherwise> 
            </c:choose> 
        </tbody>
    </table>
</body>
  1. getUserInfoById 메서드
public GreenVO getUserInfoById(String id) {

		GreenVO vo = new GreenVO(); 
		
		try {
			conn = ds.getConnection();
			String sql = "select * from green where id = ?";
			ps = conn.prepareStatement(sql);
			ps.setString(1, id);
			rs = ps.executeQuery();
			if(rs.next()) {
				vo.setIdx(rs.getInt(1));
				vo.setId(rs.getString(2));
				vo.setPw(rs.getString(3));
				vo.setName(rs.getString(4));
				vo.setAge(rs.getInt(5));
				vo.setAddr(rs.getString(6));
				vo.setReg_date(rs.getDate(7));
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if(rs != null) {rs.close();}
				if(ps != null) {ps.close();}
				if(conn != null) {ps.close();}
			}catch(Exception e2) {
				e2.printStackTrace();
			}
		}

		return vo;
	}

6. 느낀 점

  1. 이번에 여러가지 태그를 쓰면서 확실하게 느꼈던 점은 추가된 기술들을 사용하면서 자바빈즈, 특히 자바의 클래스 객체에 대해서 좀 더 면밀히 와닿을 수 있었던 계기가 되었던 것 같습니다. 물론 이전에도 학원에서 객체를 배우면서 예시를 직접 만들어보며 클래스를 이용한 인스턴스 생성 및 메서드 정의, 사용 방법들을 익힐 수 있었지만, DB를 연동하는 과정에서 사용되는 DAO나 요청 정보를 전달할 때 사용하는 VO 객체를 직접 만들어보고 사용해보며 더욱 확실히 와닿을 수 있어서 해당 프로젝트를 하는 내내 되게 흥미로웠다고 생각됩니다.
profile
인생은 본인의 삶을 곱씹어보는 R과 타인의 삶을 배워 나아가는 L의 연속이다.

0개의 댓글