간단한 웹페이지 만들기 - 관리자

임승현·2022년 12월 23일
0

JSP

목록 보기
19/20

🌈Part 1 - 관리자 아이디 만들기

◈SQL Develope 실행 후 아래 코드 입력
(회원가입 완료한 아이디를 관리자 아이디로 변경)

update member set status=9 where id='abc123';
commit;

🌈Part 2 - jsp 문서 만들기

1. admin 폴더에 header.jsp
2. security 폴더에 admin_check.jspf
3. member_manager.jsp
4. product_manager.jsp
5. order_manager.jsp
6. board_manager.jsp

🌈Part 3 - 회원관리

1. header.jsp
→관리자 관련 페이지를 요청한 경우 템플릿 페이지의 머릿부에 포함될 JSP 문서

📃header.jsp

<%@page import="xyz.itwill.dto.MemberDTO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 관리자 관련 페이지를 요청한 경우 템플릿 페이지의 머릿부에 포함될 JSP 문서 --%>
<%--
<%
	//세션에 저장된 권한 관련 정보를 반환받아 저장
	MemberDTO loginMember=(MemberDTO)session.getAttribute("loginMember");
	//
	//비로그인 사용자이거나 관리자가 아닌 경우 에러페이지로 이동되도록 응답 처리 - 비정상적인 요청
	if(loginMember==null || loginMember.getStatus()!=9) {
		out.println("<script type='text/javascript'>");
		out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
		out.println("</script>");
		return;
	}
%>    
--%>
<%-- 위에 있는 주석문을 admin_check.jspf 파일에 복사하고 include로 불러오기 --%>
<%@include file="/security/admin_check.jspf" %>   
<div id="profile">
	관리자[<%=loginMember.getName() %>]님, 환영합니다.&nbsp;&nbsp;
	<a href="index.jsp?workgroup=member&work=member_logout_action">로그아웃</a>&nbsp;&nbsp;
	<a href="index.jsp?workgroup=main&work=main_page">쇼핑몰</a>&nbsp;&nbsp;
</div> 
<div id="logo"><a href="index.jsp?workgroup=admin&work=main_page">쇼핑몰관리</a></div>
<div id="menu">
	<a href="index.jsp?workgroup=admin&work=member_manager">회원관리</a>
	<a href="index.jsp?workgroup=admin&work=product_manager">제품관리</a>
	<a href="index.jsp?workgroup=admin&work=order_manager">주문관리</a>
	<a href="index.jsp?workgroup=admin&work=board_manager">게시글관리</a>
</div>

2. member_manager.jsp
→MEMBER 테이블에 저장된 모든 회원정보를 검색하여 클라이언트에게 전달하는 JSP 문서

📃member_manager.jsp

<%@page import="xyz.itwill.dao.MemberDAO"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- MEMBER 테이블에 저장된 모든 회원정보를 검색하여 클라이언트에게 전달하는 JSP 문서 --%>
<%-- → 관리자만 요청 가능한 JSP 문서 --%>
<%-- → [선택회원삭제]를 클릭한 경우 회원정보 삭제페이지(member_remove_action.jsp)로 이동 - 체크박스로 선택된 모든 회원의 아이디 전달 --%>
<%-- → 회원정보에서 [상태]를 변경한 경우 회원상태 변경페이지(member_status_action.jsp)로 이동 - 아이디와 회원상태 전달 --%>
<%@include file="/security/admin_check.jspf" %>
<%
	//MEMBER 테이블에 저장된 모든 회원정보를 검색하여 반환하는 DAO 클래스의 메소드 호출
	List<MemberDTO> memberList=MemberDAO.getDAO().selectMemberList();
%>
<style type="text/css">
table {
	margin: 0 auto;
	border: 1px solid black;
	border-collapse: collapse;
}
th, td {
	border: 1px solid black;
	padding: 3px;
	text-align: center;
	font-size: 12px;
}
th {
	background-color: black;
	color: white;
}
.member_check { width: 80px; }
.member_id { width: 80px; }
.member_name { width: 80px; }
.member_email { width: 140px; }
.member_mobile { width: 140px; }
.member_address { width: 300px; }
.member_join { width: 150px; }
.member_login { width: 150px; }
.member_status { width: 80px; }
</style>
<h1>회원관리</h1>
<form name="memberForm" id="memberForm">
	<table>
		<tr>
			<th><input type="checkbox" id="allCheck"></th>
			<th>아이디</th>
			<th>이름</th>
			<th>이메일</th>
			<th>전화번호</th>
			<th>주소</th>
			<th>가입날짜</th>
			<th>최종로그인</th>
			<th>상태</th>
		</tr>
		<%-- --%>
		<% for(MemberDTO member:memberList) { %>
		<tr>
			<td class="member_check">
				<% if(member.getStatus()==9) { %>
					관리자
				<% } else { %>
					<input type="checkbox" name="checkId" value="<%=member.getId()%>" class="check">
				<% } %>
			</td>
			<td class="member_id"><%=member.getId() %></td>
			<td class="member_name"><%=member.getName() %></td>
			<td class="member_email"><%=member.getEmail() %></td>
			<td class="member_mobile"><%=member.getMobile() %></td>
			<td class="member_address">
				[<%=member.getZipcode() %>]<%=member.getAddress1() %> <%=member.getAddress2() %>
			</td>
			<td class="member_join"><%=member.getJoinDate() %></td>
			<td class="member_login">
				<% if(member.getLastLogin()!=null) { %>
				<%=member.getJoinDate() %>
				<% } %>
			</td>
			<td class="member_status">
				<select class="status" name="<%=member.getId()%>">
					<option value="0" <% if(member.getStatus()==0) { %> selected="selected" <% } %>>탈퇴회원</option>
					<option value="1" <% if(member.getStatus()==1) { %> selected="selected" <% } %>>일반회원</option>
					<option value="9" <% if(member.getStatus()==9) { %> selected="selected" <% } %>>관리자</option>
				</select>
			</td>
		</tr>
		<% } %>
	</table>
	<p><button type="button" id="removeBtn">선택회원삭제</button></p>
	<div id="message" style="color: red;"></div>
