본문 바로가기
ICIA 수업일지

2021.08.25 수업일지(Servlet, Spring, Mysql)

by 주성씨 2021. 8. 25.

- 이번에는 네이버 API를 이용해서 쇼핑 정보를 네이버 DB에서 불러오고 내 DB에 저장하기까지 CRUD 작업을 해보겠다.

https://developers.naver.com/docs/serviceapi/search/shopping/shopping.md#%EC%87%BC%ED%95%91

 

쇼핑 - Search API

쇼핑 NAVER Developers - 검색 API 쇼핑 검색 개발가이드 검색 > 쇼핑 네이버 쇼핑 검색 결과를 출력해주는 REST API입니다. 비로그인 오픈 API이므로 GET으로 호출할 때 HTTP Header에 애플리케이션 등록 시

developers.naver.com

 

- 네이버에서는 자바스크립트를 지원안하니 자바를 이용해서 하겠다.

- 새로운 프로젝트를 만들자.

1. name ex07

2. check apache tomcat 8.0

3. create main page

- main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script src="http://code.jquery.com/jquery-3.1.1.min.js"></script>
<script
	src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.1/handlebars.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>이주성의 지역관리 시스템</title>
<style>
@font-face {
	font-family: 'SpoqaHanSansNeo-Regular';
	src:
		url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2108@1.1/SpoqaHanSansNeo-Regular.woff')
		format('woff');
	font-weight: normal;
	font-style: normal;
}

body {
	font-family: 'SpoqaHanSansNeo-Regular';
	background: rgb(224, 224, 235);
}

#container {
	width: 960px;
	border: 1px solid rgb(99, 99, 156);
	margin: 0 auto;
	padding: 20px;
	background: white;
}

#header {
	padding: 20px;
	border: 1px solid rgb(99, 99, 156);
	background: rgb(99, 99, 156);
}

#center {
	padding: 20px;
	border: 1px solid black;
	margin-top: 10px;
	margin-bottom: 10px;
}

#footer {
	padding: 20px;
	border: 1px solid rgb(99, 99, 156);
	color: white;
	background: rgb(99, 99, 156);
}

#menu {
	overflow: hidden;
	border-bottom: 1px dotted black;
	background: rgb(99, 99, 156);
}

#menu h4 {
	float: left;
	width: 150px;
	margin-left: 20px;
	margin-right: 20px;
}

h1, h3 {
	text-align: center;
}

#content {
	border: 1px solid black;
	padding: 10px;
	margin-top: 10px;
}

a {
	text-decoration: none;
	color: white;
	padding: 10px;
}

a:hover {
	cursor: pointer;
	text-decoration: none;
	background: rgb(54, 57, 69);
	color: white;
	padding: 10px;
	border-radius: 10px;
}

a:VISITED {
	color: white;
}
</style>
</head>
<body>
	<div id="container">
		<div id="header">
			<h1>
				<a href="/">상품 관리시스템</a>
			</h1>
		</div>
		<div id="center">
			<div id="menu">
				<h4>
					<a href="/product/list">상품관리</a>
				</h4>
				<h4>
					<a href="/product/search">상품검색</a>
				</h4>
			</div>
			<div id="content"></div>
		</div>
		<div id="footer">
			<h3>Copyright 2021. SMall All rights reserved.</h3>
		</div>
	</div>
</body>
</html>

출력물

 

- create package model, controller

- create Mainservlet

- new mainservlet.java

package controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/")
public class MainServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		RequestDispatcher dis = request.getRequestDispatcher("/main.jsp");
		request.setAttribute("page", "/about.jsp");
		dis.forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

	}

}

 

- create new about.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<h1>상품관리 시스템 소개</h1>

 

- main.jsp

			<div id="content">
			<jsp:include page="${page}"></jsp:include>
			</div>

 

출력물

 

- 상품검색, 상품관리을 위한 서블릿을 만들겠다.

- create new ProductServlet.java

package controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(value = { "/product/list", "/product/list.json", "/product/search", "/product/update", "/product/read",
		"/product/insert", "/product/delete" })
public class ProductServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		switch (request.getServletPath()) {
		case "/product/search":
			RequestDispatcher dis = request.getRequestDispatcher("/main.jsp");
			request.setAttribute("page", "/product/search.jsp");
			dis.forward(request, response);
			break;
		case "/product/list":
			dis = request.getRequestDispatcher("/main.jsp");
			request.setAttribute("page", "/product/list.jsp");
			dis.forward(request, response);
			break;
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

	}

}

 

- create new search.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<h1>상품 검색</h1>

 

- create new list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<h1>상품 관리</h1>

 

출력물

 

- 네이버 쇼핑 오픈 API를 복사해서 가지고 오자.

- create model\ new NaverAPI.java

package model;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

public class NaverAPI {

