나중에 한번 공부해보도록 하자.
package jejuWebController;
import java.io.IOException;
import java.util.List;
import config.MyBatisContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import webmapper.ItemImageMapper;
@WebServlet(urlPatterns = { "/item/selectimagelist" })
public class ItemImageSelectList extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ItemImageMapper mapper = MyBatisContext.getSqlSession().getMapper(ItemImageMapper.class);
long ino = Long.parseLong(request.getParameter("ino"));
// <a href="selectimagelist.do?itemno=${obj.no}"><button>등록된이미지보기</button></a>
List<Long> no = mapper.selectItemImageList(ino);
// mapper로 itemno를 전달해서 해당하는 이미지번호만 리턴
request.setAttribute("no", no );
request.getRequestDispatcher("/WEB-INF/item_img_write.jsp").forward(request, response);
}
}
package jejuWebController;
import java.io.IOException;
import config.MyBatisContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import webmapper.ItemImageMapper;
// 컨트롤러 역활 X, DB에 있는 이미지를 URL 형태로 변경해서 반환하는 용도
@WebServlet(urlPatterns = { "/item/imagedelete.do" })
public class ItemImageDelete extends HttpServlet {
private static final long serialVersionUID = 1L;
// ex) http://127.0.0.1:8080/web01/item/image?no=물품번호
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 삭제를 위해 필요한 값 (물품번호, 이미지번호)
long imageNo = Long.parseLong(request.getParameter("no"));
long itemNo = Long.parseLong(request.getParameter("ino"));
// Mapper를 통한 삭제
int ret = MyBatisContext.getSqlSession()
.getMapper(ItemImageMapper.class)
.deleteItemImageListOne(imageNo, itemNo);
// 삭제 후 보내는 페이지
if (ret == 1) {
response.sendRedirect(request.getContextPath() + "/item" + "/imagewrite.do?ino=" + itemNo);
} else {
response.sendRedirect("imagewrite.do?ino=" + itemNo);
}
}
}
package jejuWebController;
import java.io.IOException;
import config.MyBatisContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
import webdto.ItemImage;
import webmapper.ItemImageMapper;
// 컨트롤러 역활 X, DB에 있는 이미지를 URL 형태로 변경해서 반환하는 용도
@WebServlet(urlPatterns = { "/item/imageupdate.do" })
@MultipartConfig()
public class ItemImageUpdate extends HttpServlet {
private static final long serialVersionUID = 1L;
// ex) http://127.0.0.1:8080/web01/item/image?no=물품번호
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println(request.getParameter("imageNo"));
long imageNo = Long.parseLong(request.getParameter("imageNo"));
long itemNo = Long.parseLong(request.getParameter("ino"));
Part file = request.getPart("file"); // 첨부된 이미지 파일
if (file.getSize() > 0) {
ItemImage itemimage = new ItemImage();
itemimage.setNo(imageNo);
itemimage.setItemno(itemNo);
itemimage.setFilename(file.getSubmittedFileName());
itemimage.setFilesize(file.getSize());
itemimage.setFiledata(file.getInputStream().readAllBytes());
itemimage.setFiletype(file.getContentType());
int ret = MyBatisContext.getSqlSession().getMapper(ItemImageMapper.class).updateItemImageOne(itemimage);
if (ret == 1) { // 변경 완료한 경우
// request.setAttribute("message", "변경 완료되었습니다.");
request.setAttribute("icon", "success");
request.setAttribute("title", "변경완료");
request.setAttribute("text", "화끈하시네요!");
request.setAttribute("url", "imagewrite.do?ino=" + itemNo);
request.getRequestDispatcher("/WEB-INF/alert.jsp").forward(request, response);
} else { // 변경 실패한 경우
// request.setAttribute("message", "변경 실패");
request.setAttribute("icon", "warning");
request.setAttribute("title", "변경실패");
request.setAttribute("text", "변경에 실패했어요..");
request.setAttribute("url", "imagewrite.do?ino=" + itemNo);
request.getRequestDispatcher("/WEB-INF/alert.jsp").forward(request, response);
}
} else { // 변경사항 없는 경우
// request.setAttribute("message", "변경사항 없음");
request.setAttribute("icon", "question");
request.setAttribute("title", "파일없음");
request.setAttribute("text", "파일이.. 없네요?");
request.setAttribute("url", "imagewrite.do?ino=" + itemNo);
request.getRequestDispatcher("/WEB-INF/alert.jsp").forward(request, response);
}
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<!-- sweetalert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
Swal.fire({
icon: '${icon}',
title: '${title}',
text: '${text}',
showConfirmButton: false,
timer: 2500
});
window.location.href = '${url}'; // 주소창을 바꾸고 enter키 (a 태그와 동일한 기능)
/* alert('${message}'); // 알람을 표시 */
</script>
</body>
</html>
<%@ 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'>
<title>물품이미지 등록하기</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<!-- Include stylesheet -->
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css"
rel="stylesheet">
<!-- Bootstrap -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ"
crossorigin="anonymous">
</head>
<body style="color: rgba(123, 123, 102, 0.5);">
<div id="layoutAuthentication">
<div id="layoutAuthentication_content">
<main>
<div class="container">
<div class="row justify-content-center">
<div class="col-lg ">
<div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header">
<h3 class="text-left font-weight-light my-4">🖼️ 물품이미지 등록</h3>
</div>
<form id="form"
action="${pageContext.request.contextPath}/item/imagewrite.do"
method="post" enctype="multipart/form-data">
<div class="card-body">
<div class="form-floating mt-3 mb-3">
<input type="text" name="ino" class="form-control" id="ino"
for="floatingInput" value="${ino}" readonly> <label
for="ino" class="form-label">물품번호</label>
</div>
<c:forEach var='tmp' items="${no}">
<img
src="${pageContext.request.contextPath}/item/image?no=${tmp}"
style="width: 70px; height: 70px">
</c:forEach>
<hr />
<div class="form-floating mt-3 mb-3">
<img
src="${pageContext.request.contextPath}/resources/images.png"
id="img"
style="width: 250px; height: 200px; cursor: pointer;"
onclick="clickImage()"> <input type="file" name="file"
id="file" class="form-control" style="display: none"
onchange="imageChange(this)" />
</div>
<input type="button" value="등록" id="commit" name="commit"
class="btn btn-success btn-right" onclick="insertItemImage()"></input>
<a class="btn btn-secondary" href="select.do">목록으로</a>
</div>
</form>
<form id="form1" action="imagewritebatch.do?ino=${ino}"
method="post" enctype="multipart/form-data">
<div class="card-body">
<hr />
<div class="form-floating mt-3 mb-3">
<c:forEach var="idx" begin="1" end="3" step="1">
<img
src="${pageContext.request.contextPath}/resources/images.png"
class="imgs"
style="width: 50px; height: 50px; cursor: pointer;">
<input type="file" name="file[]"
onchange="imageChangeBatch(this, '${idx-1}')" />
<br />
</c:forEach>
</div>
<input type="button" value="일괄등록"
class="btn btn-success btn-right"
onclick="insertImageBatch()"></input> <a
class="btn btn-secondary" href="select.do">목록으로</a>
</div>
</form>
<hr />
<div class="card-body">
<c:forEach var="no" items="${imageNo}">
${no} :
<img
src="${pageContext.request.contextPath}/item/image?no=${no}"
style="width: 70px; height: 70px">
<button onclick="itemImageUpdateModal('${no}', '${ino}')"
class="btn btn-warning">수정</button>
<button onclick="itemImageDelete('${no}', '${ino}')"
class="btn btn-danger">삭제</button>
<br />
</c:forEach>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1"
aria-labelledby="exampleModalLabel" aria-hidden="true">
<form action="imageupdate.do" method="post"
enctype="multipart/form-data">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">이미지 수정</h5>
<button type="button" class="btn-close"
data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
이미지 번호 : <input type="text" name="imageNo"
id="modal_image_no" readonly /><br /> 현재 적용된 이미지 : <img
src="" style="width: 90px; height: 90px"
id="modal_image_src"><br /> <input type="hidden"
name="ino" value="${ino}"> 이미지변경 : <input
name="file" type="file" id="modal_image_file"
onchange="imageUpdateChange(this)" /><br />
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-success" value="변경하기" />
<button type="button" class="btn btn-secondary"
data-bs-dismiss="modal">취소</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<!-- sweetalert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- jQuery -->
<script
src="${pageContext.request.contextPath}/resources/js/jquery-3.6.4.min.js"></script>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script>
function itemImageUpdateModal(no, ino) {
const imageNo = document.getElementById("modal_image_no"); // 이미지 넘버
const imageSrc = document.getElementById("modal_image_src"); // 이미지 주소
const imageFile = document.getElementById("modal_image_file");// 이미지 파일
imageNo.value = no;
imageSrc.src = "${pageContext.request.contextPath}/item/image?no=" + no; // 받은 이미지 넘버를 토대로 주소완성
const modal = new bootstrap.Modal(document.getElementById("exampleModal"),{});
modal.show();
}
function itemImageDelete(no, ino) {
Swal.fire({
title: '정말로 지우실건가요?',
text: "지워진 이미지는 복구할 수 없어요!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: '좋아요, 지워봅시다!'
}).then((result) => {
if (result.isConfirmed) {
// <form action="imagedelete.do" method="post" style="display:none;">
var form = document.createElement("form");
form.setAttribute("action", "imagedelete.do");
form.setAttribute("method", "post");
form.style.display = "none";
// <input type="hidden" name="imageno" value="삭제할 이미지번호">
var input = document.createElement("input");
input.setAttribute("type", "hidden");
input.setAttribute("name", "no");
input.setAttribute("value", no);
console.log(no);
// <input type="hidden" name="ino" value="삭제할 물품번호">
var input1 = document.createElement("input");
input1.setAttribute("type", "hidden");
input1.setAttribute("name", "ino");
input1.setAttribute("value", Number(ino));
console.log( Number(ino));
// form 태그에 추가
form.appendChild(input);
form.appendChild(input1);
Swal.fire({
icon: 'success',
title: '삭제 완료!',
showConfirmButton: false,
timer: 3000
})
// body에 추가
document.body.appendChild(form);
// form 전송
form.submit();
}
})
};
// document.getElementById("아이디"); id가 일치하는 1개 찾기
// document.getElementsByName("name값"); name값이 일치하는 n개 찾기
// document.getElementsByClassName("class값"); class값이 일치하는 n개 찾기
// document.getElementsByTagName("img"); 태그가 img인 n개 찾기
const imgs = document.getElementsByClassName("imgs");
const files = document.getElementsByName("file[]")
function imageChangeBatch(e, idx) {
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.png";
}
}
function insertImageBatch() { // no image 이미지를 클릭하면 "file"이라는 id의 기능을 실행시킨다. (이미지 추가하기 기능. 현재 감춰둔 상태)
console.log(imgs);
console.log(imgs.length);
console.log(e.files);
console.log(idx);
}
function clickImage() {
document.getElementById("file").click();
}
function clickImages() {
document.getElementById("file[]").click();
}
function imageChange(e) {
console.log(e.files);
if (e.files.length > 0) { // 첨부
// 파일을 첨부하면 크롬에서 "blob:http://127.0.0.1:8080/...."라고 콘솔창에 띄운다.
console.log(URL.createObjectURL(e.files[0])); // 확인용
img.src = URL.createObjectURL(e.files[0]); // 가상의 url 정보를 생성해서 추가함.
} else { // 취소
img.src = "${pageContext.request.contextPath}/resources/images.png";
}
}
function imageUpdateChange(e) {
console.log(e.files);
if (e.files.length > 0) { // 첨부
// 파일을 첨부하면 크롬에서 "blob:http://127.0.0.1:8080/...."라고 콘솔창에 띄운다.
console.log(URL.createObjectURL(e.files[0])); // 확인용
modal_image_src.src = URL.createObjectURL(e.files[0]); // 가상의 url 정보를 생성해서 추가함.
} else { // 취소
modal_image_src.src = "${pageContext.request.contextPath}/resources/images.png";
}
}
function insertItemImage() {
// 유효성 검사 한 후
const file = document.getElementById("file");
if (file.value.length <= 0) {
Swal.fire('첨부된 파일이 없어요!', '이미지가 없으면 등록할 수 없어요.', 'error')
return false;
}
// form 태그 전송
document.getElementById("form").submit();
Swal.fire({
icon : 'success',
title : '이미지등록 완료!',
showConfirmButton : false,
timer : 2000
})
}
function insertImageBatch() {
// 유효성 검사
var chk = 0;
for (let i = 0; i < imgs.length; i++) { // 반복문으로 files 전체 유효성 검사
if (files[i].value.length <= 0) {
Swal.fire('첨부된 파일이 없어요!', '이미지가 없으면 등록할 수 없어요.', 'error')
chk = 1;
break; // 반복문 종료
}
}
if (chk === 0) { // if문을 한번도 수행하지 않았다면,
//form 전송
document.getElementById("form1").submit();
Swal.fire({
icon : 'success',
title : '이미지등록 완료!',
showConfirmButton : false,
timer : 2000
})
}
}
</script>
</body>
</html>
javascript 명칭 확인할 것!
버튼누를때 이미지 넘버와 물품넘버를 넘기도록 onclick에 저장
form 태그에서 반응하기 위해서는 button이 아닌 input의 submit 형태로 바꿔주어야 함.
또한 form의 enctype을 multipart/form-data
로 지정해주었으니 @MultipartConfig
로 지정해주어야 한다.
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<form action="imageupdate.do" method="post" enctype="multipart/form-data">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">이미지 수정</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
이미지 번호 : <input type="text" name="imageNo"
id="modal_image_no" readonly /><br />
현재 적용된 이미지 : <img style="width: 90px; height: 90px"
id="modal_image_src"><br /> <input type="hidden"
name="ino" value="${ino}">
이미지변경 : <input name="file" type="file" id="modal_image_file"
onchange="imageUpdateChange(this)" /><br />
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-success" value="변경하기" />
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">취소</button>
</div>
</div>
</div>
</form>
</div>
고객 회원가입
127.0.0.1:8080/web01/customer/join.do
ROLE CUSTOMER
판매자 회원가입
127.0.0.1:8080/web01/customer/join.do
ROLE SELLER
ID 중복검사 (RestMemberIdCheck.java)
id 값 입력마다 console창에 로그가 생성되도록 설정
// 중복되는 id값의 개수를 받아옴
@Select( value = {
" SELECT COUNT(*) cnt FROM memtb ",
" WHERE id = #{id} "
} )
public int selectMemberIdCheck(@Param("id") String id);
<%@ 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>
<!-- bootstrap -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous">
</head>
<body>
<div class="container">
<div
style="width: 600px; margin: 0 auto; padding: 50px; border: 1px solid #efefef;">
<h3>회원가입</h3>
<div class="row">
<div class="col-sm">
<div class="form-floating mb-2">
<input type="text" id="id" class="form-control" onkeyup="ajaxIDCheck(this)">
<label for="id" id="lbl_check" class="form-label">사용할아이디</label>
</div>
<div class="form-floating mb-2">
<input type="password" id="pw" class="form-control" required /> <label
for="pw" id="lbl_pwCheck" class="form-label">암호</label>
</div>
<div class="form-floating mb-2">
<input type="password" id="pw1" class="form-control" onkeyup="ajaxPWCheck(this)" required/>
<label for="pw1" id="lbl_pwCheck" class="form-label" >암호재확인</label>
</div>
<div class="form-floating mb-2">
<input type="text" id="name" class="form-control" required /> <label
for="name" class="form-label">이름</label>
</div>
<div class="form-floating mb-2">
<input type="text" id="age" class="form-control" /> <label
for="age" class="form-label">나이</label>
</div>
<div>
<input type="submit" value="회원가입" class="btn btn-success">
<button type="button" class="btn btn-secondary">로그인하기</button>
</div>
</div>
</div>
</div>
</div>
<!-- sweetalert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- jQuery -->
<script src="${pageContext.request.contextPath}/resources/js/jquery-3.6.4.min.js"></script>
<!-- axios -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.3.5/axios.min.js"></script>
<script>
function ajaxPWCheck(e) {
console.log(e.value);
var pw = document.getElementById('pw').value;
var pw1 = document.getElementById('pw1').value;
if(pw.length < 6) { lbl_pwCheck
document.getElementById("lbl_pwCheck").innerText = '비밀번호는 6글자 이상이어야 합니다.';
}
if( pw != pw1 ) {
document.getElementById("lbl_pwCheck").innerText = '입력한 글자가 6글자 이상이어야 합니다.';
return false;
} else {
document.getElementById("lbl_pwCheck").innerText = '비밀번호가 일치합니다!';
document.getElementById("lbl_pwCheck").style.color = 'blue';
return true;
}
}
async function ajaxIDCheck(e){
console.log(e.value);
document.getElementById("lbl_check").innerText = '아이디';
document.getElementById("lbl_check").style.color = 'black';
document.getElementById("id").className = 'form-control';
if(e.value.length>0) {
// rest api 호출
const url = '${pageContext.request.contextPath}/api/member/idcheck.json?id=' + e.value;
const headers = {"Content-Type":"application/json"};
const {data} = await axios.get(url, {headers});
console.log(data);
if(data.ret === 1){
document.getElementById("lbl_check").innerText = '이미 사용중인 ID입니다!';
document.getElementById("lbl_check").style.color = 'red';
document.getElementById("id").className = 'form-control is-invalid';
}
else if(data.ret === 0){
document.getElementById("lbl_check").innerText = '사용가능!';
document.getElementById("lbl_check").style.color = 'blue';
}
}
}
</script>
</body>
</html>
중복되는 아이디일때는 빨간색,
사용가능한 아이디일때는 파란색으로 표시되도록 설정하였다.