JSP 강의 Day08

주세환·2023년 4월 10일
0

JSP

목록 보기
8/16

물품등록

준비단계

@WebServlet(urlPatterns = {"/item/write.do"})
public class ItemWriteController extends HttpServlet {
	private static final long serialVersionUID = 1L;

    public ItemWriteController() {
        super();
    }
    
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.getRequestDispatcher("/WEB-INF/item_write.jsp").forward(request, response);
	}

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

}

ItemWriteController.java를 생성하고

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="UTF-8">
	<meta http-equiv='X-UA-Compatible' content='IE=edge' />
	<meta name='viewport' content='width=device-width, initial-scale=1' />
	<title>물품등록</title>
	<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/bootstrap.min.css" />
	<!-- Include stylesheet -->
	<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <div style="width:1500px; margin:0 auto; padding: 50px; border:1px solid #efefef;">
        	<h3>물품등록</h3>
        	<hr />
       <!-- <form action="${pageContext.request.contextPath}/item/write.do" method="post"> -->
        	<form id="form" action="write.do" method="post">
            <div class="row">
                <div class="col-sm">
	                <div class="form-floating mb-2">
	                    <input type="text" name="name" id="title" class="form-control" autofocus required />
	                    <label for="title" class="form-label">물품명</label>
	                </div>

                    <div style="margin-bottom:5px;">
                        <!-- Create the editor container -->
						<div id="editor" style="height:300px;">
						  <p>물품설명</p>
						</div>
                    </div>
                    
                    <textarea id="content" name="content" style="display:block"></textarea>
                    
                    <div class="form-floating mb-2">
                        <input type="text" name="price" id="price" class="form-control" required />
                        <label for="price" class="form-label">가격</label>
                    </div>
                    
                    <div class="form-floating mb-2">
                        <input type="text" name="quantity" id="quantity" class="form-control" required />
                        <label for="quantity" class="form-label">수량</label>
                    </div>
                    
	                <div>
                    	<input type="submit" value="등록" class="btn btn-primary" onclick="insertItem()"/>
                    </div>
                </div>
            </div>
            </form>
		</div>            
	</div>
	
	<!-- Include the Quill library -->
	<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
	
	<!-- Initialize Quill editor -->
	<script>
	
		const toolbarOptions = [
			  ['bold', 'italic', 'underline', 'strike'],        // toggled buttons
			  ['blockquote', 'code-block'],
	
			  [{ 'header': 1 }, { 'header': 2 }],               // custom button values
			  [{ 'list': 'ordered'}, { 'list': 'bullet' }],
			  [{ 'script': 'sub'}, { 'script': 'super' }],      // superscript/subscript
			  [{ 'indent': '-1'}, { 'indent': '+1' }],          // outdent/indent
			  [{ 'direction': 'rtl' }],                         // text direction
	
			  [{ 'size': ['small', false, 'large', 'huge'] }],  // custom dropdown
			  [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
	
			  [{ 'color': [] }, { 'background': [] }],          // dropdown with defaults from theme
			  [{ 'font': [] }],
			  [{ 'align': [] }],
	
			  ['clean']                                         // remove formatting button
			];
		
		// 위쪽에 있는 태그 중에서 id가 editor인 것을 찾아서 toolbar는 toolbarOptions의 값으로 대체하고 테마를 snow로 해서 변경
		const quill = new Quill('#editor', {
			  modules: {
			    toolbar: toolbarOptions
			  },
			  theme: 'snow'
			});
		
		function insertItem(){
			// 물품명 유효성 검사
			const name = document.getElementById("name");
			if(name.value.length <= 0) {
				alert('물품명을 입력하세요.');
				name.focus();
				return false;
			}
			
			// 가격 유효성 검사
			const price = document.getElementById("price");
			if(name.value.length <= 0) {
				alert('가격을 입력하세요.');
				name.focus();
				return false;
			}
			
			// 수량 유효성 검사
			const quantity = document.getElementById("quantity");
			if(name.value.length <= 0) {
				alert('수량을 입력하세요.');
				name.focus();
				return false;
			}
			
			// div 태그의 내용을 textarea로 복사
			const divContent = quill.root.innerHTML;
			document.getElementById("content").value = divContent;
			// form 태그 전송
			document.getElementById("form").submit();
		}
	</script>
</body>
</html>

item_write.jsp를 생성한다.
코드에 작성한 것처럼 유효성 검사 또한 포함하였다.

물품명, 가격, 수량 순으로 입력되지 않은 칸이 있으면 알림창이 뜬다.


등록

@Insert({
	" INSERT INTO item (name, content, price, quantity) ",
	" VALUES(#{obj.name}, #{obj.content}, #{obj.price}, #{obj.quantity}) "
})
public int insertItemOne(@Param("obj") Item obj);

Mapper를 생성하고

@WebServlet(urlPatterns = {"/item/write.do"})
public class ItemWriteController extends HttpServlet {
	private static final long serialVersionUID = 1L;

    public ItemWriteController() {
        super();
    }
    
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.getRequestDispatcher("/WEB-INF/item_write.jsp").forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Item item = new Item();
		item.setName(request.getParameter("name"));
		item.setContent(request.getParameter("content"));
		item.setPrice(Long.parseLong(request.getParameter("price")));
		item.setQuantity(Long.parseLong(request.getParameter("quantity")));
		System.out.println(item.toString()); // 전달받은 값 확인용
		
		//mapper를 통해 데이터 추가
		int ret = MybatisContext.getSqlSession().getMapper(ItemMapper.class).insertItemOne(item);
		
		if( ret == 1 ) {
			// 절대 경로를 이용한 페이지 이동
			response.sendRedirect(request.getContextPath() +"/item" + "/select.do");
		}
		else {
			// 상대 경로를 이용한 페이지 이동
			response.sendRedirect("write.do");
		}
	}

}

