기능 설명 사진
- 이전글 다음글 기능
- 이전글을 눌러서 이전글로 이동 , 이미 읽은 글인 다음글이 읽음 표시됨
해당 기능은 이미 구현한 기능들에 덧붙인 기능이기 때문에, 이 전글들을 참고하길 바랍니다.
[스프링]게시판 이전글 다음글 구현 :: 간편 웹프로그래밍 (tistory.com)
[스프링]게시판 읽은 글 표시 :: 간편 웹프로그래밍 (tistory.com)
우선 , 기본적인 로직을 설명하자면
- readView(게시글 상세보기) 페이지의 이전글 다음글은 버튼은 카테고리 별 다음글의 PR (BNO) 를 불러온다.
다음글 : LEAD(BNO,1,9999)
이전글 : LAG(BNO,1,9999)
(위의 이전글 다음글 참고)
- 컨트롤러에서 다음글PR,이전글PR을 객체로 선언하고,
- 이전글에서 설명한 어느 회원이 어떤 글을 읽었는지 저장하는 테이블에 해당하는 DB가 있는지 확인한다.
(저장하는 테이블은 위의 읽은글 표시 참고)
- 저장테이블에 해당하는 데이터가 있다면, count해서 1을 반환하고,
- 0과 1, 로그인과 비로그인시, 다음글이 있는지 없는지를 if문을 통해 걸러내서 뷰에 표시해준다.
다음글은 이미 구현했으므로, 이전글을 구현해보겠다.
먼저, 이전글 다음글이 있는 페이지인 readView.jsp (게시글 상세보기) 의 이전글 버튼의 로직이다.
이전글이 있다면 int값으로 이전글의 PR을 반환하고 없다면 9999를 반환해서 이전글이 없습니다를 출력해준다.
Mapper.xml
이전글 다음글 쿼리이다, 현재 게시글을(BNO) 기준으로
다음,이전글의 BNO인 next와 last를 select해서
VO로 반환한다.( 자세한 것은 해당 구현글 참고)
저장테이블에 로그인한
회원의 아이디(#{memberId}) 와
이전글 BNO (#{bno}) 를
파라미터로 넣어서, 해당 회원이 이전글을 읽었는지 구분한다.
읽었다면 데이터가 있으니 1을 반환 ( insert 중복불가 , 즉 같은 내용은 1개만 입력가능)
없다면 0을 반환한다.
이제 컨트롤러에서 이전글의 bno와 회원 아이디 파라미터를 mapper의 매개변수로 넣어주면 되겠다.
Controller
관련 없는 부분은 주석처리 했다
@RequestMapping(value="/board/readView", method=RequestMethod.GET)
public String read(HttpSession session,@ModelAttribute("scri") SearchCriteria scri,BoardVO boardVO, Model model) throws Exception{
//logger.info("read");
//읽은 목록 표시
if(session.getAttribute("login") != null) {
MemberVO memberVO =(MemberVO) session.getAttribute("login");
/* if(service.boardCheck(boardVO.getBno(),memberVO.getMemberId())==0) {
service.insertBoardCheck(boardVO.getBno(), memberVO.getMemberId());
} */
//이전글 다음글 읽은 목록 표시
BoardVO movePageVO = service.movePage(boardVO);
//다음글
int nextPageCheck = service.nextPageCheck(movePageVO.getNext(), memberVO.getMemberId());
model.addAttribute("nextPageCheck", nextPageCheck);
//이전글
int lastPageCheck = service.nextPageCheck(movePageVO.getLast(),memberVO.getMemberId());
model.addAttribute("lastPageCheck", lastPageCheck);
}
/*
model.addAttribute("read", service.read(boardVO.getBno()));
model.addAttribute("scri", scri);
model.addAttribute("replyVO",new ReplyVO());
List<Map<String, Object>> fileList = service.selectFileList(boardVO.getBno());
model.addAttribute("file", fileList);
model.addAttribute("move", service.movePage(boardVO));
logger.info("fileList=" + fileList); */
return "/board/readView";
}
일단 컨트롤러의 매개변수로 이전글 다음글을 쿼리에서 뽑아내기 위한 현재글BNO , 회원ID가 필요하다.
회원ID는 세션값에서 가져온다.
HttpSession으로 받아도 되고... HttpServletRequest으로 받아도 된다.
나는 HttpSession으로 받아왔는데, 매개변수에 넣고 세션부여 key인 login을 넣어서 VO에 값을 넣어줬다.
VO.getMemberId로 VO에서 ID값을 받았고,
세션키가 null인지 확인해서 로그인을 했는지, 안했는지 구분해서
했다면 읽은 목록 표시기능이 넘어가게 만들었다.
-
request로 받고싶다면 매개변수로 HttpServletRequest request를 넣어주고,
HttpSession을 객체로 선언,
HttpSession session = request.getSession();
if(session.getAttribute(login) != null){
MemberVO memberVO = session.getAttribute(login);
String Id = memberVO.getMemberId;
}
이런 느낌으로 request로 값을 받아올 수도 있다.
본인의 상황에 맞게 사용하도록 하자.
-
BNO는 ,
@RequestParam int BNO로 받던..
VO ( boardVO) 로 받던..
HttpServletRequest로 받던,
해당글의 bno값을 매개변수로 받아와서 이전글 쿼리인 service.movePage에 매개변수로 넣어주고,
이전글의 BNO를 결과로 받는다.
이제 이전글의 BNO와 회원ID를 가져왔으니 select Count 문에 넣어주기만 하면 끝이다.
select Count 쿼리의 로직인 nextPageCehck에 매개변수로 넣어주고,
1인지 0인지의 값을 model로 뷰페이지로 넘겨준다.
Service, ServiceImpl
public int nextPageCheck(int nextbno,String memberId)throws Exception;
@Override
public int nextPageCheck(int nextbno,String memberId)throws Exception{
return dao.nextPageCheck(nextbno, memberId);
}
DAO, DAOImpl
public int nextPageCheck(int nextbno,String memberId)throws Exception;
@Override
public int nextPageCheck(int nextbno,String memberId)throws Exception{
Map<String,Object> map = new HashMap<String, Object>();
map.put("memberId", memberId);
map.put("bno", nextbno);
return sqlsession.selectOne("boardMapper.boardCheck", map);
}
두개의 파라미터를 간단하게 map에 넣어서 쿼리에 매개변수로 넣어준다.
readView.jsp
<c:choose>
<c:when test="${move.last == 9999}">
<button type="button" class="btn btn-info mr-3" disabled>이전글이 없습니다</button>
</c:when>
<c:when test="${move.last != 9999 and empty login or lastPageCheck == 0}">
<button type="button" class="btn btn-info mr-3 " onclick="location.href='/board/readView?bno=${move.last}&bgno=${scri.bgno}&sort=${scri.sort}'"> <span class="glyphicon glyphicon-menu-down" aria-hidden="true"></span>이전글</button>
<a href="/board/readView?bno=${move.last}&bgno=${scri.bgno}&sort=${scri.sort}" style="color: black"> ${move.lasttitle} </a>
</c:when>
<c:when test="${move.last != 9999 and not empty login and lastPageCheck == 1}">
<button type="button" class="btn btn-secondary mr-3 " onclick="location.href='/board/readView?bno=${move.last}&bgno=${scri.bgno}&sort=${scri.sort}'"> <span class="glyphicon glyphicon-menu-down" aria-hidden="true"></span>이전글</button>
<a href="/board/readView?bno=${move.last}&bgno=${scri.bgno}&sort=${scri.sort}" style="color: gray"> ${move.lasttitle} (읽음)</a>
</c:when>
</c:choose>
- 이전글의 bno가 없을때 ( 없으면 9999 반환)
-"이전글이 없습니다" 출력
- 이전글의 bno가 있을때 , 세션key인 login이 비어있거나( 로그인이 안됨) or 저장테이블의 count 값이 0일때
- 원래대로 출력
- 이전글의 bno가 있을때, 세션키가 있고, 저장테이블의 count값이 1일때
-원래의 모양에서 버튼 색상과 , 글자색 , "(읽음)" 을 추가해서 표시를 해준다.
결과
전 글에서 , 읽은 목록 표시를 구현 후 해당 로직에 대한 흐름이 생각나서 구현해보았다.
각 기능을 구현할 때마다, 처음부터 보고하는 것이던, 살짝 힌트만 얻어서 구현하는 것이던
항상 내가 작성한 모든 코드의 의미와 흐름을 이해하려고 노력했다.
그렇게 노력하면서 자연스럽게 코드도 기억에 오래 남게 됐고,
하나의 기능을 새로 배울때도,
전에 구현해본 코드,구현의 흐름에 대한 이해가 바탕이 되어 다른 기능에 어떻게 응용하면 될 지 문뜩 생각이 나곤 한다.
코드를 이해를 하기 위해 필요한 것은 언어실력과 CS 이므로,
공부를 하면 할 수록,
왜 그렇게 기본이 중요하다고 하는지 깨닫고 있는 요즘이다.
기본이 없으면 기능구현에 대한 로직의 이해를 할 수가 없고,
이해가 없으면, 구현을 해도 응용과 변형은 물론이고,
후에 다시 똑같이 만들려고 할 때 기억도 잘 나지 않는다.
당연히 새로운 로직을 만드는 것도 불가능 할 것이고,
결국은 실력을 높일 수도 없게 될 것 같다고 생각한다.
이번 프로젝트가 끝나면 기본에 더욱 집중해봐야겠다.
'SPRING > IceWater Community' 카테고리의 다른 글
[스프링] 질문 채택 기능 구현 (Like 지식 IN) (0) | 2021.10.08 |
---|---|
[스프링] 댓글 좋아요/싫어요 구현 - (Ajax) (3) | 2021.10.06 |
[스프링]게시판 읽은 글 표시 (3) | 2021.10.01 |
[스프링] 공지사항 구현 (0) | 2021.09.30 |
[스프링] 추천기능 구현 (OKKY사이트 추천기능 참고) (4) | 2021.09.28 |