</form>
<%-- --%>
<script type="text/javascript">
<%-- 회원정보 삭제 관련 --%>
$("#allCheck").change(function() {
	if($(this).is(":checked")) {
		$(".check").prop("checked",true);
	} else {
		$(".check").prop("checked",false);
	}
});
$("#removeBtn").click(function() {
	if($(".check").filter(":checked").length==0) {
		$("#message"),text("선택된 회원이 없습니다.");
		return;
	}
	$("#memberForm").attr("action", "<%=request.getContextPath()%>/index.jsp?workgroup=admin&work=member_remove_action");
	$("#memberForm").attr("method","post");
	//
	$("#memberForm").submit();
});
<%-- 회원정보 변경 관련 --%>
$(".status").change(function() {
	//이벤트가 발생된 입력태그의 태그 속성값을 반환받아 저장
	//→ 회원상태를 변경하고자 하는 회원의 아이디를 제공받아 저장
	var id=$(this).attr("name");
	//
	//이벤트가 발생된 입력태그의 입력값을 반환받아 저장
	//→ 변경할 회원상태를 제공받아 저장 - 변경값
	var status=$(this).val();
	//
	location.href="<%=request.getContextPath()%>/index.jsp?workgroup=admin&work=member_status_action&id="+id+"&status="+status;
});
</script>

🌀회원정보 삭제 관련

1. member_remove_action.jsp
→아이디 목록을 전달받아 MEMBER 테이블에 저장된 해당 아이디의 회원정보를 삭제하고 회원정보
관리페이지(member_manager.jsp)로 이동하기 위한 URL 주소를 클라이언트에게 전달하는 JSP 문서

📃member_remove_action.jsp

<%@page import="xyz.itwill.dao.MemberDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 아이디 목록을 전달받아 MEMBER 테이블에 저장된 해당 아이디의 회원정보를 삭제하고 회원정보 
관리페이지(member_manager.jsp)로 이동하기 위한 URL 주소를 클라이언트에게 전달하는 JSP 문서--%>
<%-- → 관리자만 요청 가능한 JSP 문서 --%>
<%@include file="/security/admin_check.jspf" %>
<%
	//비정상적인 요청에 대한 응답 처리
	if(request.getMethod().equals("GET")) {
		out.println("<script type='text/javascript'>");
		out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
		out.println("</script>");
		return;
	}
	//
	//체크박스로 선택되어 전달된 모든 회원의 아이디를 반환받아 저장
	//→ 동일한 이름으로 다수의 값이 전달되므로 request.getParameterValeus() 메소드 호출
	String[] checkId=request.getParameterValues("checkId");
	//
	//배열의 요소를 차례대로 제공받아 반복 처리
	for(String id:checkId) {
		//아이디를 전달받아 MEMBER 테이블에 저장된 해당 아이디의 회원정보를 삭제하는 DAO 클래스의 메소드 호출
		MemberDAO.getDAO().deleteMember(id);
	}
	//
	//페이지 이동
	out.println("<script type='text/javascript'>");
	out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=admin&work=member_manager';");
	out.println("</script>");
%>

🌀회원정보 변경 관련

1. member_status_action.jsp
→아이디와 회원상태를 전달받아 MEMBER 테이블에 저장된 해당 아이디의 회원상태를 변경하고 회원정보
관리페이지(member_manager.jsp)로 이동하기 위한 URL 주소를 클라이언트에게 전달하는 JSP 문서

📃member_status_action.jsp

<%@page import="xyz.itwill.dao.MemberDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 아이디와 회원상태를 전달받아 MEMBER 테이블에 저장된 해당 아이디의 회원상태를 변경하고 회원정보 
관리페이지(member_manager.jsp)로 이동하기 위한 URL 주소를 클라이언트에게 전달하는 JSP 문서 --%>
<%-- → 관리자만 요청 가능한 JSP 문서 --%>
<%@include file="/security/admin_check.jspf" %>
<%
	//비정상적인 요청에 대한 응답 처리
	if(request.getParameter("id")==null || request.getParameter("status")==null) {
		out.println("<script type='text/javascript'>");
		out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
		out.println("</script>");
		return;
	}
	//
	//전달값을 반환받아 저장
	String id=request.getParameter("id");
	int status=Integer.parseInt(request.getParameter("status"));
	//
	//아이디와 회원상태를 전달받아 MEMBER 테이블에 저장된 해당 아이디의 회원정보에서 회원상태를 변경하는 DAO 클래스의 메소드 호출
	MemberDAO.getDAO().updateStatus(id, status);
	//
	//페이지 이동
	out.println("<script type='text/javascript'>");
	out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=admin&work=member_manager';");
	out.println("</script>");
%>

🌈Part 4 - 제품관리(제품의 이미지 업로드)

