// 이미지 1개 가져가기
@Select({
" SELECT i.* FROM itemimage i WHERE NO = #{no} "
})
public ItemImage selectItemImageOne(@Param("no") long no); //이미지번호
// 물품번호를 이용해서 관련된 전체 이미지 번호 반환
@Select({
" SELECT i.NO FROM itemimage i WHERE ITEMNO = #{itemno} ORDER BY no DESC "
})
public List<Long> selectItemImageNo (@Param("itemno") long itemno);
우선 mapper를 생성한다.
@WebServlet(urlPatterns = "/item/image")
public class ItemImageServlet 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 no = Long.parseLong(request.getParameter("no"));
//no를 전달하여 mapper에서 ItemImage정보 1개 가져옴.
ItemImage obj = mapper.selectItemImageOne(no);
response.setContentType(obj.getFiletype()); // 이건 이미지다. html 아니다.
response.setStatus(200); // 200은 정상적인 처리결과다.
response.getOutputStream().write(obj.getFiledata()); // 이게 실제 정보다.
}
}
저번에 만든 ItemImageServlet.java를 가져온다.
이제 postman을 열어보자.
ItemImageServlet에 정의해둔 주소인 /item/image에 no까지 입력하면 해당하는 사진이 보이게 된다.
이때 no는 데이터베이스에서 보고 확인해야 한다.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ItemImageMapper mapper = MybatisContext.getSqlSession().getMapper(ItemImageMapper.class);
long no = Long.parseLong(request.getParameter("no"));
//no를 전달하여 mapper에서 ItemImage정보 1개 가져옴.
ItemImage obj = mapper.selectItemImageOne(no);
response.setContentType(obj.getFiletype()); // 이건 이미지다. html 아니다.
response.setStatus(200); // 200은 정상적인 처리결과다.
response.getOutputStream().write(obj.getFiledata()); // 이게 실제 정보다.
}
Servlet을 위처럼 수정하고
</form>
<hr />
<c:forEach var="no" items="${imageNo}">]
<img src="${pageContext.request.contextPath}/item/image?no=${no}"
style="width:100px;height:100px" />
<button>수정</button>
<button>삭제</button>
<br />
</c:forEach>
</div>
</div>
<script>
item_image_write.jsp를 위처럼 수정하면
이렇게 등록되어있는 사진들과 수정, 삭제 버튼이 추가된다.
<button onclick="itemImageDelete('${no}}', '${ino}')">삭제</button>
...
<script>
function itemImageDelete(no, ino) { // 삭제할이미지번호, 물품번호
const ret = confirm('삭제할까요?');
if(ret === true) {
//<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", "imageno");
input.setAttribute("value", Number(no)); // typescript
//<input type="hidden" name="ino" value="삭제할번호" />
var input1 = document.createElement("input");
input1.setAttribute("type", "hidden")
input1.setAttribute("name", "ino");
input1.setAttribute("value", Number(ino));
// form태그에 추가
form.appendChild(input);
form.appendChild(input1);
// body에 추가
document.body.appendChild(form);
// form전송
form.submit();
}
}
item_image_write.jsp의 버튼을 수정하고 script에 삭제기능을 추가하였다.
삭제를 누르면 알림창이 뜨고
확인을 누르니 imagedelete.do로 이동한다.
@WebServlet(urlPatterns = {"/item/imagedelete.do"})
@MultipartConfig()
public class ItemImageDeleteController extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Long ino = Long.parseLong( request.getParameter("ino"));
Long imageNo = Long.parseLong( request.getParameter("imageno"));
// mapper를 이용해서 삭제
int ret = MybatisContext.getSqlSession().getMapper(ItemImageMapper.class).deleteItemImageOne(imageNo);
if( ret == 1 ) {
// 절대 경로를 이용한 페이지 이동
response.sendRedirect(request.getContextPath() +"/item" + "/imagewrite.do?ino="+ino);
}
else {
// 상대 경로를 이용한 페이지 이동
response.sendRedirect("imagewrite.do?ino="+ino);
}
}
}
ItemImageDeleteController.java를 생성하자.
삭제를 눌렀더니
이렇게 오류가 떴다. 문제를 찾아보자.
<button onclick="itemImageDelete('${no}', '${ino}')">삭제</button>
에서 ${no}}로 되어있었다.
삭제를 누르면
정상적으로 삭제되고 주소도 그대로 돌아온다.
<!-- 이미지 수정 모달창 -->
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title fs-5" id="exampleModalLabel">Modal title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<script src="${pageContext.request.contextPath}/resources/js/jquery-3.6.4.min.js"></script>
<script src="${pageContext.request.contextPath}/resources/js/bootstrap.min.js"></script>
<script>
function itemUpdateModal() {
const modal = new bootstrap.Modal(document.getElementById("exampleModal"),{});
modal.show();
}
이미지 수정 모달, jQuery, bootstrap, 함수를 추가한다.
수정버튼을 누른 상태이다.
이제 모달창을 입맛대로 바꿔볼 차례이다.
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title fs-5" 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" readonly />
현재 이미지 : <img src="" style="width:100px;height:100px" />
변경 이미지 : <input type="file" />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary">저장</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">취소</button>
</div>
</div>
</div>
</div>
이렇게 바꾸었다.
이제 필요한 값들을 추가하자.
<c:forEach var="no" items="${imageNo}">
${no} =>
<img src="${pageContext.request.contextPath}/item/image?no=${no}"
style="width:100px;height:100px" />
<button onclick="itemUpdateModal()">수정</button>
<button onclick="itemImageDelete('${no}', '${ino}')">삭제</button>
<br />
</c:forEach>
위 항목을 추가하면
각 사진에 해당하는 번호가 추가된다.
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 fs-5" 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" id="modal_image_no" readonly /><br />
현재 이미지 : <img src="" style="width:100px;height:100px" id="modal_image_src" /><br />
변경 이미지 : <input type="file" id="modal_image_file" /><br />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary">저장</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">취소</button>
</div>
</div>
</div>
</form>
</div>
...
function itemUpdateModal(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;
위처럼 수정한다.
수정버튼을 누르면 이미지 번호, 현재 이미지, 변경 이미지가 출력된다.
하지만 이미지 변경은 되지 않는다.
<div class="modal-body">
이미지 번호 : <input type="text" name="imageno" id="modal_image_no" readonly /><br />
현재 이미지 : <img src="" style="width:100px;height:100px" id="modal_image_src" /><br />
<input type="hidden" name="ino" value="${ino}" />
변경 이미지 : <input type="file" name="file" id="modal_image_file" /><br />
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" value="이미지변경" />
item_image_jsp를 이렇게 변경하면
파일을 선택하고 이미지변경을 누르면
imageupdate.do로 넘어가게 된다.
@WebServlet(urlPatterns = {"/item/imageupdate.do"})
@MultipartConfig()
public class ItemImageUpdateController extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Long ino = Long.parseLong( request.getParameter("ino") ); // 물품 번호
Long imageNo = Long.parseLong( request.getParameter("imageno") ); // 이미지 번호
Part file = request.getPart("file"); // 첨부한 파일
if(file.getSize() > 0) { // 첨부가 되었다면 수정하기
// mapper를 이용하여 수정
ItemImage obj = new ItemImage();
obj.setNo( imageNo );
obj.setItemno( ino );
obj.setFilename( file.getSubmittedFileName() );
obj.setFiletype( file.getContentType() );
obj.setFilesize( file.getSize() );
obj.setFiledata( file.getInputStream().readAllBytes() );
int ret = MybatisContext.getSqlSession().getMapper(ItemImageMapper.class).updateItemImageOne(obj);
System.out.println(imageNo);
System.out.println(ino);
// 적절한 페이지로 이동
if( ret == 1 ) { // 변경 완료
request.setAttribute("message", "변경 완료");
request.setAttribute("url", "imagewrite.do?ino="+ino);
request.getRequestDispatcher("/WEB-INF/alert.jsp").forward(request, response);
}
else {// 변경 완료 안됨
request.setAttribute("message", "변경 실패");
request.setAttribute("url", "imagewrite.do?ino="+ino);
request.getRequestDispatcher("/WEB-INF/alert.jsp").forward(request, response);
}
}
else { // 변경사항 없습니다.
request.setAttribute("message", "변경 사항 없음");
request.setAttribute("url", "imagewrite.do?ino="+ino);
request.getRequestDispatcher("/WEB-INF/alert.jsp").forward(request, response);
}
}
}
ItemImageUpdateController.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>
<head>
<script>
alert('${message}'); // 알림을 표시
window.location.href='${url}'; // 주소창을 바꾸고 enter키
</script>
</head>
</html>
message와 url을 연결할 alert.jsp를 생성한다.
이제 실험해보자.
화난 페페를 넣고 이미지 변경을 눌러보면
변경이 완료되었다.
파일을 선택하지 않고 변경을 누르면
변경 사항이 없다고 뜬다.
@WebServlet(urlPatterns = {"/customer/join.do"})
public class CustomerJoinController extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/customer/customer_join.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
CustomerJoinController를 생성하고
<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: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" />
<label for="id" class="form-label">아이디</label>
</div>
<div class="form-floating mb-2">
<input type="password" id="pw" class="form-control" />
<label for="pw" class="form-label">암호</label>
</div>
<div class="form-floating mb-2">
<input type="password" id="pw1" class="form-control" />
<label for="pw1" class="form-label">암호 확인</label>
</div>
<div class="form-floating mb-2">
<input type="text" id="name" class="form-control" />
<label for="name" class="form-label">이름</label>
</div>
<div class="form-floating mb-2">
<input type="number" id="age" class="form-control" />
<label for="age" class="form-label">나이</label>
</div>
<div>
<input type="submit" value="회원가입" class="btn btn-primary" />
</div>
</div>
</div>
</div>
</div>
<script>
</script>
</body>
customer_join.jsp를 생성하면
고객용 회원가입창이 생성된다.
// 아이디 중복확인
@Select({
" SELECT COUNT(*) cnt FROM member m WHERE ID=#{id} "
})
public int selectMemberIDCheck(@Param("id") String id);
Mapper를 생성한다.
// 127.0.0.1:8080/web03/api/member/idcheck.json?id=중복확인 아이디
@WebServlet(urlPatterns = {"/api/member/idcheck.json"})
public class RestMemberIDCheckController extends HttpServlet {
private static final long serialVersionUID = 1L;
private Gson gson = new Gson(); // 라이브러리를 이용한 객체 생성
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 전달받는 문자로 된 페이지 정보
String id = request.getParameter("id");
// 아이디 전달 => 존재하면 1 없으면 0 반환
int ret = MybatisContext.getSqlSession().getMapper(MemberMapper.class).selectMemberIDCheck(id);
response.setContentType("application/json");
Map<String, Object> map = new HashMap<>();
map.put("ret", ret);
String jsonString = gson.toJson(map);
PrintWriter out = response.getWriter();
out.print(jsonString);
out.flush();
}
}
RestMemberIDCheckController.java를 생성한다.
postman에서 확인해보자.
존재하는 아이디면 1이 나오고
존재하지 않는 아이디면 0이 나온다.
이제 추가해보자.
<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>
...
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.3.5/axios.min.js"></script>
<script>
async function ajaxIDCheck(e){
console.log(e.value);
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 = '사용불가';
}
else if(data.ret === 0){
// 사용가능
document.getElementById("lbl_check").innerText = '사용가능';
}
}
else{
document.getElementById("lbl_check").innerText = '아이디';
}
}
</script>
customer_join.jsp의 아이디 창에 id, onkeyup을 추가하고 script, function을 작성한다
아이디창에 입력해보자.
asdf를 순서대로 입력하였더니 a, as, asd, asdf 키보드를 뗄 때마다 콘솔에 출력이 되는 모습을 볼 수 있다.
아이디가 중복되지 않으니 사용가능 글자가 적혀있다.
이미 존재하는 아이디인 1을 입력하자 사용불가로 변하게 된다.