상품관리 (관리자용 상품등록/수정/삭제)

Back-End/Spring 2019. 6. 18. 18:18
728x90
반응형

- 관리자용 상품등록 / 수정 / 삭제 기능 구현 -

(관리자로 로그인한 상태에서만 가능)



-상품등록-


admin_menu.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!-- jstl을 사용하기 위한 c태그 -->
<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<!-- 세션에 들어있는 관리자 id가 null값이면 로그인 페이지로 이동함 -->
</c:when>

<c:otherwise>
        ${sessionScope.admin_name}님이 로그인중입니다.
        <a href="${path}/admin/logout.do">로그아웃</a<!-- 로그인 중이면 로그아웃 페이지를 출력함) -->
    </c:otherwise>

</c:choose>  
<hr>
cs



product_write.jsp (상품 등록)

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
<%@ 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>
    //상품을 추가하기위한 정보를 담아 insert.do로 보내는 자바스크립트 함수
    function product_write() {
 
        var product_name = document.form1.product_name.value; // document는 웹페이지에 접근하기위한 객체.. form1에 있는 상품이름을 반환해서 name에 저장함
        var price = document.form1.price.value; // document는페이지에 접근하기위한 객체.. form1에 있는 상품의 값을 반환해서 price에 저장함
        var description = document.form1.description.value; // document는페이지에 접근하기위한 객체.. form1에 있는 상품의 정보를 반환해서 description에 저장함
        
        //document.form.은 폼페이지에 있는 값을 반환한다는 뜻.
 
        if (product_name == "") { //상품 이름이 입력되어 있지 않으면
            alert("상품명을 입력하세요");
            document.form1.product_name.focus(); //form1페이지에 있는 "상품명을 입력하세요" 에 커서를 올려둔다.
            return;
        }
        if (price == "") { //상품가격이 입력되어 있지 않으면
            alert("가격을 입력하세요");
            document.form1.price.focus(); //form1페이지에 있는 "가격을 입력하세요" 에 커서를 올려둔다.
            return;
        }
        if (description == "") { //상품설명이 입력되어 있지 않으면
            alert("상품설명을 입력하세요");
            document.form1.description.focus(); //form1페이지에 있는 "상품설명을 입력하세요" 에 커서를 올려둔다.
            return;
        }
  // input 태그를 마우스로 클릭하여 입력상태로 만든것을 포커스를 얻었다고 한다.
// 그리고 입력상태를 떠난 것을 포커스가 벗어났다고 한다.

        document.form1.action = "${path}/shop/product/insert.do"//insert.do 페이지로 form1에 저장된 자료를 전송함
        document.form1.submit();
    }
</script>
</head>
<body>
<%@ include file="../include/admin_menu.jsp"%>
     <!-- 관리자용 메뉴는 일반 회원의 메뉴와 다르기 때문에 일부러 관리자용 메뉴를 만들고 그 메뉴를 출력한다. -->
    <h2>상품 등록</h2>
    <form id="form1" name="form1" method="post"
        enctype="multipart/form-data">
        <!-- 파일업로드를 위해 추가하는 타입 -->
 
        <table>
            <tr>
                <td>상품명</td>
                <td><input name="product_name"></td>
            </tr>
            <tr>
                <td>가격</td>
                <td><input name="price"></td>
            </tr>
            <tr>
                <td>상품설명</td>
                <td><textarea rows="5" cols="60" name="description"
                        id="description"></textarea></td>
            </tr>
            <tr>
                <td>상품이미지</td>
                <td><input type="file" name="file1"></td>
            </tr>
            <tr>
 
                <td colspan="2" align="center"><input type="button" value="등록"
                    onclick="product_write()"<!-- "등록" 버튼을 누르면 위쪽에 있는 스크립트문에서 product_write()함수가 호출되서 실행되 insert.do페이지로 자료를 전송한다. -->
                    <input type="button" value="목록"
                    onclick="location.href='${path}/admin/product/list.do'"<!-- "목록 버튼을 누르면 list.do페이지로 이동" -->
                </td>
            </tr>
        </table>
    </form>
</body>
</html>
 cs



ProductController.java

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
    