	public static void search() {
		String clientId = "YOUR_CLIENT_ID"; // 애플리케이션 클라이언트 아이디값"
		String clientSecret = "YOUR_CLIENT_SECRET"; // 애플리케이션 클라이언트 시크릿값"

		String text = null;
		try {
			text = URLEncoder.encode("그린팩토리", "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("검색어 인코딩 실패", e);
		}

		String apiURL = "https://openapi.naver.com/v1/search/blog?query=" + text; // json
																					// 결과
		// String apiURL =
		// "https://openapi.naver.com/v1/search/blog.xml?query="+ text; // xml
		// 결과

		Map<String, String> requestHeaders = new HashMap<>();
		requestHeaders.put("X-Naver-Client-Id", clientId);
		requestHeaders.put("X-Naver-Client-Secret", clientSecret);
		String responseBody = get(apiURL, requestHeaders);

		System.out.println(responseBody);
	}

	private static String get(String apiUrl, Map<String, String> requestHeaders) {
		HttpURLConnection con = connect(apiUrl);
		try {
			con.setRequestMethod("GET");
			for (Map.Entry<String, String> header : requestHeaders.entrySet()) {
				con.setRequestProperty(header.getKey(), header.getValue());
			}

			int responseCode = con.getResponseCode();
			if (responseCode == HttpURLConnection.HTTP_OK) { // 정상 호출
				return readBody(con.getInputStream());
			} else { // 에러 발생
				return readBody(con.getErrorStream());
			}
		} catch (IOException e) {
			throw new RuntimeException("API 요청과 응답 실패", e);
		} finally {
			con.disconnect();
		}
	}

	private static HttpURLConnection connect(String apiUrl) {
		try {
			URL url = new URL(apiUrl);
			return (HttpURLConnection) url.openConnection();
		} catch (MalformedURLException e) {
			throw new RuntimeException("API URL이 잘못되었습니다. : " + apiUrl, e);
		} catch (IOException e) {
			throw new RuntimeException("연결이 실패했습니다. : " + apiUrl, e);
		}
	}

	private static String readBody(InputStream body) {
		InputStreamReader streamReader = new InputStreamReader(body);

		try (BufferedReader lineReader = new BufferedReader(streamReader)) {
			StringBuilder responseBody = new StringBuilder();

			String line;
			while ((line = lineReader.readLine()) != null) {
				responseBody.append(line);
			}

			return responseBody.toString();
		} catch (IOException e) {
			throw new RuntimeException("API 응답을 읽는데 실패했습니다.", e);
		}
	}
}

 

- 네이버 개발자 센터 오픈 API 사용 등록을 한다.

- 등록후 네이버에서 제공한 클라이언트 아이다, 시크릿값을 확인한다.

 

- productservlet.java

@WebServlet(value = { "/product/list", "/product/naver", "/product/search", "/product/update", "/product/read",
		"/product/insert", "/product/delete" })
public class ProductServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		switch (request.getServletPath()) {
		case "/product/naver":
			// static 이기 때문에 새로운 객체를 안만들어줘도 됨.
			NaverAPI.search();
			break;

 

웹에 해당 페이지로 들어가면

 

이클립스 콘솔에서 찍는걸 볼 수 있다. 그러나 한글깨짐이 있으니 인코딩해보자.

 

- naverapi.java - 반환값을 String으로 받고

