본문 바로가기
ICIA 수업일지

2021.08.19 수업일지(Spring, Servlet)

by 주성씨 2021. 8. 19.

- MVC(Model View Controller) Architecture

 MVC 패턴은 디자인 패턴 중 하나입니다. 디자인 패턴이란 프로그램이나 어떤 특정한 목적을 가지고 개발하는 것중에 발생했던 문제점들을 정리해서 상황에 따라 간편하게 적용해서 쓸 수 있는 것을 정리하여 만든 약속을 통해 쉽게 쓸 수 있는 형태로 만든 것을 말합니다. MVC는 Model, View, Controller의 약자 입니다. 하나의 어플리케이션, 프로젝트를 구성할 때 그 구성요소를 세가지의 역할로 구분한 패턴입니다.

 

- 새로운 도서관리 페이지를 만들어보자.

- 선생님이 주신 이미지 파일을 C:\에 image folder에 넣어놓도록 하자.

book.zip
1.21MB

- back to mysql

- books 라는 이름의 table을 만들고 데이터를 insert하도록 하자. 속성에는 image를 추가하였다.

create table books(
 code nchar(4) not null, 
 title nvarchar(50) not null, 
 writer nvarchar(20), 
 price int(8) not null,
 image nvarchar(100),
 primary key(code)
);

desc books;

insert into books(code, title, writer, price, image) values('1001', '뇌를 자극하는 java 프로그래밍', '김윤명', 27000,'img01.jpg');
insert into books(code, title, writer, price, image) values('1002', '좋은 사지을 만드는 노출', '정승익', 20000,'img02.jpg');
insert into books(code, title, writer, price, image) values('1003', '예제로 배우는 엑셀 2007', '김대식', 19000,'img03.jpg');
insert into books(code, title, writer, price, image) values('1004', '지금 당장 경제공부 시작하라', '최진기', 18500,'img04.jpg');
insert into books(code, title, writer, price, image) values('1005', 'Introduction to Algorithms', '토마스', 42000,'img05.jpg');
insert into books(code, title, writer, price, image) values('1006', '이것이 자바다.', '신용권', 32000,'img06.jpg');
insert into books(code, title, writer, price, image) values('1007', '안드로이드 프로그래밍 정복1', '김상형', 35000,'img07.jpg');
insert into books(code, title, writer, price, image) values('1008', '안드로이드 프로그래밍 정복2', '김상형', 32000,'img08.jpg');

select * from books;

 

- back to spring

- 새로운 프로젝트를 생성하자.

 

- java resources\src 에 model, controller package를 만들자.

 

- 서버에 ex03을 등록하자.

 

- main이라는 이름의 view를 만들어보도록 하자. webcontent\ 바로 아래.

 

- main.jsp page의 틀을 만들어보도록 하자.

<%@ 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>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>한빛미디어</title>
<link rel="stylesheet" href="/css/main.css"/>
</head>
<body>
	<div id="container">
		<div id="header">
			<h1>한빛미디어</h1>
		</div>
		<div id="center">
			<div id="menu"></div>
			<div id="content">
				<h4>도서관리</h4>
				<h4>게시판관리</h4>
			</div>
		</div>
		<div id="footer">
			<h3>Copyright 2021. 한빛미디어 All rights reserved.</h3>
		</div>
	</div>
</body>
</html>

 

- webcontent\css\ 에 main.css 를 넣어서 간단하게 스타일을 적용해보자.

@CHARSET "UTF-8";

@font-face {
	font-family: 'Cafe24SsurroundAir';
	src:
		url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2105_2@1.0/Cafe24SsurroundAir.woff')
		format('woff');
	font-weight: normal;
	font-style: normal;
}

body {
	font-family: 'Cafe24SsurroundAir';
}

#container {
	width: 960px;
	border: 1px solid black;
	margin: 0px auto;
	padding: 20px;
}

#header {
	border: 1px solid black;
	padding: 20px;
}

#center {
	border: 1px solid black;
	padding: 20px;
	margin: 10px 0px 10px 0px;
	overflow: hidden;
}

#menu {
	width: 150px;
	float: left;
	margin-right: 10px;
	text-align: center;
}

#content {
	width: 730px;
	float: left;
	border-left: 1px solid black;
	padding: 10px
}

#footer {
	border: 1px solid black;
	padding: 20px;
}