itemWriteController.java에 추가한다.

위처럼 입력하고 등록을 눌러보면

select.do를 아직 생성하지 않았으니 404에러가 뜨고

콘솔에는 등록한 값이 나온다.

하지만 유효성검사를 하기 때문에 굳이 하지 않아도 된다.

이제 select.do를 생성하여 404에러를 없애보자.


조회

	// #{ } => 값을 표현할때
	// ${ } => 컬럼명, 테이블명 등.   
	@Select({
		" SELECT i.* FROM item i WHERE ${column} LIKE '%' || #{text} || '%' ORDER BY no DESC "
	})
	public List<Item> selectItemList(@Param("column") String column, 
			@Param("text")String text);
	
	@Insert({
		" INSERT INTO item(name, content, price, quantity) ",
		" VALUES(#{obj.name}, #{obj.content}, #{obj.price}, #{obj.quantity}) "
	})
	public int insertItemOne(@Param("obj")Item obj);

지난번에 만든 Mapper를 가져와 생성하고

@WebServlet(urlPatterns = {"/item/select.do"})
public class ItemSelectController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		List<Item> list = MyBatisContext.getSqlSession()
				.getMapper(ItemMapper.class).selectItemList("name", "");

		request.setAttribute("list", list);
		request.getRequestDispatcher("/WEB-INF/item_select.jsp").forward(request, response);
	}
	
}

BoardSelectCOntroller.java를 토대로 ItemSelectController.java를 생성한다.

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>물품목록</title>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/bootstrap.min.css" />
</head>

<body>
	<div class="container">
		<a href="write.do" class="btn btn-primary">물품등록</a>
		
		<div style="width:500px; margin-top:10px;">
			<form class="row g-2">
  				<div class="col-auto">
					<input type="text" name="text" class="form-control" placeholder="검색어" style="width:300px;"/>
				</div>
				<div class="col-auto">
					<input type="submit" class="btn btn-primary" value="검색" />
				</div>
			</form>		
		</div>
		
		<table class="table table-sm table-hover">
  			<thead>
    			<tr>
					<th scope="col">번호</th>
					<th scope="col">물품명</th>
					<th scope="col">가격</th>
					<th scope="col">수량</th>
					<th scope="col">날짜</th>
			    </tr>
  			</thead>
			<tbody>
				<c:forEach var="obj" items="${list}">
				<tr>
					<td scope="row">${obj.no}</td>
					<td>${obj.name}</td>
					<td>${obj.price}</td>
					<td>${obj.quantity}</td>
					<td>${obj.regdate}</td>
				</tr>
				</c:forEach>
			</tbody>
		</table>
		
	</div>
	
	<script src="${pageContext.request.contextPath}/resources/js/jquery-3.6.4.min.js"></script>
	<script src="${pageContext.request.contextPath}/resources/js/jquery.twbsPagination.min.js"></script>
	<script>
	</script>
