D+87::쿠키(계속)_ 예외처리// (외부)파이썬(주피터)_빅데이터,크롤링

Am.Vinch·2022년 11월 1일
0

20221101_tue

controller

  • itemController
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;
	}
}
  • item_list.html

<!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개 사용가능하기 때문에 낭비하면 안된다.
: 그래서 쿠키하나에 여러개의 이미지를 쉼표하나로 연결하여 스프링부트 자바로 뿌려주면 된다.


외부강의

크롤링

크롤링 : 데이터를 긁어모은다. 대표적 예시) 구글링
스크랩핑 : 네이버쇼핑 리뷰,맛집리뷰 데이터를 긁어온다. 단 법적문제가 될 수 있어 유의해야한다.

web

web의 동작 순서 이해 중요하다!! 면접준비시 유용하다.

파이선빅데이터크롤링



예외처리

실무에서 가장 중요하다.에러마다 하나의 객체형식으로 있는다.

profile
Dev.Vinch

0개의 댓글