h1, h3 {
	text-align: center;
}

a:link {
	text-decoration: none;
	color:black;
}

a:visited {
	color:black;
}

h4 {
	display: inline-block;
	padding-left: 20px;
}

 

- 메인 서블릿(클래스)을 만들어보자. 이름은 MainServlet으로 하겠다.

 

- 변경전

package controller;

import java.io.IOException;
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 {
		
	}

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

}

 

- 변경후

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 {
		request.setAttribute("pageName", "/about.jsp");
		RequestDispatcher dis = request.getRequestDispatcher("/main.jsp");
		dis.forward(request, response);
	}

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

}

 

- content 부분에 회사 소개 부분을 넣어보자. 파일명은 about.jsp로 한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<h3>[회사 소개]</h3>
<h4>“책으로 여는 IT 세상”</h4>
<p>한빛미디어(주)는 ‘책으로 여는 IT 세.상’을 만들어 갑니다. IT 세상의 주역은 ‘우리’ 입니다.
	한빛미디어(주)는 IT 세상의 주역들을 위한 프로그래밍, 컴퓨터공학, IT 에세이, Make, 리얼타임(전자책), OA,
	그래픽, 나와 내 아이를 위한 실용 등 다양한 분야의 책으로 IT 세상을 만들어 가고 있습니다.</p>

 

- main에서 클릭시 각 페이지에 갈 수 있게 링크를 걸어보자.

<body>
	<div id="container">
		<div id="header">
			<h1><a href="/">한빛미디어</a></h1>
		</div>
		<div id="center">
			<div id="menu">
				<h4><a href="/book/list">도서관리</a></h4>
				<h4><a href="/bbs/list">게시판관리</a></h4>
			</div>
			<div id="content">
				<jsp:include page="${pageName }"></jsp:include>
			</div>
		</div>
		<div id="footer">
			<h3>Copyright 2021. 한빛미디어 All rights reserved.</h3>
		</div>
	</div>
</body>

 

- 도서관리를 담당하는 servlet을 만들어보자. 이름은 BookServlet으로 한다.

- 도서 목록을 출력하는 스위치 케이스 문을 만들어보자.

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;

// 1. 일단 패스를 정해 놓고 시작하도록 하겠다. CRUD 작업을 기본으로 하겠다.
@WebServlet(value={"/book/list","/book/insert","/book/read","/book/update","/book/delete"})
public class BookServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		switch(request.getServletPath()){
		// 2. 도서 목록 출력
		case "/book/list":
			request.setAttribute("pageName", "/book/list.jsp");
			break;
		}
		RequestDispatcher dis = request.getRequestDispatcher("/main.jsp");
		dis.forward(request, response);
	}

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

}

 

- webcontent\book\에 list.jsp를 만들어보자.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<h3>[도서관리]</h3>

 

- VO, DAO를 만들어보도록 하자.

- class로 "BookVO"라는 이름을 지정하겠다.

package model;

public class BookVO {
	// 1. 값을 변수로 지정하고 변수 속성은 꼭 확인하고 지정하자.
	private String code;
	private String title;
	private String writer;
	private int price;
	private String image;

	// 2. 값을 가지고 오고 전달할 수 있게 get, set을 한다.
	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 String getWriter() {
		return writer;
	}

	public void setWriter(String writer) {
		this.writer = writer;
	}

	public int getPrice() {
		return price;
	}

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

	public String getImage() {
		return image;
	}

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

	// 3. 값이 잘 들어갔는지 확인하기 위해서 toString을 만들어보도록 하자.
	@Override
	public String toString() {
		return "BookVO [code=" + code + ", title=" + title + ", writer=" + writer + ", price=" + price + ", image="
				+ image + "]";
	}
}

 

- class로 BookDAO(DB Access Object)라는 이름으로 만들어보자.

 

- 우선 DB를 연결한 파일을 model에 넣어보자. 이름은 Database.java로 지정하겠다. 이전 파일을 복사해서 넣어도 되지만 DB, user, password를 확인해야 한다.

 

package model;

import java.sql.Connection;
import java.sql.DriverManager;

public class Database {
	public static Connection CON;
	static {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			CON = DriverManager.getConnection("jdbc:mysql://localhost:3306/webdb", "web", "pass");
			System.out.println("접속성공");
		} catch (Exception e) {
			System.out.println("접속실패:" + e.toString());
		}
	}
}

 

