본문 바로가기
Spring/study

상품관리 프로젝트 코드 작성 -1

by avvin 2019. 6. 13.

상품관리 프로젝트 코드 작성하기  



상품관리 프로젝트 페이지 구성


쇼핑몰 페이지


자바파일


Controller


HomeController 

: home.jsp를 실행하기 위해 경유하는 컨트롤러 / 시간 정보 담아서 home.jsp  실행

MemberController

 : 로그인, 로그인 체크, 로그아웃, 

UploadController

 : 업로드폼으로 포워딩, 폼데이터 업로드, 업로드 함수

CartController

 : cart테이블 저장, cart 리스트 반환, 품목 삭제, 전체 삭제, 업데이트??<<

ProductController

 : 상품 목록, 상품 상세보기, 상품 등록 페이지로 포워딩, 등록시 상품목록페이지로 포워

AdminController

 : 관리자 로그인창으로 포워딩, 로그인 체크,  

   관리자 로그아웃처리하고 관리자로그인페이지로 포워딩  



Model


MemberDAO + Impl

MemberDTO

 : userid / passwd / name / email / join_date


CartDAO +Impl

CartDTO

 : cart_id / userid / name / product_id / product_name / price / money / amount 


ProductDAO + Impl

ProductDTO

 : product_id / product_name / price / description / picture_url / file1



Service


MemberService + Impl

CartService + Impl
ProductService + Impl

AdminService + Impl




설정파일


Mapper ( namespace로 구분 ) ★


memberMapper.xml 

 : 로그인 체크 쿼리

adminMapper.xml

 :  관리자 로그인 체크 쿼리  

cartMapper.xml

 : 장바구니 담기, 장바구니 리스트, 개별상품 삭제, 전체 삭제 쿼리  

productMapper.xml

 : 상품 리스트, 상품 상세, 상품 추가 쿼리  



기본 설정 파일  


web.xml 

 : root-context.xml, servlet-context.xml 로딩


root-context.xml

 : mybatis 객체 빈으로 등록시 Mappers.xml 스캔


servlet-context.xml

 : include나 image폴더 리소스 매핑 설정 / 업로드 경로 리소스 빈으로 등록 /

   파일 업로드에 필요한 클래스 빈으로 등록 / 컴포넌트 스캔 / 뷰로 포워딩시 pre,suffix 설정


pom.xml



//mybatis mapper 코드는 어디에?<<


views 파일 ( .jsp )


include 파일 : header / menu / admin_menu / style.css 

memberLogin / cart_list / product_detail / product_list / product_write / uploadForm / uploadResult

admin / a
dminLogin




상품관리 예제 코드 작성 순서 

 

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 DTO , DAO > Mapper(sample매퍼 사용) > Service > Controller 작성

    관리자 로그인 페이지, 관리자 메뉴 페이지.jsp




코드 작성 전 설정해야 부분

sample이나 spring01에서 프로젝트에서 파일 복사해올때 수정해야할 부분


pom.xml reference부터만 복사해오기 


web.xml 한글 인코딩 처리


servelt-context 컴포넌트 스캔 패키지 spring02로 수정


mapper 패키지의 log4j.xml 애플리케이션 로거 컨트롤러경로에서 프로젝트 이름 spring02로 수정


root-context.xml 에서 datasource bean부분 


id / password 수정

"jdbc:log4jdbc:oracle:thin@localhost:1521/xe"  // :xe 가 낮은버전에선 될수도있음


home.jsp 한글깨짐 처리해주는 코드 추가


root-context.xml 에 mybatis mapper interface bean을 자동으로 검색하여 생성해주는 코드 추가

<mybatis-spring:xcan base-package="com.example.spring02.model.memo">


( 프로젝트 서버로 실행할때 프로젝트 하나씩만 등록해놓는게 좋다. )


memo 테이블 만들기





1. 메인 페이지인 home.jsp와 include될 jsp파일 일부 작성


header.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
 
<!-- path 변수 선언, request객체가 가진 쿼리 문자열 반환된 값 저장-->
<c:set var="path" value="${pageContext.request.contextPath}" />
 
<!--자바스크립트 라이브러리인 jquery는 소스로 등록해놔야 사용 가능 -->
<script src="http://code.jquery.com/jquery-3.3.1.js"></script>
 
<!-- link : 외부 문서와 연결해주는 태그, 주로 css파일이나 폰트 관련 코드 연결해줌 -->
<link rel="stylesheet" href="${path}/include/style.css" />
cs


