자유게시판과 공지사항에 있는 조회수를 카운트하는 방법에 대해 알아보자.
[요약]
- BoardController를 수정하여 클릭 시 free-detail.jsp 로 넘어간 후 조회수가 1 오를 수 있도록 조치
- 조회수는 올라가지만 새로고침할 때 마다 조회수가 올라가는 것에 대해 조치
* 새로 Controller 작성
* redirect 이용
[freeboard-mapper 수정]
- id에 따른 자유게시판 조회수 증가
<update id="updateCnt" parameterType="int">
UPDATE FREEBOARD
SET
CNT = CNT + 1
WHERE ID = #{id}
</update>
[freeboardDao 수정]
public void updateCnt(int id) {
mybatis.update("FreeBoardDao.updateCnt", id);
}
[Service 수정]
void updateCnt(int id);
[serviceImpl 수정]
@Override
public void updateCnt(int id) {
freeBoardDao.updateCnt(id);
}
[controller 수정]
- /free-detail.do url 안에다 boardService.updateCnt(boardDto.getId()); 를 포함시키면
새로고침 할 때마다 조회수가 올라가게 된다.
@GetMapping("/free-detail.do")
public String freeDetailView(BoardDto boardDto, Model model) {
boardService = applicationContext.getBean("freeBoardServiceImpl", BoardService.class);
// 아래 줄주석처리한 부분 때문에 새로고침을 해도 조회수가 올라감
// boardService.updateCnt(boardDto.getId());
model.addAttribute("freeBoard", boardService.getBoard(boardDto.getId()));
return "board/free-detail";
}
- (참고) getBoard 메서드(freeBoardDao)
public BoardDto getBoard(int id) {
System.out.println("FreeBoardDao의 getBoard 메소드 실행");
BoardDto boardDto = new BoardDto();
// SqlSessionTemplate의 selectOne메소드 사용
boardDto = mybatis.selectOne("FreeBoardDao.getBoard", id);
System.out.println("FreeBoardDao의 getBoard 메소드 실행 종료");
return boardDto;
}
- (참고) mapper(getBoard)
<select id="getBoard" parameterType="int" resultType="board">
SELECT F.ID
, F.TITLE
, F.CONTENT
, F.WRITER_ID
, M.NICKNAME
, F.REGDATE
, F.MODDATE
, F.CNT
FROM FREEBOARD F
JOIN MEMBER M
ON F.WRITER_ID = M.ID
WHERE F.ID = #{id}
</select>
(문제점) 새로고침을 해도 조회수가 올라간다.
계속해서 free-detail 페이지를 요청하기 때문이다.
그래서 controller 에서 조회수만 별도로 기능을 분리하여 클릭했을때만 조회수가 올라가도록 한다.
[controller 수정]
@GetMapping("update-cnt.do")
public String updateCnt(BoardDto boardDto) {
// Type에 따라 자유게시판과 공지사항 구분
if(boardDto.getType().equals("free")) {
boardService = applicationContext.getBean("freeBoardServiceImpl", BoardService.class);
} else {
boardService = applicationContext.getBean("noticeServiceImpl", BoardService.class);
}
boardService.updateCnt(boardDto.getId());
// 주소창에 id값이 나오도록 Dto에서 id값을 받아와서 jsp페이지로 이동
// Type에 따라 자유게시판과 공지사항 구분
if(boardDto.getType().equals("free")) {
return "redirect:/board/free-detail.do?id=" + boardDto.getId();
} else {
return "redirect:/board/notice-detail.do?id=" + boardDto.getId();
}
}
[free-list.jsp 수정]
<tbody class="table-group-divider">
// jstl c:forEach 방식으로 list에서 하나씩 꺼내오는 방식
// var="freeboard"는 list에서 꺼내온 하나의 객체로 이름은 상관없다.
<c:forEach items="${freeBoardList}" var="freeBoard">
// 클릭시 id가 자유게시판 id를 갖고있고
// type=free인 /board/upde-cnt.do 주소로 이동
<tr class="board-tr" onclick="location.href='/board/update-cnt.do?id=${freeBoard.id}&type=free'">
<td>${freeBoard.id}</td>
<td>${freeBoard.title}</td>
<td>${freeBoard.nickname}</td>
<td>
<javatime:format value="${freeBoard.regdate}" pattern="yyyy-MM-dd"/>
</td>
<td>${freeBoard.cnt}</td>
</tr>
</c:forEach>
</tbody>
결과로 아래 사진과 같이 id가 표현되는데 이 때 주의해야 할 점이 있다.
바로
location.href
이것이다.
이 코드의 특징은
1. 고정값만 있을경우 url 주소에 일반값도 포함
2. 변수를 활용하여 url 주소 구성 시 변수값만 포함
예를들어
가. location.href = '/board/update-cnt.do?id=123&type=free';
나. location.href='/board/update-cnt.do?id=${freeBoard.id}&type=free'"
'가' 항은 id와 type값이 둘 다 고정이기 때문에 둘 다 url 주소에 포함되어 있고,
'나' 항은 id는 변수값, type은 고정값이기 때문에 id값만 url 주소에 포함되어 있다.
- (참고) ${freeBoardList}는 boardController에서 설정해 둔 표현임
@RequestMapping("/free-list.do")
public String freeListView(Model model, @RequestParam Map<String, String> searchMap) {
boardService = applicationContext.getBean("freeBoardServiceImpl", BoardService.class);
model.addAttribute("freeBoardList", boardService.getBoardList(searchMap);