- 그리고 mysql 커넥터를 웹 라이브러리에 넣도록 하자.

 

- 이제 DAO에 도서목록 출력을 위한 메서드를 만들어보자.

- BookDAO.java

package model;

import java.util.*;
import java.sql.*;

public class BookDAO {
	// 1. 도서목록 출력을 위한 메서드를 만들어보자.
	public ArrayList<BookVO> list(){
		ArrayList<BookVO> array = new ArrayList<BookVO>();
		//1_1 오류가 나는 경우를 방지하기 위해서 트라이케치로 데이터를 받겠다.
		try {
			String sql = "select * from books order by code desc limit 0,5;";
			// 1_2 DB는 객체가 아닌 Static 클래스니깐. 변수없이 선언 가능하다.
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			// 1_3 결과를 담는 rs를 만든다.
			ResultSet rs = ps.executeQuery();
			while(rs.next()){
				// 1_4 rs로 불러온 값들을 vo에 넣어두겠다.
				BookVO vo = new BookVO();
				vo.setCode(rs.getString("code"));
				vo.setTitle(rs.getString("title"));
				vo.setWriter(rs.getString("writer"));
				vo.setPrice(rs.getInt("price"));
				vo.setImage(rs.getString("image"));
                // vo에 담은 값들을 toString을 이용해 찍어보겠다.
				System.out.println(vo.toString());
				// 1_5 vo에 담은 값들을 하나씩 array에 넣어주겠다.
				array.add(vo);
			}
		} catch (Exception e) {
			System.out.println("list : "+e.toString());
			// TODO: handle exception
		}
		return array;
	}
}

 

- BookServlet.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;

import model.*;

// 1. 일단 패스를 정해 놓고 시작하도록 하겠다. CRUD 작업을 기본으로 하겠다.
@WebServlet(value={"/book/list","/book/insert","/book/read","/book/update","/book/delete"})
public class BookServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	BookDAO dao = new BookDAO();
	
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		switch(request.getServletPath()){
		// 2. 도서 목록 출력
		case "/book/list":
			// 3. dao에서 list()를 실행하여 array에 담는다. booklist를 호출할때
			request.setAttribute("array", dao.list());
			request.setAttribute("pageName", "/book/list.jsp");
			break;
		}
		RequestDispatcher dis = request.getRequestDispatcher("/main.jsp");
		dis.forward(request, response);
	}

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

}

 

- 이제 메인 페이지에서 도서관리를 클릭할 시 콘솔에서 찍히는지 확인해보자. 이 작업은 데이터가 DB에서 잘 불러오는지 확인하기 위한 작업이다.

 

- 이제 book list.jsp에서 불러온 array값들을 불러오겠다.

- 반복문을 이용하기 위해서 tag 라이브러리를 추가하고 불러온다.

 

- list.jsp에서 사용하기위해 테그라이브러리를 넣는다.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt"%>

 

- 이제 틀을 만들고 CSS해보도록 하자.

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt"%>
<style>
	.item{
	overflow: hidden;
	margin-bottom: 10px;
	border: 1px solid black;
	padding: 10px;
	border-radius:10px;
	box-shadow: 5px 5px 0px gray;
	}
	.item img{
	float: left;
	}
	.item .info{
	float: left;
	margin-left: 10px;
	}
</style>
<h3>[도서 관리]</h3>
<c:forEach items="${array}" var="vo">
	<div class="item">
		<img src="http://placehold.it/150/150" width=150/>
		<div class="info">
			<div>${vo.title}</div>
			<div>${vo.writer}</div>
			<div><f:formatNumber pattern="#,###" value="${vo.price}"/></div>
		</div>
	</div>
</c:forEach>

 

출력물

 

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

- 우선 서버를 멈춘다.

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

 

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

 

- list.jsp 에서 아래의 부분을 수정한다.

<c:forEach items="${array}" var="vo">
	<div class="item">
		<img src="/image/book/${vo.image}"/>
		<div class="info">
			<div>${vo.title}</div>
			<div>${vo.writer}</div>
			<div><f:formatNumber pattern="#,###" value="${vo.price}"/></div>
		</div>
	</div>
</c:forEach>