1. 제품정보를 저장하는 테이블 생성

create table product(num number(4) primary key, category varchar2(50)
	, name varchar2(100), image_main varchar2(100)
	, image_detail varchar2(100),qty number(8),price number(8));
create sequence product_seq;
desc product;



2. DTO 클래스 생성

📃Product.DTO.java

package xyz.itwill.dto;
/*
이름           널?       유형            
------------ -------- ------------- 
NUM          NOT NULL NUMBER(4)     - 제품번호
CATEGORY              VARCHAR2(50)  - 카테고리
NAME                  VARCHAR2(100) - 제품명
IMAGE_MAIN            VARCHAR2(100) - 대표이미지
IMAGE_DETAIL          VARCHAR2(100) - 상세이미지
QTY                   NUMBER(8)     - 제품수량
PRICE                 NUMBER(8)		- 제품가격
*/
public class ProductDTO {
	private int num;
	private String category;
	private String name;
	private String imageMain;
	private String ImageDetail;
	private int qty;
	private int price;
	//
	public ProductDTO() {
		// TODO Auto-generated constructor stub
	}
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getCategory() {
		return category;
	}
	public void setCategory(String category) {
		this.category = category;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getImageMain() {
		return imageMain;
	}
	public void setImageMain(String imageMain) {
		this.imageMain = imageMain;
	}
	public String getImageDetail() {
		return ImageDetail;
	}
	public void setImageDetail(String imageDetail) {
		ImageDetail = imageDetail;
	}
	public int getQty() {
		return qty;
	}
	public void setQty(int qty) {
		this.qty = qty;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
}

3. DAO 클래스 생성

📃ProductDAO.java

package xyz.itwill.dao;
//
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
//
import xyz.itwill.dto.ProductDTO;
//
public class ProductDAO extends JdbcDAO {
	private static ProductDAO _dao;
	//
	public ProductDAO() {
		// TODO Auto-generated constructor stub
	}
	//
	static {
		_dao=new ProductDAO();
	}
	//
	public static ProductDAO getDao() {
		return _dao;
	}
	//
	//카테고리를 전달받아 PRODUCT 테이블에 저장된 해당 카테고리의 모든 제품 정보를 검색하여 반환하는 메소드
	//→ PRODUCT 테이블에 저장된 모든 제품정보를 검색하여 반환
	public List<ProductDTO> selectProductList(String category) {
		Connection con=null;
		PreparedStatement pstmt=null;
		ResultSet rs=null;
		List<ProductDTO> productList=new ArrayList<>();
		try {
			con=getConnection();
			//
			//동적 SQL 기능을 사용하여 매개변수에 저장된 값에 따라 다른 SQL 명령이 전달되어 실행되도록 설정
			if(category.equals("ALL")) {
				String sql="select * form product order by category, name";
				pstmt=con.prepareStatement(sql);
			} else {
				String sql="select * form product where category=? order by name";
				pstmt=con.prepareStatement(sql);
				pstmt.setString(1, category);
			}
			//
			rs=pstmt.executeQuery();
			//
			while(rs.next()) {
				ProductDTO product=new ProductDTO();
				product.setNum(rs.getInt("num"));
				product.setCategory(rs.getString("category"));
				product.setName(rs.getString("name"));
				product.setImageMain(rs.getString("image_main"));
				product.setImageDetail(rs.getString("image_detail"));	
				product.setQty(rs.getInt("qty"));
				product.setPrice(rs.getInt("price"));
			}
		} catch (SQLException e) {
			System.out.println("[에러]selectProductList() 메소드의 SQL 오류 = " + e.getMessage());
		} finally {
			close(con, pstmt, rs);
		}
		return productList;
	}
	//
	// 제품정보를 전달받아 PRODUCT 테이블에 삽입하고 삽입행의 갯수를 반환하는 메소드
	public int insertProduct(ProductDTO product) {
		Connection con = null;
		PreparedStatement pstmt = null;
		int rows = 0;
		try {
			con = getConnection();
			//
			String sql = "insert into product values(product_seq.nextval,?,?,?,?,?,?)";
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, product.getCategory());
			pstmt.setString(2, product.getName());
			pstmt.setString(3, product.getImageMain());
			pstmt.setString(4, product.getImageDetail());
			pstmt.setInt(5, product.getQty());
			pstmt.setInt(6, product.getPrice());
			//
			rows = pstmt.executeUpdate();
		} catch (SQLException e) {
			System.out.println("[에러]insertProduct() 메소드의 SQL 오류 = " + e.getMessage());
		} finally {
			close(con, pstmt);
		}
		return rows;
	}
	//
	//제품번호를 전달받아 PRODUCT 테이블에 저장된 해당 제품번호의 제품정보를 검색하여 반환하는 메소드(product_modify.jsp)
	public ProductDTO selectProduct(int num) {
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		ProductDTO product = null;
		try {
			con = getConnection();
			//
			String sql = "select * from product where num=?";
			pstmt = con.prepareStatement(sql);
			pstmt.setInt(1, num);
			//
			rs = pstmt.executeQuery();
			//
			if (rs.next()) {
				product = new ProductDTO();
				product.setNum(rs.getInt("num"));
				product.setCategory(rs.getString("category"));
				product.setName(rs.getString("name"));
				product.setImageMain(rs.getString("image_main"));
				product.setImageDetail(rs.getString("image_detail"));
				product.setQty(rs.getInt("qty"));
				product.setPrice(rs.getInt("price"));
			}
		} catch (SQLException e) {
			System.out.println("[에러]selectProduct() 메소드의 SQL 오류 = " + e.getMessage());
		} finally {
			close(con, pstmt, rs);
		}
		return product;
	}
	//
	//제품정보를 전달받아 PRODUCT 테이블에 저장된 해당 제품정보를 변경하고 변경행의 갯수를 반환하는 메소드(product_modify_action.jsp)
	public int updateProduct(ProductDTO product) {
		Connection con=null;
		PreparedStatement pstmt=null;
		int rows=0;
		try {
			con=getConnection();
			//		
			String sql="update product set category=?,name=?,image_main=?,image_detail=?"
					+ ",qty=?,price=? where num=?";
			pstmt=con.prepareStatement(sql);
			pstmt.setString(1, product.getCategory());
			pstmt.setString(2, product.getName());
			pstmt.setString(3, product.getImageMain());
			pstmt.setString(4, product.getImageDetail());
			pstmt.setInt(5, product.getQty());
			pstmt.setInt(6, product.getPrice());
			pstmt.setInt(7, product.getNum());
			//
			rows=pstmt.executeUpdate();
		} catch (SQLException e) {
			System.out.println("[에러]updateProduct() 메소드의 SQL 오류 = "+e.getMessage());
		} finally {
			close(con, pstmt);
		}
		return rows;
	}
}

4. product_manager.jsp
→카테고리를 전달받아 PRODUCT 테이블에 저장된 해당 카테고리의 모든 제품정보를 검색하여 클라이언트에게 전달하는 JSP 문서

📃product_manager.jsp

<%@page import="java.text.DecimalFormat"%>
<%@page import="xyz.itwill.dao.ProductDAO"%>
<%@page import="xyz.itwill.dto.ProductDTO"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 카테고리를 전달받아 PRODUCT 테이블에 저장된 해당 카테고리의 모든 제품정보를 검색하여
클라이언트에게 전달하는 JSP 문서 --%>
<%-- → 관리자만 요청 가능한 JSP 문서 --%>    
<%-- → [제품등록]을 클릭한 경우 제품정보 입력페이지(product_add.jsp)로 이동 --%>
<%-- → [카테고리]가 변경된 경우 제품목록 출력페이지(product_manager.jsp)로 이동 - 입력값 전달 --%>
<%-- → 제품정보의 [제품명]을 클릭한 경우 제품정보 출력페이지(product_detail.jsp)로 이동 - 제품번호 전달 --%>
<%@include file="/security/admin_check.jspf" %>
<%
	//전달값을 반환받아 저장
	String category=request.getParameter("category");
	if(category==null) {//전달값이 없는 경우
		category="ALL";		
	}
	//
	//카테고리를 전달받아 PRODUCT 테이블에 저장된 해당 카테고리의 모든 제품정보를 검색하여
	//반환하는 DAO 클래스의 메소드 호출
	List<ProductDTO> productList=ProductDAO.getDAO().selectProductList(category);
%>
<style type="text/css">
#product {
	width: 1000px;
	margin: 0 auto;
}
#btn {
	text-align: right;
	margin-bottom: 5px;
}
table {
	border: 1px solid black;
	border-collapse: collapse;
}
th, td {
	border: 1px solid black;
	text-align: center;
	width: 200px;	
}
th {
	background-color: black;
	color: white;
}
.pname {
	width: 400px;
}
td a, td a:hover {
	text-decoration: underline;
	color: blue;
}
</style>
<div id="product">
	<h2>제품목록</h2>
	<%-- --%>
	<div id="btn">
		<button type="button" id="addBtn">제품등록</button>
	</div>
	<%-- --%>
	<table>
		<tr>
			<th>제품번호</th>
			<th class="pname">제품명</th>
			<th>제품수량</th>
			<th>제품가격</th>
		</tr>
		<%-- --%>
		<% if(productList.isEmpty()) { %>
		<tr>
			<td colspan="4">검색된 제품이 하나도 없습니다.</td>
		</tr>
		<% } else { %>
			<% for(ProductDTO product:productList) { %>
			<tr>
				<td><%=product.getNum() %></td>
				<td>
					<a href="<%=request.getContextPath() %>/index.jsp?workgroup=admin&work=product_detail&num=<%=product.getNum()%>">
						<%=product.getName() %>
					</a>
				</td>
				<td>
					<%=DecimalFormat.getInstance().format(product.getQty()) %>
				</td>
				<td>
					<%=DecimalFormat.getCurrencyInstance().format(product.getPrice()) %>
				</td>	
			</tr>
			<% } %>
		<% } %>
	</table>
	<%-- --%>
	<br>
	<form action="<%=request.getContextPath() %>/index.jsp?workgroup=admin&work=product_manager" 
		method="post" id="productForm">
		<select name="category" id="category">
			<option value="ALL" <% if(category.equals("ALL")) { %> selected="selected" <% } %>>
				전체(ALL)
			</option>
			<option value="CPU" <% if(category.equals("CPU")) { %> selected="selected" <% } %>>
				중앙처리장치(CPU)
			</option>
			<option value="MAINBOARD" <% if(category.equals("MAINBOARD")) { %> selected="selected" <% } %>>
				메인보드(MAINBOARD)
			</option>
			<option value="MEMORY" <% if(category.equals("MEMORY")) { %> selected="selected" <% } %>>
				메모리(MEMORY)
			</option>	
		</select>	
	</form>