//상품을 추가하는 메소드
    @RequestMapping("write.do")
    public String write() {
        return "shop/product_write";
    }

====================================================================================================================
    
//관리자 페이지에서 맵핑된 메소드
    //첨부파일을 추가하는 메소드 (그러니까 과일의 사진을 추가)
    @RequestMapping("insert.do")
    public String insert(ProductDTO dto) {
        String filename="-";
        if(!dto.getFile1().isEmpty()) { //첨부파일이 존재하면 (isEmpty()는 빈공간이라는 뜻인데 !가 붙었으므로 첨부파일이 존재하면..이라는 뜻)
            filename=dto.getFile1().getOriginalFilename(); //dto에 저장된 서버상에 업로드된 파일명을 반환해서 filename변수에 저장한다.
             String path="D:\\work\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp1\\wtpwebapps\\spring02\\WEB-INF\\views\\images\\"//이미지 파일이 저장된 경로를 지정
           //개발디렉토리가 아니라 곧바로 배포디렉토리로 설정하였다. //개발디렉토리에서 앞부분을 자르고(d:workspring02 까지), 그 부분에 배포디렉토리를 붙여넣으면 된다.
//이렇게 하지 않으면 이미지를 추가했을때 개발 디렉토리와 배포 디렉토리가 다르기 때문에 일일히 새로고침을 해주어야 한다.
이클립스에서는 개발을 할때는 워크스페이스 (개발디렉토리) 에서 개발한 코드를
톰캣에서 카피해서 배포 디렉토리에 배포를 한다. (카피를 할때 새로고침을 해야한다)


개발 디렉토리

d:workspring02


배포 디렉토리

D:work.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebappsdd\spring02
            //파일업로드시에는 예외처리를 해주어야 한다.
            try {
                new File(path).mkdir(); //새로운 파일의 경로를 생성하고 해당 경로에 폴더를 만든다.
                dto.getFile1().transferTo(new File(path+filename));  //생성한 디렉터리에 파일을 저장한다. (dto에 저장한다는 뜻)
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        dto.setPicture_url(filename); //첨부파일을 dto에 저장
        productService.insertProduct(dto); //서비스에 dto에 있는 과일 이미지 사진을 저장함
        return "redirect:/shop/product/list.do"//파일이 첨부되면 list페이지로 되돌아간다.
    }

cs



ProductServiceImpl.java 중 일부

1
2
3
4
    @Override
    public void insertProduct(ProductDTO dto) {
        productDao.insertProduct(dto);
    }
cs



ProductDAOImpl.java 중 일부

1
2
3
4
    @Override
    public void insertProduct(ProductDTO dto) {
        sqlSession.insert("product.insert", dto);
    }
cs



productMapper.java 중 일부

1
2
3
4
5
    <insert id="insert">
        insert into product values 
        (seq_product.nextval, #{product_name}, #{price}, 
        #{description}, #{picture_url} )
//seq_product.nextval은 상품코드를 시퀀스를 이용해서 발급하는 것.
//그러니까 숫자가 하나씩 올라간다는 뜻.
    </insert>
cs





-상품수정-


상품 수정을 할때는 url에 상품id(숫자)를 넘겨서 @PathVariable로 받을 예정


product_list.jsp 중 일부 (편집버튼 추가)

1
2
3
4
<c:if test = "${sessionScope.admin_userid != null}">
<br>
<a href="${path }/shop/product/edit/${row.product_id}">[편집]</a>
</c:if>
cs



ProductController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    
//상품정보 편집 페이지로 이동하고 데이터를 보내주도록하는 메소드
    //상품의 아이디를 맵핑해서..
    @RequestMapping("edit/{product_id}")
    public ModelAndView edit(@PathVariable("product_id") int product_id, ModelAndView mav) 
    {    
        //다른페이지에서  pathvariable로 받은 product_id를 product_id에 저장하고,
        //데이터를 보내고, 페이지를 이동하기위해서 ModelAndView 타입을 사용한다.
        
        mav.setViewName("/shop/product_edit"); //이동할 페이지의 이름
        //전달할 데이터를 저장
        mav.addObject("dto", productService.detailProduct(product_id)); //서비스로부터 상품 id(번호)를 받아와서 mav에 저장
        return mav; //페이지 이동
        
    }
    
cs



ProductService.java 중 일부

1
2
3
4
    @Override
    public ProductDTO detailProduct(int product_id) {
        return productDao.detailProduct(product_id); //
    }
cs



ProductDAOImpl.java 중 일부

1
2
3
4
5
6
    @Override
    public ProductDTO detailProduct(int product_id) {
        return sqlSession.selectOne(
                "product.detail_product", product_id);
    }
 
cs



product_edit.jsp

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>
    //상품을 갱신하는 함수
    //컨트롤러의 update.do로 맵핑된다.
    function product_update() {
        document.form1.action = "${path}/shop/product/update.do";
        document.form1.submit();
    }
 
    //상품을 삭제하는 함수
    //컨트롤러의 delete.do로 맵핑된다.
    function product_delete() {
        if (confirm("삭제하시겠습니까?")) {
            document.form1.action = "${path}/shop/product/delete.do";
            document.form1.submit();
        }
    }
</script>
</head>
<body>
    <%@ include file="../include/admin_menu.jsp"%>
    <h2>상품 정보 편집</h2>
    <form id="form1" name="form1" method="post"
        enctype="multipart/form-data">
        <!-- 파일 업로드를 하기위한 타입, 필수로 작성해야 한다.-->
        <table>
            <!-- 관리자로그인을 한 후에 들어갈 수 있는 상품정보 편집정보 -->
            <!-- 해당되는 자료들은 dto에서 가져와서 보여준다. -->
            <tr>
                <td>상품명</td>
                <td><input name="product_name" value="${dto.product_name}"></td>
            </tr>
 
            <tr>
                <td>가격</td>
                <td><input name="price" type="number" value="${dto.price }"></td>
            </tr>
 
            <tr>
                <td>상품설명</td>
                <td><textarea rows="5" cols="60" name="description"
                        id="description">${dto.description }</textarea></td>
            </tr>
        </table>
    </form>
</body>
</html>
cs



ProductController.java

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

//상품의 정보를 수정 (갱신) 할때 View에서 맵핑되는 메소드
    @RequestMapping("update.do")
    public String update(ProductDTO dto) {
        String filename = "-";
        
        if(!dto.getFile1().isEmpty()) { //첨부파일이 존재하면
            filename = dto.getFile1().getOriginalFilename();//dto에 저장된 서버상에 업로드된 파일명을 반환해서 filename변수에 저장한다.
            String path="D:\\work\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp1\\wtpwebapps\\spring02\\WEB-INF\\views\\images\\"
            //이미지 파일이 저장된 경로를 지정
            
            try {
                new File(path).mkdir(); //새로운 파일의 경로를 생성하고 해당 경로에 폴더를 만든다.
                dto.getFile1().transferTo(new File(path+filename)); //지정된 디렉토리로 카피하는 명령어
            } catch (Exception e) {     //생성한 디렉터리에 파일을 저장한다. (dto에 저장한다는 뜻)
                e.printStackTrace();
            }
            dto.setPicture_url(filename); //이미지의 경로
        }else {
            //새로운 첨부파일이 올라가지않고 기존에 있는 정보를 그대로 써야하는 경우
            //기존의 정보를 가져와서 dto2변수에 넣고, dto
            ProductDTO dto2= productService.detailProduct(dto.getProduct_id());
            dto.setPicture_url(dto2.getPicture_url());
        }
        
        productService.updateProduct(dto);
        return "redirect:/shop/product/list.do";
    }
cs



ProductServiceImpl.java 중 일부

1
2
3
4
    @Override
    public void updateProduct(ProductDTO dto) {
        productDao.updateProduct(dto);
    }
cs



ProductDAO.Impl.java 중 일부

1
2
3
4
    @Override
    public void updateProduct(ProductDTO dto) {
        sqlSession.update("Product.update_product",dto);
    }
cs



productMapper.xml 중 일부

1
2
3
4
5
6
7
8
9
<mapper namespace="product">
<update id = "update_product">
update product
set product_name = #{product_name},
    price=#{price}, description=#{description},
    picture_url=#{picture_url}
    where product_id=#{product_id}
    <!-- 상품 id와 맞는 상품의 가격, 설명, 사진을 갱신하는 쿼리문 -->
</update>
cs




-상품삭제-


상품을 삭제할때는 안에 상품안에 저장되어 있는 이미지파일도 같이 삭제하여야함.


product_edit.jsp에서 컨트롤러로 맵핑됨


ProductController.java 중 일부

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    
//상품 정보를 삭제할때 뷰 (product_edit.jsp)페이지와 매핑되는 메소드
    //상품 정보를 삭제할때는 그 정보 안에 담긴 이미지도 같이 삭제 해야 한다.
    @RequestMapping("delete.do")
    public String delete(@RequestParam int product_id) {     //RequestParam 어노테이션을 사용해서 상품의 id를 받아온다.
        String filename=productService.fileInfo(product_id)//fileaname변수에 파일을 삭제하기위해 서비스에서 상품의 id를 매개변수로 삼아 서비스에 저장한후 filename 변수에 저장
        if(filename != null && !filename.equals("-")) { //filename이 null값이 아니거나, filename안에 들어있는것이 아닌 것이 "-"와 같으면, (그러니까 filename에 값이 담겨있을 경우!!!!!)
            String path="D:\\work\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp1\\wtpwebapps\\spring02\\WEB-INF\\views\\images\\";
            //상품에 담겨있는 이미지도 같이 삭제해야하기 때문에 이미지 경로를 지정
            
            File f = new File(path+filename); //이미지 파일을 삭제하기 위해 (파일의 객체 (경로와 파일이 담겨있음)을 생성하고 변수 f에 저장)
            
            if(f.exists()) { 
                //exists()메소드는 유효성을 검사하는 메소드, 그러니까 값이 존재하는지 안하는지 판단하는 메소드이다.
                //f안에 이미지 파일과 경로가 존재한다면, delete()메소드로 변수 f안에 있는 이미지파일과 경로를 제거 (즉 파일을 제거)
                f.delete();
            }
        }
        productService.deleteProduct(product_id); //이미지를 삭제한 후에 나머지 (가격 등등) 자료들도 삭제하기 위해 서비스에 id를 매개변수로 줘서 저장(삭제함)
        return "redirect:/shop/product/list.do"//최신화 한 후에 list.jsp로 redirect한다.
                
    }
cs



먼저 저장되어 있는 이미지를 삭제하기 위해서 서비스 => DAO => Mapper을 거쳐서 다시 컨트롤러로 이동하고 저장된 이미지를 filename변수에 저장


ProductServiceImpl.java 중 일부

1
2
3
4
5
    @Override
    public String fileInfo(int product_id) {
        
        return productDao.fileInfo(product_id);
    }
cs



ProductDAOImpl.java 중 일부

1
2
3
4
    @Override
    public String fileInfo(int product_id) {
        return sqlSession.selectOne("product.file_info",product_id);
    }
cs



productMapper.xml 중 일부 

1
2
3
4
5
6
<mapper namespace="product">
<select id = "file_info" resultType="String">
    select picture_url from product
    where product_id=#{product_id}
    <!-- product테이블안에 있는 입력된 id에 해당하는 이미지를 검색하는 쿼리문  -->
</select>
</mapper>
cs



============== 이미지를 삭제한 후에 나머지 자료들을 삭제하기 위해 서비스를 호출해서 매개값(id)를 줘서 자료를 삭제 ===========



ProductServiceImpl.java 중 일부

1
2
3
4
    @Override
    public void deleteProduct(int product_id) {
        productDao.deleteProduct(product_id);
    }
cs



ProductDAOImpl.java 중 일부

1
2
3
4
5
    @Override
    public void deleteProduct(int product_id) {
        sqlSession.delete("product.product_delete",product_id);
 
    }
cs



productMapper.xml 중 일부

1
2
3
4
5
<mapper namespace="product">
<delete id = "product_delete">
    delete from product where product_id=#{product_id}
    <!-- product테이블안에 있는 상품번호가 ?인 객체를 삭제하는 쿼리문 -->    
</delete>
cs


728x90
반응형
: