mvcPage
table.sql
하단에 다음의 내용을 추가/* 상품 관리 */
CREATE TABLE zitem(
item_num NUMBER NOT NULL,
name VARCHAR2(30) NOT NULL,
price NUMBER(8) NOT NULL,
quantity NUMBER(5) NOT NULL,
photo1 VARCHAR2(60) NOT NULL,
photo2 VARCHAR2(60) NOT NULL,
detail CLOB NOT NULL,
reg_date DATE DEFAULT SYSDATE NOT NULL,
modify_date DATE,
status NUMBER(1) NOT NULL,
CONSTRAINT zitem_pk PRIMARY KEY(item_num)
);
CREATE SEQUENCE zitem_seq;
WEB-INF
폴더 오른쪽 클릭하고 새 파일 shop.properties
생성# 상품 관리/관리자
/item/list.do=kr.item.action.AdminListAction
/item/writeForm.do=kr.item.action.AdminWriteFormAction
/item/write.do=kr.item.action.AdminWriteAction
WEB-INF
폴더의 web.xml
를 열고, 왼쪽 하단의 Source
탭 선택 후 <init-param>
태그 사이의 내용을 다음처럼 수정 <init-param>
<param-name>propertiesPath</param-name>
<param-value>/WEB-INF/member.properties,/WEB-INF/board.properties,/WEB-INF/shop.properties</param-value>
</init-param>
src/main/java
오른쪽 클릭하고 새 패키지 kr.item.vo
생성 후 새 클래스 ItemVO
생성package kr.item.vo;
import java.sql.Date;
public class ItemVO {
private int item_num; // 상품 번호
private String name; // 상품명
private int price; // 가격
private int quantity; // 판매 수량
private String photo1; // 상품 사진 파일명1
private String photo2; // 상품 사진 파일명2
private String detail; // 상품 정보
private Date reg_date; // 등록일
private Date modify_date; // 수정일
private int status; // 상품 표시 여부
public int getItem_num() {
return item_num;
}
public void setItem_num(int item_num) {
this.item_num = item_num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public String getPhoto1() {
return photo1;
}
public void setPhoto1(String photo1) {
this.photo1 = photo1;
}
public String getPhoto2() {
return photo2;
}
public void setPhoto2(String photo2) {
this.photo2 = photo2;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public Date getReg_date() {
return reg_date;
}
public void setReg_date(Date reg_date) {
this.reg_date = reg_date;
}
public Date getModify_date() {
return modify_date;
}
public void setModify_date(Date modify_date) {
this.modify_date = modify_date;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
src/main/java
오른쪽 클릭하고 새 패키지 kr.item.dao
생성 후 새 클래스 ItemDAO
생성package kr.item.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import kr.item.vo.ItemVO;
import kr.util.DBUtil;
public class ItemDAO {
// 싱글턴 패턴
private static ItemDAO instance = new ItemDAO();
public static ItemDAO getInstance() {
return instance;
}
private ItemDAO() {}
// 관리자 : 상품 등록
public void insertItem(ItemVO item) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try {
// 커넥션 풀로부터 커넥션 할당
conn = DBUtil.getConnection();
// SQL문 작성
sql = "INSERT INTO zitem (item_num, name, price, quantity, photo1, photo2, detail, status) "
+ "VALUES (zitem_seq.NEXTVAL, ?, ?, ?, ?, ?, ?, ?)";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setString(1, item.getName());
pstmt.setInt(2, item.getPrice());
pstmt.setInt(3, item.getQuantity());
pstmt.setString(4, item.getPhoto1());
pstmt.setString(5, item.getPhoto2());
pstmt.setString(6, item.getDetail());
pstmt.setInt(7, item.getStatus());
// SQL문 실행
pstmt.executeUpdate();
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
DBUtil.executeClose(null, pstmt, conn);
}
}
// 관리자/사용자 : 전체 상품 갯수/검색 상품 갯수
public int getItemCount(String keyfield, String keyword, int status) throws Exception {
int count = 0;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
String sub_sql = "";
int cnt = 0; // 가변적 ? 번호
try {
// 커넥션 풀로부터 커넥션 할당
conn = DBUtil.getConnection();
// 검색 처리
if(keyword!=null && !"".equals(keyword)) {
if(keyfield.equals("1")) sub_sql = "AND name LIKE ?";
else if(keyfield.equals("2")) sub_sql = "AND detail LIKE ?";
}
// SQL문 작성
sql = "SELECT COUNT(*) FROM zitem WHERE status > ? " + sub_sql; // 전체 검색시에는 인자로 0 전달
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setInt(++cnt, status);
if(keyword != null && !"".equals(keyword)) {
pstmt.setString(++cnt, "%" + keyword + "%");
}
// SQL문을 실행해서 결과 행을 ResultSet에 담아 반환
rs = pstmt.executeQuery();
if(rs.next()) {
count = rs.getInt(1);
}
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
DBUtil.executeClose(rs, pstmt, conn);
}
return count;
}
// 관리자/사용자 : 전체 목록/검색 목록
public List<ItemVO> getListItem(int startRow, int endRow, String keyfield, String keyword, int status) throws Exception {
List<ItemVO> list = null;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
String sub_sql = "";
int cnt = 0; // 가변적 ? 번호
try {
// 커넥션 풀로부터 커넥션 할당
conn = DBUtil.getConnection();
// 검색 처리
if(keyword!=null && !"".equals(keyword)) {
if(keyfield.equals("1")) sub_sql = "AND name LIKE ?";
else if(keyfield.equals("2")) sub_sql = "AND detail LIKE ?";
}
// SQL문 작성
sql = "SELECT * FROM (SELECT i.*, ROWNUM AS rnum "
+ "FROM (SELECT * FROM zitem WHERE status > ? " + sub_sql
+ " ORDER BY item_num DESC) i) WHERE rnum >= ? AND rnum <= ?";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setInt(++cnt, status);
if(keyword!=null && !"".equals(keyword)) {
pstmt.setString(++cnt, "%" + keyword + "%");
}
pstmt.setInt(++cnt, startRow);
pstmt.setInt(++cnt, endRow);
// SQL문을 실행해서 결과 행들을 ResultSet에 담아 반환
rs = pstmt.executeQuery();
list = new ArrayList<ItemVO>();
while(rs.next()) {
ItemVO item = new ItemVO();
item.setItem_num(rs.getInt("item_num"));
item.setName(rs.getString("name"));
item.setPrice(rs.getInt("price"));
item.setQuantity(rs.getInt("quantity"));
item.setPhoto1(rs.getString("photo1"));
item.setPhoto2(rs.getString("photo2"));
item.setReg_date(rs.getDate("reg_date"));
item.setModify_date(rs.getDate("modify_date"));
item.setStatus(rs.getInt("status"));
// 자바빈을 ArrayList에 저장
list.add(item);
}
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
DBUtil.executeClose(rs, pstmt, conn);
}
return list;
}
// 관리자/사용자 : 상품 상세
public ItemVO getItem(int item_num) throws Exception {
ItemVO item = null;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
try {
// 커넥션 풀로부터 커넥션 할당
conn = DBUtil.getConnection();
// SQL문 작성
sql = "SELECT * FROM zitem WHERE item_num=?";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setInt(1, item_num);
// SQL문을 실행해서 결과 행을 ResultSet에 담아 반환
rs = pstmt.executeQuery();
if(rs.next()) {
item = new ItemVO();
item.setItem_num(item_num);
item.setName(rs.getString("name"));
item.setPrice(rs.getInt("price"));
item.setQuantity(rs.getInt("quantity"));
item.setPhoto1(rs.getString("photo1"));
item.setPhoto2(rs.getString("photo2"));
item.setDetail(rs.getString("detail"));
item.setStatus(rs.getInt("status"));
}
}
catch(Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
DBUtil.executeClose(rs, pstmt, conn);
}
return item;
}
// 관리자 : 상품 수정
public void updateItem(ItemVO item) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
String sub_sql = "";
int cnt = 0; // 가변적 ? 번호
try {
// 커넥션 풀로부터 커넥션 할당
conn = DBUtil.getConnection();
if(item.getPhoto1()!=null) sub_sql += ", photo1=?";
if(item.getPhoto2()!=null) sub_sql += ", photo2=?";
// SQL문 작성
sql = "UPDATE zitem SET name=?, price=?, quantity=?" + sub_sql
+ ", detail=?, modify_date=SYSDATE, status=? WHERE item_num=?";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setString(++cnt, item.getName());
pstmt.setInt(++cnt, item.getPrice());
pstmt.setInt(++cnt, item.getQuantity());
if(item.getPhoto1()!=null) pstmt.setString(++cnt, item.getPhoto1());
if(item.getPhoto2()!=null) pstmt.setString(++cnt, item.getPhoto2());
pstmt.setString(++cnt, item.getDetail());
pstmt.setInt(++cnt, item.getStatus());
pstmt.setInt(++cnt, item.getItem_num());
// SQL문 실행
pstmt.executeUpdate();
}
catch (Exception e) {
throw new Exception(e);
}
finally {
// 자원 정리
DBUtil.executeClose(null, pstmt, conn);
}
}
// 관리자 : 상품 삭제
public void deleteItem(int item_num) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
PreparedStatement pstmt2 = null;
String sql = null;
try {
// 커넥션 풀로부터 커넥션 할당
conn = DBUtil.getConnection();
// 오토 커밋 해제
conn.setAutoCommit(false);
// 삭제하고자 하는 상품이 카트에 담겨 있으면 카트에 저장된 상품을 삭제
// SQL문 작성
sql = "DELETE FROM zcart WHERE item_num=?";
// PreparedStatement 객체 생성
pstmt = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt.setInt(1, item_num);
// SQL문 실행
pstmt.executeUpdate();
// 상품 테이블에서 상품 삭제
// SQL문 작성
sql = "DELETE FROM zitem WHERE item_num=?";
// PreparedStatement 객체 생성
pstmt2 = conn.prepareStatement(sql);
// ?에 데이터를 바인딩
pstmt2.setInt(1, item_num);
// SQL문 실행
pstmt2.executeUpdate();
// SQL문 실행이 모두 성공하면
conn.commit();
}
catch(Exception e) {
// SQL문 실행이 하나라도 실패하면
conn.rollback();
throw new Exception(e);
}
finally {
// 자원 정리
DBUtil.executeClose(null, pstmt2, null);
DBUtil.executeClose(null, pstmt, conn);
}
}
}
src/main/java
오른쪽 클릭하고 새 패키지 kr.item.action
생성 후 새 클래스 AdminListAction
생성package kr.item.action;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import kr.controller.Action;
import kr.item.dao.ItemDAO;
import kr.item.vo.ItemVO;
import kr.util.PagingUtil;
public class AdminListAction implements Action {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpSession session = request.getSession();
Integer user_num = (Integer)session.getAttribute("user_num");
if(user_num==null) { // 로그인되어 있지 않은 경우
return "redirect:/member/loginForm.do";
}
Integer user_auth = (Integer)session.getAttribute("user_auth");
if(user_auth!=3) { // 관리자로 로그인하지 않은 경우
return "/WEB-INF/views/common/notice.jsp";
}
// 관리자로 로그인한 경우
String pageNum = request.getParameter("pageNum");
if(pageNum==null) pageNum = "1";
String keyfield = request.getParameter("keyfield");
String keyword = request.getParameter("keyword");
ItemDAO dao = ItemDAO.getInstance();
int count = dao.getItemCount(keyfield, keyword, 0); // status가 0이면 미표시(1)와 표시(2)를 모두 출력
// 페이지 처리
PagingUtil page = new PagingUtil(keyfield, keyword, Integer.parseInt(pageNum), count, 20, 10, "list.do");
List<ItemVO> list = null;
if(count>0) {
list = dao.getListItem(page.getStartCount(), page.getEndCount(), keyfield, keyword, 0); // status가 0이면 미표시(1)와 표시(2)를 모두 출력
}
request.setAttribute("count", count);
request.setAttribute("list", list);
request.setAttribute("pagingHtml", page.getPagingHtml());
// JSP 경로 반환
return "/WEB-INF/views/item/admin_list.jsp";
}
}
AdminWriteFormAction
생성package kr.item.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import kr.controller.Action;
public class AdminWriteFormAction implements Action {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpSession session = request.getSession();
Integer user_num = (Integer)session.getAttribute("user_num");
if(user_num==null) { // 로그인되어 있지 않은 경우
return "redirect:/member/loginForm.do";
}
Integer user_auth = (Integer)session.getAttribute("user_auth");
if(user_auth!=3) { // 관리자로 로그인하지 않은 경우
return "/WEB-INF/views/common/notice.jsp";
}
// 관리자로 로그인한 경우
return "/WEB-INF/views/item/admin_writeForm.jsp";
}
}
AdminWriteAction
생성package kr.item.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.oreilly.servlet.MultipartRequest;
import kr.controller.Action;
import kr.item.dao.ItemDAO;
import kr.item.vo.ItemVO;
import kr.util.FileUtil;
public class AdminWriteAction implements Action {
@Override
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpSession session = request.getSession();
Integer user_num = (Integer)session.getAttribute("user_num");
if(user_num==null) { // 로그인되어 있지 않은 경우
return "redirect:/member/loginForm.do";
}
Integer user_auth = (Integer)session.getAttribute("user_auth");
if(user_auth!=3) { // 관리자로 로그인하지 않은 경우
return "/WEB-INF/views/common/notice.jsp";
}
// 관리자로 로그인한 경우
MultipartRequest multi = FileUtil.createFile(request);
ItemVO item = new ItemVO();
item.setName(multi.getParameter("name"));
item.setPrice(Integer.parseInt(multi.getParameter("price")));
item.setQuantity(Integer.parseInt(multi.getParameter("quantity")));
item.setPhoto1(multi.getFilesystemName("photo1"));
item.setPhoto2(multi.getFilesystemName("photo2"));
item.setDetail(multi.getParameter("detail"));
item.setStatus(Integer.parseInt(multi.getParameter("status")));
ItemDAO dao = ItemDAO.getInstance();
dao.insertItem(item);
// JSP 경로 반환
return "redirect:/item/list.do";
}
}
common
폴더의 header.jsp
를 열고 <c:if test="${!empty user_num && user_auth == 3}">
태그 사이의 내용을 다음처럼 수정 <c:if test="${!empty user_num && user_auth == 3}">
<a href="${pageContext.request.contextPath}/member/memberList.do">회원 관리</a>
<a href="${pageContext.request.contextPath}/item/list.do">상품 관리</a>
</c:if>
views
폴더의 하위 폴더로 item
생성 후 새 JSP 파일 admin_list.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 목록</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/layout.css">
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.6.0.min.js"></script>
</head>
<body>
<div class="page-main">
<jsp:include page="/WEB-INF/views/common/header.jsp"/>
<h2>상품 목록</h2>
<form id="search_form" action="list.do" method="get">
<ul class="search">
<li>
<select name="keyfield">
<option value="1">상품명</option>
<option value="2">내용</option>
</select>
</li>
<li>
<input type="search" size="16" name="keyword" id="keyword">
</li>
<li>
<input type="submit" value="검색">
</li>
</ul>
</form>
<div class="list-space align-right">
<input type="button" value="상품 등록" onclick="location.href = 'writeForm.do';">
<input type="button" value="목록으로" onclick="location.href = 'list.do';">
<input type="button" value="홈으로" onclick="location.href = '${pageContext.request.contextPath}/main/main.do';">
</div>
<c:if test="${count==0}">
<div class="result-display">
표시할 상품이 없습니다.
</div>
</c:if>
<c:if test="${count>0}">
<table>
<tr>
<th>상품명</th>
<th>가격</th>
<th>재고 수</th>
<th>등록일</th>
<th>상태</th>
</tr>
<c:forEach var="item" items="${list}">
<tr>
<td><a href="modifyForm.do?item_num=${item.item_num}">${item.name}</a></td>
<td><fmt:formatNumber value="${item.price}"/></td>
<td><fmt:formatNumber value="${item.quantity}"/></td>
<td>${item.reg_date}</td>
<td>
<c:if test="${item.status==1}">미표시</c:if>
<c:if test="${item.status==2}">표시</c:if>
</td>
</tr>
</c:forEach>
</table>
<div class="align-center">
${pagingHtml}
</div>
</c:if>
</div>
</body>
</html>
item
폴더에 새 JSP 파일 admin_writeForm.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 등록</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/layout.css">
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
$('#write_form').submit(function(event) {
if($('input[type=radio]:checked').length<1) {
alert('상품 표시 여부를 지정하세요!');
return false;
}
let isValid = true; // submit()의 return 값 지정
$('li').each(function() {
let input = $(this).find('input[type!="button"],textarea');
if(!input.val().trim()) {
let word = $(this).find('label').text();
let last = word.charCodeAt(word.length-1);
let post;
if(last>'가'.charCodeAt(0) && last<'힣'.charCodeAt(0)) {
post = (last - '가'.charCodeAt(0)) % 28 > 0 ? '을' : '를';
}
else {
post = '을/를';
}
if(input.attr('type')=='file') post += ' 선택하세요!';
else post += ' 입력하세요!';
alert(word + post);
input.val('').focus();
isValid = false; // submit()의 return 값 지정
return false; // each() 루프 중단
}
}); // end of each
return isValid;
}); // end of submit
});
</script>
</head>
<body>
<div class="page-main">
<jsp:include page="/WEB-INF/views/common/header.jsp"/>
<h2>상품 등록</h2>
<form action="write.do" method="post" enctype="multipart/form-data" id="write_form">
<ul>
<li>
<label>상품 표시 여부</label>
<input type="radio" name="status" value="1" id="status1">미표시
<input type="radio" name="status" value="2" id="status2">표시
</li>
<li>
<label for="name">상품명</label>
<input type="text" name="name" id="name" maxlength="10">
</li>
<li>
<label for="price">가격</label>
<input type="number" name="price" id="price" min="1" max="99999999">
</li>
<li>
<label for="quantity">수량</label>
<input type="number" name="quantity" id="quantity" min="0" max="99999">
</li>
<li>
<label for="photo1">상품 사진1</label>
<input type="file" name="photo1" id="photo1" accept="image/jpeg,image/gif,image/png">
</li>
<li>
<label for="photo2">상품 사진2</label>
<input type="file" name="photo2" id="photo2" accept="image/jpeg,image/gif,image/png">
</li>
<li>
<label for="detail">상품 설명</label>
<textarea rows="5" cols="30" name="detail" id="detail"></textarea>
</li>
</ul>
<div class="align-center">
<input type="submit" value="등록">
<input type="button" value="목록으로" onclick="location.href = 'list.do';">
</div>
</form>
</div>
</body>
</html>