</div>
<%-- --%>
<script type="text/javascript">
$("#addBtn").click(function() {
	location.href="<%=request.getContextPath()%>/index.jsp?workgroup=admin&work=product_add";
});
$("#category").change(function() {
	$("#productForm").submit();
});
</script>

5. product_add.jsp
→사용자로부터 제품정보를 입력받기 위한 JSP 문서

📃product_add.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 사용자로부터 제품정보를 입력받기 위한 JSP 문서 --%>
<%-- → 관리자만 요청 가능한 JSP 문서 --%>
<%-- → [제품등록]을 클릭한 경우 제품정보 삽입페이지(product_add_action.jsp)로 이동 - 입력값 전달 --%>
<%@include file="/security/admin_check.jspf" %>
<style type="text/css">
#product {
	width: 800px;
	margin: 0 auto;
}
table {
	margin: 0 auto;
}
td {
	text-align: left;
}
</style>
<div id="product">
	<h2>제품등록</h2>
	<%-- 사용자로부터 파일을 입력받아 요청 페이지로 전달하기 위해서는 반드시 form 태그의 enctype 속성값을 [multipart/form-data]으로 설정 --%>
	<form action="<%=request.getContextPath() %>/index.jsp?workgroup=admin&work=product_add_action" 
		method="post" enctype="multipart/form-data" id="productForm">
		<table>
			<tr>
				<td>카테고리</td>
				<td>
					<select name="category">
						<option value="CPU">중앙처리장치(CPU)</option>
						<option value="MAINBOARD">메인보드(MAINBOARD)</option>
						<option value="MEMORY">메모리(MEMORY)</option>
					</select>
				</td>
			</tr>
			<tr>
				<td>제품명</td>
				<td>
					<input type="text" name="name" id="name">
				</td>
			</tr>
			<tr>
				<td>대표이미지</td>
				<td>
					<input type="file" name="imageMain" id="imageMain">
				</td>
			</tr>
			<tr>
				<td>상세이미지</td>
				<td>
					<input type="file" name="imageDetail" id="imageDetail">
				</td>
			</tr>
			<tr>
				<td>제품수량</td>
				<td>
					<input type="text" name="qty" id="qty">
				</td>
			</tr>
			<tr>
				<td>제품가격</td>
				<td>
					<input type="text" name="price" id="price">
				</td>
			</tr>
			<tr>
				<td colspan="2">
					<button type="submit">제품등록</button>
				</td>
			</tr>
		</table>	
	</form>
	<div id="message" style="color: red;"></div>
