비회원, 작성자가 본인이 아닌 글의 회원은 하루에 한 번 조회수를 1 증가할 수 있다.
🔑 게시글 상세조회를 할 때 조회수가 증가됨
-> 쿠키에 접속한 게시글의 번호를 저장해 하루에 한 번 증가하게 만듦
// 게시글 상세 조회
@GetMapping("/{boardCode}/{boardNo}")
public String boardDetail(@PathVariable("boardCode") int boardCode
, @PathVariable("boardNo") int boardNo
, Model model /*데이터 전달용 객체*/
, RedirectAttributes ra /*리다이렉트 시 데이터 전달용 객체*/
, @SessionAttribute(value="loginMember", required=false) Member loginMember
// 세션에서 로그인 멤버를 얻어오는데 없으면 null, 있으면 회원 정보 저장
// 쿠키를 이용한 조회수 증가에서 사용
, HttpServletRequest req
, HttpServletResponse resp
) throws ParseException {
Map<String, Object> map = new HashMap<String, Object>();
map.put("boardCode", boardCode);
map.put("boardNo", boardNo);
// 게시글 상세 조회 서비스 호출
Board board = service.selectBoard(map);
String path = null;
if(board != null) { // 조회 결과가 있을 경우
// ---------------------------------------------
// 현재 로그인 상태인 경우
// 로그인 한 회원이 해당 게시글에 좋아요를 눌렀는지 확인
if(loginMember != null) { // 로그인 상태인 경우
// 회원번호를 map에 추가
// map(boardCode, boardNo, memberNo)
map.put("memberNo", loginMember.getMemberNo());
// 좋아요 여부 확인 서비스 호출
int result = service.boardLikeCheck(map);
// 좋아요를 누른 적이 있을 경우
if(result>0) model.addAttribute("likeCheck", "on");
}
// ---------------------------------------------
// 쿠키를 이용한 조회수 증가 처리
// 1) 비회원 또는 로그인한 회원의 글이 아닌 경우
if(loginMember == null || // 비회원도 그냥 조회수 증가하게 할게요
loginMember.getMemberNo() != board.getMemberNo()
) {
// 2) 쿠키 얻어오기
Cookie c = null;
// 요청에 담겨있는 모든 쿠키 얻어오기
Cookie[] cookies = req.getCookies();
🔑 "readBoard"라는 쿠키가 존재한다면 그 쿠키를 c에 대입
- c에 현재 게시판 번호가 없다면 게시판 번호를 쿠키에 추가 -> DB에서 조회수 증가 -> 조회수 동기화 -> 쿠키 수명 지정
- c에 현재 게시판 번호가 있다면 그대로 조회수 관련 메소드 종료
🔑 "readBoard"라는 쿠키가 존재하지 않는다면 -> 쿠키 생성(게시판 번호가 value) -> DB에서 조회수 증가 -> 조회수 동기화 -> 쿠키 수명 지정
if(cookies != null) { // 쿠키가 존재할 경우
// 쿠키 중 "readBoardNo"라는 쿠키를 찾아 c에 대입
for( Cookie cookie : cookies) {
if(cookie.getName().equals("readBoardNo")) {
c = cookie;
break;
}
}
}
int result = 0;
// 3) 기존 쿠키가 없거나(c==null)
// 존재는 하나, 현재 게시글 번호가 쿠키에 저장되지 않은 경우(오늘 해당 게시글 본 적 없음)
if(c == null) {
// 쿠키가 존재 X -> 하나 새로 생성
c = new Cookie("readBoardNo", "|" + boardNo + "|");
// 조회수 증가하는 서비스 호출
result = service.updateReadCount(boardNo);
} else {
// 현재 게시글 번호가 쿠키에 있는지 확인
// Cookie.getValue() : 쿠키에 저장된 모든 값을 읽어옴
// -> String으로 반환
// String.indexOf("문자열")
// : 찾는 문자열이 몇 번 인덱스에 존재하는지를 반환
// 단, 없으면 -1 반환
if(c.getValue().indexOf("|" + boardNo + "|") == -1) {
// 쿠키에 현재 게시글 번호가 없다면
// 기존 값에 게시글 번호 추가해서 다시 세팅
c.setValue(c.getValue() + "|" + boardNo + "|");
// 조회수 증가 서비스 호출
result = service.updateReadCount(boardNo);
}
} // 3) 종료
// 4) 조회수 증가 성공 시
// 쿠키가 적용되는 경로, 수명(당일 23시 59분 59초) 지정
if(result>0) {
// 조회된 board의 조회수와 DB의 조회수를 동기화
board.setReadCount(board.getReadCount() + 1);
c.setPath("/"); // "/" 이하 경로 요청 시 쿠키 서버로 전달
// 수명 지정
Calendar cal = Calendar.getInstance(); // 싱글톤 패턴
cal.add(cal.DATE , 1);
// 날짜 표기법 변경 객체(DB의 TO_CAHR()과 비슷)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// java.util.Date
Date a = new Date(); // 현재 시간
Date temp = new Date(cal.getTimeInMillis()); // 내일(24시간 후)
// 내일 시간이 2023-08-24 12:17:40
Date b = sdf.parse(sdf.format(temp)); // 내일 0시 0분 0초
// 내일 0시 0분 0초 - 현재 시간
long diff = (b.getTime() - a.getTime()) / 1000;
// 내일 0시 0분 0초까지 남은 시간 반환
c.setMaxAge((int)diff); // 수명 설정
resp.addCookie(c); // 응답 객체를 이용해서 클라이언트에게 전달
}
}
model.addAttribute("board",board);
path = "board/boardDetail";
} else {
path ="redirect:/board/" + boardCode; // 게시판 첫 페이지로 리다이렉트
ra.addFlashAttribute("message", "존재하지 않는 게시글입니다.");
}
return path;
}
@PostMapping("/like")
@ResponseBody // 반환되는 값이 비동기 요청한 곳으로 돌아가게 함
public int like(@RequestBody Map<String, Integer> paramMap) {
// System.out.println(paramMap);
return service.like(paramMap);
}