</body>

item_select.jsp또한 board_select.jsp를 복사하고 수정하여 생성한다.


이렇게 작성했던 item들의 목록들이 나온다면 성공.

이미지 등록

등록 화면

<thead>
  			<tr>
			<th scope="col">번호</th>
			<th scope="col">물품명</th>
			<th scope="col">가격</th>
			<th scope="col">수량</th>
			<th scope="col">날짜</th>
			<th scope="col">이미지</th>
	    </tr>
			</thead>
	<tbody>
		<c:forEach var="obj" items="${list}">
		<tr>
			<td scope="row">${obj.no}</td>
			<td>${obj.name}</td>
			<td>${obj.price}</td>
			<td>${obj.quantity}</td>
			<td>${obj.regdate}</td>
			<td><a href="imagewrite.do?ino=${obj.no}" button class="btn btn-primary">이미지 등록</button></td>
		</tr>
		</c:forEach>
	</tbody>

item_select.jsp를 위처럼 수정해준다.

이렇게 이미지 등록 버튼이 생성된다.


@WebServlet(urlPatterns = {"/item/imagewrite.do"})
public class ItemImageWriteController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String ino = request.getParameter("ino");
		request.setAttribute("ino", ino);
		request.getRequestDispatcher("/WEB-INF/item_image_write.jsp").forward(request, response);
	}

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

ItemImageWriteController.java를 생성하여 위처럼 작성하고

<%@ 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 lang="ko">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>물품이미지등록</title>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/bootstrap.min.css" />
</head>

<body>
	<div class="container">
        <div style="width:800px; margin:0 auto; padding: 50px; border:1px solid #efefef;">
        	<h3>물품이미지등록</h3>
        	<hr />
        	<form id="form" action="${pageContext.request.contextPath}/item/imagewrite.do" method="post">
	            <div class="row">
	                <div class="col-sm">
		                <div class="form-floating mb-2">
		                    <input type="text" name="ino" id="ino"
		                    	style="background-color:#efefef;" 
		                    	value="${ino}" class="form-control" readonly />
		                    <label for="ino" class="form-label">물품번호</label>
		                </div>
		                
		                <div class="form-floating mb-2">
		                	<img src="" style="width:100px;height:100px">
		                    <input type="file" name="file" id="file" class="form-control" />
		                </div>
	
		                <div>
	                    	<input type="button" value="등록" class="btn btn-primary" 
	                    		onclick="insertImageItem()"/>
	                    	<a href="select.do" class="btn btn-success">목록으로</a>	
	                    </div>
	                </div>
	            </div>
            </form>
		</div>            
	</div>
	
	<script>
		function insertImageItem() {
			
		}
	</script>
</body>
</html>

item_image_write.jsp를 생성한다.

이미지 등록 버튼을 누르면

물품 번호가 나오며 이미지를 등록하는 창으로 이동하게 된다.

파일 선택을 누르면 이렇게 사진을 선택할 수 있는 창이 나오게 된다.

또한 목록으로 버튼을 누르면 다시 목록으로 가게 된다.


<div class="form-floating mb-2">
	<img src="${pageContext.request.contextPath}/resources/images/default.png" 
		id="img" style="width:100px;height:100px">
    <input type="file" name="file" id="file" class="form-control" onchange="imageChange(this)"/>
</div>

...