pageContext.request.contextPath : EL문에서 getContextPath() (현재 프로젝트 path 리턴하는 함수) 대신 사용  




menu.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
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
<!-- path value = ${pageContext.request.contextPath}
     header.jsp에서 코어태그로 변수 path 선언-->
<a href="${path}">Home</a>
<!-- 이전에 만들어뒀던 한줄메모장  -->
<a href="${path}/memo/list.do">한줄메모장</a>
<a href="${path }/upload/uploadForm">업로드 테스트</a>
<a href="${path }/shop/product/list.do">상품 목록</a>
 
<!-- admin_userid는 
     admin/login_check.do에서 넘어온 session에 저장된 정보-->
<c:if test="${sessionScope.admin_userid == 'admin'} ">
    <a href="${path }/shop/product/write.do">상품등록</a>
</c:if>
 
<a href="${path/shop/cart/list.do}">장바구니</a>
 
<div style="text-align : right;">
 
<c:choose>
<!-- 넘어온 session 데이터가 없어도(선언된 적 없는 변수여도) 
     dot써서 비교 가능한가봄 -->
    <c:when test="${sessionScope.userid == null }">
        <a href="${path}/member/login.do">로그인</a>
        <a href="${path}/admin/login.do">관리자 로그인</a>
    </c:when>
    <c:otherwise>
        ${sessionScope.name}님이 로그인중입니다.
        <a href="${path}/member/logout.do">로그아웃</a>
    </c:otherwise>
</c:choose>
</div>
<!--수평선 -->
<hr
 
cs



home.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
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Home</title>
<!-- jsp:액션태그 아니고 지시자 include -->
<%@include file="include/header.jsp" %>
</head>
<body>
<%@include file="include/menu.jsp" %>
<c:if test ="${sessionScope.userid != null }">
    <h2>
        ${sessionScope.name}(${sessionScope.userid})
        님의 방문을 환영합니다. 
    </h2>
</c:if>
<!-- HomeController.java에서 Model에 담겨 넘어오는 serverTime -->
<P>  The time on the server is ${serverTime}. </P>
 
<!-- 배포 디렉토리(실제 경로) 확인 ★★★-->
<!--application (javax.servlet.ServletContext )
    : 웹 어플리케이션 Context의 정보를 저장하고 있는 jsp내장객체   -->
<%=application.getRealPath("/") %>
</body>
</html>
 
cs



<%=application.getRealPath("/") %>

현재 프로젝트의 H/W 상의 실제 경로를 출력한다.

E:\SpringWorkspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\spring02\ 




2. pom에 파일업로드, 썸네일 라이브러리 등록


1
2
3
4
5
6
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
cs


1
2
3
4
5
6
7
        <!-- https://mvnrepository.com/artifact/org.imgscalr/imgscalr-lib -->
        <dependency>
            <groupId>org.imgscalr</groupId>
            <artifactId>imgscalr-lib</artifactId>
            <version>4.2</version>
        </dependency>
 
cs



3. servlet-context에 리소스 매핑 설정 / 파일업로드에 필요한 클래스를 빈으로 등록 ★★★


servlet-context 리소스 매핑 부분에  

include될 jsp파일과 images 리소스 매핑 (스프링에서 읽어들이도록)

1
2
3
4
    <resources location="/WEB-INF/views/include/"
        mapping="/include/**" />
    <resources location="/WEB-INF/views/images/"
        mapping="/images/**" />    
cs



파일 업로드 관련 설정 

파일 업로드 시 필요한 스프링 프레임워크 내장 클래스를 빈으로 등록

1
2
3
4
5
6
7
8
    <beans:bean id="multipartResolver"
     class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <beans:property name="maxUploadSize" value="10485760" />
    </beans:bean>
    <!-- 웹 상이 아닌  하드웨어상 디렉토리 설정 시 필요-->
    <beans:bean id="uploadPath" class="java.lang.String">
        <beans:constructor-arg value="d:/upload" />
    </beans:bean>
cs


org.springframework.web.multipart.commons.CommonsMultipartResolver

스프링프레임워크 파일업로드 관련 내장 객체, 스프링 내장객체여도 빈으로 등록을 해야한다. 




4 ~ 6. 파일업로드에 필요한 페이지 작성  


파일 업로드 관련 설정을 끝냈으니 업로드 관련 페이지 작성


