Spring Boot와 MongoDB 연동 실습 (방명록)

Back-End/Spring 2019. 7. 10. 13:37

Spring Boot와 MongoDB 연동 해서 방명록 만들기





 

  

  -방명록 리스트-


  1. home.jsp에 include되어있는 menu.jsp에 있는 방명록 링크를 클릭.


  2. 클릭하면 guestbook.do url이 GuestbookController.java (컨트롤러로 넘어간다)


  3. guestbook.do와 맵핑되는 메소드에서는 다시 guestbook jsp페이지로 이동시킨다.


  4. guestbook.jsp에서는 gbList( ) 자바스크립트함수가 실행되서 컨트롤러에 gbList.do url과 맵핑된다.


  5. gbList.do와 맵핑된 메소드에선 Dao를 호출해 hashmap에 방명록리스트와, 방명록 글갯수를 gb_list로 리턴시킨다.


  6. gb_list에선 방명록에 적힌 게시물수, 이름, 날짜, 이메일, 등을 표시한다. 


  7. 결과적으로 guestbook.jsp (방명록목록) 페이지를 실행하면 gbList.do로 맵핑되어서 방명록 리스트를 가져온다.



  -방명록 글쓰기-


  1. guestbook.jsp 페이지에서 글쓰기 버튼을 누르면 컨트롤러에 gbWrite.to로 맵핑이 된다.


  2. gbWrite.do로 맵핑된 메소드에서는 다시 gb_write.jsp 페이지로 이동시킨다.


  3. gb_write.jsp페이지에서는 작성할 방명록 글 정보를 입력한 후 "확인" 버튼을 누르면 post방식으로 컨트롤러의 gbInsert.do url로 맵핑시킨다.


  4. gbInsert.do로 맵핑된 메소드에서는 mongoDB에 DTO에 담긴 레코드들을 추가해서 목록을 갱신시켜 guestbook.do로 맵핑시킨다.


  5. guestbook.do로 맵핑된 메소드에서는 guestbook.jsp 페이지로 이동시킨다.


  6. guestbook.jsp 페이지로 이동하면 방금 작성한 방명록 글이 추가되어있는것을 확인할 수 있다.


  

  -방명록 글 수정, 삭제-


  1. gb_list.jsp 페이지에서 방명록 작성할때 적은 비밀번호를 적고 "편집" 버튼을 누르면 컨트롤러에 gbEdit.do로 맵핑 시킨다.


  2. gbEdit.do로 맵핑된 메소드에선 hashmap에 _id(키값)을 사용해서 dto에 담긴 값들을 담고, gb_edit.jsp페이지로 이동시키고 map도 같이 보낸다.


  3. gb_edit.jsp 페이지에서는 수정과 삭제를 하려면 키값이 필요하기 때문에 아까 보낸 map에 있는 _id값 (키 값)을 꺼내서 사용한다.


  -글 수정-


  4. 먼저 "수정" 버튼을 누르면 gb_edit() 자바스크립트 함수가 실행되서 컨트롤러에 있는 gbUpdate.do로 맵핑되서 자료를 전송한다.


  5. gbUpdate.do로 맵핑된 메소드에서는 넘겨 받은 자료를 dto객체를 생성해 저장하고, dao에 저장한 후에 guestbook.do로 맵핑된다.


  6. guestbook.do로 맵핑된 메소드에서는 다시 guestbook.jsp 페이지로 이동시킨다.


  7. 이동하면 방금 수정한 방명록 글이 수정되어있는 것을 확인할 수 있다.


  

 -글 삭제-

 

  4. "삭제" 버튼을 누르면 gb_del() 자바스크립트 함수가 실행되서 컨트롤러에 있는 gbDelete.do로 맵핑되서 자료를 전송한다.


  5. gbDelete.do로 맵핑된 메소드에서는 Dao에 articleDelete()메소드에 _id값(키값)을 매개값으로 해서 레코드를 삭제한다.


  6. 레코드를 삭제한 후에 guestbook.do로 맵핑되서 guestbook.jsp 페이지로 다시 이동한다.


  7. 이동하면 방명록의 글이 삭제된것을 확인할 수 있다.