</div>
<%-- --%>
<script>
$("#productForm").submit(function() {
	if($("#name").val()=="") {
		$("#message").text("제품명을 입력해 주세요.");
		$("#name").focus();
		return false;
	}
	//
	if($("#imageMain").val()=="") {
		$("#message").text("대표이미지를 입력해 주세요.");
		$("#name").focus();
		return false;
	}
	//
	if($("#imageDetail").val()=="") {
		$("#message").text("상세이미지를 입력해 주세요.");
		$("#name").focus();
		return false;
	}
	//
	if($("#qty").val()=="") {
		$("#message").text("제품수량을 입력해 주세요.");
		$("#name").focus();
		return false;
	}
	//
	if($("#price").val()=="") {
		$("#message").text("제품가격을 입력해 주세요.");
		$("#name").focus();
		return false;
	}
});	
</script>

6. product_add_action.jsp
→제품정보를 전달받아 PRODUCT 테이블에 삽입하고 제품목록 출력페이지로 이동하기 위한 URL 주소를 클라이언트에게 전달하는 JSP 문서

📃product_add_action.jsp

<%@page import="xyz.itwill.dao.ProductDAO"%>
<%@page import="xyz.itwill.dto.ProductDTO"%>
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 제품정보를 전달받아 PRODUCT 테이블에 삽입하고 제품목록 출력페이지(product_manager.jsp)로 이동하기 위한 URL 주소를 클라이언트에게 전달하는 JSP 문서 --%>
<%-- → 제품 관련 이미지는 서버 디렉토리에 저장하고 PRODUCT 테이블에서는 업로드 처리된 이미지 파일명 저장 --%>
<%-- → 관리자만 요청 가능한 JSP 문서 --%>
<%-- 입력페이지에서 전달된 [multipart/form-data]를 처리하기 위해 cos 라이브러리(cos.jar)의 클래스 사용 --%>
<%-- → src/webapp/WEB-INF/lib 폴더에 cos.jar 파일 붙여넣기 --%>
<%@include file="/security/admin_check.jspf" %>
<%
	//비정상적인 요청에 대한 응답 처리
	if(request.getMethod().equals("GET")) {
		out.println("<script type='text/javascript'>");
		out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
		out.println("</script>");
		return;
	}
	//
	//전달받은 파일을 저장하기 위한 서버 디렉토리의 파일 시스템 경로를 반환받아 저장
	//→ 작업디렉토리(WorkSpace)가 아닌 웹디렉토리(WebApps)의 파일 시스템 경로 반환
	//→ webapp 폴더에 product_image 폴더 생성
	String saveDirectory=request.getServletContext().getRealPath("/product_image");
	//System.out.println("saveDirectory = "+saveDirectory);//파일경로 확인용
	//
	//MultipartRequest 객체 생성
	//→ [multipart/form-data]를 처리하기 위한 객체
	//→ 사용자로부터 입력받아 전달된 모든 파일을 서버 디렉토리에 자동으로 저장 - 업로드
	MultipartRequest multipartRequest=new MultipartRequest(request, saveDirectory, 30*1024*1024, "utf-8", new DefaultFileRenamePolicy());
	//
	//전달값과 업로드된 파일명을 반환받아 저장
	String category=multipartRequest.getParameter("category");
	String name=multipartRequest.getParameter("name");
	String imageMain=multipartRequest.getFilesystemName("imageMain");
	String imageDetail=multipartRequest.getFilesystemName("imageDetail");
	int qty=Integer.parseInt(multipartRequest.getParameter("qty"));
	int price=Integer.parseInt(multipartRequest.getParameter("price"));
	//
	//ProductDTO 객체를 생성하여 전달값과 업로드 파일명으로 필드값 변경
	ProductDTO product=new ProductDTO();
	product.setCategory(category);
	product.setName(name);
	product.setName(name);
	product.setImageMain(imageMain);
	product.setImageDetail(imageDetail);
	product.setQty(qty);
	product.setPrice(price);
	//
	//제품정보를 전달받아 PRODUCT 테이블에 삽입하는 DAO 클래스의 메소드 호출
	int rows=ProductDAO.getDAO().insertProduct(product);
	//
	if(rows<=0) {//PRODUCT 테이블에 제품정보가 삽입되지 않은 경우
		//서버 디렉토리에 업로드되어 저장된 제품 관려 이미지 파일 삭제
		//File 객체 : 파일 정보를 저장하기 위한 객체
		//File.delete() : File 객체에 저장된 파일을 삭제하기 위한 메소드
		new File(saveDirectory, imageMain).delete();
		new File(saveDirectory, imageDetail).delete();
	}
	//
	//페이지 이동
	out.println("<script type='text/javascript'>");
	out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=admin&work=product_manager';");
	out.println("</script>");