ㄴ 이미지 크기를 조정하려면 .item img {width}를 100px로 주자

출력물

 

- 도서 등록 해보도록 하자. insert 를 만들어 주도록 하겠다.

- list.jsp

</style>
<h3>[도서 관리]</h3>
<h4><a href="/book/insert">도서 등록</a></h4>

 

- bookservlet.java

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		switch(request.getServletPath()){
		// 2. 도서 목록 출력
		case "/book/list":
			// 2_1. dao에서 list()를 실행하여 array에 담는다. booklist를 호출할때
			request.setAttribute("array", dao.list());
			request.setAttribute("pageName", "/book/list.jsp");
			break;
			// 3. 도서 정보 출력
		case "/book/insert":
			
			request.setAttribute("pageName", "/book/insert.jsp");
			break;
		}
		RequestDispatcher dis = request.getRequestDispatcher("/main.jsp");
		dis.forward(request, response);
	}

 

- new insert.jsp

- 도서 등록을 위한 form을 만들어보자.

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<style>
	input[type="text"]{
	width: 100%;
	height: 25px;
	}
	#image{
	margin: 10px;
	}
	input[type="file"]{
	margin: 0px 0px 10px 10px;
	}
	</style>
<h3>[도서 등록]</h3>
<form name="frm">
	<input type="text" name="code" placeholder="도서 코드" />
	<hr />
	<input type="text" name="title" placeholder="도서 제목" />
	<hr />
	<input type="text" name="writer" placeholder="도서 저자" />
	<hr />
	<input type="text" name="price" placeholder="도서 가격" />
	<hr />
	<img id="image" src="http://placehold.it/200/200" width=200/>
	<input type="file" name="image" />
	<hr />
	<div>
		<input type="submit" value="도서 등록" /> 
		<input type="reset" value="등록 취소" />
	</div>
</form>

 

- 마지막 코드값을 구하고 거기에 1을 더해 새로운 도서를 등록할때 이용할 수 있도록 하자.

- BookDAO.java

	// 2. 도서등록을 위한 마지막 코드 출력
	public String maxCode(){
		// 2_1 code 변수 선언
		String code = "";
		try {
			// 2_4 값을 sql로 받아와 code에 넣는다.
			String sql = "select max(code) from books;";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ResultSet rs = ps.executeQuery();
			if(rs.next()){
				code=rs.getString("max(code)");
			}
		} catch (Exception e) {
			// 2_3 오류 콘솔 출력
			System.out.println("insert : "+e.toString());
		}
		
		// 2_2 code값 return
		return code;
	}

 

- BookServlet.jsp

		// 3. 도서 정보 출력
		case "/book/insert":
			int code = Integer.parseInt(dao.maxCode());
			request.setAttribute("code", code+1);
			request.setAttribute("pageName", "/book/insert.jsp");
			break;
		}

 

- insert.jsp

- value 값을 넣어주고 수정이 불가능하게 readonly로 설정한다.

<h3>[도서 등록]</h3>
<form name="frm">
	<input type="text" name="code" placeholder="도서 코드" value="${code}" readonly/>
	<hr />

 

- 이제 등록할 때의 스크립트문을 만들어주도록 하겠다.

- insert.jsp

- 이미지가 보이게하고, 이미지 파일 선택버튼을 보이지 않게 하겠다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<style>
input[type="text"] {
	width: 100%;
	height: 25px;
}

#image {
	margin: 10px;
}

input[type="file"] {
	margin: 0px 0px 10px 10px;
}
</style>
<h3>[도서 등록]</h3>
<form name="frm">
	<input type="text" name="code" placeholder="도서 코드" value="${code}"
		readonly />
	<hr />
	<input type="text" name="title" placeholder="도서 제목" />
	<hr />
	<input type="text" name="writer" placeholder="도서 저자" />
	<hr />
	<input type="text" name="price" placeholder="도서 가격" />
	<hr />
	<img id="image" src="http://placehold.it/200/200" width=200 /> 
	<input type="file" name="image" style="display:none" />
	<hr />
	<div>
		<input type="submit" value="도서 등록" /> <input type="reset"
			value="등록 취소" />
	</div>