GuestbookDTO.java (방명록 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
package com.example.spring04.model.guestbook.dto;
 
import java.util.Date;
 
public class GuestbookDTO {
    
    private String _id;     //키값, id
    private String name;    //이름
    private String email;    //이메일
    private String passwd;    //비밀번호
    private String content;    //내용
    private Date post_date;    //날짜
    //getter,setter,toString()
    
    public String get_id() {
        return _id;
    }
    public void set_id(String _id) {
        this._id = _id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPasswd() {
        return passwd;
    }
    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public Date getPost_date() {
        return post_date;
    }
    public void setPost_date(Date post_date) {
        this.post_date = post_date;
    }
    @Override
    public String toString() {
        return "GuestbookDTO [_id=" + _id + ", name=" + name + ", email=" + email + ", passwd=" + passwd + ", content="
                + content + ", post_date=" + post_date + "]";
    }
    
}
 
cs



GuestbookDAO.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.example.spring04.model.guestbook.dao;
 
import java.util.List;
 
import com.example.spring04.model.guestbook.dto.GuestbookDTO;
 
public interface GuestbookDAO {
    
    public List<GuestbookDTO> getArticleList(); //방명록 목록
    
    public void articleInsert(GuestbookDTO dto); //글쓰기
    
    public void articleUpdate(GuestbookDTO dto); //수정
    
    public void articleDelete(String _id); //삭제
    
    public GuestbookDTO gbDetail(String _id); //상세화면
    
}
cs



GuestbookDAOImpl.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
package com.example.spring04.model.guestbook.dao;
 
import java.util.Date;
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
 
import com.example.spring04.model.guestbook.dto.GuestbookDTO;
@Repository //dao bean
public class GuestbookDAOImpl implements GuestbookDAO {
 
    @Autowired //스프링에서 지원하는 의존성 주입 어노테이션
    MongoTemplate mongoTemplate; //mongodb 실행 객체
    
    String COLLECTION_NAME="guestbook"//컬렉션(테이블) 이름을 guestbook라고 한다.
    
    @Override
    //방명록 리스트를 보여주는 메소드
    public List<GuestbookDTO> getArticleList() {
        Query query=new Query(); //db에 명령내릴것들을 저장하는 객체인 query객체 생성
        query.with(new Sort(Sort.Direction.DESC, "post_date")); //쿼리 객체에 작성날짜의 내림차순으로 저장시킨다.
        List<GuestbookDTO> list=
                (List<GuestbookDTO>)mongoTemplate.find(
                query, GuestbookDTO.class, COLLECTION_NAME);
        //날짜내림차순(query)으로 COLLECTION_NAME테이블에 있는 값들을 찾아서 DTO 타입으로 변환해서 list배열에 넣는다.
        
        //리스트에 있는 글내용을 하나씩 dto에 저장하고 줄간격 변경을 하고, 줄간격변경한 글 내용을 다시 dto에 저장
        for(GuestbookDTO dto : list) { 
            //list에 있는 값들을 dto에 넣고, 줄간격을
            String content = dto.getContent();
            content= content.replace("\r\n""<br>");
            dto.setContent(content);
        }
        
        return list;//리스트 반환
    }
 
    @Override
    //방명록 글쓰기 메소드
    public void articleInsert(GuestbookDTO dto) {
        dto.setPost_date(new Date());    //날짜는 글작성할때 따로 작성해서 글을 쓰는게 아니므로 새로운 객체를 만들어 저장
        mongoTemplate.insert(dto, COLLECTION_NAME); //dto와 COLLECTION_NAME(테이블이름)으로 insert한다.
    }
 
    @Override
    public void articleUpdate(GuestbookDTO dto) {
        // update guestbook set name=?, email=?, content=?
        // where _id=?        
        //new Criteria("필드명").is(값)
        System.out.println(dto);
        Query query = new Query(new Criteria("_id").is(dto.get_id()));
        // 수정할 내용들을 매핑
        Update update=new Update();
        update.set("name", dto.getName());  //dto에 저장된 이름을 update객체에 name라는 이름으로 저장
        update.set("email", dto.getEmail());    //dto에 저장된 이름을 update객체에 email라는 이름으로 저장
        update.set("content", dto.getContent());    //dto에 저장된 글내용을 update객체에 content라는 이름으로 저장
        
        // 1개의 레코드만 수정 (1개의 게시물만 수정한다는 뜻이다. _id값 (키값)을 한개만 받아왔기 때문에)
        mongoTemplate.updateFirst(query, update, COLLECTION_NAME);
        // ( (query=날짜 내림차순으로 정렬시키는 쿼리), (update=이름, 이메일, 글내용), (COLLECTION_NAME=테이블이름) )
    }
 
    @Override
    //게시글을 삭제하는 메소드
    public void articleDelete(String _id) {
        Query query=new Query(new Criteria("_id").is(_id)); 
        //저장된 _id값이 내가 입력한 _id값과 같은지 확인하고, 그 값을 query객체에 저장
        
        mongoTemplate.remove(query, COLLECTION_NAME);
        //remove는 삭제하는 메소드 (_id값 (키값)과 COLLECTION_NAME(테이블이름)으로 자료를 삭제한다.
        
        }
    
    @Override
    //게시물 1개의 상세정보를 보여주는 메소드
    public GuestbookDTO gbDetail(String _id) {
        // findById() 1개의 Document 리턴
        // find() Document 리스트 리턴
        // findById(_id, 자료형클래스, 컬렉션이름)
        return mongoTemplate.findById(_id, GuestbookDTO.class, COLLECTION_NAME);
        //_id(키값)으로 COLLECTION_NAME(테이블)에 저장된 값들을 DTO타입으로 저장해서 리턴한다.
    }
    
}
cs



GuestbookController.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
package com.example.spring04.controller;
 
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
 
import com.example.spring04.model.guestbook.dao.GuestbookDAO;
import com.example.spring04.model.guestbook.dto.GuestbookDTO;
 
@Controller //컨트롤러 빈 선언
public class GuestbookController {
 
    @Autowired    //스프링객체 의존성 주입 어노테이션
    GuestbookDAO guestbookDao;    //dao를 호출하므로 의존성을 주입
    
    @RequestMapping("/guestbook.do")
    //guestbook.do로 맵핑되어서 다시 guestbook (jsp페이지)로 다시 이동한다.
    public String guestbook() {
        return "guestbook/guestbook";
    }

guestbook.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
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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" %>
<script>
 
$(function(){ //페이지 로딩이 되면  바로 gbList()함수가 실행
    gbList();
});
 
function gbList(){
    //비동기 방식으로 gbList.do를 호출해서 안에 있는 데이터를 받아옴
    $.ajax({
        url: "${path}/gbList.do",
        
        //데이터가 이동되는게 성공했다면 
        success: function(result){//리스트가 출력된게 result변수로 넘어옴
            $("#gbList").html(result);//id가 gbList인 값안에 result값이 찍히게 된다.
        }
    });
}
</script>
</head>
<body>
<%@ include file="../include/menu.jsp" %>
<h2>방명록</h2>
<input type="button" value="글쓰기" 
    onclick="location.href='${path}/gbWrite.do'">
<div id="gbList"<!-- 이 쪽에 방명록 리스트가 불러와져서 찍히게 된다. --> </div>    
</body>
</html>
cs

    
    @RequestMapping("/gbList.do")
    //guestbook (jsp)페이지가 실행이되면 바로 이 메소드로 맵핑되어서 DAO에 있는 방명록 리스트를 가져온다.
    public ModelAndView gbList() {
        List<GuestbookDTO> items=guestbookDao.getArticleList();
        Map<String,Object> map=new HashMap<>();
        map.put("list", items); //방명록 리스트를 list라는 이름으로 map(해쉬맵)에 저장한다.
        map.put("count", items.size()) ;    //방명록 리스트의 갯수를 count라는 이름으로 map(해쉬맵)에 저장
        return new ModelAndView("guestbook/gb_list""map", map);    //gb_list페이지를 호출하고, map에 담긴 자료를 같이 넘긴다.
    }


gb_list.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
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="../include/header.jsp" %>
게시물수 : ${map.count}건
<c:forEach var="dto" items="${map.list}"
<!-- 개별값은 dto이고, map에 담긴 list -->
 
<form method="post" action="${path}/gbEdit.do"
<!-- post방식으로 컨트롤러에 gbEdit.do로 맵핑한다. -->
 
    <input type="hidden" name="_id" value="${dto._id}">
    <!-- dto에 있는 _id(키값)을 받고, _id라는 이름에 변수로 저장하고, 히든타입으로 넘긴다. -->
    
    <table border="1" style="width:600px;">
        <tr align="center">
        <!-- width는 칸을 %크기로 나눈것 -->
            <td width="20%">이름</td>
            <td width="30%">${dto.name}</td>
            <td width="20%">날짜</td>
            <td width="30%">
            <!-- 날짜에 패턴(타입을 지정) -->
                <fmt:formatDate value="${dto.post_date}"
                    pattern="yyyy-MM-dd HH:mm:ss"/>
            </td>
        </tr>
        <tr>
            <td align="center">이메일</td>
            <td colspan="3">${dto.email}</td>
        </tr>
        <tr>
            <td colspan="4">${dto.content}</td>
        </tr>
        <tr>
                <td colspan="4" align="center">    
                    비밀번호 <input type="password" name="passwd">
                <input type="submit" value="편집">
            </td>
        </tr>
    </table>
</form>
</c:forEach>
cs
    
    @RequestMapping("/gbWrite.do")
    public String gbWrite() {
        return "guestbook/gb_write";
    }

gb_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
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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" %>
</head>
<body>
<%@ include file="../include/menu.jsp" %>
<h2>글쓰기</h2>
<form name="form1" method="post" action="${path}/gbInsert.do">
<table border="1" width="500px">
    <tr>
        <td>이름</td>
        <td><input name="name"></td>
    </tr>
    <tr>
        <td>이메일</td>
        <td><input name="email"></td>
    </tr>
    <tr>
        <td>비밀번호</td>
        <td><input type="password" name="passwd"></td>
    </tr>
    <tr>
        <td colspan="2">
            <textarea rows="5" cols="55" name="content"></textarea>
        </td>
    </tr>
    <tr>
        <td colspan="2" align="center">
            <input type="submit" value="확인">
            <input type="reset" value="취소">
        </td>
    </tr>
</table>
</form>
</body>
</html>
cs
    
    @RequestMapping("/gbInsert.do")
    public String gbInsert(@ModelAttribute GuestbookDTO dto) {
        //mongodb에 Document(레코드) 추가
        guestbookDao.articleInsert(dto);
        //페이지 이동(목록 갱신)
        return "redirect:/guestbook.do";
    }
    
    @RequestMapping("/gbEdit.do")
    public ModelAndView gbEdit(String _id) {
        // _id : mongodb의 Document(레코드)의 식별자
        GuestbookDTO dto=guestbookDao.gbDetail(_id);
        Map<String,Object> map=new HashMap<>();
        map.put("dto", dto);
        return new ModelAndView("guestbook/gb_edit","map",map);
    }


gb_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
56
57
58
59
60
61
62
63
64
65
66
67
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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" %>
<script>
//컨트롤러에 있는 gbUpdate.do로 맵핑되어서 자료를 전송한다.
function gb_edit(){
    document.form1.action="${path}/gbUpdate.do";
    document.form1.submit();
}
 
//컨트롤러에 있는 gbDelete.do로 맵핑되어서 자료를 전달한다.
function gb_del(){
    if(confirm("삭제하시겠습니까?")){
        document.form1.action="${path}/gbDelete.do";
        document.form1.submit();
    }
}
 
</script>
</head>
<body>
<%@ include file="../include/menu.jsp" %>
<form method="post" name="form1">
<table border="1" width="500px">
    <tr>
    <!-- map에 저장된 dto값들을 하나씩 출력해서 넣어준다. -->
        <td>이름</td>
        <td><input name="name" value="${map.dto.name}"></td>
    </tr>
    <tr>
        <td>이메일</td>
        <td><input name="email" value="${map.dto.email}"></td>
    </tr>
    <tr>
        <td>비밀번호</td>
        <td><input type="password" name="passwd"></td>
    </tr>
    <tr>
        <td colspan="2">
            <textarea rows="5" cols="55" name="content">${map.dto.content}</textarea>
              
        </td>
    </tr>
    <tr>
        <td colspan="2">
        <!-- 수정과 삭제를 하기위해서는 키값이 필요하다. 그렇기 때문에 히든타입으로 (_id) 받아온다. -->
            <input type="hidden" name="_id" value="${map.dto._id}">
            
            <input type="button" value="수정" onclick="gb_edit()"
            <!-- 수정버튼을 누르면 위쪽에 있는 자바스크립트 함수 gb_edit()가 실행된다.-->
            
            <input type="button" value="삭제" onclick="gb_del()">
            <!-- 삭제버튼을 누르면 위쪽에 있는 자바스크립트 함수 gb_del()가 실행된다.-->
            
            <input type="button" value="목록"
                onclick="location.href='${path}/guestbook.do';">
                    </td>
                </tr>
            </table>
        </form>
    </body>
</html>
cs

    
    @RequestMapping("/gbUpdate.do")
    //public String gbUpdate(@ModelAttribute GuestbookDTO dto) {
    public String gbUpdate(@RequestParam String _id
            , @RequestParam String name
            , @RequestParam String email
            , @RequestParam String content
            , @RequestParam String passwd) {        
        //System.out.println(dto);
        //Document(레코드) 수정
        GuestbookDTO dto=new GuestbookDTO();
        dto.set_id(_id);
        dto.setName(name);
        dto.setEmail(email);
        dto.setContent(content);
        dto.setPasswd(passwd);
        
        guestbookDao.articleUpdate(dto);
        //목록 페이지로 이동
        return "redirect:/guestbook.do";
    }
    
    @RequestMapping("/gbDelete.do")
    public String gbDelete(String _id) {
        //Document(레코드) 삭제
        guestbookDao.articleDelete(_id);
        //목록 페이지로 이동
        return "redirect:/guestbook.do";
    }
}

cs




  guestbook.jsp 에서  글쓰기 버튼을 만들어서 클릭하면 gbWrite( )함수가 호출되고, 그 함수에서 컨트롤러의 gbWrite.do로 맵핑되고,


  컨트롤러에서는 gbWrite.do로 맵핑된 메소드에서 gb_write (방명록 글쓰기) 페이지로 이동하게 리턴시키고,  


  방명록을 작성 (이름, 이메일, 비밀번호,본문내용)을 입력하고 "확인" 버튼을 누르면 javascript check( ) 함수가 호출되서, 


  id가 form1인 태그를 가져와서 컨트롤러에 gbInsert.do로 맵핑시킨다.


  gdInsert.do로 가면 form에 붙여놨던 자료들이 넘어가게 되고, 저장된 이름이 null이면 


  (그러니까 이름을 입력하지 않고 확인버튼을 누르면) gbWritd.do로 맵핑시킨다.







: