Spring WEB

Spring MVC - 게시판 만들기C(R)UD - feat.입문편

엘호리스 2018. 8. 21. 00:53

게시판 상세내용 출력하는 화면을 구현해보자.

이제부터는 같은 작업을 반복하는 것에 불구하지만 작업흐름 이해를 위해 한꺼번에 구현하지 않고

기능 하나씩 구현하는 과정으로 포스팅을 해나가겠다.


우선적으로 게시글 목록 페이지에서 게시물을 클릭하면 상세내용을 보여주는 페이지로 넘어가게 코드를 수정하자.


board_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
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <%@ include file="../include/menu.jsp" %>
    <h2>board_list 페이지입니다.</h2>
    <a href="${path}/board/writer_page">글쓰기</a>
    <table border="1">
        <tr>
            <th>번호</th>
            <th>제목</th>
            <th>글쓴이</th>
            <th>작성일자</th>
            <th>조회수</th>
        </tr>
        <c:forEach var="row" items="${list}">
        <tr>
            <td>${row.bno}</td>
            <!-- 게시물 조회를 위해서 get방식으로 게시물번호 값을 넘겨주자 -->
            <td><a href="${path}/board/read.do?bno=${row.bno}">${row.title}</a></td>
            <td>${row.writer}</td>
            <td>
                <fmt:formatDate value="${row.regdate}" pattern="yyyy-MM-dd HH:mm:ss" />
            </td>
            <td>${row.viewcnt}</td>
        </tr>
        </c:forEach>
    </table>
</body>
</html>
cs

여기서 눈여겨 봐야할 코드는 26 라인에 있는 GET 방식으로 값을 넘겨주는 코드이다.

${path}/board/read.do?bno=${row.bno}

${path} : localhost:8080/example


tomcat server.xml 소스 내에 context 태그 안 속성으로 path 값이 /example로 설정 되어있는 것을 볼 수 있다.


/board/read.do : Controller 매핑을 통해 뷰 리졸버를 거쳐 /WEB-INF/views/board_read.jsp를 반환한다.

?bno=${row.bno} : GET 메서드를 통해 서버쪽으로 bno란 값에 ${row.bno}값을 전송한다.

${row.bno} : 게시글 번호값


게시물 목록에서 글제목을 클릭할 수 있게 a 태그를 사용해줬다.



다음으로 게시물 상세내용을 보여줄 페이지를 구현해보자.

board_read.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
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <%@ include file="../include/menu.jsp" %>
    <h2>board_read 페이지입니다.</h2>
    <a href="${path}/board/writer_page">글쓰기</a>
    <table border="1">
        <th> 정보 </th>
        <th> 데이터 </th>
        <tr>
            <td>작성일자</td>
            <td><fmt:formatDate value="${data.regdate}" pattern="yyyy-MM-dd HH:mm:ss" />
            </td>
        </tr>
        <tr>
            <td>글번호</td><td>${data.bno}</td>
        </tr>
        <tr>
            <td>글제목</td><td>${data.title}</td>
        </tr>
        <tr>
            <td>글내용</td><td>${data.content}</td>
        </tr>
        <tr><td>글쓴이</td><td>${data.writer}</td></tr>
        <tr><td>조회수</td><td>${data.viewcnt}</td></tr>
        
    </table>
    <a href="#">수정</a>
    <a href="#">삭제</a>
    
</body>
</html>
cs


테이블 형태로 페이지를 꾸며주고 안에 서버로부터 전송받을 데이터들을 변수로 넣어주었다.

이제 서버쪽 MVC 작업이 남았다.


BoardController.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
package com.board.example.controller;
 
import java.util.List;
 
import javax.inject.Inject;
 
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
 
import com.board.example.dto.BoardDTO;
import com.board.example.service.BoardService;
import com.sun.media.jfxmedia.logging.Logger;
 
 
@Controller
@RequestMapping("/board/*")
public class BoardController {
    @Inject
    BoardService boardService;
    
    // 과거 ModelAndView를 활용한 방법
//    @RequestMapping("list.do")
//    public ModelAndView boardMenu() throws Exception {
//        List<BoardDTO> list = boardService.boardList();
//        ModelAndView mav = new ModelAndView();
//        mav.setViewName("board/board_list");
//        mav.addObject("list", list);
//        return mav; // board/board_list.jsp로 이동
//    }
    
    // 현재 자주 쓰는 Model 클래스를 DI 하는 방법
    @RequestMapping("list.do")
    public String boardList(Model model) throws Exception {
        List<BoardDTO> list = boardService.boardList(); // list 변수에 결과 값을 담는다
        model.addAttribute("list", list); // model에 데이터 값을 담는다
        return "board/board_list"// board/board_list.jsp로 이동
    }
    
    // writer_page.jsp 매핑
    @RequestMapping("writer_page")
    public String writerpage() {
        return "board/writer_page";
    }
    
