20221101_tue
package Kh.study.shop.item.controller;
@Controller
@RequestMapping("/item")
class ItemController {
@Resource(name = "itemService")
private ItemService itemService;
//상품목록페이지
//boolean isLoginFail : 로그인 실패시 true/ 그렇지않으면 false
@GetMapping("/list")
public String itemList(boolean isLoginFail, Model model,ItemVO itemVO
,@CookieValue(required = false) String imgName) { //쿠키데이터 받아올때 조건 사용해야하는 어노테이션(@CookieValue) : 쿠키데이터가 없을 수도 있으니 필수는 아니다. 넘어오면 받고 안넘어오면 받지마라.그래서 requied가 false이다.
//-----로그인 성공 및 실패 여부를 html에 데이터 전달하기-------//
// System.out.println("@@@@@@@@@@@@@@@@@@@" + isLoginFail);
model.addAttribute("isLoginFail",isLoginFail);
// 상품 목록 조회(이미지 첨부 )
model.addAttribute("itemList", itemService.selectItemList());
//쿠키데이터 던지기
model.addAttribute("cookie_imgName",imgName);
return "content/item/item_list";
}
//상품상세페이지
@GetMapping("/detailItem")
public String detailItem(Model model ,String itemCode
, HttpServletResponse response //스프링하기전에 jsp할때 두 개의 두 포스트 안에 있던 것들이다.
, @CookieValue(required = false, name = "imgName") String cookieImgName) { // 그냥 html에서 받아오는 cookieImgName이 아니라 쿠키데이터에서 가져오는 데이터인데 필수는 아니다!!
ItemVO item = itemService.selectDetailItem(itemCode);
model.addAttribute("item", item);
// 상세보기한 상품의 이름을 쿠키에 저장한다.
// JAVAX.SERVLET.HTTP.cookie 의 쿠키 선택하기
// 쿠키생성
Cookie cookie = new Cookie("name", "java");//쿠키를 굽는다.(실제표현)!!! 무조건 문자열만 들어간다! 숫자는 들어가지않는다
//매개변수 : 쿠키 데이터 유지 초(60이면 1분)
//cookie.setMaxAge(60 * 60 * 24); // 하루
//cookie.setMaxAge(0);// 웹브라우저가 종료되면 쿠키데이터가 소멸
cookie.setMaxAge(60);//1분
// 생성된 쿠키 데이터를 클라이언트에 전달.
response.addCookie(cookie);//위에서 저장을 시킨 데이터를 만든 것을 response 영역에 쿠키저장한것이다.
Cookie cookie2 = new Cookie("age","20");
response.addCookie(cookie2);
// 상세보기 한 상품명을 쿠키로 저장 : 실제우리가 쿠키의 이름(cookie_itemName)으로 데리고 올때는 변수명이 아니라 실제데이터(itemName)를 부르는 지칭을 가져와야한다.
// 아래 페이지 에러뜨는 거에 대한 해결방법이다.
String imgName = "";
for(ImgVO img : item.getImgList()) {
if (img.getIsMain().equals("Y")) {// 포문돌려서 빼낸 이미지리스트 중 대표이미지라면
imgName = img.getAttachedName();
}
}
//java.net. 선택한다.
//인코딩만 진행하면 공백이 + 문자로 바뀌어버린다. 예) "안 녕" -> "안+녕"
// replaceAll :첫번째 매개변수를 두번째 매개변수로 바꿔준다.
// \\+ : 역슬러시 \\ 두개를 앞에 사용해야 +를 문자로 인식한다.
// %20 :빈값(공백)을 암호화하거나 인코딩하려면 %20 로 표기해야한다.
// 트라이 캐취문 마지막 사용해서 예외처리해준다.
/* [ 정석 버전 : 하지만 많이 사용한다면 메소드를 만들어주는 것이 좋다. ]
* String encodeImgName = "";
* try { encodeImgName = URLEncoder.encode(imgName,
* "UTF-8").replaceAll("\\+","%20"); } catch (UnsupportedEncodingException e) {
* e.printStackTrace(); }
*/
// [ 메도스 버전 : 메소드를 아래 별도로 만들어 사용하기 ]
String encodeImgName = null;
// 쿠키는 최대 20개만 갖을 수 있도록 제한이 있기 때문에 한번에 여러이미지들을 쿠키에 담기위해 이렇게 문자열 쉼표하나로 나열하여 사용한다.
if(cookieImgName != null) {// 쿠키에 데이터가 있다면
encodeImgName = cookieImgName + "," + getEncodeStr(imgName);
}
else {//쿠키에 데이터가 없다면
encodeImgName = getEncodeStr(imgName);
}
Cookie cookie_imgName = new Cookie("imgName", encodeImgName);// 데이터는 똑같은 이름으로 했을 경우 가장 최근에 들어간 데이터만 불러온다.
response.addCookie(cookie_imgName);
// 여기까지 하면 다른 특별한 페이지(상세페이지...)로 이동시,
// 페이지 에러가 뜬다. 그래서 해결방법은?
return "content/item/detail_item";
}
//예외처리 메소드 만들기
public String getEncodeStr(String str) {
//java.net. 선택한다.
String result = "";
try {
result = URLEncoder.encode(str, "UTF-8").replaceAll("\\+","%20");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultra.net.nz/thymeleaf/layout"
layout:decorate="layout/base_layout">
<!-- 같이열리는 base_layout페이지에서 content란 영역은 이 부분이 열린다. -->
<div layout:fragment="content">
<!-- 노란줄이 끄여도 사용가능 -->
<style>
.banner{
background-color: gray;
position: absolute;
z-index: 10;
width: 8rem;
height: 16rem;
top: 10rem;
right: 1rem;
}
.no-stop{
padding: 0 10px 0px;
}
.no-stop li {
width: 50px;
height: 30px;
background-color: blue;
margin-bottom: 10px;
}
</style>
<div class="banner">
<th:block th:if="${cookie_imgName != null}">
<span>오늘 본 상품</span>
<div th:text="${cookie_imgName}"></div>
</th:block>
</div>
<ul class="no-stop">
<li></li>
<li></li>
<li></li>
</ul>
<!-- <div class="row">
</div> -->
<div class="row"><!-- 상품목록내용 -->
<div class="col-12">
<th:block th:if="${#lists.size(itemList) == 0}">
<div> 등록된 상품이 없습니다.</div>
</th:block>
</div>
<th:block th:unless="${#lists.size(itemList) == 0}">
<th:block th:each="itemInfo , status : ${itemList}">
<div class="col-3 mb-3 mt-3">
<div class="card" style="width: 18rem;">
<!-- 첨부이미지 데이터가져올때 주의할 점: 상품목록조회하여 하나씩뽑은 아이템정보에서의 imgList의 imgVO중 attachedName값이다. -->
<!-- 단, 리스트의 데이터를 꺼내기위해 배열로 접근하는데 0번째를 추출하면 메인이미지를 찾아가서 꺼내기때문이다. -->
<img th:onclick="|location.href='@{/item/detailItem(itemCode=${itemInfo.itemCode})}'|"
class="card-img-top" height="400px" th:src="|@{/images/}${itemInfo.imgList[0].attachedName}|">
<!-- <img th:onclick="location.href='@{/item/detailItem}';" class="card-img-top" height="300px" src="/images/퇴근길의 마음.jpg"> -->
<!-- 타임리프경로설정_ 데이터변수명 가져가는 방법_3가지 -->
<!-- <img th:src="@{'/images/' + ${itemInfo.imgList[0].attachedName}}">
<img th:src="@{/images/} + ${itemInfo.imgList[0].attachedName}">
<img th:src="|@{/images/}${itemInfo.imgList[0].attachedName}|"> -->
</div>
<div style="font-size: 25px;" class="card-body">
No.
<span th:text="${status.count}"></span>
<div th:text="${itemInfo.itemName}"></div>
<!-- <span style="color: gray; font-size: 21px;" th:text="${#numbers.formatInteger(itemInfo.itemPrice, 3, 'COMMA') + '원'}"></span> -->
<span style="color: gray; font-size: 21px;" th:text="${#numbers.formatCurrency(itemInfo.itemPrice)}"></span>
<span style="color: gray; font-size: 21px;"></span>
</div>
</div>
</th:block>
</th:block>
</div>
<!-- <div id="test" class="aaa"></div>
document.querySelector('#test').class; ->aaa 빼내기 -->
<!-- 디자인 영역 -->
<!-- 10/31 제이쿼리문법으로 스타일주기 -->
<script type="text/javascript">
// 애니메이션 연습용
$('.no-stop li').hover(function(){
$(this).stop().animate({width:'300px'},500);// 1000이 1초여서 500이면 0.5초동안 실행한다는 의미
},function(){
$(this).stop().animate({width:'50px'},500);
});
//오늘 본 상품 스크롤에 따른 위치 변화 애니메이션
const bannerTag = document.querySelector('.banner');
//선택한 태그의 디자인 속성 값을 가져 온다.
const bannerStyle = window.getComputedStyle(bannerTag);
let bannerTop = bannerStyle.getPropertyValue('top'); //160px
//숫자로 만들어 줘야 한다 (px제외)
bannerTop = parseInt(bannerTop.substr(0, bannerTop.length - 2));
//페이지에서 스크롤 변화가 일어나면 자동으로 실행되는 구문
$(window).scroll(function(){
//현재 스크롤바의 상단 좌표
let currentTop = $(window).scrollTop();
console.log(currentTop);
//오늘 본 상품 div의 상단위치 = 현재 스크롤 바 위치 (0(최초 실행 시)) + div의 상단위치 (160px) 숫자로 만들어 줘야 함!
//변경 되어야 하는 div의 상단 위치 좌표
let newPostion = currentTop + bannerTop + 'px';
$('.banner').stop().animate({top:newPostion}, 500);
});
</script>
</div>
</html>
이제는 인코딩이 되었기 때문에 어디를 들어가든 상품이미지명이 이렇게 뜬다
: 쿠키는 최대한 20개 사용가능하기 때문에 낭비하면 안된다.
: 그래서 쿠키하나에 여러개의 이미지를 쉼표하나로 연결하여 스프링부트 자바로 뿌려주면 된다.
크롤링 : 데이터를 긁어모은다. 대표적 예시) 구글링
스크랩핑 : 네이버쇼핑 리뷰,맛집리뷰 데이터를 긁어온다. 단 법적문제가 될 수 있어 유의해야한다.
실무에서 가장 중요하다.에러마다 하나의 객체형식으로 있는다.