%>

7. product_detail.jsp
→제품번호를 전달받아 PRODUCT 테이블에 저장된 해당 제품번호의 제품정보를 검색하여 클라이언트에게 전달하는 JSP 문서

📃product_detail.jsp

<%@page import="java.text.DecimalFormat"%>
<%@page import="java.awt.Image"%>
<%@page import="xyz.itwill.dao.ProductDAO"%>
<%@page import="xyz.itwill.dto.ProductDTO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 제품번호를 전달받아 PRODUCT 테이블에 저장된 해당 제품번호의 제품정보를 검색하여 
클라이언트에게 전달하는 JSP 문서 --%>  
<%-- → 관리자만 요청 가능한 JSP 문서 --%>    
<%-- [제품정보변경]을 클릭한 경우 제품정보 입력페이지(product_modify.jsp)로 이동 - 제품번호 전달 --%>
<%@include file="/security/admin_check.jspf" %>
<%
	//비정상적인 요청에 대한 응답 처리
	if(request.getParameter("num")==null) {
		out.println("<script type='text/javascript'>");
		out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
		out.println("</script>");
		return;			
	}
	//전달값을 반환받아 저장
	int num=Integer.parseInt(request.getParameter("num"));
	//
	//제품번호를 전달받아 PRODUCT 테이블에 저장된 해당 제품번호의 제품정보를 검색하여 반환하는 DAO 클래스의 메소드 호출
	ProductDTO product=ProductDAO.getDAO().selectProduct(num);
	//
	//검색된 제품정보가 없는 경우 에러페이지로 이동하여 응답 처리 - 비정상적인 요청
	if(product==null) {
		out.println("<script type='text/javascript'>");
		out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
		out.println("</script>");
		return;
	}
%>
<style type="text/css">
table {
	margin: 0 auto;
	border: 1px solid black;
	border-collapse: collapse;	
}
td {
	border: 1px solid black;
}
.title {
	background-color: black;
	color: white;
	text-align: center;
	width: 100px;
}
.value {
	padding: 5px;
	text-align: left;
	width: 500px;
}
</style>
<%-- --%>
<h2>제품상세정보</h2>
<table>
	<tr>
		<td class="title">제품번호</td>
		<td class="value"><%=product.getNum() %></td>
	</tr>
	<tr>
		<td class="title">카테고리</td>
		<td class="value"><%=product.getCategory() %></td>
	</tr>
	<tr>
		<td class="title">제품명</td>
		<td class="value"><%=product.getName() %></td>
	</tr>
	<tr>
		<td class="title">대표이미지</td>
		<td class="value">
			<img src="<%=request.getContextPath()%>/product_image/<%=product.getImageMain()%>" width="200">
		</td>
	</tr>
	<tr>
		<td class="title">상세이미지</td>
		<td class="value">
			<img src="<%=request.getContextPath()%>/product_image/<%=product.getImageDetail()%>" width="400">
		</td>
	</tr>
	<tr>
		<td class="title">제품수량</td>
		<td class="value"><%=DecimalFormat.getInstance().format(product.getQty()) %></td>
	</tr>
	<tr>
		<td class="title">제품가격</td>
		<td class="value"><%=DecimalFormat.getInstance().format(product.getPrice()) %>원</td>
	</tr>
</table>
<p><button type="button" onclick="location.href='<%=request.getContextPath()%>/index.jsp?workgroup=admin&work=product_modify&num=<%=product.getNum()%>';">제품정보변경</button></p>

8. product_modify.jsp
→제품번호를 전달받아 PRODUCT 테이블에 저장된 해당 제품번호의 제품정보를 검색하여 입력태그의 초기값으로 설정하고 사용자로부터 변경값을 입력받기 위한 JSP 문서

