상품관리 프로젝트 코드 작성 -4
상품관리 예제 코드 작성 순서
7강) 상품관리 프로젝트 코드 작성 -1 (상품 테이블, 파일업로드 테스트)
1. jsp페이지 및 리소스 파일 넣고 servlet-context에 등록, url 매핑 : include / images ...
2. pom에 파일업로드, 썸네일 라이브러리 등록
3. 등록한 라이브러리에서 사용할 클래스를 servlet-context에 빈으로 등록
4. UploadController.java
5. 파일 업로드 폼.jsp
6. 업로드 결과.jsp
-----------------------------------------------------------------------------------------------------
8강 ) 상품관리 프로젝트 코드 작성 -2 ( 상품목록, 상세화면 )
7. 사용자 페이지
: productDTO , DAO > Mapper(sample매퍼 사용) > Service > Controller 작성
/ 상품 목록jsp
-----------------------------------------------------------------------------------------------------
9강) 상품관리 프로젝트 코드 작성 -3
8. 로그인 페이지, 로그아웃
: Member DTO , DAO > Mapper(sample매퍼 사용) > Service > Controller 작성
9. 장바구니 (cart 테이블 )
: Cart DTO , DAO > Mapper(sample매퍼 사용) > Service > Controller 작성
-----------------------------------------------------------------------------------------------------
10강) 상품관리 프로젝트 코드 작성 -4
10. 관리자 로그인/ 상품 등록, 수정, 삭제 (admin테이블 )
: Admin DAO > Mapper(sample매퍼 사용) > Service > Controller 작성
관리자 페이지, 관리자 로그인 페이지, 관리자 메뉴 페이지.jsp
ProductController에 만들어둔 insert.do / url맵핑된 메서드 작성
관리자 로그인
상품관리_관리자.sql
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | create table admin( userid varchar2(50) not null, passwd varchar2(50) not null, name varchar2(50) not null, email varchar2(100), join_date date default sysdate, primary key(userid) ); insert into admin(userid, passwd, name) values ('admin', '1234', '관리자'); select * from admin; commit; |
admin 테이블을 생성하는데 MemberDTO와 같은 구성이므로 데이터 맵핑 타입은 MemberDTO로 한다.
private String userid;
private String passwd;
private String name;
private String email;
private Date join_date;
AdminDAO.java
1 2 3 4 5 6 7 8 9 10 | package com.example.spring02test.model.admin; import com.example.spring02test.model.member.DTO.MemberDTO; public interface AdminDAO { //MemberDAO와 다를게 없음, 매퍼에서 접근하는 테이블명만 다르다. public String login_check(MemberDTO dto); } | cs |
AdminDAOImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package com.example.spring02test.model.admin; import javax.inject.Inject; import org.apache.ibatis.session.SqlSession; import com.example.spring02test.model.member.DTO.MemberDTO; @Repository public class AdminDAOImpl implements AdminDAO { @Inject SqlSession session; @Override public String login_check(MemberDTO dto) { return session.selectOne("admin.login_check", dto); } } | cs |
AdminService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 | package com.example.spring02test.service.admin; import com.example.spring02test.model.member.DTO.MemberDTO; public interface AdminService { //Member 로그인 데이터 처리할 때는 서비스에서 세션 객체 데이터 처리하던데 //Admin 로그인할때 세션객체 처리는 컨트롤러에서 다 하는듯함 (왜 방식을 통일하지 않은건지...) //logout도 db에 접속할 필요 없이 세션만 초기화해주면 되는거라 //세션객체 데이터 처리를 컨트롤러에서 하는거면 로그아웃 메서드도 컨트롤러에만 있으면 된다. public String login_check(MemberDTO dto); } | cs |
AdminServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.example.spring02test.service.admin; import javax.inject.Inject; import org.springframework.stereotype.Service; import com.example.spring02test.model.admin.AdminDAO; import com.example.spring02test.model.member.DTO.MemberDTO; @Service public class AdminServiceImpl implements AdminService { @Inject AdminDAO adminDao; @Override public String login_check(MemberDTO dto) { return adminDao.login_check(dto); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | package com.example.spring02test.controller.admin; import javax.inject.Inject; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.example.spring02test.model.member.DTO.MemberDTO; import com.example.spring02test.service.admin.AdminService; @Controller @RequestMapping("/admin/*") public class AdminController { @Inject AdminService adminService; //로그인창으로 넘겨주는 메서드 @RequestMapping("login.do") public String login() { return "admin/login"; } //로그인 시도 시 실행 @RequestMapping("login_check.do") public ModelAndView login_check( MemberDTO dto, HttpSession session, ModelAndView mav) { String name = adminService.login_check(dto); if(name != null) { //로그인 성공시 //로그인 성공시에 세션에 로그인 정보를 담아야한다. //기껏 세션 객체 파라미터 자리에 위치시켜놓고 안쓰면 안된다. //관리자 계정의 아이디, 이름 저장 session.setAttribute("admin_userid", dto.getUserid()); session.setAttribute("admmin_name", dto.getName()); mav.setViewName("admin/admin"); mav.addObject("message", "success"); return mav; } mav.setViewName("admin/login"); mav.addObject("message", "error"); //error와 success로 로그인 성공여부 알아내어 c:if 사용할 예정 return mav; } //관리자 로그아웃 처리 @RequestMapping("logout.do") public String logout(HttpSession session) { session.invalidate();//세션 무효화 return "redirect:/admin/login.do"; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <%@ include file="../include/header.jsp" %> </head> <body> <%@ include file="../include/admin_menu.jsp" %> <c:if test="${message =='success' }"> <h2> ${sessionScope.admin_name } ${sessionScope.admin_user_id }님 환영합니다. </h2> </c:if> </body> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <%@ include file="../include/header.jsp" %> <script> $(function(){ $("#btnLogin").click(function(){ var userid = $("#userid").val(); var passwd = $("#passwd").val(); if(userid==""){ alert("아이디를 입력하세요"); $("#userid").focus(); return; } if(passwd==""){ alert("비밀번호를 입력하세요"); $("#passwd").focus(); return; } //form에 action이 설정돼있지 않고, submit도 없다. //button은 폼데이터를 다른 페이지로 넘기는 기능이 없으므로 //자바스크립트 함수를 이용해 넘기는데, //이 때, 자바스크립트에서 html의 기능을 구현해주기도하는 //document 객체를 사용한다. document.form1.action="${path}/admin/login_check.do" document.form1.submit(); }); }); </script> </head> <body> <%@ include file="../include/menu.jsp" %> <h2>관리자 로그인</h2> <form name="form1" method="post"> <table border="1" method="post"> <tr> <td>아이디 </td> <!-- type안쓰면 기본값은 type="text"--> <td> <input id="userid" name="userid"> </td> </tr> <tr> <td> <input type="password" id="passwd" name="passwd"> </td> </tr> <tr> <td colspan="2" align="center"> <button type="button" id="btnLogin" > 로그인 </button> <c:if test="${param.message == 'nologin'}"> <div style="color:red"> 로그인 하세요. </div> </c:if> <c:if test="${message=='error'}"> <div style="color:red"> 아이디와 비밀번호를 확인해주세요. </div> </c:if> <c:if test="${message=='logout'}"> <div style="color:red"> 로그아웃 되었습니다. </div> </c:if> </td> </tr> </table> </form> </body> </html> |
- 표현식으로 attribute / parameter 등을 JSP파일에서 출력할 용도로 사용하는 언어
- attribute는 $[ atribute 이름 ]으로 출력
- 파라미터는 ${param.이름} 또는 ${ paramValue.이름[인덱스] }의 형태로 출력
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <a href="${path}/shop/product/list.do">상품목록</a> <a href="${path}/shop/product/write.do">상품등록</a> <c:choose> <c:when test="${sessionScope.admin_userid == null }"> <a href="${path}/admin/login.do">관리자 로그인</a> </c:when> <c:otherwise> ${sessionScope.admin_name}님이 로그인중입니다. <a href ="${path}/admin/logout.do">로그아웃</a> </c:otherwise> </c:choose> <hr> |
1 2 3 4 5 | <!-- 개발디렉토리에 있는 데이터를 톰캣이 배포디렉토리에 카피한다. --> <!-- 배포 디렉토리(실제 경로) 확인 ★★★--> <!--application (javax.servlet.ServletContext ) : 웹 어플리케이션 Context의 정보를 저장하고 있는 객체 --> <%=application.getRealPath("/") %> | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <%@ include file="../include/header.jsp" %> <script> $(function(){ $("#btnAdd").click(function(){ loation.href="${path}/shop/product/write.do"; }); }); /* Add버튼을 누르면 write.do 실행하는 함수 */ </script> </head> <body> <%@ include file="../include/menu.jsp" %> <h2>상품 목록</h2> <button type="button" id="btnAdd"> 상품 등록 </button> <table border="1" width="500px"> <tr> <th> 상품ID</th> <th> </th> <th>상품명</th> <th>가격</th> </tr> <!-- list(ProductDTO)의 원소 변수 row 선언--> <c:forEach var="row" items="${list}"> <tr align="center"> <td>${row.product_id}</td> <td> <img src="${path}/images/${row.picture_url}" width="100" height="100"> </td> <td> <a href="${path}/shop/product/detail/${row.product_id}"> ${row.product_name}</a> <!-- 관리자에게만 편집 버튼 표시 --> <c:if test="${sessionScope.admin_userid != null }"> <br> <a href="${path}/shop/product/edit/${row.product_id}"> [편집]</a> </c:if> </td> <td> <fmt:formatNumber value="${row.price}" pattern="#,###"/> </td> </tr> </c:forEach> </table> </body> </html> | cs |
MultipartFile 인터페이스에서 많이 쓰이는 메소드들
메 소 드 | 내 용 |
String getName() | 파라미터 이름 |
String getOriginalFilename() | 파일 이름 |
boolean isEmpty() | 파일이 존재하지 않으면 true 반환 |
long getSize() | 파일 크기 |
byte[] getBytes() throws IOException | 파일 데이터 |
InputStream getInputStream() throws IOException | 파일 데이터를 읽어오는 InputStream을 얻어온다 사용이 끝난 후에는 알아서 잘 종료 해줄 것 |
void transferTo(File file) throws IOException | 파일 데이터를 지정한 file로 저장 |
출처: https://ggoreb.tistory.com/73 [나는 초보다]
1 2 3 4 | @RequestMapping("write.do") public String write() { return "shop/product_write"; }//데이터처리 없이 글쓰기 페이지로 포워딩 | cs |
[네이버 지식백과] 웹에디터 [Web Editer] (매일경제, 매경닷컴)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!-- views/shop/product_write.jsp --> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <%@ include file="../include/header.jsp" %> <!-- ckeditor 사용을 위해 js 파일 연결 --> <script src="${path}/ckeditor/ckeditor.js"></script> </head> <body> <%@ include file="../include/admin_menu.jsp" %> <script> function product_write(){ // 태그를 name으로 조회할 경우 //var product_name=document.form1.product_name.value; // 태그를 id로 조회할 경우 var product_name=$("#product_name").val(); var price=$("#price").val(); var description=$("#description").val(); if(product_name==""){ //빈값이면 alert("상품이름을 입력하세요"); $("#product_name").focus(); //입력포커스 이동 return; //함수 종료, 폼 데이터를 제출하지 않음 } if(price==""){ alert("가격을 입력하세요"); $("#price").focus(); return; } /* if(description==""){ alert("상품 설명을 입력하세요"); $("#description").focus(); return; } */ //폼 데이터를 받을 주소 document.form1.action="${path}/shop/product/insert.do"; //폼 데이터를 서버에 전송 document.form1.submit(); } </script> <h2>상품 등록</h2> <form name="form1" method="post" enctype="multipart/form-data"> <table> <tr> <td>상품명</td> <td><input name="product_name" id="product_name"></td> </tr> <tr> <td>가격</td> <td><input name="price" id="price"></td> </tr> <tr> <td>상품설명</td> <td><textarea rows="5" cols="60" name="description" id="description"></textarea> <script> //id가 description인 태그에 ckeditor를 적용시킴 //CKEDITOR.replace("description"); //이미지 업로드 안됨 CKEDITOR.replace("description",{ filebrowserUploadUrl : "${path}/imageUpload.do" }); </script> </td> </tr> <tr> <td>상품이미지</td> <td> <input type="file" name="file1" id="file1"> </td> </tr> <tr> <td colspan="2" align="center"> <input type="button" value="등록" onclick="javascript:product_write()"> <input type="button" value="목록" onclick="location.href='${path}/shop/product/list.do'"> </td> </tr> </table> </form> </body> </html> | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | //상품 등록 @RequestMapping("insert.do") public String insertProduct(ProductDTO dto) { //새로운 첨부파일이 있으면 //경로 변수에 배포디렉토리를 등록하고 //배포 디렉토리 확인 : 앞부분은 <%=application.getRealPath("/") %> //프로젝트 단위 이하 파일 경로는 같다 //File객체로 배포디렉토리가 존재하지 않을 시 디렉토리 생성하는 함수 호출 //임시 디렉토리에 저장된 첨부파일을 이동??? // //인강에 자세한 내용은 X String filename=""; //file1은 dto에 만들어둔 파일을 다루는 객체 필드 //이 객체가 비어있지 않다면 //== 파일객체(임시디렉토리)에 저장된 첨부파일을 배포디렉토리로 이동? if(!dto.getFile1().isEmpty()) { //첨부 파일의 이름 filename=dto.getFile1().getOriginalFilename(); //파일, 디렉토리 다룰땐 예외처리 필수 try { String path="D:\\work\\.metadata\\.plugins\\" + "org.eclipse.wst.server.core\\tmp1\\wtpwebapps\\" + "spring02\\WEB-INF\\views\\images\\"; //디렉토리가 존재하지 않으면 생성 new File(path).mkdir(); //파일객체에 저장된 (임시 디렉토리에 저장된) 첨부파일을 이동 //디렉토리를 생성했으니 new File(경로 + 파일이름)으로 파일을 생성하고 // (MultipartFile)file객체의 //transferTo(데이터 붙여넣기 될 파일)메서드를 사용하여 파일 복사 dto.getFile1().transferTo(new File(path+filename)); } catch (Exception e) { e.printStackTrace(); } } //picture_url에는 파일 이름이 들어간다. dto.setPicture_url(filename);//String타입 //여기까지 updateProduct와 똑같다. //updatProduct는 상품 정보 수정시 새로 첨부된 파일이 없으면 //else문을 통해 기존에 있던 파일을 file 객체에 저장한다. //insertProduct이므로 file 객체가 비어있으면 아무 처리도 하지 않는다. productService.insertProduct(dto); return "redirect:/shop/product/list.do"; } | cs |
1 2 3 4 5 6 7 8 9 10 11 | // 상품 디테일 정보 불러와서 수정 @RequestMapping("edit/{product_id}") public ModelAndView edit( @PathVariable("product_id") int product_id, ModelAndView mav) { mav.setViewName("shop/product_edit"); mav.addObject("dto", productService.detailProduct(product_id)); return mav; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | //상품 정보 수정 @RequestMapping("update.do") public String updateProduct(ProductDTO dto) { //새로운 첨부파일이 있으면 //경로 변수에 배포디렉토리를 등록하고 //배포 디렉토리 확인 : 앞부분은 <%=application.getRealPath("/") %> //프로젝트 단위 이하 파일 경로는 같다 //File객체로 배포디렉토리가 존재하지 않을 시 디렉토리 생성하는 함수 호출 //임시 디렉토리에 저장된 첨부파일을 이동??? // //인강에 자세한 내용은 X String filename=""; //file1은 dto에 만들어둔 파일을 다루는 객체 필드 //이 객체가 비어있지 않다면 //== 파일객체(임시디렉토리)에 저장된 첨부파일을 배포디렉토리로 이동? if(!dto.getFile1().isEmpty()) { //첨부 파일의 이름 filename=dto.getFile1().getOriginalFilename(); //파일, 디렉토리 다룰땐 예외처리 필수 try { String path="D:\\work\\.metadata\\.plugins\\" + "org.eclipse.wst.server.core\\tmp1\\wtpwebapps\\" + "spring02\\WEB-INF\\views\\images\\"; //디렉토리가 존재하지 않으면 생성 new File(path).mkdir(); //파일객체에 저장된 (임시 디렉토리에 저장된) 첨부파일을 이동 //디렉토리를 생성했으니 new File(경로 + 파일이름)으로 파일을 생성하고 // (MultipartFile)file객체의 //transferTo(데이터 붙여넣기 될 파일)메서드를 사용하여 파일 복사 dto.getFile1().transferTo(new File(path+filename)); } catch (Exception e) { e.printStackTrace(); } //picture_url에는 파일 이름이 들어간다. dto.setPicture_url(filename);//String타입 } else { //(상품)"새로운" 첨부파일이 없을때 //기존에 첨부한 파일 정보를 가져와서 ProductDTO dto2 = productService.detailProduct(dto.getProduct_id()); //저장 dto.setPicture_url(dto2.getPicture_url()); } productService.updateProduct(dto); return "redirect:/shop/product/list.do"; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | //상품 삭제 //@RequestParam은 폼의 개별값, //@ModelAtrribute는 폼의 전체 데이터(dto) 받아올 때 사용 @RequestMapping("delete.do") public String delete(@RequestParam int product_id) { //첨부파일 삭제 String filename = productService.fileInfo(product_id); System.out.println("첨부파일 이름 : " +filename); if(filename != null && !filename.equals("")) { String path = "D:\\work\\.metadata\\.plugins\\org.eclipse.wst.server.core" + "\\tmp1\\wtpwebapps\\spring02\\WEB-INF\\views\\images\\"; //상품이미지 디렉토리 File f = new File(path+filename); System.out.println("파일존재여부 :" + f.exists()); if(f.exists()) { f.delete(); System.out.println("삭제되었습니다."); } } //레코드 삭제 productService.deletePrduct(product_id); //화면 이동 return "redirect:/shop/product/list.do"; } |