    // 게시글 from 데이터 처리
    @RequestMapping(value="insert.do", method=RequestMethod.POST)
    public String boardWriter(BoardDTO bdto) throws Exception {
        boardService.writerBoard(bdto);
        return "redirect:list.do";
    }
    
    // 게시글 상세내용 불러오기 
    @RequestMapping(value="read.do", method=RequestMethod.GET)
    public String boardRead(@RequestParam int bno,Model model) throws Exception {
        BoardDTO data = boardService.boardRead(bno); // bno값을 넘김
        model.addAttribute("data", data); // model에 데이터 값을 담는다
        return "board/board_read"// board/board_list.jsp로 이동
    }
    
}
cs

컨트롤러에서 GET방식으로 통신을 할 것을 지정해주고 (method=RequestMethod.GET)

프론트단에서 파라미터값으로 넘어오는 값을 받기 위해 설정해주고 (@RequestParam int bno)

서비스 메서드를 호출하면서 bno 값을 넘겨준다. (boardService.boardRead(bno))


BoardService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.board.example.service;
 
import java.util.List;
 
import com.board.example.dto.BoardDTO;
 
public interface BoardService {
    // 게시물 목록 조회
    public List<BoardDTO> boardList() throws Exception;
    // 게시물 글 쓰기
    public void writerBoard(BoardDTO bdto) throws Exception;
    // 게시물 상세내용 불러오기
    public BoardDTO boardRead(int bno) throws Exception;
}
cs


BoardServiceImpl.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
package com.board.example.service;
 
import java.util.List;
 
import javax.inject.Inject;
 
import org.springframework.stereotype.Service;
 
import com.board.example.dao.BoardDAO;
import com.board.example.dto.BoardDTO;
 
@Service
public class BoardServiceImpl implements BoardService {
    @Inject
    BoardDAO boardDao;
    // 게시물 목록 불러오기
    @Override
    public List<BoardDTO> boardList() throws Exception {
        return boardDao.boardList(); 
    }
    // 게시물 글 쓰기
    @Override
    public void writerBoard(BoardDTO bdto) throws Exception {
        boardDao.writerBoard(bdto);
    }
    // 게시물 상세내용 불러오기
    @Override
    public BoardDTO boardRead(int bno) throws Exception {
        return boardDao.boardRead(bno);
    }
}
cs


BoardDAO.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.board.example.dao;
 
import java.util.List;
 
 
import com.board.example.dto.BoardDTO;
 
public interface BoardDAO {
    // 게시물 목록 보기
    public List<BoardDTO> boardList() throws Exception;
    // 게시물 작성
    public void writerBoard(BoardDTO bdto) throws Exception;
    // 게시물 상세내용 불러오기
    public BoardDTO boardRead(int bno) throws Exception;
}
cs


BoardDAOImpl.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
package com.board.example.dao;
 
import java.util.List;
 
import javax.inject.Inject;
 
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
 
import com.board.example.dto.BoardDTO;
 
@Repository
public class BoardDAOImpl implements BoardDAO {
    @Inject
    SqlSession sqlSession;
    // 게시물 목록 불러오기
    @Override
    public List<BoardDTO> boardList() throws Exception {
        return sqlSession.selectList("board.boardList"); 
    }
    // 게시물 글쓰기
    @Override
    public void writerBoard(BoardDTO bdto) throws Exception {
        sqlSession.insert("board.boardWriter", bdto);
    }
    // 게시물 상세내용 불러오기
    @Override
    public BoardDTO boardRead(int bno) throws Exception {
        return sqlSession.selectOne("board.boardRead", bno);
    }
}
cs

여기서 눈여겨 봐야할 점은 29 라인의 sqlSession.selectOne 이다.

데이터베이스에서 레코드의 단일 행을 가져올 것이므로 selectOne을 사용한다.


boardMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<!-- 다른 mapper와 중복되지 않도록 네임스페이스 기재 -->
<mapper namespace="board">
    <!-- 게시글 목록 불러오기 -->
    <select id="boardList" resultType="com.board.example.dto.BoardDTO">
        select bno,title,writer,regdate,viewcnt
        from board order by bno desc
    </select>
    <!-- Create 부분에 해당하는 글 쓰기 쿼리 -->
    <insert id="boardWriter">
        insert into board (bno, title, content, writer ) 
        values ((select nvl(max(bno)+1,1) from board), #{title}, #{content}, #{writer} )
    </insert>
    <!--  게시글 상세내용 불러오기  -->
    <select id="boardRead" resultType="com.board.example.dto.BoardDTO">
        select bno,title,content,writer,regdate,viewcnt
        from board where bno = #{bno}
    </select>
    
</mapper>
cs



작업완료. 게시글 상세내용 페이지 화면

이제 수정과 삭제 기능을 구현해보자~