베스트 게시물 관련 게시판 구현 (내 프로젝트에 적용)
Back-End/Spring 2019. 9. 26. 17:34회원 게시판에 있는 게시글 중에 추천수 상위 10개의 글만 '베스트 게시물 게시판' 으로 옮겨서 출력하기.
만약 추천수가 동일하다면 조회수 순으로 순위를 매기도록 구현함.
menu.jsp (메뉴 출력 view)
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 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!-- views/include/menu.jsp --> <%@ include file="header.jsp"%> <center> <!-- 다른 기능들 링크가 걸려있는 메뉴 페이지 --> ㅣ <a href="${path}/home">메인페이지</a> ㅣ <!-- 어떠한 아이디로든 로그인되지 않았을 경우에만 회원가입 링크를 출력시킨다. --> <c:if test = "${sessionScope.user_id == null and sessionScope.navername == null and sessionScope.kakaonickname == null and sessionScope.facebookname == null and sessionScope.admin_id == null}"> <a href="${path}/member/email.do">회원가입</a> ㅣ </c:if> <a href="${path}/board/list.do">회원 게시판</a> ㅣ <a href="${path}/board/best_list.do">베스트 게시물 게시판</a> ㅣ <!-- 관리자가 로그인 하지 않았을 경우에만 로그인 링크를 출력시킴 --> <c:if test = "${sessionScope.user_id == null and sessionScope.navername == null and sessionScope.kakaonickname == null and sessionScope.facebookname == null and sessionScope.admin_id == null}"> <a href="${path}/admin/admin_login_view.do">관리자 로그인</a> ㅣ </c:if> <a href="${path}/board/admin_board_list.do">공지사항</a> ㅣ <br> <br> <c:if test = "${sessionScope.admin_id != null}"> 관리자 메뉴 : ㅣ <a href="${path}/admin/admin_member_forced_eviction_view.do">회원 강제 탈퇴</a> ㅣ <a href = "${path}/admin/admin_member_info.do">회원 정보</a> ㅣ </c:if> </center> | cs |
bestboard.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 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 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <%@ include file="../include/header.jsp"%> <%@ include file="../include/menu.jsp"%> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> //게시판 목록 페이지로 이동하게 하는 함수 function list(page){ console.log("페이지를 이동합니다."); location.href="list.do?curPage="+page; }; </script> <%@ include file="../include/login.jsp"%><br> <center> <h2>베스트 게시물 게시판</h2> <table border = "1" width = "800px" align = "top"> <center> <tr> <th>추천수 순위</th> <th>회원 게시글 번호</th> <th>제목</th> <th>작성자</th> <th>내용</th> <th>날짜</th> <th>조회수</th> <th>추천수</th> <!-- forEach var = "개별데이터" items = "집합데이터" --> <c:forEach var = "row" items = "${map.list}"> <!-- 컨트롤러에서 map안에 list를 넣었기 때문에 이렇게 받는다. --> <tr> <td>${row.rk}</td> <!-- 게시글 순위 --> <td>${row.member_bno}</td> <!-- 글번호 --> <!-- 클릭하면 컨트롤러의 view.do로 이동하고, 게시물번호, 페이지 번호, 검색옵션, 키워드를 같이 넘긴다 --> <td> <a href="best_board_view.do?member_bno=${row.member_bno}">${row.title}</a> <c:if test="${row.rcnt > 0}"> <span style="color:red;">( ${row.rcnt} )</span> </c:if> </td> <td>${row.user_id}</td> <!-- 작성자의 이름 --> <td>${row.content}</td> <!-- 글의내용 --> <td>${row.reg_date}</td> <!-- 날짜의 출력형식을 변경함 --> <td>${row.viewcnt}</td> <!-- 조회수 --> <td>${row.recommend}</td> <!-- 추천수 --> </tr> </c:forEach> </table> <form name="form1" method="post" action="list.do"> <select name="search_option"> <option value="user_id" <c:if test="${map.search_option == 'user_id'}">selected</c:if> >작성자</option> <option value="title" <c:if test="${map.search_option == 'title'}">selected</c:if> >제목</option> <option value="content" <c:if test="${map.search_option == 'content'}">selected</c:if> >내용</option> <option value="all" <c:if test="${map.search_option == 'all'}">selected</c:if> >작성자+내용+제목</option> </select> <input name="keyword" value="${map.keyword}"> <input type="submit" value="조회"> </form> </center> <br><br><%@ include file="../include/Botton.jsp"%> </body> </html> | cs |
bestboardview.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 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 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <%@ include file="../include/header.jsp" %> <%@ include file="../include/menu.jsp" %> <script src="${path}/include/js/common.js"></script> <script src="${path}/ckeditor/ckeditor.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> $(function(){ //목록 버튼 $("#btnList").click(function(){ location.href="best_list.do"; }); //추천하기 버튼 $("#btnRecommend").click(function(){ if(confirm("해당 글을 추천하시겠습니까?")){ document.form1.action="recommend.do"; document.form1.submit(); alert("해당 글을 추천하였습니다.") } }); }); </script> <h2>베스트 게시물 보기</h2> <!-- 게시물을 작성하기 위해 컨트롤러의 insert.do로 맵핑 --> <form id="form1" name="form1" method="post" action="${path}/board/insert.do"> <input type = "hidden" id = "member_bno" name = "member_bno" value = "${dto.member_bno }"> <div>제목 <input name="title" id="title" size="80" value="${dto.title}" placeholder="제목을 입력하세요"><br><br> <!-- placeholder은 제목을 입력할 수 있도록 도움말을 출력함 --> </div> <div>조회수 : ${dto.viewcnt} </div><br><br> <div style="width:800px;"> <textarea id="content" name="content" rows="3" cols="80" placeholder="내용을 입력하세요">${dto.content}</textarea></div><br><br> </form> <!-- 마찬가지로 내용을 입력하도록 도움말을 출력함 --> <script> // ckeditor 적용 //id가 content인 태그 (글의 내용을 입력하는 태그)를 ck에디터를 적용한다는 의미 CKEDITOR.replace("content",{ height: "300px" }); CKEDITOR.replace("r_content",{ height: "300px" }); </script> <div style = "width:700px; text-align:center;"> <!-- 수정, 삭제에 필요한 글번호를 hidden 태그에 저장한다. --> <input type = "hidden" name = "member_bno" value = "${dto.member_bno }"> <!-- 관리자에게는 삭제 버튼을 표시한다. --> <c:if test = "${sessionScope.admin_id != null}"> <button type = "button" id = "btnDelete">삭제</button> </c:if> <!-- 로그인이 되어있고, 본인 글이 아닐경우에만 추천할 수 있도록 버튼을 출력 --> <c:if test = "${sessionScope.user_id != null and sessionScope.user_id != dto.user_id or sessionScope.navername != null and sessionScope.navername != dto.user_id or sessionScope.kakaonickname != null and sessionScope.kakaonickname != dto.user_id or sessionScope.facebookname != null and sessionScope.facebookname != dto.user_id}"> <button type = "button" id = "btnRecommend">추천하기</button> </c:if> <!-- 관리자에게도 추천 버튼 출력 --> <!-- 관리자에게는 삭제 버튼을 표시한다. --> <c:if test = "${sessionScope.admin_id != null}"> <button type = "button" id = "btnRecommend">추천하기</button> </c:if> <!-- 글목록은 본인이 아니어도 확인 가능하게 한다. --> <button type = "button" id = "btnList">목록</button><br><br> <body> <br><br><%@ include file="../include/Botton.jsp"%> </body> </html> | cs |
MemberBoardController.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 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 | package com.example.hansub_project.controller.board; import java.io.PrintWriter; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; 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.example.hansub_project.Member_Pager; import com.example.hansub_project.controller.member.MemberController; import com.example.hansub_project.model.board.dto.MemberBoardDTO; import com.example.hansub_project.model.board.dto.MemberBoardReplyDTO; import com.example.hansub_project.model.member.dto.MemberDTO; import com.example.hansub_project.service.board.MemberBoardService; import com.example.hansub_project.service.member.MemberService; @Controller //게시판 관련 컨트롤러를 선언함 public class MemberBoardController { @Inject //서비스를 호출하기위해서 의존성을 주입함 MemberBoardService memberboardservice; @Inject MemberService memberservice; //로깅을 위한 변수 private static final Logger logger= LoggerFactory.getLogger(MemberBoardController.class); //베스트 게시판 게시글 출력 @RequestMapping("/board/best_list.do") //세부적인 url mapping public ModelAndView best_list(//RequestParam으로 옵션, 키워드, 페이지의 기본값을 각각 설정해준다. ) throws Exception{ List<MemberBoardDTO> list = memberboardservice.bestlistAll(); ModelAndView mav = new ModelAndView(); Map<String,Object> map = new HashMap<>(); //넘길 데이터가 많기 때문에 해쉬맵에 저장한 후에 modelandview로 값을 넣고 페이지를 지정 map.put("list", list); //map에 list(게시글 목록)을 list라는 이름의 변수로 자료를 저장함. mav.addObject("map", map); //modelandview에 map를 저장 mav.setViewName("board/bestboard"); //자료를 넘길 뷰의 이름 return mav; //게시판 페이지로 이동 } //베스트 게시판 게시물 세부 내용 확인 @RequestMapping(value = "/board/best_board_view", method= {RequestMethod.GET, RequestMethod.POST}) public ModelAndView best_board_view(@RequestParam int member_bno, HttpSession session) throws Exception{ //조회수 증가 쿼리 memberboardservice.increaseViewcnt(member_bno, session); ModelAndView mav = new ModelAndView(); mav.setViewName("board/bestboardview"); //view로 자료를 넘기기위해서 mav에 값들을 저장해서 view.jsp로 리턴시킨다. mav.addObject("dto", memberboardservice.read(member_bno)); //상세보기를 한번 클릭하면 조회수를 1증가시킨다. return mav; //view로 넘어가서 출력이 된다. } } | cs |
MemberBoardServiceImpl.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 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 | package com.example.hansub_project.service.board; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.inject.Inject; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Service; import com.example.hansub_project.model.board.dao.MemberBoardDAO; import com.example.hansub_project.model.board.dto.MemberBoardDTO; @Service //서비스 빈으로 설정함 public class MemberBoardServiceImpl implements MemberBoardService { @Inject //dao를 호출하기 때문에 의존성을 주입한다. MemberBoardDAO memberboarddao; @Override public void create(MemberBoardDTO dto) throws Exception { memberboarddao.create(dto); //dto를 매개값으로 dao를 호출한다. } //게시물 읽기 @Override public MemberBoardDTO read(int member_bno) throws Exception { return memberboarddao.read(member_bno); } //게시글 수정 @Override public void update(MemberBoardDTO dto) throws Exception { memberboarddao.update(dto); } //게시물 삭제 관련 메소드 @Override public void delete(int member_bno) throws Exception { memberboarddao.delete(member_bno); } @Override public List<MemberBoardDTO> listAll(String search_option, String keyword,int start, int end) throws Exception { return memberboarddao.listAll(search_option, keyword, start, end); } //조회수를 증가하게하는 쿼리 //조회수 처리를 할때 일정 시간이 지난후 다시 클릭할때만 조회수가 증가하도록 설정 @Override public void increaseViewcnt(int member_bno, HttpSession session) throws Exception { long update_time = 0; //null을 방지하기 위해 초기값을 null로 설정함 if(session.getAttribute("update_time_"+member_bno)!=null) { //최근에 조회수를 올린 시간이 null이 아니면 update_time = (long)session.getAttribute("update_time_"+member_bno); } long current_time = System.currentTimeMillis(); //일정 시간이 경과한 후에 조회수를 증가시킨다. if(current_time - update_time > 5 * 1000) { //조회수가 1증가했을때로부터 5000초 후에 다시 클릭을 해야 조회수가 다시 1 증가한다는 말이다. //조회수 증가 처리 memberboarddao.increateViewcnt(member_bno); //조회수를 올린 시간을 저장함 session.setAttribute("update_time_"+member_bno, current_time); } } @Override public int countArticle(String search_option, String keyword) throws Exception { return memberboarddao.countArticle(search_option,keyword); } //게시글 추천관련 메소드 구현 @Override public void recommend(int member_bno) throws Exception { memberboarddao.recommend(member_bno); } //베스트 게시판 게시글 목록 출력 @Override public List<MemberBoardDTO> bestlistAll() throws Exception { return memberboarddao.bestlistAll(); } } | cs |
MemberBoardDAOImpl.java (게시판 DAO 중 일부)
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 | package com.example.hansub_project.model.board.dao; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.apache.ibatis.session.SqlSession; import org.springframework.stereotype.Repository; import com.example.hansub_project.model.board.dto.MemberBoardDTO; import com.example.hansub_project.model.member.dao.MemberDAO; @Repository //dao 선언 public class MemberBoardDAOImpl implements MemberBoardDAO { @Inject //db에 접속하기 위해 의존관계를 주입 SqlSession sqlSession; //게시글 쓰기 @Override public void create(MemberBoardDTO dto) throws Exception { sqlSession.insert("memberboard.insert",dto); } //게시글 수정 @Override public void update(MemberBoardDTO dto) throws Exception { sqlSession.update("memberboard.update", dto); } //게시물 삭제 관련 @Override public void delete(int member_bno) throws Exception { sqlSession.delete("memberboard.deleteArticle", member_bno); //mapper로 게시글 번호를 넘긴다. } //게시물 목록을 리턴 @Override public List<MemberBoardDTO> listAll(String search_option, String keyword, int start, int end) throws Exception { Map<String,Object> map = new HashMap<>(); map.put("search_option", search_option); map.put("keyword", keyword); map.put("start", start); //맵에 자료 저장 map.put("end", end); //매개변수는 시작 레코드의 번호, 끝 번호, 옵션과 키워드가 들어간다. return sqlSession.selectList("memberboard.listAll", map); } //조회수 증가처리를 하는 메소드 @Override public void increateViewcnt(int member_bno) throws Exception { sqlSession.update("memberboard.increaseViewcnt", member_bno); } @Override public int countArticle(String search_option, String keyword) throws Exception { Map<String,String> map=new HashMap<>(); map.put("search_option", search_option); map.put("keyword", "%"+keyword+"%"); return sqlSession.selectOne("memberboard.countArticle",map); } //게시글 상세정보 @Override public MemberBoardDTO read(int member_bno) throws Exception { return sqlSession.selectOne("memberboard.read", member_bno); } //추천수 증가처리 메소드 @Override public void recommend(int member_bno) throws Exception { sqlSession.update("memberboard.recommend", member_bno); } //베스트 게시글 게시판 게시글 목록 출력 @Override public List<MemberBoardDTO> bestlistAll() throws Exception { return sqlSession.selectList("bestboard.bestlistAll"); } } | cs |
bestboardMapper.xml (베스트 게시판 관련 게시글 목록 출력 Mapper)
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 | <?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="bestboard"> <!-- 베스트게시물 게시판에 출력되는 목록 mapper --> <!-- 순위를 출력할때 먼저 추천수 기준으로 순위를 매기고 추천수가 동일한 경우에는 조회수를 기준으로 순위를 다시 매겨서 중복이 없도록 출력한다. --> <select id="bestlistAll" resultType="com.example.hansub_project.model.board.dto.MemberBoardDTO"> select member_bno, user_id, reg_date, viewcnt, title, rcnt, content, recommend, row_number() over (order by recommend desc, viewcnt desc) as rk from ( select recommend, member_bno, user_id, reg_date, viewcnt, title, rcnt, content from member_board order by recommend desc ) <![CDATA[where rownum <= 10]]> </select> </mapper> | cs |
'Back-End > Spring' 카테고리의 다른 글
메뉴바에 디자인 넣어보기 (수정중) (0) | 2019.09.28 |
---|---|
베스트게시물 게시판 (디자인 코드 추가, 내 프로젝트에 적용) (2) | 2019.09.27 |
소셜 로그인 (네이버, 카카오톡, 페이스북) 후 프로필 확인 (내 프로젝트 적용)) (1) | 2019.09.24 |
프로필보기 기능 구현 (내 프로젝트에 적용) (0) | 2019.09.23 |
java에서 List형태로 저장한 값 출력 및 날짜형식 변환 (0) | 2019.09.20 |