📃product_modify.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 제품번호를 전달받아 PRODUCT 테이블에 저장된 해당 제품번호의 제품정보를 검색하여 입력태그의 초기값으로 설정하고 사용자로부터 변경값을 입력받기 위한 JSP 문서 --%>
<%-- → 관리자만 요청 가능한 JSP 문서 --%>
<%-- → [제품변경]을 클릭한 경우 제품정보 변경페이지(product_modify_action.jsp)로 이동 - 입력값 전달 --%>
<%@include file="/security/admin_check.jspf" %>
<%
	//비정상적인 요청에 대한 응답 처리
	if(request.getParameter("num")==null) {
		out.println("<script type='text/javascript'>");
		out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
		out.println("</script>");
		return;			
	}
	//전달값을 반환받아 저장
	int num=Integer.parseInt(request.getParameter("num"));
	//
	//제품번호를 전달받아 PRODUCT 테이블에 저장된 해당 제품번호의 제품정보를 검색하여 반환하는 DAO 클래스의 메소드 호출
	ProductDTO product=ProductDAO.getDAO().selectProduct(num);
	//
	//검색된 제품정보가 없는 경우 에러페이지로 이동하여 응답 처리 - 비정상적인 요청
	if(product==null) {
		out.println("<script type='text/javascript'>");
		out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
		out.println("</script>");
		return;
	}
%>
<style type="text/css">
#product {
	width: 800px;
	margin: 0 auto;
}
table {
	margin: 0 auto;
}
td {
	text-align: left;
}
</style>
<div id="product">
	<h2>제품변경</h2>
	<%-- --%>
	<%-- 사용자로부터 파일을 입력받아 요청 페이지로 전달하기 위해서는 반드시 form 태그의
	enctype 속성값을 [multipart/form-data]으로 설정 --%>
	<form action="<%=request.getContextPath() %>/index.jsp?workgroup=admin&work=product_modify_action" 
		method="post" enctype="multipart/form-data" id="productForm">
		<%-- 변경할 제품정보를 구분하기 위한 식별자로 제품번호 전달 --%>
		<input type="hidden" name="num" value="<%=product.getNum()%>">
		<%-- 제품 관련 이미지를 변경하지 않을 경우 기존 제품 관련 이미지를 사용하기 위해 전달하거나
		제품 관련 이미지를 변경할 경우 기존 제품 관련 이미지를 서버 디렉토리에서 삭제하기 위해 전달 --%>
		<input type="hidden" name="currentImageMain" value="<%=product.getImageMain()%>">
		<input type="hidden" name="currentImageDetail" value="<%=product.getImageDetail()%>">
		<table>
			<tr>
				<td>카테고리</td>
				<td>
					<select name="category">
						<option value="CPU" <% if(product.getCategory().equals("CPU")) { %> selected="selected" <% } %>>중앙처리장치(CPU)</option>
						<option value="MAINBOARD" <% if(product.getCategory().equals("MAINBOARD")) { %> selected="selected" <% } %>>메인보드(MAINBOARD)</option>
						<option value="MEMORY" <% if(product.getCategory().equals("MEMORY")) { %> selected="selected" <% } %>>메모리(MEMORY)</option>
					</select>
				</td>
			</tr>
			<tr>
				<td>제품명</td>
				<td>
					<input type="text" name="name" id="name" value="<%=product.getName()%>">
				</td>
			</tr>
			<tr>
				<td>대표이미지</td>
				<td>
					<img src="<%=request.getContextPath()%>/product_image/<%=product.getImageMain()%>" width="200">
					<br>
					<span style="color: red;">이미지를 변경하지 않을 경우 입력하지 마세요.</span>
					<br>
					<input type="file" name="imageMain" id="imageMain">
				</td>
			</tr>
			<tr>
				<td>상세이미지</td>
				<td>
				<img src="<%=request.getContextPath()%>/product_image/<%=product.getImageDetail()%>" width="400">
					<br>
					<span style="color: red;">이미지를 변경하지 않을 경우 입력하지 마세요.</span>
					<br>
					<input type="file" name="imageDetail" id="imageDetail">
				</td>
			</tr>
			<tr>
				<td>제품수량</td>
				<td>
					<input type="text" name="qty" id="qty" value="<%=product.getQty()%>">
				</td>
			</tr>
			<tr>
				<td>제품가격</td>
				<td>
					<input type="text" name="price" id="price" value="<%=product.getPrice()%>">
				</td>
			</tr>
			<tr>
				<td colspan="2">
					<button type="submit">제품변경</button>
				</td>
			</tr>
		</table>	
	</form>
	<div id="message" style="color: red;"></div>
</div>
<script>
$("#productForm").submit(function() {
	if($("#name").val()=="") {
		$("#message").text("제품명을 입력해 주세요.");
		$("#name").focus();
		return false;
	}
	if($("#qty").val()=="") {
		$("#message").text("제품수량을 입력해 주세요.");
		$("#name").focus();
		return false;
	}
	if($("#price").val()=="") {
		$("#message").text("제품가격을 입력해 주세요.");
		$("#name").focus();
		return false;
	}
});	
</script>

8. product_modify_action.jsp
→제품번호를 전달받아 PRODUCT 테이블에 저장된 해당 제품번호의 제품정보를 검색하여 입력태그의 초기값으로 설정하고 사용자로부터 변경값을 입력받기 위한 JSP 문서