</form>
<script>
	// 2. 이미지 클릭 할 경우
	$('#image').on('click',function(){
		$(frm.image).click();
	});
	
	// 1. 이미지 파일이 바뀔경우 보여주도록 한다.
	$(frm.image).on('change', function() {
		var reader = new FileReader();
		reader.onload = function(e) {
			$("#image").attr("src", e.target.result);
		}
		reader.readAsDataURL(this.files[0]);
	});
	
</script>

출력물

 

- 이제 submit할 경우의 유효성 체크를 넣어보자.

	// 3. submit될때 유효성 체크
	$(frm).on('submit',function(e){
		e.preventDefault();
		var title = $(frm.title).val();
		if(title==''){
			alert('도서 제목을 입력하세요.');
			$(frm.title).focus();
			return;
		};
		var writer = $(frm.writer).val();
		if(writer==''){
			alert('도서 저자를 입력하세요.');
			$(frm.writer).focus();
			return;
		};
		var price = $(frm.price).val();
		if(price==''|| price.replace(/[0-9]/g,'')){
			alert('도서 가격을 숫자로 입력하세요.');
			$(frm.price).focus();
			return;
		};
		var image = $(frm.image).val();
		if(image==''){
			alert('도서 표지를 등록하세요.');
			return;
		};
		
		if(!confirm('도서를 등록하시겠습니까?')) return;
	});

 

출력물

 

- 등록한 이미지 업로드를 위한 작업을 하자.

- insert.jsp

<form name="frm" enctype="multipart/form-data" method="post" action="/book/insert">
		if (!confirm('도서를 등록하시겠습니까?'))
			return;
		
		frm.submit();
	});

 

- post 이니 서블릿으로 가서 post작업을 하도록 한다.

- BookServlet.java

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println("/book/insert...");
		request.setCharacterEncoding("UTF-8");
		// 4. 파일 업로드 작업
		// "c:/image/book" ; 저장경로, 1000*1000*10; 파일 용량 limit
		// "UTF-8" ; format, "new DefaultFileRenamePolicy()" ; 이름이 겹칠경우 새로운 이름을 지정
		MultipartRequest multi = new MultipartRequest(request, "c:/image/book", 1000 * 1000 * 10,
				"UTF-8", new DefaultFileRenamePolicy());
		String strImage = multi.getFilesystemName("image");
		System.out.println("image : " + strImage);

	}

 

- 각각의 내용을 도서등록하기 위한 메서드를 DAO에 만들어보도록 하자.

- BookDAO.java

	// 3. 도서등록을 위한 메서드
	// return이 없으니 void로
	// "BookVO vo" ; 데이터 insert를 위한 매개변수
	public void insert(BookVO vo) {
		try {
			String sql = "insert into books(code, title, writer, price, image) values(?,?,?,?,?);";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ps.setString(1, vo.getCode());
			ps.setString(2, vo.getTitle());
			ps.setString(3, vo.getWriter());
			ps.setInt(4, vo.getPrice());
			ps.setString(5, vo.getImage());
			// 실행
			ps.execute();
		} catch (Exception e) {
			System.out.println("insert : " + e.toString());
		}
	}

 

- BookServlet.java

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		// 4. 파일 업로드 작업
		// "c:/image/book" ; 저장경로, "1000*1000*10"; 파일 용량 limit
		// "UTF-8" ; format, "new DefaultFileRenamePolicy()" ; 이름이 겹칠경우 새로운 이름을 지정
		MultipartRequest multi = new MultipartRequest(request, "c:/image/book", 1000 * 1000 * 10,
				"UTF-8", new DefaultFileRenamePolicy());
		String strImage = multi.getFilesystemName("image");
		BookVO vo = new BookVO();
		vo.setCode(multi.getParameter("code"));
		vo.setTitle(multi.getParameter("title"));
		vo.setWriter(multi.getParameter("writer"));
		vo.setPrice(Integer.parseInt(multi.getParameter("price")));
		vo.setImage(strImage);
		dao.insert(vo);
		response.sendRedirect("/book/list");
	}

 

지정 경로에 저장된것을 확인할 수 있다.

 

출력물 / 데이터가 제대로 들어갔는지 확인할 수 있다.

 

- 도서 목록 페이지를 만들어보자.

- list.jsp - 페이지를 넘기기위한 버튼을 만들어보자.

</c:forEach>
<div id="pagination">
<button id="prev">&lt;</button>
<span>1/3</span>
<button id="next">&gt;</button>
</div>

출력물

 