menu.jsp의 업로드 테스트와 연결   //POST방식 명시하지 않았으므로 GET방식으로 넘어감.


1
<a href="${path }/upload/uploadForm">업로드 테스트</a>
cs



UploadController.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
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
91
package com.example.spring02test.controller.upload;
 
import java.io.File;
import java.util.UUID;
 
import javax.annotation.Resource;
 
import org.slf4j.Logger; // 하단의 로깅툴 설명 참고
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
 
@Controller
public class UploadController {
    //logger는 상수(전역변수)로 설정 
    private static final Logger logger =
            LoggerFactory.getLogger(UploadController.class);
    
    //servlet-context에 리소스로 등록한 uploadPath
    //매핑 등록한 리소스 주입받을때 쓰는 @Resource 어노테이션
    @Resource(name="uploadPath")
    //아래 파일 업로드하는 메서드에서 File 객체인 target 경로 설정시 사용됨
    String uploadPath//다른이름으로 변수 선언해도 된다.
    
    
    //POST 방식이라고 명시하지 않으면 폼데이터는 GET방식으로 넘어온다.
    //업로드 폼으로 포워딩해주는 메서드
    @RequestMapping(value="/upload/uploadForm",
            method = RequestMethod.GET)
    public void uploadFrom() {
    //GET방식으로 넘어올 땐 이 메서드 실행    
    //리턴값 없으므로 RequestMapping에 매핑된 url.jsp로 포워딩
    //upload/uploadForm.jsp로 포워딩
    }//menu.jsp에서 '업로드 테스트' 누르면 이 메서드 실행됨.(GET 방식)
    
    
    //POST 방식이라고 명시하지 않으면 폼데이터는 GET방식으로 넘어온다.
    //파일 올릴때 post방식 명시하여 이 메서드 실행
    @RequestMapping(value="/upload/uploadForm",
            method = RequestMethod.POST)
    public ModelAndView uploadFrom(
            MultipartFile file, ModelAndView mav)throws Exception {
        //파일을 올리면 MultipartFile 객체에 담긴다.
        logger.info("파일 이름 : " + file.getOriginalFilename());        
        logger.info("파일 크기 : " + file.getSize());
        //Content Type : 파일 종류??
        logger.info("컨텐트 타입 : " + file.getContentType());
    
        String savedName = file.getOriginalFileName();
        
        savedName = uploadFile(savedName, file.getBytes());
        //uploadFile()는 파일 이름 적절하게 바꿔서 저장하고 이름만 리턴해주는 메서드
        
        mav.setViewName("upload/uploadResult");
        mav.addObject("savedName", savedName);
        //uploadResult페이지에는 업로드된 파일 이름만 포워딩해주면 된다.
        return mav; //uploadResult.jsp로 포워딩
    }
    
    
    //파일 이름이 중복되지 않도록 처리
    //파일 원래 이름과 내용 매개값으로 받아옴
    private String uploadFile(String originalName, byte[] fileData
    throws Exception {
        //uuid 생성 (Universal Unique Identifier, 범용 고유 식별자)
        //java.util.UUID
        UUID uid = UUID.randomUUID();//클래스멤버
        //저장된 파일 이름 : uuid + _ + 
        //uuid타입이므로 toString() 처리해줘야함
        String savedName = uid.toString() + "_" + originalName;
        //java.io의 File 클래스 객체 생성하여 
        //매개값으로 업로드 경로와 저장할 이름 넣기
        File target = new File(uploadPath, savedName);
        
        //★★★
        //임시 디렉토리에 저장된 업로드된 파일을 지정된 디렉토리로 복사
        //FileCopyUtils.copy(바이트 배열, 파일 객체)
        //target은 uploadPath설정, 이름 설정 완료된 객체
        //fileData는 파일 내용
        //임시디렉토리가 어디...??아무튼 uploadPath에 파일 복사해주는 과정
        FileCopyUtils.copy(fileDatatarget);
 
        return savedName;
    }
 
}
 
cs


파일 종류? : 파일 어플리케이션 이름, 확장자 같은 파일 종류 정보인듯  



로깅툴  ('spring 3강 로깅, 데이터베이스(Oracle) 연결 테스트' 에 정리한 내용 )


1) 로깅툴을 사용하는 이유

- System.out.println()은 IO리소스를 많이 사용하여 시스템이 느려질 수 있음

- 로그를 파일로 저장하여 분석할 필요가 있음


2) 로깅툴의 종류