📃product_modify_action.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 제품정보를 전달받아 PRODUCT 테이블에 저장된 해당 제품정보를 변경하고 제품정보 
출력페이지(product_detail.jsp)로 이동하기 위한 URL 주소를 클라이언트에게 전달하는 JSP 문서 - 제품번호 전달 --%>
<%-- → 제품 관련 이미지가 전달된 경우 기존 이미지를 삭제하고 새로운 이미지를 서버 디렉토리에 저장 --%>
<%-- → 관리자만 요청 가능한 JSP 문서 --%>
<%@include file="/security/admin_check.jspf" %>
<%
	//비정상적인 요청에 대한 응답 처리
	if(request.getMethod().equals("GET")) {
		out.println("<script type='text/javascript'>");
		out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=error&work=error_400';");
		out.println("</script>");
		return;			
	}
	//
	//전달받은 파일을 저장하기 위한 서버 디렉토리의 시스템 경로를 반환받아 저장
	String saveDirectory=request.getServletContext().getRealPath("/product_image");
	//
	//[multipart/form-data]를 처리하기 위한 MultipartRequest 객체 생성
	//→ 사용자로부터 입력받아 전달된 모든 파일을 서버 디렉토리에 자동으로 저장 - 업로드
	MultipartRequest multipartRequest=new MultipartRequest(request, saveDirectory, 30*1024*1024, "utf-8", new DefaultFileRenamePolicy());
	//
	//전달값과 업로드된 파일명을 반환받아 저장
	int num=Integer.parseInt(multipartRequest.getParameter("num"));
	String currentImageMain=multipartRequest.getParameter("currentImageMain");
	String currentImageDetail=multipartRequest.getParameter("currentImageDetail");
	String category=multipartRequest.getParameter("category");
	String name=multipartRequest.getParameter("name");
	String imageMain=multipartRequest.getFilesystemName("imageMain");
	String imageDetail=multipartRequest.getFilesystemName("imageDetail");
	int qty=Integer.parseInt(multipartRequest.getParameter("qty"));
	int price=Integer.parseInt(multipartRequest.getParameter("price"));
	//
	//ProductDTO객체를 생성하여 전달값과 업로드 파일명으로 필드값 변경
	ProductDTO product=new ProductDTO();
	product.setNum(num);
	product.setCategory(category);
	product.setName(name);
	if(imageMain==null) {//전달된 대표이미지 파일이 없는 경우 - 대표이미지 미변경
		product.setImageMain(currentImageMain);		
	} else {//전달된 대표이미지 파일이 있는 경우 - 대표이미지 변경
		product.setImageMain(imageMain);
		//서버 디렉토리에 저장된 기존 제품의 대표이미지 파일 삭제
		new File(saveDirectory, currentImageMain).delete();
	}
	if(imageDetail==null) {//전달된 상세이미지 파일이 없는 경우 - 상세이미지 미변경
		product.setImageDetail(currentImageDetail);		
	} else {//전달된 상세이미지 파일이 있는 경우 - 상세이미지 변경
		product.setImageDetail(imageDetail);
		//서버 디렉토리에 저장된 기존 제품의 상세이미지 파일 삭제
		new File(saveDirectory, currentImageDetail).delete();
	}
	product.setQty(qty);
	product.setPrice(price);
	//
	//제품정보를 전달받아 PRODUCT 테이블에 저장된 해당 제품정보를 변경하는 DAO 클래스의 메소드 호출
	ProductDAO.getDAO().updateProduct(product);
	//
	//페이지 이동
	out.println("<script type='text/javascript'>");
	out.println("location.href='"+request.getContextPath()+"/index.jsp?workgroup=admin&work=product_detail&num="+product.getNum()+"';");
	out.println("</script>");
%>

🌈Part 5 - 제품 목록 관련

1. product_list.jsp
→PRODUCT 테이블에 저장된 모든 제품정보를 검색하여 클라이언트에게 전달하는 JSP 문서

📃product_list.jsp

<%@page import="java.text.DecimalFormat"%>
<%@page import="xyz.itwill.dao.ProductDAO"%>
<%@page import="xyz.itwill.dto.ProductDTO"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- PRODUCT 테이블에 저장된 모든 제품정보를 검색하여 클라이언트에게 전달하는 JSP 문서 --%>
<%
	//PRODUCT 테이블에 저장된 모든 제품정보를 검색하여 반환하는 DAO 클래스의 메소드 호출
	List<ProductDTO> productList=ProductDAO.getDAO().selectProductList("ALL");
%>
<style type="text/css">
#productList {
	width: 1200px;
	margin: 0 auto;
}
.product {
	width: 350px;
	margin: 10px;
	padding: 10px 5px;
	border: 1px solid black;
	text-align: center;
	float: left;
}
</style>
<div id="productList">
	<% for(ProductDTO product:productList) { %>
		<% if(product.getQty()!=0) {//제품수량이 존재하는 경우 %>
			<%-- 제품정보 출력 --%>
			<div class="product">
				<div style="font-size: 14px;"><%=product.getName() %></div>
				<div>
					<a href="#">
						<img src="<%=request.getContextPath()%>/product_image/<%=product.getImageMain()%>" width="200">
					</a>
				</div>
				<div>
					<%=DecimalFormat.getCurrencyInstance().format(product.getPrice()) %>
				</div>
			</div>
		<% } %>
	<% } %>
	<div style="clear: both;"></div>	
</div>

0개의 댓글