- 다음 이전 버튼을 눌러서 페이지를 넘겨보자

- list.jsp

<script>
	// 페이지 번호 변수 설정
	var page = 1;
	$("#next").on('click', function() {
		page++;
		location.href='/book/list?page='+page;
	});
</script>

 

- BookServlet.java - 목록을 출력할때 page값을 받아오는 작업을 하도록 하자.

		// 2. 도서 목록 출력
		case "/book/list":
			// 2_2. page값을 받아오는 작업 // new
			// 페이지 값이 없으면 null이면 1이고 있으면 getParameter의 값을 받아오면 된다.
			int page = request.getParameter("page")==null ? 1:
			Integer.parseInt(request.getParameter("page"));
			request.setAttribute("page", page);
			// 2_1. dao에서 list()를 실행하여 array에 담는다. booklist를 호출할때
			request.setAttribute("array", dao.list(page)); // new
			request.setAttribute("pageName", "/book/list.jsp");
			break;

 

- list.jsp

<div id="pagination">
	<button id="prev" <c:out value="${page==1?'disabled':''}"/>>&lt;</button>
	<span id="page"></span>
	<button id="next">&gt;</button>
</div>

<script>
	// 페이지 번호 변수 설정
	// 서블릿에서 받아와서 변수에 넣고
	// 그 값을 html에 삽입한다.
	var page = '${page}';
	$('#page').html(page);
	
	$("#next").on('click', function() {
		page++;
		location.href='/book/list?page='+page;
		$('#page').html(page);
	});
	$("#prev").on('click', function() {
		page--;
		location.href='/book/list?page='+page;
		$('#page').html(page);
	});
</script>

 

- BookDAO.java

	// 1. 도서목록 출력을 위한 메서드를 만들어보자.
	public ArrayList<BookVO> list(int page) { // new
		ArrayList<BookVO> array = new ArrayList<BookVO>();
		// 1_1 오류가 나는 경우를 방지하기 위해서 트라이케치로 데이터를 받겠다.
		try {
			String sql = "select * from books order by code desc limit ?,3;"; // renew
			// 1_2 DB는 객체가 아닌 Static 클래스니깐. 변수없이 선언 가능하다.
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ps.setInt(1, (page-1)*3); // new
			// 1_3 결과를 담는 rs를 만든다.
			ResultSet rs = ps.executeQuery();
			while (rs.next()) {
				// 1_4 rs로 불러온 값들을 vo에 넣어두겠다.
				BookVO vo = new BookVO();
				vo.setCode(rs.getString("code"));
				vo.setTitle(rs.getString("title"));
				vo.setWriter(rs.getString("writer"));
				vo.setPrice(rs.getInt("price"));
				vo.setImage(rs.getString("image"));
				// 1_5 vo에 담은 값들을 하나씩 array에 넣어주겠다.
				array.add(vo);
			}
		} catch (Exception e) {
			System.out.println("list : " + e.toString());
		}
		return array;
	}

 

- 전체 데이터 갯수를 출력하여 마지막 페이지를 구해보자.

- BookDAO.java

	// 4. 전체 데이터 갯수 출력
	public int total() {
		int total = 0;
		try {
			String sql = "select count(*) from books;";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ResultSet rs = ps.executeQuery();
			if(rs.next()){
				total = rs.getInt("count(*)");
			}
		} catch (Exception e) {
			System.out.println("total : " + e.toString());
		}
		return total;
	}

 

- BookServlet.java

		// 2. 도서 목록 출력
		case "/book/list":
			// 2_2. page값을 받아오는 작업
			// 페이지 값이 없으면 null이면 1이고 있으면 getParameter의 값을 받아오면 된다.
			int page = request.getParameter("page")==null ? 1:
			Integer.parseInt(request.getParameter("page"));
			int total = dao.total();
			int lastPage = total%3 == 0? total/3:(total/3)+1;
			request.setAttribute("lastPage", lastPage);
			request.setAttribute("total", total);
			request.setAttribute("page", page);
			// 2_1. dao에서 list()를 실행하여 array에 담는다. booklist를 호출할때
			request.setAttribute("array", dao.list(page));
			request.setAttribute("pageName", "/book/list.jsp");
			break;

 

