일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 회원가입 기능
- Bcrypt
- 스프링 HikariCP
- spring 프로젝트
- 로그아웃 기능 구현
- 로그인 기능
- 스프링 프로젝트
- 스프링 파일 삭제
- 스프링 이미지
- BCrypt 적용
- 스프링 메일 전송
- oracle 설치방법
- 스프링 쇼핑몰
- 쇼핑몰 프로젝트
- ResponseEntity
- spring 쇼핑몰
- 정규표현식
- 스프링 쇼핑몰 프로젝트
- 스프링 포트폴리오
- 스프링 게시판 구현
- 인증번호 전송
- 삭제 구현
- 스프링 업로드
- 파일 업로드
- 이미지 출력
- arraylist
- 스프링 프로젝트 기본 설정
- 스프링 게시판
- 스프링 프로젝트 설정
- 쇼핑몰 포트폴리오
- Today
- Total
Kim VamPa
[Spring][쇼핑몰 프로젝트][20] 상품조회 기능 구현 - 1 본문
프로젝트 Github : https://github.com/sjinjin7/Blog_Project
프로젝트 포스팅 색인(index) : https://kimvampa.tistory.com/188
목표
상품 조회 페이지 구현
이번 포스팅에서는 상품 목록(goodsManage.jsp) 페이지에서 상품의 이름을 클릭하였을 때 이동하는 조회 페이지를 구현하고자 합니다. 조회 페이지에는 선택한 상품에 관한 등록된 정보가 출력되어야 합니다. 앞서 구현했던 작가 조회 페이지 구현과 동일합니다. 단, 조금 신경 써야 할 처리가 출판일과 카테고리 항목입니다. 이는 다음 포스팅에서 진행합니다.
정보를 불러오기 위한 Mapper 부터 작업을 하여 service, controller, jsp 순으로 진행하겠습니다.
순서
1. Mapper 메서드
2. Service 메서드
3. Controller
4. View 처리
1. Mapper 메서드
AdminMapper.java
조회 쿼리를 호출하는 메서드를 AdminMapper.java 인터페이스에 추가합니다.
/* 상품 조회 페이지 */
public BookVO goodsGetDetail(int bookId);
AdminMapper.xml
위에서 작성한 메서드가 실행할 태그 및 쿼리문을 작성합니다. 조회 페이지에 사용자가 보기 편하도록 작가ID가 아닌 작가 이름이 나오도록 서브쿼리를 삽입하였습니다.
<!-- 상품 조회 페이지 -->
<select id="goodsGetDetail" resultType="com.vam.model.BookVO">
select bookId, bookName, (select authorName from vam_author where authorId =vam_book.authorId) authorName,
authorId, publeYear, publisher, cateCode, bookPrice, bookStock, bookDiscount, bookIntro, bookContents, regDate, updateDate
from vam_book where bookId = #{bookId}
</select>
AdminMapperTests.java
작성한 Mapper 메서드가 정상적으로 동작하는지 확인을 하기 위해서 AdminMapperTest.java 클래스에 아래의 코드를 추가 및 Junit 테스트를 합니다.
/* 상품 조회 페이지 */
@Test
public void goodsGetDetailTest() {
int bookId = 150;
BookVO result = mapper.goodsGetDetail(bookId);
System.out.println("상품 조회 데이터 : " + result);
}
2. Service 메서드
Mapper와 Controller을 연결 시켜줄 Service 메서드를 작성하겠습니다. AdminService.java 인터페이스에 아래의 메서드 선언부를 추가합니다.
/* 상품 조회 페이지 */
public BookVO goodsGetDetail(int bookId);
AdminServiceImpl.java 클래스에 앞서 추가한 메서드를 오버라이딩 하여 구현합니다.
/* 상품 조회 페이지 */
@Override
public BookVO goodsGetDetail(int bookId) {
log.info("(service)bookGetDetail......." + bookId);
return adminMapper.goodsGetDetail(bookId);
}
3. Controller
AdminController.java 클래스에 '상품 조회 페이지' 이동을 위한 url 매핑 메서드를 아래와 같이 추가해줍니다.
사용자가 선택한 상품에 대한 정보를 가져오는 mapper 메서드를 실행시키기 위해 int 타입의 bookId 변수를 파라미터로 추가하였고, 상품 조회 페이지 이동 후 다시 목록 페이지로 이동할 때 필요로 한 데이터인 Criteria 클래스, 상품 조회 페이지에 데이터를 전 달해 주기 위해 Model 클래스를 파라미터로 추가하였습니다.
구현부에는 Model 클래스를 사용하여 전달받은 Criteria 정보와 상품 조회 정보를 페이지에 전달하는 코드를 추가하였습니다.
/* 상품 조회 페이지 */
@GetMapping("/goodsDetail")
public void goodsGetInfoGET(int bookId, Criteria cri, Model model) {
logger.info("goodsGetInfo()........." + bookId);
/* 목록 페이지 조건 정보 */
model.addAttribute("cri", cri);
/* 조회 페이지 정보 */
model.addAttribute("goodsInfo", adminService.goodsGetDetail(bookId));
}
4. View 처리
사용자가 '상품 목록(goodsManage.jsp) 페이지'에서 상품 이름을 클릭하였을때 '상품 조회(goodsDetail.jsp) 페이지'로 이동할 수 있도록 해주는 작업을 먼저 진행합니다.
goodsManage.jsp에서 상품 이름이 출력되는 코드를 아래의 태그와 같이 <a> 태그로 감싸줍니다. <a> 태그의 href속성은 선택되는 상품의 ID가 출력이 되도록 작성하였습니다.
<a class="move" href='<c:out value="${list.bookId}"/>'>
<c:out value="${list.bookName}"></c:out>
</a>
작성한 <a> 태그가 동작하도록 <script> 태그에 아래의 Javascript코드를 추가해줍니다.
/* 상품 조회 페이지 */
$(".move").on("click", function(e){
e.preventDefault();
moveForm.append("<input type='hidden' name='bookId' value='"+$(this).attr("href") + "'>");
moveForm.attr("action", "/admin/goodsDetail");
moveForm.submit();
});
"goodsDetail" jsp, css파일을 새로 생성해주고, jsp파일에 css파일을 연결해주는 <link> 태그를 추가해줍니다. 그리고 jquery를 사용하기 위해 <script> 코드와 jstl을 사용하기 위해 라이브러리 코드를 추가해주었습니다.
서버를 구동시켜서 '상품 목록'페이지에서 '상품 조회'페이지로 이동하는지 확인합니다.
확인을 위해 작성한 <h1> 태그를 지우고 <body> 태그 내부에 아래의 코드를 추가해줍니다.
코드
<%@include file="../includes/admin/header.jsp" %>
<div class="admin_content_wrap">
<div class="admin_content_subject"><span>상품 상세</span></div>
<div class="admin_content_main">
<div class="form_section">
<div class="form_section_title">
<label>책 제목</label>
</div>
<div class="form_section_content">
<input name="bookName" value="<c:out value="${goodsInfo.bookName}"/>" disabled>
</div>
</div>
<div class="form_section">
<div class="form_section_title">
<label>등록 날짜</label>
</div>
<div class="form_section_content">
<input value="<fmt:formatDate value='${goodsInfo.regDate}' pattern='yyyy-MM-dd'/>" disabled>
</div>
</div>
<div class="form_section">
<div class="form_section_title">
<label>최근 수정 날짜</label>
</div>
<div class="form_section_content">
<input value="<fmt:formatDate value='${goodsInfo.updateDate}' pattern='yyyy-MM-dd'/>" disabled>
</div>
</div>
<div class="form_section">
<div class="form_section_title">
<label>작가</label>
</div>
<div class="form_section_content">
<input id="authorName_input" readonly="readonly" value="${goodsInfo.authorName }" disabled>
</div>
</div>
<div class="form_section">
<div class="form_section_title">
<label>출판일</label>
</div>
<div class="form_section_content">
<input name="publeYear" autocomplete="off" readonly="readonly" value="<c:out value="${goodsInfo.publeYear}"/>" disabled>
</div>
</div>
<div class="form_section">
<div class="form_section_title">
<label>출판사</label>
</div>
<div class="form_section_content">
<input name="publisher" value="<c:out value="${goodsInfo.publisher}"/>" disabled>
</div>
</div>
<div class="form_section">
<div class="form_section_title">
<label>책 카테고리</label>
</div>
<div class="form_section_content">
<div class="cate_wrap">
<span>대분류</span>
<select class="cate1" disabled>
<option value="none">선택</option>
</select>
</div>
<div class="cate_wrap">
<span>중분류</span>
<select class="cate2" disabled>
<option value="none">선택</option>
</select>
</div>
<div class="cate_wrap">
<span>소분류</span>
<select class="cate3" name="cateCode" disabled>
<option value="none">선택</option>
</select>
</div>
</div>
</div>
<div class="form_section">
<div class="form_section_title">
<label>상품 가격</label>
</div>
<div class="form_section_content">
<input name="bookPrice" value="<c:out value="${goodsInfo.bookPrice}"/>" disabled>
</div>
</div>
<div class="form_section">
<div class="form_section_title">
<label>상품 재고</label>
</div>
<div class="form_section_content">
<input name="bookStock" value="<c:out value="${goodsInfo.bookStock}"/>" disabled>
</div>
</div>
<div class="form_section">
<div class="form_section_title">
<label>상품 할인율</label>
</div>
<div class="form_section_content">
<input id="discount_interface" maxlength="2" disabled>
</div>
</div>
<div class="form_section">
<div class="form_section_title">
<label>책 소개</label>
</div>
<div class="form_section_content bit">
<textarea name="bookIntro" id="bookIntro_textarea" disabled>${goodsInfo.bookIntro}</textarea>
</div>
</div>
<div class="form_section">
<div class="form_section_title">
<label>책 목차</label>
</div>
<div class="form_section_content bct">
<textarea name="bookContents" id="bookContents_textarea" disabled>${goodsInfo.bookContents}</textarea>
</div>
</div>
<div class="btn_section">
<button id="cancelBtn" class="btn">상품 목록</button>
<button id="enrollBtn" class="btn enroll_btn">수정 </button>
</div>
</div>
<form id="moveForm" action="/admin/goodsManage" method="get" >
<input type="hidden" name="pageNum" value="${pageMaker.cri.pageNum}">
<input type="hidden" name="amount" value="${pageMaker.cri.amount}">
<input type="hidden" name="keyword" value="${pageMaker.cri.keyword}">
</form>
</div>
<%@include file="../includes/admin/footer.jsp" %>
등록 페이지의 태그 코드들을 그대로 가져와서 일부를 수정 및 추가하였습니다.
- <form> 태그를 지웠습니다.
- 각 항목의 경고 문구 태그를 지웠습니다.
- 각 input 태그의 name 속성을 지웠습니다. (안 지워도 상관없습니다.)
- 작가 검색 버튼을 지웠습니다.
- '상품 ID', '상품 등록 날짜', '상품 수정 날짜'가 출력되도록 코드를 추가하였습니다.
- 각 <input>, <select> 태그에 사용자가 입력을 할 수 없도록 disabled 속성을 추가하였습니다.
- 각 <input> 태그 <textarea> 태그에 서버로부터 전달받은 상품 정보가 출력되도록 코드를 추가하였습니다.
페이지를 꾸며주기 위해서 'goodsDetail.css' 파일에 아래의 코드를 추가해줍니다.
@charset "UTF-8";
*{
margin: 0;
padding:0;
}
a{
text-decoration: none;
}
ul{
list-style: none;
}
/* 화면 전체 렙 */
.wrapper{
width: 100%;
}
/* content 랩 */
.wrap{
width : 1080px;
margin: auto;
}
/* 홈페이지 기능 네비 */
.top_gnb_area{
width: 100%;
height: 50px;
background-color: #f0f0f1;
position:relative;
}
.top_gnb_area .list{
position: absolute;
top: 0px;
right: 0;
}
.top_gnb_area .list li{
list-style: none;
float : left;
padding: 13px 15px 0 10px;
font-weight: 900;
cursor: pointer;
}
/* 관리제 페이지 상단 현페이지 정보 */
.admin_top_wrap{
height:110px;
line-height: 110px;
background-color: #5080bd;
margin-bottom: 15px;
}
.admin_top_wrap>span{
margin-left: 30px;
display:inline-block;
color: white;
font-size: 50px;
font-weight: bolder;
}
/* 관리자 wrap(네비+컨텐츠) */
.admin_wrap{
}
/* 관리자페이지 네비 영역 */
.admin_navi_wrap{
width: 20%;
height: 300px;
float:left;
height: 100%;
}
.admin_navi_wrap li{
display: block;
height: 80px;
line-height: 80px;
text-align: center;
}
.admin_navi_wrap li a{
display: block;
height: 100%;
width: 95%;
margin: 0 auto;
cursor: pointer;
font-size: 30px;
font-weight: bolder;
}
.admin_navi_wrap li a:link {color: black;}
.admin_navi_wrap li a:visited {color: black;}
.admin_navi_wrap li a:active {color: black;}
.admin_navi_wrap li a:hover {color: black;}
.admin_list_02{
background-color: #c8c8c8;
}
/* 관리자페이지 컨텐츠 영역 */
.admin_content_wrap{
width: 80%;
float:left;
min-height: 700px;
}
.admin_content_subject{ /* 관리자 컨텐츠 제목 영역 */
font-size: 40px;
font-weight: bolder;
padding-left: 15px;
background-color: #6AAFE6;
height: 80px;
line-height: 80px;
color: white;
}
/* 관리자 컨텐츠 메인 영역 */
.form_section{
width: 95%;
margin-left: 2%;
margin-top: 20px;
border: 1px solid #dbdde2;
background-color: #efefef;
}
.form_section_title{
padding: 20px 35px;
}
.form_section_title label{
display: block;
font-size: 20px;
font-weight: 800;
}
.form_section_content{
padding: 20px 35px;
border-top: 1px solid #dbdde2;
}
.form_section_content input{
width: 98%;
height: 25px;
font-size: 20px;
padding: 5px 1%;
}
.ui-datepicker-trigger { /* 캘린더 css 설정 */
margin-left: 25px;
width: 14%;
height: 38px;
font-weight: 600;
background-color: #dfe8f5;
font-size: 15px;
cursor:pointer;
}
.authorId_btn { /* 작가 선택 css 설정 */
margin-left: 20px;
width: 14%;
height: 38px;
font-weight: 600;
background-color: #dfe8f5;
font-size: 15px;
cursor:pointer;
}
.ck-content { /* ckeditor 높이 */
height: 170px;
}
/* 버튼 영역 */
.btn_section{
text-align: center;
margin: 80px 0;
}
.btn{
min-width: 180px;
padding: 4px 30px;
font-size: 25px;
font-weight: 600;
line-height: 40px;
}
.enroll_btn{
background-color: #dbdde2;
margin-left:15px;
}
#enrollBtn:hover {
background-color: #c9cbd0;
}
.form_section_content select { /* 카테고리 css 설정 */
width: 92%;
height: 35px;
font-size: 20px;
text-align-last: center;
margin-left: 5px;
}
.cate_wrap span {
font-weight: 600;
}
.cate_wrap:not(:first-child) {
margin-top: 20px;
}
/* footer navai 영역 */
.footer_nav{
width:100%;
height:50px;
}
.footer_nav_container{
width: 100%;
height: 100%;
background-color:#8EC0E4;
}
.footer_nav_container>ul{
font-weight : bold;
float:left;
list-style:none;
position:relative;
padding-top:10px;
line-height: 27px;
font-family: dotum;
margin-left: 10px;
}
.footer_nav_container>ul>li{
display:inline;
width: 45px;
height: 19px;
padding: 10px 9px 0 10px;
}
.footer_nav_container>ul>span{
margin: 0 4px;
}
/* footer 영역 */
.footer{
width:100%;
height:130px;
background-color:#D4DFE6;
padding-bottom : 50px;
}
.footer_container{
width: 100%;
height: 100%;
margin: auto;
}
.footer_left>img {
width: 150%;
height: 130px;
margin-left: -20px;
margin-top: -12px;
}
.footer_left{
float :left;
width: 170px;
margin-left: 20px;
margin-top : 30px;
}
.footer_right{
float :left;
width: 680px;
margin-left: 70px;
margin-top : 30px;
}
/* float 속성 해제 */
.clearfix{
clear: both;
}
추가 해준 후 정상적으로 출력이 되는지 '상품 조회 페이지'에 접속해봅니다.
결과물을 보시면 아직 출력이 안된 부분이 있거나 데이터는 출력이 되어있지만 가공을 해주어야 하는 부분이 있습니다. 이는 다음 포스팅에서 진행합니다.
REFERENCE
DATE
- 2020.04.20
'스프링 프레임워크 > 쇼핑몰 프로젝트' 카테고리의 다른 글
[Spring][쇼핑몰 프로젝트][20] 상품조회 기능 구현 - 3 (9) | 2021.04.22 |
---|---|
[Spring][쇼핑몰 프로젝트][20] 상품조회 기능 구현 - 2 (3) | 2021.04.21 |
[Spring][쇼핑몰 프로젝트][19] 상품목록 기능 구현 (8) | 2021.04.13 |
[Spring][쇼핑몰 프로젝트][18] 상품 등록 - 입력란 수정& 외래키 설정 (6) | 2021.04.05 |
[Spring][쇼핑몰 프로젝트][18] 상품 등록 - 유효성 검사 (6) | 2021.04.02 |