<script>
	function imageChange(e){
		const img = document.getElementById("img");
		console.log(e.files);
		if(e.files.length > 0){ // 첨부
			// 파일을 첨부하면 크롬에서 blob:http://1.237....
			img.src = URL.createObjectURL( e.files[0] ); // 가상의 url정보를 생성해서 추함.
		}
		else { // 취소
			img.src = "${pageContext.request.contextPath}/resources/images/default.png";
		}
	}

	function insertImageItem() {
		
	}
</script>

item_image_write.jsp를 위처럼 수정, 추가해준다.

파일을 선택하면 해당하는 이미지가 보인다.


<div class="form-floating mb-2">
	<img src="${pageContext.request.contextPath}/resources/images/default.png" 
		id="img" style="width:100px;height:100px; cursor:pointer;"
		onclick="clickImage()">
		
    <input type="file" name="file" id="file" class="form-control"
    	style="display:none"
    	onchange="imageChange(this)" />
</div>

...

<script>
	function clickImage () {
		document.getElementById("file").click();
	}

item_image_write.jsp를 위처럼 수정, 추가한다.

  • resources-images 폴더에 default.png 파일을 추가하였다.

파일추가 버튼이 사라졌다. 사진 파일을 누르면

이렇게 사진을 추가할 수 있다.

사진을 추가한 모습.

사진을 누르고 확인이 아닌 취소 버튼을 눌렀을 때의 모습.


이미지 등록

@Insert({
	" INSERT INTO itemimage(filename, filesize, filetype, filedata, itemno) ",
	" VALUES(#{obj.filename}, #{obj.filesize}, #{obj.filetype}, #{obj.filedata}, #{obj.itemno}) "
})
public int insertItemImageOne(@Param("obj") ItemImage obj);

mapper를 추가하고

@WebServlet(urlPatterns = {"/item/imagewrite.do"})
@MultipartConfig()
public class ItemImageWriteController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String ino = request.getParameter("ino");
		request.setAttribute("ino", ino);
		request.getRequestDispatcher("/WEB-INF/item_image_write.jsp").forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Long ino = Long.parseLong( request.getParameter("ino"));
		Part file = request.getPart("file");
		
		ItemImage obj = new ItemImage();
		obj.setItemno(ino);
		obj.setFilename(file.getSubmittedFileName());
		obj.setFilesize(file.getSize());
		obj.setFiletype(file.getContentType());
		obj.setFiledata(file.getInputStream().readAllBytes());
		System.out.println(obj);
		// mapper로 추가 후
		
		int ret = MybatisContext.getSqlSession().getMapper(ItemImageMapper.class).insertItemImageOne(obj);
		if( ret == 1 ) {
			// 절대 경로를 이용한 페이지 이동
			response.sendRedirect(request.getContextPath() +"/item" + "/imagewrite.do?ino="+ino);
		}
		else {
			// 상대 경로를 이용한 페이지 이동
			response.sendRedirect("imagewrite.do");

		}
	}
}

ItemImageWriteController.java를 수정한다.

<body>
	<div class="container">
        <div style="width:800px; margin:0 auto; padding: 50px; border:1px solid #efefef;">
        	<h3>물품 이미지 등록</h3>
        	<hr />
        	<form id="form" action="${pageContext.request.contextPath}/item/imagewrite.do" method="post"
        		enctype="multipart/form-data">
                
...
                
function insertImageItem() {
			// 유효성 검사한 후
			const file = document.getElementById("file");
if (file.value.length <= 0) {
	alert('파일첨부');
}
			// form 태그 전송
			document.getElementById("form").submit();
		}
	</script>
</body>                

item_image_write.jsp를 위처럼 수정, 추가한다.

페페사진을 등록해보자.

등록을 누르니 페페 사진이 사라졌다. 제대로 등록이 되었는지 H2에서 확인해보자.

REGDATE를 보면 현재 날짜와 시간인 2023-04-10 14:08 을 볼 수 있다.
제대로 등록이 되었다는 뜻!