- list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt"%>
<style>
.item {
	overflow: hidden;
	margin-bottom: 10px;
	border: 1px solid black;
	padding: 10px;
	border-radius: 10px;
	box-shadow: 5px 5px 0px gray;
}

.item:hover {
	cursor: pointer;
}

.item img {
	float: left;
	width: 100px;
}

.item .info {
	float: left;
	margin-left: 10px;
}

#pagination {
	text-align: center;
}
</style>
<h3>[도서 관리]</h3>
<h4>
	<a href="/book/insert">도서 등록</a>
</h4>
<div>전체도서갯수 : ${total}</div>
<c:forEach items="${array}" var="vo">
	<div class="item">
		<img src="/image/book/${vo.image}" />
		<div class="info">
			<div>${vo.title}</div>
			<div>${vo.writer}</div>
			<div>
				<f:formatNumber pattern="#,###" value="${vo.price}" />
			</div>
		</div>
	</div>
</c:forEach>
<div id="pagination">
	<button id="prev" <c:out value="${page==1?'disabled':''}"/>>&lt;</button>
	<span id="page"></span>
	<button id="next" <c:out value="${page==lastPage?'disabled':''}"/>>&gt;</button>
</div>

<script>
	// 페이지 번호 변수 설정
	// 서블릿에서 받아와서 변수에 넣고
	// 그 값을 html에 삽입한다.
	var page = '${page}';
	var total = '${total}';
	var lastPage = '${lastPage}';

	$('#page').html(page + '/' + lastPage);

	$("#next").on('click', function() {
		page++;
		location.href = '/book/list?page=' + page;
		$('#page').html(page + '/' + lastPage);
	});
	$("#prev").on('click', function() {
		page--;
		location.href = '/book/list?page=' + page;
		$('#page').html(page + '/' + lastPage);
	});
</script>

 

출력물

 

- READ 작업을 하도록 하자.

- list.jsp

<div style="margin-bottom: 10px">전체도서갯수 : ${total}</div>
<c:forEach items="${array}" var="vo">
	<div class="item">
		<img src="/image/book/${vo.image}" />
		<div class="info">
			<div class="code">${vo.code}</div> // new
			<div>${vo.title}</div>
			<div>${vo.writer}</div>
			<div>
				<f:formatNumber pattern="#,###" value="${vo.price}" />
			</div>
		</div>
	</div>
</c:forEach>
<div id="pagination">
	<button id="prev" <c:out value="${page==1?'disabled':''}"/>>&lt;</button>
	<span id="page"></span>
	<button id="next" <c:out value="${page==lastPage?'disabled':''}"/>>&gt;</button>
</div>

<script>
	// 페이지 번호 변수 설정
	// 서블릿에서 받아와서 변수에 넣고
	// 그 값을 html에 삽입한다.
	var page = '${page}';
	var total = '${total}';
	var lastPage = '${lastPage}';

	$('#page').html(page + '/' + lastPage);

	// 각행의 이미지를 클릭한 경우 // new
	$('.item').on('click','img',function(){
		var code = $(this).parent().find('.code').html();
		location.href='/book/read?code='+code;
	});

 

- BookServlet.java - 도서 정보 출력을 위한 케이스문을 만들어보도록 하자.

		// 3. 도서 정보 출력
		case "/book/read":
			request.setAttribute("pageName", "/book/read.jsp");
			break;

 

- insert.jsp 를 복사해서 read.jsp 를 만들자.

- BookDAO에서 도서정보를 출력하는 메서드를 만든다.

	// 5. 도서 정보를 출력하는 메서드
	public BookVO read(String code){
		BookVO vo = new BookVO();
		try {
			String sql = "select * from books 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.setWriter(rs.getString("writer"));
				vo.setPrice(rs.getInt("price"));
				vo.setImage(rs.getString("image"));
				System.out.println("...");
			}
		} catch (Exception e) {
			System.out.println("read : "+e.toString());
		}
		return vo;
	}

 

- BookServlet.java

		// 5. 도서 정보 출력
		case "/book/read":
			String scode = request.getParameter("code");
			request.setAttribute("vo", dao.read(scode));
			request.setAttribute("pageName", "/book/read.jsp");
			break;

 

- read.jsp

