1. 내용 : 펀딩 사이트들의 내용을 크롤링하여 모은 뒤 화면에 띄워주었다.
2. 과정 중 특이점 : 게시판을 만들 때 카테고리 별로 보여주는 것은 했어서 이번에는 정렬 기능을 넣어보았다. where 조건만 추가하면 되서 많이 어렵지 않았다. 페이지네이션도 이전 화면구현 때와 JSP 수업 때 했어서 동일하게 구현하였다.
3. 화면 및 코드 설명
각 사이트에서 진행되는 펀딩들을 모아서 보려면 먼저 텀블벅, 와디즈, 오마이펀딩 사이트를 크롤링해해야 한다. 파이썬을 이용해서 각 사이트에서 필요한 정보를 크롤링하고 그 결과를 오라클 DB에 저장하였다.
그리고 저장된 내용을 가지고 펀딩 리스트를 구현하였는데 화면은 아래와 같다.
1) 펀딩 화면
펀딩 이미지, 제목, 달성율과 그 퍼센트, 찜한 숫자, 카테고리, 남은 기간, 사이트 이름이 뜨게 있다.
아래에는 페이지네이션도 구현해두었다.
2) xml
<sql id="search">
<if test="@org.apache.commons.lang3.StringUtils@isNotBlank(searchCategory)">
AND fu_cate = #{searchCategory}
</if>
<if test="@org.apache.commons.lang3.StringUtils@isNotBlank(searchSite)">
AND fu_site = #{searchSite}
</if>
</sql>
<sql id="array">
<if test="@org.apache.commons.lang3.StringUtils@isBlank(arraryType)">
ORDER BY dbms_random.value
</if>
<if test="@org.apache.commons.lang3.StringUtils@isNotBlank(arraryType)">
ORDER BY ${arraryType}
</if>
</sql>
<select id="getFundingList" parameterType="com.study.funding.vo.FundingVO"
resultType="com.study.funding.vo.FundingVO">
SELECT * FROM (
SELECT a.*, ROWNUM as rnum FROM (
SELECT
fu_no , fu_site , fu_title
, fu_cate , fu_enter , fu_img
, fu_percent , fu_amount , fu_dday
, fu_url , fu_like
FROM
funding
WHERE 1=1
<include refid="search"></include>
<include refid="array"></include>
) a
) b
WHERE rnum BETWEEN #{firstRow} AND #{lastRow}
</select>
그리고 <include refid="search"></include> 과 <include refid="array"></include>로 조건문이 들어가게 만들었고 rnum을 사용해서 페이지를 구분하였다
@org.apache.commons.lang3.StringUtils를 사용해서 카테고리나 정렬 부분이 isNotBlank거나 isBlank일 때 특정 조건이 sql문에 들어가도록 만들었다.
그래서 위의 사진과 같이 사용자가 원하는 카테고리와 사이트로 분류해서 보거나 원하는 조건으로 정렬할 수 있게 하였다. 이걸 하면서 xml문에서 ${ }와 #{ }이 어떤 차이가 있는지를 정확하게 알게 되었다.
* xml문에서 #{ }은 ' '이 필요할 때 사용했다.
예를 들어 사용자가 wadiz를 선택했을 때 AND fu_site = #{searchSite}은 오라클 sql에서 AND fu_site = 'wadiz'로 적용된다.
${ }은 ' '이 필요 없을 때 사용했다.
사용자가 최신순을 정렬로 선택했을 때 ORDER BY ${arraryType}은 오라클 sql에서 ORDER BY fu_dday desc 로 적용된다.
3) jsp + css (jsp 전체 코드는 아래의 더보기 클릭)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<%@include file="/WEB-INF/inc/header.jsp" %>
<meta charset="UTF-8">
<title>펀딩 전체 보기</title>
<link rel="stylesheet" type="text/css" href="<%=request.getContextPath() %>/resources/css/funding/fundingList.css" />
</head>
<body>
<%@include file="/WEB-INF/inc/top.jsp" %>
<div class="container">
<form class="fucategory" name="search" action="fundingList.wow" method="post" class="form-horizontal">
<input type="hidden" name="curPage" value="${searchVO.curPage }">
<input type="hidden" name="rowSizePerPage" value="${searchVO.rowSizePerPage }">
<div class="form-group">
<div class="row">
<div class="col-1"> <b>분류</b></div>
<div class="col">
<select id="id_searchCategory" name="searchCategory" class="form-control input-sm">
<option value="">--선택하세요--</option>
<c:forEach items="${cateList }" var="cate" varStatus="st">
<option value="${cate}" ${searchVO.searchCategory eq cate ? "selected='selected'" : ""}>${cate}</option>
</c:forEach>
</select>
</div>
<div class="col-1"> <b>사이트</b></div>
<div class="col">
<select id="id_searchSite" name="searchSite" class="form-control input-sm">
<option value="">--선택하세요--</option>
<option value="tumblbug" ${searchVO.searchSite eq "tumblbug" ? "selected='selected'" : ""}>텀블벅</option>
<option value="wadiz" ${searchVO.searchSite eq "wadiz" ? "selected='selected'" : ""}>와디즈</option>
<option value="ohmycompany" ${searchVO.searchSite eq "ohmycompany" ? "selected='selected'" : ""}>오마이컴퍼니</option>
</select>
</div>
<div class="col-1"> <b>정렬</b></div>
<div class="col">
<select id="id_arrarytype" name="arraryType" class="form-control input-sm">
<option value="">--선택하세요--</option>
<option value="fu_dday desc" ${searchVO.arraryType eq "fu_dday desc" ? "selected='selected'" : ""}>최신순</option>
<option value="fu_amount desc" ${searchVO.arraryType eq "fu_amount desc" ? "selected='selected'" : ""}>달성율 높은 순</option>
<option value="fu_dday" ${searchVO.arraryType eq "fu_amount" ? "selected='selected'" : ""}>마감순</option>
</select>
</div>
<div class="col-2">
<button type="submit" class="btn btn-sm btn-primary btn-lg"> 선택</button>
</div>
</div>
</div>
</form>
</div>
<div class="container" id="list">
<c:forEach items="${fundingList }" var="funding" varStatus="st">
<div class="funding">
<a href="fundingView.wow?fuNo=${funding.fuNo }&memId=${USER_INFO.userId}"><img class="fundingimg" alt="" src="${funding.fuImg }"></a>
<a href="fundingView.wow?fuNo=${funding.fuNo }&memId=${USER_INFO.userId}"><b>${funding.fuTitle }</b></a>
<div class="amount">${funding.fuAmount } 달성(${funding.fuPercent } %)</div>
<div class="category">♥ ${funding.fuLike } <b>|</b> ${funding.fuCate } </div>
<div class="fuDday"><b>${funding.fuDday eq "0" ? "오늘 마감": funding.fuDday }${funding.fuDday eq "0" ? "" : "일 남음"}|</b> ${funding.fuSite } </div>
</div>
</c:forEach>
</div>
<!-- START : 페이지네이션 -->
<div class="container" id="paging">
<ul class="pagination">
<!-- 첫 페이지 -->
<li class="page-item"><a class="page-link" href="fundingList.wow?curPage=1" data-page="1">
<span aria-hidden="true">«</span></a></li>
<!-- 이전 페이지 -->
<c:if test="${searchVO.firstPage!=1 }">
<li class="page-item"><a class="page-link" href="fundingList.wow?curPage=${searchVO.firstPage-1 }"
data-page="${searchVO.firstPage-1 }"><span aria-hidden="true"><</span></a></li>
</c:if>
<!-- 페이지 넘버링 -->
<c:forEach begin="${searchVO.firstPage }" end="${searchVO.lastPage }" var="i">
<c:if test="${searchVO.curPage !=i }">
<li class="page-item"><a class="page-link" href="fundingList.wow?curPage=${i }" data-page="${i }">${i }</a></li>
</c:if>
<c:if test="${searchVO.curPage ==i }">
<li class="page-item active"><a class="page-link" href="#">${i }</a></li>
</c:if>
</c:forEach>
<!-- 다음 페이지 -->
<c:if test="${searchVO.lastPage!=searchVO.totalPageCount }">
<li class="page-item"><a class="page-link" href="fundingList.wow?curPage=${searchVO.lastPage+1 }" data-page="${searchVO.lastPage+1 }">
<span aria-hidden="true">></span></a></li>
</c:if>
<!-- 마지막 페이지 -->
<li class="page-item"><a class="page-link" href="fundingList.wow?curPage=${searchVO.totalPageCount }" data-page="${searchVO.totalPageCount }">
<span aria-hidden="true">»</span></a></li>
</ul>
</div>
<!-- END : 페이지네이션 -->
<script type="text/javascript">
$form=$("form[name='search']");
$curPage=$form.find("input[name='curPage']");
// 페이지 링크 클릭
$('ul.pagination li a[data-page]').click(function(e) {
e.preventDefault();
$curPage.val($(this).data('page'));
$form.submit();
}); // ul.pagination li a[data-page]
$form.find("button[type=submit]").click(function(e) {
e.preventDefault();
$curPage.val(1);
$form.submit();
});
$('#id_rowSizePerPage').change(function(e) {
$curPage.val(1);
$form.find("input[name='rowSizePerPage']").val($(this).val());
$form.submit();
}); // '#id_rowSizePerPage'.change
</script>
</body>
</html>
① 카테고리, 사이트 별 분류
<div class="col-1"> <b>분류</b></div>
<div class="col">
<select id="id_searchCategory" name="searchCategory" class="form-control input-sm">
<option value="">--선택하세요--</option>
<c:forEach items="${cateList }" var="cate" varStatus="st">
<option value="${cate}" ${searchVO.searchCategory eq cate ? "selected='selected'" : ""}>${cate}</option>
</c:forEach>
</select>
</div>
카테고리는 select를 이용해서 선택하여 분류하는데 Controller에서 List를 받아서 그걸 forEach를 사용하여 나타낸다.
<div class="container" id="list">
<c:forEach items="${fundingList }" var="funding" varStatus="st">
<div class="funding">
<a href="fundingView.wow?fuNo=${funding.fuNo }&memId=${USER_INFO.userId}"><img class="fundingimg" alt="" src="${funding.fuImg }"></a>
<a href="fundingView.wow?fuNo=${funding.fuNo }&memId=${USER_INFO.userId}"><b>${funding.fuTitle }</b></a>
<div class="amount">${funding.fuAmount } 달성(${funding.fuPercent } %)</div>
<div class="category">♥ ${funding.fuLike } <b>|</b> ${funding.fuCate } </div>
<div class="fuDday"><b>${funding.fuDday eq "0" ? "오늘 마감": funding.fuDday }${funding.fuDday eq "0" ? "" : "일 남음"}|</b> ${funding.fuSite } </div>
</div>
</c:forEach>
</div>
화면단에서는 DB의 정보를 받아서 forEach로 반복하여 표현하는데 페이지네이션을 이용해서 페이지를 구분해주었다. 각각의 펀딩들은 Grid를 이요해서 나눴는데 그에 대한 CSS 파일은 아래와 같다.
#list{
display: grid;
grid-template-columns: repeat(auto-fill, minmax(20%, auto));
row-gap: 40px;
/* row의 간격을 10px로 */
column-gap: 20px;
/* column의 간격을 20px로 */
}
.funding{
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 260px 3fr 1fr 1fr 1fr
}
Grid는 이번에 처음 사용해봤는데 표처럼 깔끔하게 정리할 수가 있어서 좋았다.
4) Controller
@RequestMapping(value = "funding/fundingList.wow")
public String fundingList(Model model, @ModelAttribute("searchVO") FundingSerchVO serchVO) {
List<FundingVO> fundingList = fuService.getFundingList(serchVO);
List<String> cateList = Arrays.asList("문구", "여행·레저","반려동물",
"예술·디자인","뷰티", "기부·후원","클래스·컨설팅","문화·출판","게임·취미","생활 용품",
"테크·가전","스포츠·모빌리티","패션·잡화","푸드","액세서리" , "향수", "실용·취미");
model.addAttribute("fundingList", fundingList);
model.addAttribute("cateList", cateList);
return "funding/fungdingList";
}
Controller에서는 cateList를 만들어서 모델에 담아서 보내주었다. 하드코딩 하지 않아도 되서 좋았음!
'SPRING > SPRING 프로젝트' 카테고리의 다른 글
SPRING 프로젝트 - 펀딩 사이트 (6) : 회원가입 (0) | 2022.09.06 |
---|---|
SPRING 프로젝트 - 펀딩 사이트 (5) : 찜하기와 공유하기 (0) | 2022.09.06 |
SPRING 프로젝트 - 펀딩 사이트 (3) : 로그인 화면 구현 (0) | 2022.08.29 |
SPRING 프로젝트 - 펀딩 사이트 (2) : DB (0) | 2022.08.24 |
SPRING 프로젝트 - 펀딩을 한 번에 볼 수 있는 사이트 (1) : 개요 (0) | 2022.08.23 |
댓글