여러개 등록

 ...
      
            <form id="form1" action="imagewritebatch.do?ino=${ino}" method="post" 
            	enctype="multipart/form-data">
            	<c:forEach var="idx" begin="1" end="3" step="1">
            		<img src="${pageContext.request.contextPath}/resources/images/default.png"
            			class="imgs" 
            			style="width:50px;height:50px; cursor:pointer;"/>
            		<input type="file" name="file[]" onchange="imageChangeBatch(this, '${idx-1}')"/>
            		<br />
            	</c:forEach>
            	<input type="button" value="일괄등록"  onclick="insertIamgeBatch()" class="btn btn-primary" />
            	<a href="select.do" class="btn btn-success">목록으로</a>
            </form>
            
		</div>
	</div>
	
	<script>
		// document.getElementById("아이디"); id가 일치하는 1개 찾기
		// document.getElementsByName("name값"); name값이 일치하는 n개 찾기 
		// document.getElementsByClassName("class값"); class값이 일치하는  n개 찾기
		// document.getElementsByTagName("img"); 태그가 img인 n개 찾기
		
		const imgs  = document.getElementsByClassName("imgs"); //<img src class="imgs" />
		const files = document.getElementsByName("file[]");    //<input type="file" name="file[]" />
		
		function imageChangeBatch(e, idx){ //첨부한파일정보, type=file의 위치(0부터)
			if(e.files.length > 0) {
				imgs[ Number(idx) ].src=URL.createObjectURL( e.files[0] );// 가상의 url정보를 생성해서 추가함.
			}
			else{
				imgs[ Number(idx) ].src="${pageContext.request.contextPath}/resources/images/default.png";
			}
		}
		
		function insertIamgeBatch() {
			var chk = 0;
			for(let i=0; i<files.length; i++) { //files전체 반복
				if(files[i].value.length <= 0){ // 첨부하지 않은 것을 발견하면
					alert('이미지 첨부하세요.'); // 알림창 표시
					chk = 1; 
					break; //반복문 종료
				}
			}
			if(chk === 0){ // if문을 한번도 수행하지 않았다면 form 전송
				document.getElementById("form1").submit();
			}
		}

		function insertImageItem() {
			// 유효성 검사 한 후
			const file = document.getElementById("file");
			if(file.value.length <= 0){
				alert('파일첨부 하세요');
			}
			
			// form태그 전송
			document.getElementById("form").submit();
		}
	</script>
</body>
</html>

item_image_write.jsp를 위처럼 추가한다.

3개를 한 번에 등록할 수 있게 되었다.

이미지를 선택하지 않고 일괄등록을 누르면 이미지를 첨부하라는 알림이 뜬다.

이렇게 3개를 한 번에 추가할 수 있다.

일괄등록을 누른 모습이다.

imagewritebatch.do를 생성하지 않았으니 404 오류가 나온다.


@WebServlet(urlPatterns = {"/item/imagewritebatch.do"})
@MultipartConfig()
public class ItemImageWriteBatchController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String ino = request.getParameter("ino");
		request.setAttribute("ino", ino);
		request.getRequestDispatcher("/WEB-INF/item_image_write.jsp").forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Long ino = Long.parseLong( request.getParameter("ino"));
		
		Collection<Part> file = request.getParts();
		

		for(Part filePart : file) {
			// name값이 files인것만 필터
			if(filePart.getName().equals("file[]")) {
				ItemImage obj = new ItemImage();
				obj.setItemno(ino);
				obj.setFilename(filePart.getSubmittedFileName());			
				obj.setFiletype(filePart.getContentType());
				obj.setFilesize(filePart.getSize());
				obj.setFiledata(filePart.getInputStream().readAllBytes());
				
				// 여기서 mapper로 insest수행
				// insert all 한 번에 추가하기
				MybatisContext.getSqlSession().getMapper(ItemImageMapper.class)
						.insertItemImageOne(obj);
			}
		}
		response.sendRedirect(request.getContextPath() +"/item" + "/imagewrite.do?ino="+ino);
	}
}

예전에 만든 BoardImageInsertBatchServlet을 참조하여 ItemImageWriteBatchController.java를 만들었다.

jsp에서 파일명을 files[]로 했기 때문에 if(filePart.getName().equals("file[]"))로 받아야 한다.

이렇게 우는 페페를 등록하면

사진 3개가 동시에 들어간 것을 확인할 수 있다.

0개의 댓글