<h3>[도서 정보]</h3>
<form name="frm" enctype="multipart/form-data" method="post" action="/book/update">
	<input type="text" name="code" value="${vo.code}"
		readonly />
	<hr />
	<input type="text" name="title" value="${vo.title}" />
	<hr />
	<input type="text" name="writer" value="${vo.writer}" />
	<hr />
	<input type="text" name="price" value="${vo.price}" />
	<hr />
	<div style="text-align: center">
		<img id="image" src="/image/book/${vo.image}" width=200 />
	</div>
	<input type="file" name="image" style="display: none" />
	<hr />
	<div style="text-align: center">
		<input type="submit" value="도서 수정" /> <input type="reset"
			value="수정 취소" />
	</div>
</form>

 

출력물

 

- update 작업을 해보자.

- BookDAO.java

	// 6. 도서 정보를 수정하는 메서드
	public void update(BookVO vo){
		try{
			String sql="update books set title=?,writer=?,price=?,image=? where code=?";
			PreparedStatement ps=Database.CON.prepareStatement(sql);
			ps.setString(1, vo.getTitle());
			ps.setString(2, vo.getWriter());
			ps.setInt(3, vo.getPrice());
			ps.setString(4, vo.getImage());
			ps.setString(5, vo.getCode());
			ps.execute();
		}catch(Exception e){
			System.out.println("update:" + e.toString());
		}
	}

 

- BookServlet.java

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		// 4. 파일 업로드 작업
		// "c:/image/book" ; 저장경로, "1000*1000*10"; 파일 용량 limit
		// "UTF-8" ; format, "new DefaultFileRenamePolicy()" ; 이름이 겹칠경우 새로운 이름을 지정
		MultipartRequest multi = new MultipartRequest(request, "c:/image/book", 1000 * 1000 * 10,
				"UTF-8", new DefaultFileRenamePolicy());
		String strImage = multi.getFilesystemName("image");
		BookVO vo = new BookVO();
		vo.setCode(multi.getParameter("code"));
		vo.setTitle(multi.getParameter("title"));
		vo.setWriter(multi.getParameter("writer"));
		vo.setPrice(Integer.parseInt(multi.getParameter("price")));
		vo.setImage(strImage);
		
		String oldImage = multi.getParameter("oldImage");
		switch(request.getServletPath()){
		case "/book/delete":
			dao.delete(vo.getCode());
			File file = new File("c:/image/book/"+oldImage);
			file.delete();
			break;
		case "/book/insert":
			dao.insert(vo);
			break;
		case "/book/update":
			if(strImage==null){ // 새로운 이미지가 없는 경우
				vo.setImage(oldImage);
			}else{ // 새로운 이미지가 있는 경우
				file = new File("c:/image/book/"+oldImage);
				file.delete();
			}
			dao.update(vo);
			break;
		}
		
		response.sendRedirect("/book/list");
	}

 

 

 

- delete 작업을 해보자.

  1. - BookDAO.java
	// 7. 도서 정보를 삭제하는 메서드
	public void delete(String code){
		try {
			String sql = "delete from books where code=?";
			PreparedStatement ps = Database.CON.prepareStatement(sql);
			ps.setString(1, code);
			ps.execute();
		} catch (Exception e) {
			System.out.println("delete : "+e.toString());
		}
	}

 

- 리드뷰

	<div style="text-align: center">
		<input type="submit" value="도서 수정" />
		<input type="button" value="도서 삭제" id="btnDelete"/>
		<input type="reset" value="수정 취소" />
	</div>
</form>
<script>
	var code = '${vo.code}';

	// 삭제 버튼을 클릭한 경우
	$('#btnDelete').on('click',function(){
		if(!confirm(code + "을(를) 삭제하시겠습니까?")) return;
		frm.action='/book/delete';
		frm.submit();
	});

 

-북서블릿

		String oldImage = multi.getParameter("oldImage");
		switch(request.getServletPath()){
		case "/book/delete":
			dao.delete(vo.getCode());
			File file = new File("c:/image/book/"+oldImage);
			file.delete();
			break;
		case "/book/insert":
			dao.insert(vo);
			break;
		case "/book/update":
			if(strImage==null){ // 새로운 이미지가 없는 경우
				vo.setImage(oldImage);
			}else{ // 새로운 이미지가 있는 경우
				file = new File("c:/image/book/"+oldImage);
				file.delete();
			}
			dao.update(vo);
			break;
		}

 

ex03.war
1.06MB

 

출력