- commons-logging : 스프링3에서 사용하던 로깅툴


- log4j : 효율적인 메모리 관리로 그동안 많이 사용되었음


logback : log4j보다 성능이 우수하여 최근에 많이 사용되고 있음


  SLF4J : logback 사용을 위한 인터페이스




SLF4J 설정 방법 //sample 프로젝트에 이미 설정돼있음


1. pom.xml 의 slf4j-version을 1.7.25로 설정

2. pom.xml 에 라이브러리 추가

3. src/main/resouces에 있는 logback.xml 파일 작성 

4. 로그를 수집할 클래스에 변수 선언

5. 로그를 수집할 method에서 로그 수집 명령어 호출




uploadResult.jsp는 uploadForm.jsp의 iframe으로 들어가도록 함


아이프레임이란 내부 프레임(inline frame)이라는 의미로 하나의 HTML문서내에서 다른 HTML문서를 보여주고자 할때 사용합니다.

일반적인 프레임(frame)과 비교해보면 아이프레임은 <frameset> 태그 사이에 올 필요가 없으며, 독립적으로 마치 <img> 태그를 사용하듯 문서 내의 

원하는 위치에 삽입할 수 있습니다.

아이프레임에서 사용할 수 있는 속성도 <img> 태그과 유사합니다.


출처 : http://www.homejjang.com/05/iframe.php




uploadForm.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
<%@ 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" %>
<style> /* uploadResult.jsp 표시할 부분 iframe으로 설정 */
iframe {
    width : 400px;
    height : 200px;
    border : 1px;
    border-style : solid;
}
</style>
</head>
<body>
<%@ include file="../include/menu.jsp" %>
 
<!--폼데이터 POST방식으로 보내기/
    enctype="multipart/form-data" ★★★
    target="iframe1"설정 해놓으면 데이터 처리 결과가 아래의 iframe1으로 간다.
    uploadFile 메서드는 업로드된 파일 이름만 리턴한다-->
<form id="form1" action="${path}upload/uploadForm" method="post"
enctype = "multipart/form-data" target="iframe1">
 
<!-- input type=file의 name값은 upload/uploadForm으로 url매핑된 메서드
     MultipartFile 매개값과 이름이 같아야함★★★ -->
<input type ="file" name ="file">
<input type ="submit" value="업로드">
</form>
 
<iframe name="iframe1"></iframe>
 
</body>
</html>
cs



<!-- input type=file의 name값은 upload/uploadForm으로 url매핑된 메서드
     MultipartFile 매개값과 이름이 같아야함★★★ -->
<input type ="file" name ="file">


UploadController.java


    @RequestMapping(value="/upload/uploadForm",
            method = RequestMethod.POST)
    public ModelAndView uploadFrom(
            MultipartFile file, ModelAndView mav)throws Exception {
        //파일을 올리면 MultipartFile 객체에 담긴다.



uploadResult.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"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<%@ include file="../include/header.jsp" %>
</head>
<body>
 
파일이 업로드 되었습니다.
파일명 : ${savedName}
 
</body>
</html>
cs



form 태그의 enctype  //인코딩 타입


파일을 업로드 할때 <form>태그에서 ENCTYPE="multipart/form-data"라는 애트리뷰트를 반드시 써야 한다.

 

그렇게 하지 않으면 웹 서버로 데이터를 넘길때 파일의 경로명만 전송되고 파일 내용이 전송되지 않기 때문이다.

 

그리고 이때 METHOD 애트리뷰트에는 'POST' 값을 지정해야 한다.

 

** <form>태그의 속성인 method, action, enctype 등은 입력받은 데이터를 어떻게 처리할 것인지 세부적으로 설정하는 데 사용된다.

  method는 전송 방식,

  action은 전송 목적지,

  enctype은 전송되는 데이터 형식을 설정한다.

 

 

** enctype

enctype 속성은 다음 세가지의 값으로 지정될 수 있다.

 

1. application/www-form-urlencoded

디폴트값이다. enctype을 따로 설정하지 않으면 이 값이 설정된다. 폼데이터는 서버로 전송되기 전에 URL-Encode 된다.

 

2. multipart/form-data

파일이나 이미지를 서버로 전송할 경우 이 방식을 사용한다.

 

3. text/plain

이 형식은 인코딩을 하지 않은 문자 상태로 전송한다.



출처: https://tibang.tistory.com/entry/form태그의-enctype-속성 [T없이맑은날]