앞서 작성한 Spring으로 만드는 간단한 게시판 만들기(1) (로그인)을 만들고 실제로 게시판을 구현할것이다.

게시판의 세부 기능은 C(Create),R(Read),U(Update),D(Delete)로 나눌수 있다.

기능을 구현하기에 앞서 일전에 언급했었던 것을 생성해야한다.

Board

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
 
import javax.persistence.*;
 
@Entity
@Table(name = "board")
public class Board {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
 
    private Long id;
    private String content;
    private String title;
    private String writer;
    private Date date;
 
    public Long getId() {
        return id;
    }
 
    public String getContent() {
        return content;
    }
 
    public String getTitle() {
        return title;
    }
 
    public String getWriter() {
        return writer;
    }
 
    public Date getDate() {
        return date;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public void setTitle(String title) {
        this.title = title;
    }
 
    public void setWriter(String writer) {
        this.writer = writer;
    }
 
    public void setContent(String content) {
        this.content = content;
    }
 
    public void setDate(Date date) {
        this.date = date;
    }
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

BoardRepository

1
2
3
4
5
6
7
8
9
 
import org.springframework.stereotype.Repository;
 
@Repository
public interface BoardRepository extends JpaRepository<Board,Long> {
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

BoardController

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
 
 
import org.springframework.stereotype.Controller;
 
 
@Controller
public class BoardController {
 
    private final BoardListService listService;
    private final BoardWriteService boardWriteService;
    private final BoardInfoService boardInfoService;
    private final BoardDeleteService boardDeleteService;
    private final BoardUpdateService boardUpdateService;
 
    public BoardController(BoardListService listService, BoardWriteService boardWriteService,BoardInfoService boardInfoService,BoardDeleteService boardDeleteService,BoardUpdateService boardUpdateService)
    {
        this.listService=listService;
        this.boardWriteService=boardWriteService;
        this.boardInfoService=boardInfoService;
        this.boardDeleteService=boardDeleteService;
        this.boardUpdateService=boardUpdateService;
    }
 
    @GetMapping(value="/board")
    public String listShow(@RequestParam(value="pageNum",defaultValue = "1")int pageNum){
        listService.boardList(pageNum);
        return "board";
    }
    @PostMapping(value = "/boardWriteRequest")
    public String writeRequest(@RequestParam Map<String,String> paraMap)
    {
        String title=paraMap.get("title");
        String content = paraMap.get("content");
        String writer = paraMap.get("writer");
 
        return "redirect:/board"//board로 바로가서 출력값 보여준다
    }
    @GetMapping(value="/Info")
    public String getInfo(@RequestParam(value = "freeId")long freeId)
    {
        boardInfoService.InfoService(freeId);
        return "boardInfo";
    }
    @GetMapping(value="/boardDelete")
    public String getDelete(@RequestParam(value = "freeId"long freeId)
    {
        boardDeleteService.deleteService(freeId);
        return "redirect:/board";
    }
    @GetMapping(value="/boardUpdate")
    public String getUpdate(@RequestParam(value="freeId"long freeId)
    {
        boardInfoService.InfoService(freeId);
        return "boardUpdate";
    }
    @PostMapping(value="/update")
    public String update(@RequestParam Map<String,String> paraMap)
    {
        String id=paraMap.get("freeId");
        String title=paraMap.get("title");
        String content = paraMap.get("content");
 
 
        return "boardInfo";
    }
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

PageMaker --> 게시판의 페이지 

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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
 
public class PageMaker {
    private int totalCount;// 전체 게시물 개수
    private int pageNum=1;// 현재 페이지 번호
    private int contentNum = 10;// 한 페이지에 몇 개 표시할지
    private int startPage = 1;// 현재 페이지 블록의 시작페이지
    private int endPage = 5;// 현재 페이지 블록의 마지막 페이지
    private boolean prev = false;// 이전 페이지로 가는 화살표
    private boolean next;// 다음 페이지로 가는 화살표
    private int currentBlock;// 현재 페이지 블록
    private int lastblock;// 마지막 페이지 블록
 
    public void prevNext(int pageNum) {
        if (pageNum > 0 && pageNum < 6) {
            setPrev(false);
            setNext(true);
        }
        else if (getLastblock() == getCurrentBlock()) {
            setPrev(true);
            setNext(false);
        }
        else {
            setPrev(true);
            setNext(true);
        }
    }
 
    public int calcpage(int totalCount , int contentNum) {
        int totalPage = totalCount / contentNum;
        if (totalCount % contentNum > 0) {
            totalPage++;
        }
        return totalPage;
    }
 
    public int getTotalCount() {
        return totalCount;
    }
    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
    }
 
    public int getPageNum() {
        return pageNum;
    }
 
    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }
 
    public int getContentNum() {
        return contentNum;
    }
 
    public void setContentNum(int contentNum) {
        this.contentNum = contentNum;
    }
 
    public int getStartPage() {
        return startPage;
    }
    public void setStartPage(int currentBlock) {
        this.startPage = (currentBlock * 5- 4;
        //1 2 3 4 5
        //6 7 8 9 10
        //11 12 13
    }
    public int getEndPage() {
        return endPage;
    }
    public void setEndPage(int getLastBlock, int getCurrentBlock) {
        if (getLastBlock == getCurrentBlock) { // 현재 페이지 블록이 마지막 블록이면
            this.endPage = calcpage(getTotalCount(), getContentNum()); // 페이지 개수를 끝페이지로 지정
        }
        else {
            this.endPage = getStartPage() + 4// 시작 페이지 + 4를 끝페이지로 지정
        }
    }
    public boolean isPrev() {
        return prev;
    }
    public void setPrev(boolean prev) {
        this.prev = prev;
    }
    public boolean isNext() {
        return next;
    }
    public void setNext(boolean next) {
        this.next = next;
    }
    public int getCurrentBlock() {
        return currentBlock;
    }
    public void setCurrentBlock(int pageNum) { // 페이지 번호 5 들어옴
        //페이지 번호를 통해서 구한다.
        //페이지 번호 / 페이지 그룹 안의 개수
        //1p 1 / 5 => 0.2
        //5p 5 / 5 = > 1 -> 나머지는 0
        this.currentBlock = pageNum / <span style="

다음으로는 C,R,U,D Service이다.

첫번째로는 ListService이다 게시글을 저장하면 데이터베이스에서 게시글 리스틀을 전부 가져오는 역활을 한다. 하지만 여기서 주의해야 할점은 첫번째 만들었을 때 게시글의 갯수가 0이니깐 분류를 해야한다. 나는 if(freeboardPage.getsize()==0)일때와 그렇지 않을때 2가지로 나누었다.

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
 
import org.springframework.stereotype.Service;
 
 
@Service
public class BoardListService {
    public final HttpSession session;
    public final BoardRepository boardRepository;
    public final PageMakerService pageMakerService;
 
    public BoardListService(HttpSession session,BoardRepository boardRepository, PageMakerService pageMakerService)
    {
        this.session=session;
        this.boardRepository=boardRepository;
        this.pageMakerService=pageMakerService;
    }
 
    public String boardList(int pageNum)
    {
        PageMaker pageMaker = pageMakerService.generatePageMaker(pageNum,10,boardRepository);
        PageRequest pageRequest = PageRequest.of(pageNum-1,10);
        Page<Board> freeboardPage = boardRepository.findAll(pageRequest);
 
        if(freeboardPage.getSize()==0)
        {
            session.setAttribute("boardList",new ArrayList<Board>());
            session.setAttribute("pageMaker",pageMaker);
            return "board";
        }
 
        List<Board> freeboardList = freeboardPage.getContent();
        session.setAttribute("boardList",freeboardList);
        session.setAttribute("pageMaker",pageMaker);
 
        return "board";
    }
 
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

두번째로는 Create부분이다.

Front에서 받아온 값을 객체 생성 및 값을 set해주고 해당되는 객체를  Repository에 save()를 해주고 session set을 해준다.

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
 
 
import org.springframework.stereotype.Service;
 
 
@Service
public class BoardWriteService {
 
    private final BoardRepository boardRepository;
    private final HttpSession httpSession;
 
    public BoardWriteService(BoardRepository boardRepository,HttpSession httpSession)
    {
        this.boardRepository=boardRepository;
        this.httpSession=httpSession;
    }
 
    public void write(String title, String content, String writer)
    {
        Board board = new Board();
        board.setTitle(title);
        board.setContent(content);
        board.setWriter(writer);
        httpSession.setAttribute("board",board);
    }
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

세번째로는 Read부분이다.

나는 게시글에서 게시글의 재목을 클릭을 하였을 때 제목, 작성자, 내용 이렇게 3가지를 보이게 하였다.

해당되는 Id값을 가지고 Reposiroty에서 검색한다음 이것을 객체로 받아 session을 set해주면 front에서 session.board.getTitle()이렇게 하면 우리가 작성한 제목을 볼 수 있다.

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
 
 
import org.springframework.stereotype.Service;
 
 
@Service
public class BoardInfoService {
    private final BoardRepository boardRepository;
    private final HttpSession session;
 
    public BoardInfoService(BoardRepository boardRepository, HttpSession session)
    {
        this.boardRepository=boardRepository;
        this.session= session;
    }
 
    public void InfoService(long freeId)
    {
        Board board = boardRepository.findById(freeId).get();
 
        session.setAttribute("board",board);
 
    }
 
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

네번째로는 Delete부분이다. 해당되는 Id를 가지고 Repository에서 deleteById를 해주면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
 
import org.springframework.stereotype.Service;
 
@Service
public class BoardDeleteService {
    private final BoardRepository boardRepository;
 
    public BoardDeleteService(BoardRepository boardRepository)
    {
        this.boardRepository=boardRepository;
    }
    public void deleteService(long freeId)
    {
        boardRepository.deleteById(freeId);
    }
 
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

마지막으로 Update부분이다. update는 처음에 생각하기 어려웠으나 Read+Create라는것을 알 수있었다. 이유는 게시글을 수정하기 위해서는 이전에 값을 알아야하고 또 이값을 다시 create하는것이기 때문이다.(그렇다고 코드상에 객체를 따로 생성하지는 않았다.)

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
 
 
import org.springframework.stereotype.Service;
 
 
@Service
public class BoardUpdateService {
 
    private final HttpSession session;
    private final BoardRepository boardRepository;
 
    public BoardUpdateService(HttpSession session, BoardRepository boardRepository)
    {
        this.session=session;
        this.boardRepository= boardRepository;
    }
    public void Update(long id,String title,String content)
    {
        Board board= boardRepository.findById(id).get();//여기에서 findById가 optional이기 때문에 .get()을 사용해야 한다.
        board.setTitle(title);
        board.setContent(content);
 
        session.setAttribute("board",board);
    }
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

 

Front

 

Board.html

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
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      th:with="lang=${#locale.language}" th:lang="${lang}">
<head>
    <title>Bootstrap Example</title>
    <meta charset="utf-8">
    <link href="ballad.css" rel="stylesheet" type="text/css">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        table{
            width: 100%;
            border-top: 1px solid #444444;
            border-collapse: collapse;
        }
        th, td{
            border-bottom: 1px solid #444444;
            padding: 10px;
        }
    </style>
    <script>
        function page(pageNum){
            location.href="/board?pageNum="+pageNum;
        }
        function getPost(freeid) {
            location.href="/Info?freeId="+freeid;
        }
    </script>
</head>
<body>
<div class="container">
    <h3> Board</h3>
    <h4><span th:text="${session.user.getUserId()}" ></span>님 환영합니다!</h4>
    <div class="col-sm-8 text-left">
        <table>
            <thead>
            <tr>
                <th>&nbsp;&nbsp;글 번호&nbsp;&nbsp;</th>
                <th>&nbsp;&nbsp;글 제목&nbsp;&nbsp;</th>
                <th>&nbsp;&nbsp;작성자&nbsp;&nbsp;</th>
            </tr>
            <th:block th:if="${session.boardList!=null}">
                <th:block th:each="board:${session.boardList}">
                    <tr>
                        <td><span th:text="${board.getId()}"></span></td>
                        <td><a th:onclick="|javascript:getPost('${board.getId()}')|" th:text="${board.getTitle()}"></a></td>
                        <td><span th:text="${board.getWriter()}"></span></td>
                    </tr>
                </th:block>
            </th:block>
            </thead>
            </table>
<!--        <a th:if="${session.pageMaker.isPrev()}" style="text-decoration: none;" th:onclick="|javascript:page('${session.pageMaker.getStartPage()}')|">&laquo;</a>-->
<!--        <th:block th:each="pageNum:${#numbers.sequence(session.pageMaker.getStartPage(),session.pageMaker.getEndPage())}">-->
<!--            &nbsp;<a th:text="${pageNum}" th:onclick="|javascript:page('${pageNum}')|"></a>&nbsp;-->
<!--        </th:block>-->
<!--        <a th:if="${session.pageMaker.isNext()}" style="text-decoration: none;" th:onclick="|javascript:page('${session.pageMaker.getEndPage()}')|">&raquo;</a>-->
    </div>
</div>
<div class="col-sm-8 text-right">
    <button type="button" style="color: white; background-color: gray; border-radius: 0.5em" onclick="location.href='/boardWrite'">글쓰기</button>
</div>
</body>
</html>
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

BoardInfo.html(상세보기)

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
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      th:with="lang=${#locale.language}" th:lang="${lang}">
<head>
    <title>Bootstrap Example</title>
    <meta charset="utf-8">
    <link href="ballad.css" rel="stylesheet" type="text/css">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        th,td{
            padding:50px;
        }
    </style>
    <script>
        function page(pageNum){
            location.href="/board?pageNum="+pageNum;
        }
        function getDelete(freeid) {
            location.href = "/boardDelete?freeId=" + freeid;
        }
        function getUpdate(freeid){
            location.href = "/boardUpdate?freeId=" +freeid;
        }
    </script>
</head>
<body>
<div class ="container-fluid text-center">
    <span style="font-size: 20px">제목</span>&nbsp;&nbsp;&nbsp;<textarea style="height: 20px;" th:text="${session.board.getTitle()}"  readonly="readonly"></textarea>
    <br>
    <span style="font-size: 20px">작성자</span>&nbsp;&nbsp;&nbsp; <textarea style="height: 20px" th:text="${session.board.getWriter()}" readonly="readonly"></textarea>
    <br><br>
    <textarea style="height: 100px;width: 100px;" th:text="${session.board.getContent()}"  readonly="readonly"></textarea>
</div>
<div class="col-sm-8 text-right">
    <button type="button" style="color: white; background-color: gray; border-radius: 0.5em" th:onclick="|javascript:getUpdate('${session.board.getId()}')|">수정</button>
</div>
<div class="col-sm-8 text-right">
    <button type="button" style="color: white; background-color: gray; border-radius: 0.5em" th:onclick="|javascript:getDelete('${session.board.getId()}')|">삭제</button>
</div>
</body>
</html>
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

BoardWrite.html (Create 부분)

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
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      th:with="lang=${#locale.language}" th:lang="${lang}">
<title>W3.CSS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link href="board.css" rel="stylesheet" type="text/css">
<body>
 
<div class="w3-container">
    <h3>주의!</h3>
    <div class="w3-panel w3-red">
        <p style="">욕, 심한말, 법적신고가능함!</p>
    </div>
</div>
 
<form action="/boardWriteRequest" method="post">
    <input type="text" placeholder="글 제목" name="title">
    <br><br>
    <textarea placeholder="글 내용" name="content"></textarea>
    <br><br>
    <input type="hidden" th:value="${session.user.getUserName()}" name="writer">
    <div class="button">
        <button type="submit">Submit</button>
    </div>
</form>
 
</body>
</html>
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

BoardUpdate.html

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
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      th:with="lang=${#locale.language}" th:lang="${lang}">
<title>글 수정페이지</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link href="board.css" rel="stylesheet" type="text/css">
<body>
 
<div class="w3-container">
    <h3>주의!</h3>
    <div class="w3-panel w3-red">
        <p style="">욕, 심한말, 법적신고가능함!</p>
    </div>
</div>
 
<form action="/update" method="post">
    <input type="text"  th:value="${session.board.getTitle()}" name="title">
    <br><br>
    <input style="height:300px;width: 300px "  th:value="${session.board.getContent()}" name="content"></input>
    <br><br>
    <input type="hidden" th:value="${session.board.getId()}" name="freeId">
    <div class="button">
        <button type="submit">Submit</button>
    </div>
</form>
 
</body>
</html>
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

처음 Spring을 배우는데 많은 어려움이 있었지만 하나하나 해결해 나가는데 매우 재미있었던것 같다. 

이번주 부터는 이 게시판과는 별개로 따로 만든 게시판을 서버에 올렸는데 그 과정을 Posting할 예정이고 그 게시판을 Refactoring 및 Restful하게 만들 계획이다. (이 게시판은 Service Flow를 확실히 이해하기 위해 다시 처음부터 만들었던 코드이다,)

 

Service Flow를 이해하기 위한 나의 그림

 

'SpringBoot' 카테고리의 다른 글

Homebrew 설치 및 gradle설치  (0) 2019.07.23
사용중인 포트 찾아서 Kill하기  (0) 2019.07.23
Spring으로 만드는 간단한 게시판(1)  (0) 2019.07.22
Get & Post  (0) 2019.07.08
해시(Hash) 와 암호화(Encryption)  (0) 2019.07.08

+ Recent posts