프로젝트 구조
이전 포스팅에서 관리자 목록 페이지를 생성했습니다.
오늘은 상품 등록/목록 기능 구현을 해보겠습니다.
프로젝트 흐름은 Controller = > Service => DAO => View 단 순으로 진행합니다.
admin_menu.jsp
이전 포스팅에서 생성했던 관리자 메뉴 페이지에 폼 생성해서 Controller에 요청을 보냅니다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="path" value="${pageContext.request.contextPath }"/>
<div style="text-align: center;">
<a href="${path}/admin/list.do">상품 목록</a> | <!-- 기능 추가 -->
<c:if test="${sessionScope.admin_userid != null }">
<a href="${path}/admin/write.do">상품등록</a> |
<!-- 관리자 아이디 확인 시 표출 / 기능 추가 -->
</c:if>
<a href="${path}/pdf/list.do">PDF</a> |
<a href="${path }/chart/chart1.do">구글 차트(json)</a> |
<a href="${path }/chart/chart2.do">구글 차트(db)</a> |
<a href="${path }/jchart/chart1.do">JFreeChart(png)</a> |
<a href="${path }/jchart/chart2.do">JFreeChart(pdf)</a> |
<div style="text-align: right;">
<c:choose>
<c:when test="${sessionScope.admin_userid == null }">
<!-- 로그인하지 않은 상태 -->
<a href="${path}/member/login.do">일반 로그인</a> |
<a href="${path}/admin/login.do">관리자 로그인</a> |
</c:when>
<c:otherwise>
<!-- 로그인한 상태 -->
${sessionScope.admin_name }님이 로그인중입니다.
<a href="${path}/admin/logout.do">로그아웃</a> |
</c:otherwise>
</c:choose>
</div>
</div>
<hr>
Controller
상품 등록 기능은 Service 에 요청을 보내는 것보단 등록할 수 있는 폼으로 리턴을 해주고, 목록 페이지는 이전에 생성했던 Product Service에 listProduct()를 호출합니다.
상품 목록 기능은 ModelAndView 타입으로 요청을 보내는데 , ModelAndView는 데이터와 이동하고자 하는 View Page를 같이 저장하는 생성자 입니다.
package com.example.spring.controller.admin;
import javax.inject.Inject;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.example.spring.model.member.dto.MemberDTO;
import com.example.spring.service.admin.AdminService;
import com.example.spring.service.shop.ProductService;
@Controller
@RequestMapping("admin/*") //공통 url mapping
public class AdminController {
@Inject
AdminService adminService;
@Inject
ProductService productService;
@RequestMapping("login.do")//세부 url
public String login() {
return "admin/login";
}
@RequestMapping("login_check.do")
public ModelAndView login_check(MemberDTO dto, HttpSession session,
ModelAndView mav) {
String name=adminService.loginCheck(dto);//로그인 체크
if(name != null) {//로그인 성공
//관리자용 세션변수
session.setAttribute("admin_userid", dto.getUserid());
session.setAttribute("admin_name", name);
//일반 사용자용 세션변수
session.setAttribute("userid", dto.getUserid());
session.setAttribute("name", name);
mav.setViewName("admin/admin");
}else {
mav.setViewName("admin/login");
mav.addObject("message", "error");
}
return mav;
}
@RequestMapping("logout.do")
public String logout(HttpSession session) {
session.invalidate();//세션 초기화
//관리자 로그인 페이지로 이동
return "redirect:/admin/login.do";
}
// 상품 등록 폼으로 이동
@RequestMapping("write.do")
public String write() {
return "admin/admin_product_write";
}
// 상품 목록 페이지 Service 단에 요청
@RequestMapping("list.do")
public ModelAndView list(ModelAndView mav) {
mav.setViewName("/admin/admin_product_list");
mav.addObject("list", productService.listProduct());
return mav;
}
}
먼저 목록 페이지 요청 처리 합니다.
ProductService
Service단은 DAO와 연결해 줍니다.
import java.util.List;
import javax.inject.Inject;
import org.springframework.stereotype.Service;
import com.example.spring.model.shop.dao.ProductDAO;
import com.example.spring.model.shop.dto.ProductDTO;
@Service
public class ProductServiceImpl implements ProductService {
@Inject
ProductDAO productDao;
@Override
public List<ProductDTO> listProduct() {
return productDao.listProduct();
}
ProductDAO
상품 목록은 한 가지 데이터를 가져오는 게 아닌,
전체 데이터를 가져와야 하기 때문에 selectOne()이 아니라 selectLIst()로 mapper 파일에 요청을 보냅니다.
import java.util.List;
import javax.inject.Inject;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import com.example.spring.model.shop.dto.ProductDTO;
@Repository
public class ProductDAOImpl implements ProductDAO {
@Inject
SqlSession sqlSession;
@Override
public List<ProductDTO> listProduct() {
return sqlSession.selectList("product.product_list");
}
productMapper.xml
DAO에서 요청을 select문으로 요청을 보냈으니, mapper 에서도 동일한 SQL문으로 코드 작업을 하는데,
여기서 주의할 점은 select문은 resultType을 꼭 설정을 해줘야 합니다.
상품 목록의 타입은 DTO 타입으로 요청을 보냈기 때문에 DTO 경로를 타입으로 설정해 줍니다.
<!-- 다른 mapper와 중복되지 않도록 네임스페이스 기재 -->
<mapper namespace="product">
<select id="product_list" resultType="com.example.spring.model.shop.dto.ProductDTO">
select * from product
order by product_name
</select>
mapper 작업이 끝났다면 Controller 에서 View Page 설정한 admin_product_list 페이지를 생성합니다.
admin_product_list
상품 목록 페이지는 유저 폼과는 다르게 관리자 ID 값이 들어오면 편집 기능이 할 수 있게 만들어 줍니다.
<%@ 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>
<%@ include file="../include/header.jsp" %>
</head>
<body>
<%@ include file="../include/admin_menu.jsp" %>
<h2>상품목록</h2>
<table border="1" style="width: 100%;">
<tr>
<th>상품코드</th>
<th> </th>
<th>상품명</th>
<th>가격</th>
</tr>
<c:forEach var="row" items="${list}">
<tr>
<td>${row.product_id}</td>
<td><img src="${path}/images/${row.picture_url}"
width="100px" height="100px"></td>
<td><a href="${path}/shop/product/detail/${row.product_id}">${row.product_name}</a>
<!-- 관리자에게만 편집 버튼 표시 -->
<c:if test="${sessionScope.admin_userid != null }"> <br>
<a href="${path}/shop/product/edit/${row.product_id}">[편집]</a>
</c:if>
</td>
<td><fmt:formatNumber value="${row.price}" pattern="#,###" /></td>
</tr>
</c:forEach>
</table>
</body>
</html>
product_list.jsp (Form)
목록 페이지에 데이터가 정상적으로 출력되는 걸 확인했습니다.
다음으로 상품 등록 기능 구현을 하는데, Controller 에서 view 단 페이지를 리턴 시켰습니다.
그럼 상품 등록 페이지를 생성합니다.
admin_product_write
상품 등록 페이지에서는 간단한 안전성 검사 처리를 하고 Controller에 요청을 보냅니다.
<%@ 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>
<%@ include file="../include/header.jsp" %>
<script type="text/javascript">
function product_write() {
var product_name=$("#product_name").val();
var price=$("#price").val();
var description=$("#description").val();
if(product_name==""){//빈값이면
alert("상품이름을 입력하세요");
$("#product_name").focus();
return;
}
if(price==""){//빈값이면
alert("가격을 입력하세요");
$("#price").focus();
return;
}
if(description==""){//빈값이면
alert("상품설명을 입력하세요");
$("#description").focus();
return;
}
document.form1.action="${path}/shop/product/insert.do"; <!-- Controller에 보냄 -->
document.form1.submit();
}
</script>
</head>
<body>
<%@ include file="../include/admin_menu.jsp" %>
<h2>상품 등록</h2>
<form name="form1" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>상품명</td>
<td> <input name="product_name" id="product_name"> </td>
</tr>
<tr>
<td>가격</td>
<td> <input name="price" id="price"> </td>
</tr>
<tr>
<td>상품설명 </td>
<td>
<textarea rows="5" cols="60" name="description" id="description"></textarea>
</td>
</tr>
<tr>
<td>상품이미지 </td>
<td> <input type="file" name="file1" id="file1"> </td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="button" value="등록" onclick="product_write()">
<input type="button" value="목록" onclick="location.href='${path}/admin/list.do'">
</td>
</tr>
</table>
</form>
</body>
</html>
Controller
상품 등록 페이지에서 상품 이미지를 첨부하려면 File 객체를 사용해야 합니다.
첨부 파일이 유/무 처리 해주고 디렉터리 설정도 해줍니다.
@RequestMapping("insert.do")
public String insert(@ModelAttribute ProductDTO dto) {
String filename="-"; //not null로 했을때 "-"으로 처리 되게함.
//첨부 파일이 있으면
if(!dto.getFile1().isEmpty()) {
//첨부 파일의 이름
filename=dto.getFile1().getOriginalFilename();
try {
//개발디렉토리, 배포디렉토리
//디렉토리 구분자 : 윈도우즈 \, 유닉스(리눅스) /
// " "안에다 \를 쓰면 특수무자로 알아듣기 때문에 \를 하나 더 써야함.
String path="C:\\work\\.metadata\\.plugins\\org.eclipse.wst.server.core"
+ "\\tmp0\\wtpwebapps\\spring02\\WEB-INF\\views\\images";
//디렉토리가 존재하지 않으면 생성
new File(path).mkdir();
//임시 디렉토리에 저장된 첨부파일을 이동
dto.getFile1().transferTo(new File(path+filename));
} catch (Exception e) {
e.printStackTrace();
}
}
dto.setPicture_url(filename);
productService.insertProduct(dto);
// 목록으로 이동
return "redirect:/shop/product/list.do";
}
ProductService
@Override
public void insertProduct(ProductDTO dto) {
productDao.insertProduct(dto);
}
ProductDAO
@Override
public void insertProduct(ProductDTO dto) {
sqlSession.insert("product.insert", dto);
}
productMapper
상품을 등록할 때 상품 번호는 시퀀스로 설정해주고, 해당 데이터들은 함수로 연결합니다.
<!-- 상품 등록 -->
<insert id="insert">
insert into product values
(seq_product.nextval,#{product_name},#{price},#{description},#{picture_url})
</insert>
코드 작업은 끝났습니다.
데이터가 정상적으로 등록되는지 확인합니다.
출력
< 상품 등록 >
< 목록 페이지 >
마치며
오늘은 상품 목록/등록 기능을 구현했습니다.
다음 포스팅에서 뵙겠습니다.
'[ JAVA ] > JAVA Spring' 카테고리의 다른 글
[ Spring ] Interceptor (0) | 2023.04.17 |
---|---|
[ Spring ] 상품 수정/삭제 기능 구현 (0) | 2023.04.14 |
[ Spring ] 관리자 페이지 목록 구현 (0) | 2023.04.12 |
[ Spring ] 장바구니 기능 구현 (0) | 2023.04.11 |
[ Spring ] 상품 목록 기능 구현 (0) | 2023.04.10 |