Ajax로 DB에 있는 게시판 목록 끌어오기를 해보았다. 왔다 갔다하는게 이해가 잘 안됐었는데 까먹지 않기 위해 기록!
이 화면에서 저 버튼을 눌렀을 때 각각 타입별 게시판이 목록에 나타나게 하는게 목표이다.
게시판은 추가 수정될 수 있으니 DB에서 값을 끌어와야 변한 내용이 그때그때 화면에 출력 될 것 이다.
header.html 전문
<header class="py-3 mb-4 border-bottom">
<div class="container">
<div>
<a class="logo" href="/">
<img alt="사이트 로고" class="logo me-5" th:src="@{/img/logo.png}">
</a>
<ul id="menu-box">
<li>
<a class="nav-link px-2 link-dark" onclick="boardListAjax('review')" href="#">숙소리뷰</a>
<ul class="dropdown-menu text-small" id="dropdown-box-review" style="display: block;"></ul>
</li>
<li class="dropdown">
<a href="#" id="dropdownBoard1" onclick="boardListAjax('basic')">숙소톡톡</a>
<ul class="dropdown-menu text-small" id="dropdown-box-basic" style="display: block;"></ul>
</li>
</ul>
<script>
//******Type별 게시판 목록 조회*******//
function boardListAjax(type) {
const getListAjax = function (type) {
return new Promise((resolve, reject) => {
$.ajax({
url: '/loadboardtype',
method: 'POST',
dataType: 'json',
data: {
type: type
},
success: function (data) {
resolve(data);
},
error: function (e) {
reject(e);
}
});
});
};
async function listRequestProcess(type) {
try {
const boardList = await getListAjax(type);
var htmlStr = '';
console.log(boardList);
console.log(boardList.length);
if (boardList.length == 0) {
htmlStr += `<li class='dropdown-item'>게시판이 없습니다.</li>`;
} else {
for (let i = 0; i < boardList.length; i++) {
htmlStr += `<li class='dropdown-item'><a href='/board/${boardList[i].boardNo}'>${boardList[i].title}</a></li>`;
}
}
$("#dropdown-box-"+type).html(htmlStr);
} catch (error) {
console.log("error : ", error);
};
};
listRequestProcess(type)
};
//****** Type별 게시판 목록 조회 *******//
</script>
<div id="login-box" th:if="${session.member} == null">
<button class="btn btn-outline-primary me-2" onclick="location.href='/join'"
type="button">회원가입
</button>
<button class="btn btn-primary" onclick="location.href='/login'" type="button">로그인</button>
</div>
<div id="user-box" th:if="${session.member}">
<ul class="notice-box">
<li class="dropdown">
<a aria-expanded="false" aria-haspopup="true"
class="nav-link px-2 link-dark dropdown-toggle user-alarm"
data-toggle="dropdown" href="#" id="dropdownAlarmList">알림<span
class="notion"></span></a>
<div aria-labelledby='dropdownAlarmList' class='dropdown-menu text-small' id="alarm-box">
</div>
</li>
<li>
<a class="nav-link px-2 link-dark user-note" th:href="@{/note/list}">쪽지<span class="notion">
<!-- <i
class="ico">3</i> --></span></a></li>
</ul>
<div class="dropdown private-box">
<a aria-expanded="false" aria-haspopup="true"
class="d-block link-dark text-decoration-none dropdown-toggle"
data-toggle="dropdown" href="#" id="dropdownUserMenu">
<img alt="mdo" class="rounded-circle" height="32" src="https://github.com/mdo.png"
width="32"><span class="user-name" th:text="${session.member.nick}"></span>
</a>
<ul aria-labelledby="dropdownUserMenu" class="dropdown-menu text-small">
<li><a class="dropdown-item" sec:authorize="hasRole('ROLE_ADMIN')" th:href="@{/intranet}"
th:if="${session.member.grade} == 5">관리자 페이지</a></li>
<!-- <li><a class="dropdown-item" th:href="@{/member/room?type=review}">나의 숙소 리뷰</a></li> -->
<li><a class="dropdown-item" th:href="@{/member/room?type=basic}">내가 쓴 게시글</a></li>
<li><a class="dropdown-item" th:href="@{/member/gradeup_list}">등업신청</a></li>
<li><a class="dropdown-item" th:href="@{/member}">정보수정</a>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li>
<a class="dropdown-item" th:href="@{/logout}">로그아웃</a>
</li>
</ul>
</div>
</div>
</div>
</header>
BoardController.java 전문
package com.example.board.controller;
import com.example.board.model.*;
import com.example.board.service.*;
import com.example.common.exception.Constants;
import com.example.member.model.MemberVo;
import com.example.member.service.MemberService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
@Slf4j
public class BoardController {
@Autowired
public MemberService memberService;
@Autowired
private BoardService boardService;
@Autowired
private PostService postService;
@Autowired
private AttachService attachService;
@Autowired
private RoomService roomService;
@Autowired
private ReviewService reviewService;
@Autowired
private CommentService commentService;
// ########## 게시글 ########## //
// 게시글 작성 폼
@GetMapping("/post/write")
public String writeForm(@RequestParam(value = "boardNo", required = false) Integer boardNo, Model model, HttpServletRequest request) {
// 작성자 본인이거나 관리자 인지 권한 확인
// 세션 준비
HttpSession session = request.getSession();
MemberVo member = (MemberVo) session.getAttribute("member");
// 회원이 아닌 경우 작성이 제한됨
if (member == null) {
//회원이 아닌 경우 로그인 페이지로 이동함
return "redirect:/login?redirectUrl=" + request.getRequestURL() + "?" + request.getQueryString();
} else {
// 회원인 경우
//해당 게시판 접근권한이 있는지 확인 할것
//게시판 목록을 통해 게시글을 작성하려 할때, 유입된 게시판에 작성이 선택된다.
int defaultListNo = 0;
if (boardNo == null) {
defaultListNo = 1;
} else {
defaultListNo = boardNo;
}
List<BoardVo> boards = this.boardService.retrieveBoardList();
HashMap<Integer, String> boardList = new HashMap<Integer, String>();
for (BoardVo board : boards) {
boardList.put(board.getBoardNo(), board.getTitle());
}
List<RoomVo> roomList = this.roomService.retrieveRoomList();
model.addAttribute("roomList", roomList);
// request 영역에 디폴트 게시판 정보를 저장한다.
model.addAttribute("defaultListNo", defaultListNo);
// request 영역에 게시판 리스트 정보를 저장한다.
model.addAttribute("boardList", boardList);
return "page/post_write";
}
}
//게시글 작성 시 이미지, 동영상, 리뷰 사용 체크
@ResponseBody
@GetMapping("/post/checkUse")
public Map checkUse(@RequestParam(value = "boardNo", required = false, defaultValue = "1") int boardNo) {
BoardVo board = this.boardService.retrieveBoard(boardNo);
Map<String, Object> map = new HashMap<String, Object>();
map.put("board", board);
return map;
}
// 유형별 게시판 조회
// retrieveBoardListByType
@ResponseBody
@PostMapping("/loadboardtype")
public List<BoardVo> boardListByType(@RequestParam("type") String type) {
List<BoardVo> boards = this.boardService.retrieveBoardListByType(type);
return boards;
}
// 게시글 목록
@GetMapping("/board/{boardNo}")
public String list(@PathVariable(name = "boardNo", required = false) int boardNo, Model model) {
//게시판 ID로 해당 게시판 내 게시글 목록을 가져온다.
List<PostVo> posts = postService.retrieveAllPosts(boardNo);
//게시판 ID로 해당 게시판 이름을 가져온다
BoardVo board = boardService.retrieveBoard(boardNo);
model.addAttribute("posts", posts);
model.addAttribute("board", board);
return "page/post_list";
}
// 내가 작성한 게시글 목록
@GetMapping("/member/room")
public String myList(HttpServletRequest request, Model model) {
HttpSession session = request.getSession();
MemberVo member = (MemberVo) session.getAttribute("member");
int MemNo = member.getMemNo();
List<PostVo> posts = this.postService.retrieveMyPosts(MemNo);
model.addAttribute("posts", posts);
return "page/member_room";
}
// 회원이 작성한 게시글 목록 (회원 정보 확인/회원이 작성한 글)
@GetMapping("/member/{memNo}")
public String memberWriteList(@PathVariable("memNo") int memNo, Model model) {
List<PostVo> posts = this.postService.retrieveMyPosts(memNo);
model.addAttribute("posts", posts);
return "page/member_post_list";
}
// 게시글 상세보기
@GetMapping("/post/{postNo}")
public String read(@PathVariable("postNo") int postNo, Model model, HttpServletRequest request, HttpServletResponse response) {
// ######### 게시글 상세정보 시작 ######### //
PostVo post = this.postService.retrieveDetailBoard(postNo);
if (post == null) {
throw new RuntimeException(Constants.ExceptionMsgClass.NOTPOST.getExceptionMsgClass());
}
List<AttachVo> attachVoList = this.attachService.retrievePostAttach(postNo);
ReviewVo review = this.reviewService.retrieveReview(postNo);
BoardVo board = this.boardService.retrieveBoard(post.getBoardNo());
RoomVo room = new RoomVo();
if (review != null) {
room = this.roomService.retrieveRoom(review.getRoomNo());
}
model.addAttribute("post", post);
model.addAttribute("attachList", attachVoList);
model.addAttribute("review", review);
model.addAttribute("room", room);
// ######### 게시글 상세정보 시작 ######### //
// ######### 게시글 조회수 증가 시작 ######### //
// 조회수 중복방지는 필요한 기능이지만, 완벽하게 차단해야 할만큼 중대한 사항은 아니라고 생각, 따라서 쿠키를 사용
Cookie oldCookie = null;
Cookie[] cookies = request.getCookies();
//request에서 넘어온 쿠키가 있는 경우
if (cookies != null) {
for (Cookie cookie : cookies) {
//이미 게시글을 1개 이상 본 기록이 있는 경우
if (cookie.getName().equals("postView")) {
//게시글 조회 쿠키 기록을 가져온다.
oldCookie = cookie;
}
}
}
//게시글 조회 기록이 있는 경우 (oldCookie = 이전 게시글 조회 기록)
if (oldCookie != null) {
log.info("oldCookie:{}", oldCookie.getValue());
//현재 조회하려는 게시글을 본 쿠키 기록이 없는 경우
if (!oldCookie.getValue().contains("[" + postNo + "]")) {
//조회수를 올린다
postService.upHitcount(postNo);
// 현재 게시글을 조회했다고 쿠키에 추가한다.
oldCookie.setValue(oldCookie.getValue() + "_[" + postNo + "]");
//웹어플리케이션의 모든 URL 범위에서 전송할 수 있도록 Path를 설정해준다.
oldCookie.setPath("/");
//하루에 한번만 조회수가 올라가게 한다.
oldCookie.setMaxAge(60 * 60 * 24);
response.addCookie(oldCookie);
}
} else { //게시글 조회 기록이 없는 경우
//조회수를 올린다.
postService.upHitcount(postNo);
//게시글 조회 기록 쿠키를 생성한다.
Cookie newCookie = new Cookie("postView", "[" + postNo + "]");
//웹어플리케이션의 모든 URL 범위에서 전송할 수 있도록 Path를 설정해준다.
newCookie.setPath("/");
//하루에 한번만 조회수가 올라가게 한다.
newCookie.setMaxAge(60 * 60 * 24);
response.addCookie(newCookie);
}
// ######### 게시글 조회수 증가 끝 ######### //
// ######해당 게시판에서 댓글 사용 여부 판단######
int useComment = this.boardService.retrieveBoard(post.getBoardNo()).getUseComment();
model.addAttribute("useComment", useComment);
System.out.println("useCommentssssss" + useComment);
if (useComment != 0) {
// ######### 댓글 목록 시작 ######### //
List<CommentVo> comments = this.commentService.retrieveCommentList(postNo);
model.addAttribute("comments", comments);
// ######### 댓글 목록 조회 끝 ######### //
}
// ######해당 게시판에서 댓글 사용 여부 끝 ######### //
return "page/post_detail";
}
// 게시글 수정폼
@GetMapping("/post/modify/{postNo}")
public String modifyFrom(@PathVariable("postNo") int postNo, Model model, HttpServletRequest request) {
// 작성자 본인이거나 관리자 인지 권한 확인
// 세션 준비
HttpSession session = request.getSession();
MemberVo member = (MemberVo) session.getAttribute("member");
// 회원이 아닌 경우 작성이 제한됨
if (member == null) {
//회원이 아닌 경우 로그인 페이지로 이동함
return "redirect:/login?redirectUrl=" + request.getRequestURL();
} else {
// 회원 id
int memNo = member.getMemNo();
// 작성된 게시글 작성자 id
int writerNo = this.postService.retrieveDetailBoard(postNo).getWriterNo();
System.out.println("회원" + memNo + "작성자" + writerNo);
// 작성자 본인이 아닌 경우
if (memNo != writerNo) {
//권한 없음 페이지로 이동
return "redirect:/denine";
} else {
// 작성자 본인인 경우
// 게시글 정보 가져오기
PostVo post = this.postService.retrieveDetailBoard(postNo);
//현존하지 않은 게시글인 경우
if (post == null) {
throw new RuntimeException(Constants.ExceptionMsgClass.NOTPOST.getExceptionMsgClass());
}
//게시판 목록 정보 가져오기
List<String> boardNames = this.postService.retrieveBoardName();
//HashMap 데이터 형에 게시판 목록 담기
HashMap<Integer, String> boardList = new HashMap<Integer, String>();
int i = 1;
for (String string : boardNames) {
boardList.put(i, string);
i++;
}
//게시판 목록 model셋팅
model.addAttribute("boardList", boardList);
//게시글 정보 model셋팅
model.addAttribute("post", post);
return "page/post_modify";
}
}
}
// 게시글 수정
@PostMapping("/post/update")
public String update(@Valid PostVo post, HttpServletRequest request) {
// 작성자 본인이거나 관리자 인지 권한 확인
// 세션 준비
HttpSession session = request.getSession();
MemberVo member = (MemberVo) session.getAttribute("member");
// 회원이 아닌 경우 작성이 제한됨
if (member == null) {
//회원이 아닌 경우 로그인 페이지로 이동함
return "redirect:/login?redirectUrl=/post/" + post.getPostNo();
} else {
// 회원 id
int memNo = member.getMemNo();
// 작성된 게시글 작성자 id
int writerNo = this.postService.retrieveDetailBoard(post.getPostNo()).getWriterNo();
System.out.println("회원" + memNo + "작성자" + writerNo);
// 작성자 본인이 아닌 경우
if (memNo != writerNo) {
//권한 없음 페이지로 이동
return "redirect:/denine";
} else {
// 작성자 본인인 경우
// 값 셋팅
PostVo postVo = new PostVo();
postVo.setPostNo(post.getPostNo());
postVo.setBoardNo(post.getBoardNo());
postVo.setSubject(post.getSubject());
postVo.setContent(post.getContent());
postVo.setTag(post.getTag());
// 수정 쿼리 실행
this.postService.modifyPost(postVo);
return "redirect:/post/" + post.getPostNo();
}
}
}
// 게시글 삭제
@GetMapping("/post/delete/{postNo}")
public String delete(@PathVariable("postNo") int postNo, HttpServletRequest request) {
// 작성자 본인이거나 관리자 인지 권한 확인
// 세션 준비
HttpSession session = request.getSession();
MemberVo member = (MemberVo) session.getAttribute("member");
// 회원이 아닌 경우 작성이 제한됨
if (member == null) {
//회원이 아닌 경우 로그인 페이지로 이동함
return "redirect:/login?redirectUrl=/post/" + postNo;
} else {
// 회원 id
int memNo = member.getMemNo();
// 작성된 게시글 작성자 id
PostVo post = this.postService.retrieveDetailBoard(postNo);
int writerNo = post.getWriterNo();
System.out.println("회원" + memNo + "작성자" + writerNo);
// 작성자 본인이 아닌 경우
if (memNo != writerNo) {
//권한 없음 페이지로 이동
return "redirect:/denine";
} else {
// 작성자 본인인 경우
// 해당 게시글의 board pk값 받아옴 (삭제 후 목록이로 이동하기 위함)
int boardNo = post.getBoardNo();
// 삭제 쿼리 실행
this.postService.removePost(postNo);
//게시글 삭제시 총 개수 수정 boardNo
//게시글 등록은 filecontroller에 있음
boardService.reviseBoardPost(boardNo, -1);
return "redirect:/board/" + boardNo;
}
}
}
}
DB의 테이블(=해당 목록에 맞게 데이터를 입력해서 완성된 하나의 집합체)과 데이터 유형과
숙소리뷰 = review / 숙소톡톡 = basic 타입으로 db에 지정되어있다
여튼 화면에서 사용자가 숙소 톡톡 을 클릭하면 html단의 //Type별 게시판 목록 조회///부분을 실행하라고 한다
function boardListAjax(type) // <====요 부분을 실행시켜 함수를 실행시킴
그럼 밑의 실행문으로 명령이 내려가고
listRequestProcess(type) // <====요게 실행문
이 실행문은 또 명령을 Controller단의 지정해준 주소
("/loadboardtype")
로 가져간다 (header.html에 찾아보면 주소 지정해준 부분이 있다)
가져가서
// 유형별 게시판 조회
// retrieveBoardListByType
@ResponseBody
@PostMapping("/loadboardtype")
public List<BoardVo> boardListByType(@RequestParam("type") String type) {
List<BoardVo> boards = this.boardService.retrieveBoardListByType(type);
return boards;
}
여기서 실행되면 mapper의 쿼리문을 담아서 다시 header.html로 리턴해준다
잘담아왔다면
$.ajax({
url: '/loadboardtype',
method: 'POST',
dataType: 'json',
data: {
type: type
},
success: function (data) {
resolve(data);
},
error: function (e) {
reject(e);
}
});
요 부분에 따라서 data라는 이름으로 html 페이지에서 쓸 정보를 담아준다
실패하면 에러
성공했다는 가정하에 이제
async function listRequestProcess(type) {
try {
const boardList = await getListAjax(type);
var htmlStr = '';
//console.log(boardList);
//console.log(boardList.length);
if (boardList.length == 0) {
htmlStr += `<li class='dropdown-item'>게시판이 없습니다.</li>`;
} else {
for (let i = 0; i < boardList.length; i++) {
htmlStr += `<li class='dropdown-item'><a href='/board/${boardList[i].boardNo}'>${boardList[i].title}</a></li>`;
}
}
$("#dropdown-box-"+type).html(htmlStr);
} catch (error) {
console.log("error : ", error);
};
};
listRequestProcess(type)
};
이 부분을 실행해준다
위의 실행문은 받아온 type값에 따라서 게시판 목록을 뽑아준다!
자세히 보면
async function listRequestProcess(type) {
try {
const boardList = await getListAjax(type);
var htmlStr = '';
//console.log(boardList);
//console.log(boardList.length);
if (boardList.length == 0) {
htmlStr += `<li class='dropdown-item'>게시판이 없습니다.</li>`;
} else {
for (let i = 0; i < boardList.length; i++) {
htmlStr += `<li class='dropdown-item'><a href='/board/${boardList[i].boardNo}'>${boardList[i].title}</a></li>`;
}
}
$("#dropdown-box-"+type).html(htmlStr);
} catch (error) {
console.log("error : ", error);
};
};
for문으로 가져온 객체의 갯수 값만큼 목록을 뽑아 보여주고 해당 순서의 boardNo를 뽑아 링크를 걸어준다
만약 게시판이 없다면 게시판이 없다는 안내문구도 보여준다!
$("#dropdown-box-"+type).html(htmlStr);
이 부분은 함수부분에 받아져있는 boardVo에 지정되어있는 항목에 따라 DB에서 받아온 값들을 type에 따라서 나눠서 넣어주는 역할을 한다
id="dropdown-box-basic" //또는
id="dropdown-box-review"
요렇게 위에서 id를 지정해 준 부분이 있다
***********아직 프론트 부분의 보여지는 부분은 구현하지 않은 상태이다********
부트스트랩의 드롭다운을 쓰다가 바꾸는 중
+) async await에 대해선 여기를 참고하면 좋을것 같다
https://joshua1988.github.io/web-development/javascript/js-async-await/
자바스크립트 async와 await
(중급) 자바스크립트 개발자를 위한 async, await 사용법 설명. 쉽게 알아보는 자바스크립트 async await 개념, 사용법, 예제 코드, 예외 처리 방법
joshua1988.github.io