	public static String search() { // renew
		// static 이기 때문에 productservlet에 따로 객체를 새롭게 안만들어줘도 된다.
		String clientId = ""; // 애플리케이션 클라이언트 아이디값"
		String clientSecret = ""; // 애플리케이션 클라이언트 시크릿값"

		String text = null;
		try {
			text = URLEncoder.encode("그린팩토리", "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("검색어 인코딩 실패", e);
		}

		String apiURL = "https://openapi.naver.com/v1/search/blog?query=" + text; // json
																					// 결과
		// String apiURL =
		// "https://openapi.naver.com/v1/search/blog.xml?query="+ text; // xml
		// 결과

		Map<String, String> requestHeaders = new HashMap<>();
		requestHeaders.put("X-Naver-Client-Id", clientId);
		requestHeaders.put("X-Naver-Client-Secret", clientSecret);
		String responseBody = get(apiURL, requestHeaders);

		System.out.println(responseBody);
		return responseBody; // renew
	}

 

- 한글 깨짐을 트라이 케치로 인코딩해보자.

	private static String readBody(InputStream body) {
		InputStreamReader streamReader = null; // renew
		try {
			streamReader = new InputStreamReader(body,"UTF-8");
		} catch (Exception e1) {
			e1.printStackTrace();
		}

 

- productservlet

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html);charset=UTF-8");
		PrintWriter out = response.getWriter();
		switch (request.getServletPath()) {
		case "/product/naver":
			// static 이기 때문에 새로운 객체를 안만들어줘도 됨.
			out.println(NaverAPI.search());
			break;

 

웹에 한글깨짐없이 출력된다.

 

- 블로그로 테스트를 했으니 쇼핑 API로 변경해보자.

https://developers.naver.com/docs/serviceapi/search/shopping/shopping.md#%EC%87%BC%ED%95%91

 

쇼핑 - Search API

쇼핑 NAVER Developers - 검색 API 쇼핑 검색 개발가이드 검색 > 쇼핑 네이버 쇼핑 검색 결과를 출력해주는 REST API입니다. 비로그인 오픈 API이므로 GET으로 호출할 때 HTTP Header에 애플리케이션 등록 시

developers.naver.com

 

- Naverapi.java

		String text = null;
		try {
			text = URLEncoder.encode("노트북", "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("검색어 인코딩 실패", e);
		}

		String apiURL = "https://openapi.naver.com/v1/search/shop.json?query=" + text; // json

 

노트북 키워드로 검색된것을 확인할 수 있다.

 

- search.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<style>
h1 {
	text-shadow: 2px 2px 2px gray;
}
</style>
<h1>상품 검색</h1>

<script>
	getList();
	function getList() {
		$.ajax({
			type : 'get',
			url : '/product/naver',
			dataType : 'json',
			success : function(data) {
				alert(data.total);
			}
		})
	}
</script>

 

확인

 

- template을 이용해보자.

- search.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<style>
h1 {
	text-shadow: 2px 2px 2px gray;
}

.item {
	overflow: hidden;
	border: 1px solid black;
	margin-bottom: 10px;
	font-family: none;
}

img {
	float: left;
	padding: 10px;
	border: 1px solid gray;
	margin: 10px;
}

.info {
	float: left;
	margin-left: 10px;
	padding: 10px;
}
</style>
<h1>상품 검색</h1>
<div id="condition">
	검색
</div>
<div id="products"></div>
<script id="temp" type="text/x-handlebars-template">
{{#each items}}
<div class="item">
	<img src="{{image}}" width=200/>
	<div class="info">
		<div class="id">{{productId}}</div>
		<div class="title">{{{title}}}</div>
		<div class="price">{{lprice}}</div>
		<div class="mall">{{mallName}}</div>
	</div>
</div>
{{/each}}
</script>
<script>
	getList();
	function getList() {
		$.ajax({
			type : 'get',
			url : '/product/naver',
			dataType : 'json',
			success : function(data) {
				var temp = Handlebars.compile($('#temp').html());
				$('#products').html(temp(data));
			}
		})
	}
</script>

 

출력물

 

- 이제 상품을 검색해보자.

<h1>상품 검색</h1>
<div id="condition">
	검색 : <input type="text" id="query" value="노트북"/>
</div>
<script>
	getList();
	
	$('#query').on('keypress',function(e){
		if(e.keyCode==13){
			getList();
		}
	})
	
	function getList() {
		var query = $('#query').val();
		$.ajax({
			type : 'get',
			url : '/product/naver',
			dataType : 'json',
			data:{'query':query},
			success : function(data) {
				var temp = Handlebars.compile($('#temp').html());
				$('#products').html(temp(data));
			}
		})
	}
</script>

 

- productservlet

		case "/product/naver":
			// static 이기 때문에 새로운 객체를 안만들어줘도 됨.
			String query = request.getParameter("query");
			out.println(NaverAPI.search(query));
			break;

 

- naverapi

	public static String search(String query) {
		// static 이기 때문에 productservlet에 따로 객체를 새롭게 안만들어줘도 된다.
		String clientId = ""; // 애플리케이션 클라이언트 아이디값"
		String clientSecret = ""; // 애플리케이션 클라이언트 시크릿값"

		String text = null;
		try {
			text = URLEncoder.encode(query, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("검색어 인코딩 실패", e);
		}

 

출력물

 

- 상품을 다섯개 씩 출력되게 하겠다.

- NaverAPI.java

한번 검색시 출력되는 갯수는 display로 지정한다.

 

		String apiURL = "https://openapi.naver.com/v1/search/shop.json?query=" + text; // json
		apiURL += "&display=5";

 

5개씩 출력됨을 확인할 수 있다.

 

- 더보기 버튼으로 목록을 더 출력해보자.

- search.jsp

<button id="more">더보기</button>
<script>
	// 전역변수
	var pageNum = 1;

	getList();
	
	// 더보기 클릭
	$('#more').on('click',function(){
		pageNum++;
		getList();
	})
	
	$('#query').on('keypress',function(e){
		if(e.keyCode==13){
			pageNum=1;
			$('#products').html('');
			getList();
		}
	})
	
	function getList() {
		var query = $('#query').val();
		$.ajax({
			type : 'get',
			url : '/product/naver',
			dataType : 'json',
			data:{'query':query,"pageNum":pageNum},
			success : function(data) {
				var temp = Handlebars.compile($('#temp').html());
				$('#products').append(temp(data));
			}
		})
	}
</script>

 

- preoductservlet.java

		case "/product/naver":
			// static 이기 때문에 새로운 객체를 안만들어줘도 됨.
			String query = request.getParameter("query");
			int page = Integer.parseInt(request.getParameter("pageNum"));
			out.println(NaverAPI.search(query, page));
			break;

 

- naverapi

	public static String search(String query, int pageNum) {
		// static 이기 때문에 productservlet에 따로 객체를 새롭게 안만들어줘도 된다.
		String clientId = "z3KOjXI9rjwIRFoYR_Hm"; // 애플리케이션 클라이언트 아이디값"
		String clientSecret = "IJNWE8ERBI"; // 애플리케이션 클라이언트 시크릿값"

		String text = null;
		try {
			text = URLEncoder.encode(query, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("검색어 인코딩 실패", e);
		}
		int start = (pageNum-1)*5+1;
		String apiURL = "https://openapi.naver.com/v1/search/shop.json?query=" + text; // json
		apiURL += "&display=5&start="+start;

 

더보기로 5개 더 출력됨을 확인할 수 있다.

 

- 검색한 데이터를 상품관리로 가지고 오자.

- back to mysql

-- 2021.08.25
create table product(
	code nvarchar(20) primary key,
	title nvarchar(200) not null,
	price int(50),
    mall nvarchar(200),
    image nvarchar(200),
    wdate datetime default now()
);
desc product;

확인

 

- back to eclipse

- 어제 사용한 라이브러리 복사해서 확인

- database.java 복사 확인

- create new ProductVO.java

package model;

import java.util.Date;

public class ProductVO {
	private String code;
	private String title;
	private int price;
	private String mall;
	private String image;
	private Date wdate;

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	public String getMall() {
		return mall;
	}

	public void setMall(String mall) {
		this.mall = mall;
	}

	public String getImage() {
		return image;
	}

	public void setImage(String image) {
		this.image = image;
	}

	public Date getWdate() {
		return wdate;
	}

	public void setWdate(Date wdate) {
		this.wdate = wdate;
	}

	@Override
	public String toString() {
		return "ProductVO [code=" + code + ", title=" + title + ", price=" + price + ", mall=" + mall + ", image="
				+ image + ", wdate=" + wdate + "]";
	}

}

 

- create new productdao.java

- 네이버 서버로 부터 가지고올 데이터의 상품등록을 위한 메서드를 생성한다.

package model;

import java.sql.PreparedStatement;

public class ProductDAO {
	// 1. 상품등록 메서드
	public void insert(ProductVO vo) {
		try {
			String sql = "insert into product(code,title,mall,price,image) values(?,?,?,?,?);";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ps.setString(1, vo.getCode());
			ps.setString(2, vo.getTitle());
			ps.setString(3, vo.getMall());
			ps.setInt(4, vo.getPrice());
			ps.setString(5, vo.getImage());
			ps.execute();
		} catch (Exception e) {
			System.out.println("insert : " + e.toString());
		}
	}
}

 

- productservlet.java

@WebServlet(value = { "/product/list", "/product/naver", "/product/search", "/product/update", "/product/read",
		"/product/insert", "/product/delete" })
public class ProductServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	ProductDAO dao=new ProductDAO(); // dao 선언

 

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		ProductVO vo = new ProductVO();
		vo.setCode(request.getParameter("code"));
		vo.setTitle(request.getParameter("title"));
		vo.setMall(request.getParameter("mall"));
		vo.setPrice(Integer.parseInt(request.getParameter("price")));
		// 이미지는 다운로드 받아서 하니 여기서는 일단
		switch (request.getServletPath()) {
		case "/product/insert":
			dao.insert(vo);
			break;
		}
	}

 

- search.jsp

<script id="temp" type="text/x-handlebars-template">
{{#each items}}
<div class="item">
	<img src="{{image}}" width=200/>
	<div class="info">
		<div class="id">{{productId}}</div>
		<div class="title">{{{title}}}</div>
		<div class="price">{{lprice}}</div>
		<div class="mall">{{mallName}}</div>
	</div>
	<h4>저장</h4>
</div>
{{/each}}
</script>
<button id="more">더보기</button>
<script>
	// 전역변수
	var pageNum = 1;

	getList();

	// 세이브 버튼
	$('#products').on('click','.item h4',function(){
		if(!confirm("상품을 등록 하시겠습니까?"))return;
		var code = $(this).parent().find(".id").html();
		var title = $(this).parent().find(".title").html();
		var price = $(this).parent().find(".price").html();
		var mall = $(this).parent().find(".mall").html();
		
		$.ajax({
			type:'post',
			url:'/product/insert',
			data:{"code":code,"title":title,"price":price,"mall":mall},
			success:function(){
				alert("저장 성공");
			}
		})
	})

 

출력물

 

db에 5개 저장 후 확인

 

- 중복되는 데이터를 확인하도록 하자.

- productdao.java

	// 2. 중복체크 메서드
	public int checkCode(String code) {
		int check = 0;
		try {
			String sql = "select * from product where code=?";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ps.setString(1, code);
			ResultSet rs = ps.executeQuery();
			if (rs.next()) {
				check = 1;
			}
		} catch (Exception e) {
			System.out.println("checkCode : " + e.toString());
		}

		return check;
	}

 

- productservlet

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		PrintWriter out = response.getWriter();
		ProductVO vo = new ProductVO();
		String code = request.getParameter("code");
		vo.setCode(code);
		vo.setTitle(request.getParameter("title"));
		vo.setMall(request.getParameter("mall"));
		vo.setPrice(Integer.parseInt(request.getParameter("price")));
		// 이미지는 다운로드 받아서 하니 여기서는 일단
		switch (request.getServletPath()) {
		case "/product/insert":
			int check = dao.checkCode(code);
			if (check == 0) {
				dao.insert(vo);
			}
			out.println(check);
			break;
		}
	}

 

- search.jsp

	// 세이브 버튼
	$('#products').on('click', '.item h4', function() {
		if (!confirm("상품을 등록 하시겠습니까?"))
			return;
		var code = $(this).parent().find(".id").html();
		var title = $(this).parent().find(".title").html();
		var price = $(this).parent().find(".price").html();
		var mall = $(this).parent().find(".mall").html();

		$.ajax({
			type : 'post',
			url : '/product/insert',
			data : {
				"code" : code,
				"title" : title,
				"price" : price,
				"mall" : mall
			},
			success : function(check) {
				if (check == 0) {
					alert("저장 성공");
				} else {
					alert("이미 등록된 상품입니다.")
				}
			}
		})
	})

 

출력물

 

- 이미지를 저장해서 등록해보자.

- search

	// 세이브 버튼
	$('#products').on('click', '.item h4', function() {
		if (!confirm("상품을 등록 하시겠습니까?"))
			return;
		var code = $(this).parent().find(".id").html();
		var title = $(this).parent().find(".title").html();
		var price = $(this).parent().find(".price").html();
		var mall = $(this).parent().find(".mall").html();
		var image = $(this).parent().find("img").attr("src");
		$.ajax({
			type : 'post',
			url : '/product/insert',
			data : {
				"code" : code,
				"title" : title,
				"price" : price,
				"mall" : mall,
				"image" : image
			},
			success : function(check) {
				if (check == 0) {
					alert("저장 성공");
				} else {
					alert("이미 등록된 상품입니다.")
				}
			}
		})
	})

 

- productservlet

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		PrintWriter out = response.getWriter();
		ProductVO vo = new ProductVO();
		String code = request.getParameter("code");
		vo.setCode(code);
		vo.setTitle(request.getParameter("title"));
		vo.setMall(request.getParameter("mall"));
		vo.setPrice(Integer.parseInt(request.getParameter("price")));

		switch (request.getServletPath()) {
		case "/product/insert":
			int check = dao.checkCode(code);
			if (check == 0) {
				// image download
				String image = request.getParameter("image");
				String file = System.currentTimeMillis() + ".jpg";
				InputStream inStr = null;
				OutputStream outStr = null;
				try {
					URL url = new URL(image);
					inStr = url.openStream();
					outStr = new FileOutputStream("c:/image/product/" + file);
					while (true) {
						int data = inStr.read();
						if (data == -1)
							break;
						outStr.write(data);
					}
				} catch (Exception e) {
					System.out.println("image download : " + e.toString());
				}
				vo.setImage(file);
				dao.insert(vo);
			}
			out.println(check);
			break;
		}
	}

 

저장되고 테이블에서 확인가능하다.

 

- 상품목록 출력을 위한 메서드를 만들자.

- productdao

	// 3. 상품목록 출력 메서드
	public JSONObject list() {
		JSONObject obj = new JSONObject();
		try {
			String sql = "select count(*) from product order by wdate desc;";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ResultSet rs = ps.executeQuery();
			if (rs.next()) {
				obj.put("total", rs.getInt("count(*)"));
			}
		} catch (Exception e) {
			System.out.println("list : " + e.toString());
		}
		return obj;
	}

 

- productservlet.java

	// 3. 상품목록 출력 메서드
	public JSONObject list() {
		JSONObject obj = new JSONObject();
		try {
			// total count
			String sql = "select count(*) from product;";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ResultSet rs = ps.executeQuery();
			if (rs.next()) {
				obj.put("total", rs.getInt("count(*)"));
			}
			
			// 목록 jsonarray에 넣기
			sql = "select * from product order by wdate desc limit 0, 5;";
			ps = Database.CON.prepareStatement(sql);
			rs = ps.executeQuery();
			JSONArray jArray = new JSONArray();
			while (rs.next()) {
				JSONObject obj1 = new JSONObject();
				obj1.put("code", rs.getString("code"));
				obj1.put("title", rs.getString("title"));
				obj1.put("price", rs.getInt("price"));
				obj1.put("mall", rs.getString("mall"));
				obj1.put("image", rs.getString("image"));
				jArray.add(obj1);
			}
			obj.put("array", jArray);
		} catch (Exception e) {
			System.out.println("list : " + e.toString());
		}
		return obj;
	}

 

웹에 출력됨을 확인할 수 있다.

 

- 이제 이미지를 가지고 오도록 하겠다.

- 우선 서버를 멈춘다.

- 소스의 해당 라인에 아래 코드를 넣는다.

<Context docBase="c:/image" path="/image" reloadable="true"/>

 

- list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<style>
h1 {
	text-shadow: 2px 2px 2px gray;
}

.item {
	overflow: hidden;
	border: 1px solid black;
	margin-bottom: 10px;
	font-family: none;
}

img {
	float: left;
	padding: 10px;
	border: 1px solid gray;
	margin: 10px;
}

.infoTitle {
	float: left;
	margin-left: 10px;
	padding: 10px;
	font-size: 20px;
}

.info {
	float: left;
	margin-left: 10px;
	padding: 10px;
	font-size: 20px;
	width: 350px;
	text-overflow: ellipsis;
	white-space: nowrap;
	overflow: hidden;
}

.info .title {
	font-weight: bold;
}

#condition {
	border-top: 1px solid black;
	padding: 10px;
	margin-top: 10px;
}
</style>
<h1>상품 관리</h1>
<div id="condition">
	검색 : <input type="text" id="query" value="" /> Total : <span
		id="total"></span>건
</div>
<div id="products"></div>
<script id="temp" type="text/x-handlebars-template">
{{#each array}}
<div class="item">
	<img src="/image/product/{{image}}" width=200/>
	<div class="infoTitle">
		<div>- 상품 코드 :</div>
		<div>- 상품 이름 :</div>
		<div>- 상품 가격 :</div>
		<div>- 상품 관리 :</div>
	</div>
	<div class="info">
		<div class="code">{{code}}</div>
		<div class="title">{{{title}}}</div>
		<div class="price">{{price}}</div>
		<div class="mall">{{mall}}</div>
	</div>
</div>
{{/each}}
</script>
<button id="more">더보기</button>
<script>
	getList();
	function getList() {
		$.ajax({
			type : 'get',
			url : '/product/list.json',
			dataType : 'json',
			success : function(data) {
				var temp = Handlebars.compile($('#temp').html());
				$('#products').html(temp(data));
				$('#total').html(data.total);
			}
		})
	}
</script>

 

출력물

 

 

- 정보 하나씩 불러오기

- productdao.java

	// 4. 상품정보 확인
	public ProductVO read(String code) {
		ProductVO vo = new ProductVO();
		try {
			String sql = "select * from product where code=?";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ps.setString(1, code);
			ResultSet rs = ps.executeQuery();
			if (rs.next()) {
				vo.setCode(rs.getString("code"));
				vo.setTitle(rs.getString("title"));
				vo.setPrice(rs.getInt("price"));
				vo.setMall(rs.getString("mall"));
				vo.setImage(rs.getString("image"));
			}
		} catch (Exception e) {
			System.out.println("read : " + e.toString());
		}
		return vo;
	}

 

- productservlet

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		switch (request.getServletPath()) {
		case "/product/read":
			request.setAttribute("page", "/product/read.jsp");
			request.setAttribute("vo", dao.read(request.getParameter("code")));
			RequestDispatcher dis = request.getRequestDispatcher("/main.jsp");
			dis.forward(request, response);
			break;

 

 

- create new read.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<style>
form{
	width: 100%;
}
input[type=text] {
	width: 50%;
	height: 25px;
	margin-bottom: 10px;
	float: left;
}
form[name=frm]{
	overflow: hidden;
}
img{
	float: left;
}
</style>
<h1>상품 정보</h1>
<form name="frm">
	<img src="/image/product/${vo.image}" width=400 />
	<input type="text" value="${vo.code}" readonly /> 
	<input type="text" value="${vo.title}" />
	<input type="text" value="${vo.price}" />
	<input type="text" value="${vo.mall}" />
</form>

 

출력물

 

<form name="frm">
	<img src="/image/product/${vo.image}" width=400 />
	<input type="text" value="${vo.code}" readonly /> 
	<input type="text" value="${vo.title}" />
	<input type="text" value="${vo.price}" />
	<input type="text" value="${vo.mall}" />
	<hr />
	<input type="submit" value="정보수정"/>
	<input type="reset" value="수정취소"/>
</form>
<script>
	$(frm).on('submit',function(e){
		e.preventDefault();
		if(!confirm($(vo.code)+"을(를) 수정하시겠습니까?"))return;
	});
</script>

 

- ProductDAO.java

	// 5. 상품 수정 메서드
	public void update(ProductVO vo){
		try {
			String sql = "update product set title=?, price=?, mall=? where code=?";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ps.setString(1, vo.getTitle());
			ps.setInt(2, vo.getPrice());
			ps.setString(3, vo.getMall());
			ps.setString(4, vo.getCode());
			ps.execute();
		} catch (Exception e) {
			System.out.println("update : " + e.toString());
		}
	}

 

- productservlet

		switch (request.getServletPath()) {
		case "/product/update":
			dao.update(vo);
			response.sendRedirect("/product/list");
			break;

 

- read.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<style>
form{
	width: 100%;
}
input[type=text] {
	width: 50%;
	height: 25px;
	margin-bottom: 10px;
	float: left;
}
form[name=frm]{
	overflow: hidden;
}
img{
	float: left;
}
</style>
<h1>상품 정보</h1>
<form name="frm">
	<img src="/image/product/${vo.image}" width=400/>
	<input type="text" value="${vo.code}" readonly name="code"/> 
	<input type="text" value="${vo.title}" name="title"/>
	<input type="text" value="${vo.price}" name="price"/>
	<input type="text" value="${vo.mall}" name="mall"/>
	<hr />
	<input type="submit" value="정보수정"/>
	<input type="reset" value="수정취소"/>
</form>
<script>
	$(frm).on('submit',function(e){
		e.preventDefault();
		if(!confirm("수정하시겠습니까?"))return;
		frm.action="/product/update";
		frm.method="post";
		frm.submit();
	});
</script>

 

출력물

 

- 삭제, 검색, 이전 이후 버튼 해보기

1. 검색하기 및 검색 후 토탈 갯수 변하게 하기

list.jsp

<h1>상품 관리</h1>
<div id="condition">
	검색 : <input type="text" id="search" value="" /> Total : <span
		id="total"></span>건
</div>
<div id="products"></div>
<script id="temp" type="text/x-handlebars-template">
{{#each array}}
<div class="item">
	<img src="/image/product/{{image}}" width=200/>
	<div class="infoTitle">
		<div>- 상품 코드 :</div>
		<div>- 상품 이름 :</div>
		<div>- 상품 가격 :</div>
		<div>- 상품 관리 :</div>
	</div>
	<div class="info">
		<div class="code">{{code}}</div>
		<div class="title">{{{title}}}</div>
		<div class="price">{{price}}</div>
		<div class="mall">{{mall}}</div>
	</div>
	<h4 onClick="location.href='/product/read?code={{code}}'">수정</h4>
	<h4>삭제</h4>
</div>
{{/each}}
</script>
<button id="more">더보기</button>
<script>
	var pNum = 1;
	
	getList();

	$('#search').on('keypress', function(e) {
		if (e.keyCode == 13) {
			pNum = 1;
			getList();
		}
	})

	function getList() {
		var search = $('#search').val();
		$.ajax({
			type : 'get',
			url : '/product/list.json',
			dataType : 'json',
			data : {
				"pNum" : pNum,
				"search" : search
			},
			success : function(data) {
				var temp = Handlebars.compile($('#temp').html());
				$('#products').html(temp(data));
				$('#total').html(data.total);
			}
		})
	}
</script>

 

productservlet.java

		case "/product/list.json":
			// 페이지 값을 지정해주는 삼항연산자.
			int pNum = request.getParameter("pNum") == null ? 1 : Integer.parseInt(request.getParameter("pNum"));
			// int page = Integer.parseInt(request.getParameter("page"));

			// 서치값을 받아오자. 널이면 "" 아니면 값을 받아온다.
			String search = request.getParameter("search") == null ? "" : request.getParameter("search");
			out.println(dao.list(pNum, search));
			break;

 

productdao.java

	// 3. 상품목록 출력 메서드
	public JSONObject list(int pNum, String search) {
		JSONObject obj = new JSONObject();
		try {
			// total count
			String sql = "select count(*) from product where title like ?;";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ps.setString(1, "%"+search+"%");
			ResultSet rs = ps.executeQuery();
			if (rs.next()) {
				obj.put("total", rs.getInt("count(*)"));
			}

			// 목록 jsonarray에 넣기
			sql = "select * from product where title like ? order by wdate desc limit ?, 5;";
			ps = Database.CON.prepareStatement(sql);
			ps.setString(1, "%" + search + "%");
			ps.setInt(2, (pNum - 1) * 5);
			rs = ps.executeQuery();
			JSONArray jArray = new JSONArray();
			while (rs.next()) {
				JSONObject obj1 = new JSONObject();
				obj1.put("code", rs.getString("code"));
				obj1.put("title", rs.getString("title"));
				obj1.put("price", rs.getInt("price"));
				obj1.put("mall", rs.getString("mall"));
				obj1.put("image", rs.getString("image"));
				jArray.add(obj1);
			}
			obj.put("array", jArray);
		} catch (Exception e) {
			System.out.println("list : " + e.toString());
		}
		return obj;
	}

 

출력물 gif

 

2. 삭제하기 메서드를 만들어보자.

- list.jsp

<div id="products"></div>
<script id="temp" type="text/x-handlebars-template">
{{#each array}}
<div class="item">
	<img src="/image/product/{{image}}" width=200/>
	<div class="infoTitle">
		<div>- 상품 코드 :</div>
		<div>- 상품 이름 :</div>
		<div>- 상품 가격 :</div>
		<div>- 상품 관리 :</div>
	</div>
	<div class="info">
		<div class="code">{{code}}</div>
		<div class="title">{{{title}}}</div>
		<div class="price">{{price}}</div>
		<div class="mall">{{mall}}</div>
	</div>
	<h4 onClick="location.href='/product/read?code={{code}}'">수정</h4>
	<h4><a href="/product/delete" code="{{code}}" image="{{image}}" style="padding:0px;">삭제</a></h4>
</div>
{{/each}}
</script>
<button id="more">더보기</button>
<script>
	var pNum = 1;
	
	getList();

	$('#products').on('click','.item h4 a',function(e){
		e.preventDefault();
		var code = $(this).attr("code");
		var image = $(this).attr("image");
		if(!confirm(code+" 을(를) 삭제하시겠습니까?")) return;
		$.ajax({
			type:'get',
			url:'/product/delete',
			data:{
				"code":code,
				"image":image
			},
			success:function(){
				alert("상품을 삭제하였습니다.");
				getList();
			}
		})
	})

 

- productservlet.java

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		switch (request.getServletPath()) {
		case "/product/delete":
			String code = request.getParameter("code");
			String image = request.getParameter("image");
			// 이미지 데이터 삭제
			dao.delete(code);
			File file = new File("c:/image/product/"+image);
			file.delete();
			break;

 

- productdao.java

	// 6. 상품 삭제 메서드
	public void delete(String code){
		try {
			String sql = "delete from product where code=?";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ps.setString(1, code);
			ps.execute();
		} catch (Exception e) {
			System.out.println("delete : "+e.toString());
		}
	}

 

이미지가 삭제되는 것도 있고 안되는것도 있다.

 

3. 페이지 이전 이후 버튼을 만들고 넘겨보자.

list.jsp

#btnCase{
	text-align: center;
}
<div id="btnCase">
<button id="prev">&lt;</button>
<span id="page"></span>
<button id="next">&gt;</button>
</div>
<script>
	var pNum = 1;
	
	getList();

	$('#prev').on('click',function(){
		pNum--;
		getList();
	})
	$('#next').on('click',function(){
		pNum++;
		getList();
	})
	function getList() {
		var search = $('#search').val();
		$.ajax({
			type : 'get',
			url : '/product/list.json',
			dataType : 'json',
			data : {
				"pNum" : pNum,
				"search" : search
			},
			success : function(data) {
				var temp = Handlebars.compile($('#temp').html());
				$('#products').html(temp(data));
				$('#total').html(data.total);
				$('#page').html(pNum+"/"+data.last);
				if(pNum==1){
					$('#prev').attr('disabled',true);
				}else{
					$('#prev').attr('disabled',false);
				}
				if(pNum==data.last){
					$('#next').attr('disabled',true);
				}else{
					$('#next').attr('disabled',false);
				}
				if(data.total==0){
					$('#page').html(data.total);
				}
			}
		})
	}
</script>

 

- productdao.java

	// 3. 상품목록 출력 메서드
	public JSONObject list(int pNum, String search) {
		JSONObject obj = new JSONObject();
		try {
			// total count
			String sql = "select count(*) from product where title like ?;";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ps.setString(1, "%"+search+"%");
			ResultSet rs = ps.executeQuery();
			if (rs.next()) {
				int total = rs.getInt("count(*)");
				int last = total%5 == 0? total/5 : total/5+1;
				obj.put("total", total);
				obj.put("last", last);
			}
			
			// 목록 jsonarray에 넣기
			sql = "select * from product where title like ? order by wdate desc limit ?, 5;";
			ps = Database.CON.prepareStatement(sql);
			ps.setString(1, "%" + search + "%");
			ps.setInt(2, (pNum - 1) * 5);
			rs = ps.executeQuery();
			JSONArray jArray = new JSONArray();
			while (rs.next()) {
				JSONObject obj1 = new JSONObject();
				obj1.put("code", rs.getString("code"));
				obj1.put("title", rs.getString("title"));
				obj1.put("price", rs.getInt("price"));
				obj1.put("mall", rs.getString("mall"));
				obj1.put("image", rs.getString("image"));
				jArray.add(obj1);
			}
			obj.put("array", jArray);
		} catch (Exception e) {
			System.out.println("list : " + e.toString());
		}
		return obj;
	}

 

이전 이후 버튼 과 삭제 검색을 수행해 보았다.

 

ex07.zip
1.10MB