20240219 spring 웹 표준 기술 modal RESTAPI RESTFULL
board.jsp
게시글 디테일 모달
<!-- 글쓰기 모달 만들기 -->
<div class="modal" id="write">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">글쓰기 창입니다.</h3>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mt-2">
<form action="./write" method="post" onsubmit="return writeCheck()" name="frm">
<input type="text" id="title" name="title" class="form-control mb-2" required="required" placeholder="제목을 입력하세요">
<textarea id="content" name="content" class="form-control mb-2 vh-500" required="required"></textarea>
<button type="submit" class="btn btn-info">글쓰기</button>
</form>
</div>
</div>
<div class="modal-footer">
2024-02-19 웹표준 기술 / RESTAPI / RESTFULL
</div>
</div>
</div>
</div>
<!-- 내용보기 detail 모달 만들기 -->
<div class="modal" id="detail">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">글 내용 보기</h3>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mt-2">
제목 <br> 본문 내용
</div>
</div>
<div class="modal-footer">디테일 모달 닫기</div>
</div>
</div>
</div>
td class에 onclick="detail()" 추가 -> detail() 펑션 만들어야 함
detail() 괄호 안에 ${row.board_no } = 몇 번째 글을 클릭했어
<tbody>
<c:forEach items="${list }" var="row">
<tr>
<td>${row.board_no }</td>
<td class="title" onclick="detail(${row.board_no })">
<%-- <a href="./detail?no=${row.board_no }"> </a>--%>
${row.board_title }
<c:if test="${row.comment gt 0}">
<span class="badge">${row.comment }</span>
</c:if>
</td>
<td>${row.board_write }</td>
<td>${row.board_date }</td>
<td>${row.board_count }</td>
</tr>
</c:forEach>
</tbody>
SweetAlert
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
위의 코드를 입력하고 alert 대신에 swal 로 기입함.
function detail(){
/* swal("Good job!", "상세보기 입니다.", "success"); // sweet alert 사용 : title, text, icon, button */
swal({
title:"Good job!",
text:"상세보기입니다.",
icon:"success",
button:"좋아요"});
}
<td class="title" onclick="detail(${row.board_no })"> = 몇 번째 글을 클릭했어
no값이 들어오는지 alert 확인 (swal 지우고 기본 alert만)
function detail(no){
alert(no);
}
클릭하면 text에 글 번호가 나옴.
function detail(no){
swal({
title:"Good job!",
text:"번호는 " + no,
icon:"success",
button:"좋아요"});
// alert(no);
}
modal 확인
function detail(no){}에 추가 : 모달이 잘 뜨는지 확인용도
// 모달 보이게 하기
let detailModal = new bootstrap.Modal('#detail', {}); // {옵션}
detailModal.show(); // detail modal을 보여줘
detail.jsp
내용보기 모달 만들기
모달 타이틀에 id 추가
<h5 class="modal-title" id="modalTitle">글 내용 보기</h5>
모달 보이게 하는 let 부분에 적용함.
모달 title에 글 번호가 뜸. title안의 text를 no로 보이도록.
let detailModal = new bootstrap.Modal('#detail', {}); // {옵션}
$("#modalTitle").text(no);
detailModal.show();
모달 제목, 내용에도 id 추가
글 내용보기 : id="modalTitle"
제목, 본문내용 : id="modalContent"
<!-- detail 모달 -->
<div class="modal" id="detail">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalTitle">글 내용 보기</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mt-2" id="modalContent">
제목<br>
본문내용
</div>
</div>
<div class="modal-footer">
Detail 모달 닫기
</div>
</div>
</div>
</div>
let detailModal = new bootstrap.Modal('#detail', {}); // {옵션}
$("#modalTitle").text(no);
$("#modalContent").text("변경된 내용입니다.");
detailModal.show();
-> title, content의 id를 변경한 후, function detail(no)에서 모달 보이게 하기
let detailModal = new bootstrap.Modal('#detail', {}); // {옵션}
$("#modalTitle").text(no);
$("#modalContent").text("변경된 내용입니다.");
detailModal.show();
jQuery
ajax를 쓰기 위해 jQuery 추가
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"
integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g=="
crossorigin="anonymous" referrerpolicy="no-referrer">
</script>
$.ajax({
url : "restDetail",
type : "post",
dataType : "text",
data : {'no' : no}, // 날라갈 데이터(no) text -> json
success : function(data){
alert(data);
},
error : function(error){
alert(error);
}
});
}
</script>
RestController.java
먼저 출력문으로 값이 오는지 확인함.
@Controller
public class RestController {
@Autowired
private BoardService boardService;
@PostMapping("/restDetail")
public BoardDTO restDetail(@Param("no") int no) {
// System.out.println("restDetail : " + no);
BoardDTO detail = boardService.detail(no); // detail에 담겨서 옵니다.
System.out.println(detail.getBoard_title());
// System.out.println(detail.getBoard_content());
return detail;
}
}
@ResponseBody 어노테이션 추가
@Controller
public class RestController {
@Autowired
private BoardService boardService;
@PostMapping("/restDetail")
public @ResponseBody BoardDTO restDetail(@Param("no") int no) { // 결과는 body에 출력해 (view를 안 보여주게)
BoardDTO detail = boardService.detail(no); // detail에 담겨서 옵니다.
return detail;
}
}
board.jsp
$("#modalTitle").text(data.board_title);
$("#modalContent").html(data.board_content);
detailModal.show();
function detail(no){
// 모달 보이게 하기
let detailModal = new bootstrap.Modal('#detail', {}); // {옵션}
$.ajax({
url : "/restDetail",
type : "post",
dataType : "json",
data : {'no' : no},
success : function(data){ //text -> json
//alert(data.board_title);
$("#modalTitle").text(data.board_title);
$("#modalContent").html(data.board_content);
detailModal.show();
},
error : function(error){
alert(error);
}
});
}
</script>
a링크와 onclick 동시에 사용하기.
<tbody>
<c:forEach items="${list }" var="row">
<tr>
<td onclick="detail(${row.board_no })">${row.board_no }</td>
<td class="title">
<a href="./detail?no=${row.board_no }">
${row.board_title }
<c:if test="${row.comment gt 0}">
<span class="badge">${row.comment }</span>
</c:if>
</a>
</td>
<td>${row.board_write }</td>
<td>${row.board_date }</td>
<td>${row.board_count }</td>
</tr>
</c:forEach>
</tbody>
detail.jsp
댓글쓰기 창과 버튼 css
<!-- 2024-02-19 -->
<hr>
<div class="container">
<form action="./commentWrite" method="post">
<div class="row">
<div class="col-xs-8 col-sm-8 col-md-11 col-xl-11">
<textarea class="form-control" style="height: 100%;"></textarea>
</div>
<div class="col-xs-4 col-sm-4 col-md-1 col-xl-1">
<button class="btn btn-success" style="width: 100px; height: 100%;">댓글쓰기</button>
</div>
</div>
</form>
</div>
BoardController.java
댓글은 컨트롤러를 따로 만들지 않고, board에 포함시켜서 작업함.
// 2024-02-19 댓글쓰기 psd = 글 번호 no, 댓글 내용 comment, 글쓴이 필요함.
@PostMapping("/commentWrite")
public String commentWrite() {
return "redirect:/detail";
}
detail.jsp
글 번호 가져오기
댓글 버튼 아래에 코드 추가
<input type="hidden" name="no" value="${detail.board_no }">
textarea에 name 붙여줌.
<textarea class="form-control" name="comment" style="height: 100%;"></textarea>
<div class="container">
<form action="./commentWrite" method="post">
<div class="row">
<div class="col-xs-8 col-sm-8 col-md-11 col-xl-11">
<textarea class="form-control" name="comment" style="height: 100%;"></textarea>
</div>
<div class="col-xs-4 col-sm-4 col-md-1 col-xl-1">
<button class="btn btn-success" style="width: 100px; height: 100%;">댓글쓰기</button>
</div>
</div>
<input type="hidden" name="no" value="${detail.board_no }">
</form>
</div>
detail.jsp 에 글 번호 no, 댓글 내용 comment 추가 -> CommentDTO 생성해서 불러오기
// 2024-02-19 댓글쓰기 psd = 글 번호(no), 댓글 내용(comment), 글쓴이 필요함.
@PostMapping("/commentWrite")
public String commentWrite(CommentDTO comment) {
System.out.println("접근?"); // 확인용도
return "redirect:/detail";
}
CommentDTO.java
import lombok.Data;
@Data
public class CommentDTO { // 필요한거 : 글 번호, 댓글 내용, 작성자 (mid)
private int no;
private String comment, mid;
}
CommentDTO 생성 후에 BoardController에서 값이 오는지 확인하기
System.out.println(comment.getNo());
System.out.println(comment.getComment());
System.out.println(comment.getMid());
BoardController.java
// 2024-02-19 댓글쓰기 psd = 글 번호 no, 댓글 내용 comment, 글쓴이 필요함.
@PostMapping("/commentWrite")
public String commentWrite(CommentDTO comment) {
int result = boardService.commetWrite(comment); // boardService 실행 시 dto를 가지고 날아감
System.out.println("댓글쓰기 결과 : " + result); // 1이면 정상, 0이면 에러
return "redirect:/detail";
}
-> boardService.commetWrite(comment);의 commentWrite가 없기 때문에 boardService에 생성해주기.
public int commetWrite(CommentDTO comment) {
comment.setMid("test2"); // mid에 있는 아이디 하나 불러오기
return boardDAO.commentWrite(comment); // DAO에게 일 시키기
}
-> commentWrite를 BoardDAO에 생성해주기
public int commentWrite(CommentDTO comment) {
return sqlSession.insert("board.commentWrite", comment);
}
board-mapper.xml
<!-- 2024-02-19 -->
<insert id="commentWrite" parameterType="commentDTO">
INSERT INTO comment (board_no, ccomment, mno)
VALUES (#{no}, #{comment}, (SELECT mno FROM member WHERE mid=#{mid}))
</insert>
mybatis-config.xml
<typeAlias type="org.-----.dto.CommentDTO" alias="commentDTO"/>
BoardController.java
public detail 부분 파라미터 값 변경
@Param("no) -> @RequestParam(value = "no", defaultValue = "0", required = true) 으로 수정
축약한다면 @RequestParam(value = "no")
@GetMapping("/detail")
public String detail(@RequestParam(value = "no", defaultValue = "0", required = true) String no, Model model) { // @Param : spring이 알아서 처리함
// @RequestParam : http 요청을 컨트롤러에 전달할 때 사용. url에서 오는 거
// no가 없으면 기본값은 "" 이걸로 가져감. (몇 번글로 넘어감)
// defaultValue를 0으로 세팅하면 바로 error로 넘어감. (0번 글이 없으니까)
// required 반드시 있어야 하는 경우 (없어도 가능함. 기본은 true로 되어있음 / 필요없는 경우는 false로 적음)
int reNo = util.str2Int(no);
if(reNo != 0) {
// 0이 아니라면 (정상: DB에 물어보기, 값 가져오기, 붙이기(model 객체), 이동하기)
BoardDTO detail = boardService.detail(reNo);
model.addAttribute("detail", detail);
return "detail"; // 주소창이 detail?no= 이렇게 detail이 들어감.
} else { // 0이라면 (비정상: 에러 페이지로 이동하기)
return "redirect:/error"; // controller에 있는 error매핑을 실행해 (http://localhost/error)
}
-> 글 번호를 받아서 글 번호로 페이지 이동하도록 return 코드 수정
// 2024-02-19 댓글쓰기 psd = 글 번호 no, 댓글 내용 comment, 글쓴이 필요함.
@PostMapping("/commentWrite")
public String commentWrite(CommentDTO comment) {
int result = boardService.commetWrite(comment); // boardService 실행 시 dto를 가지고 날아감
System.out.println("댓글쓰기 결과 : " + result); // 1이면 정상, 0이면 에러
return "redirect:/detail?no="+comment.getNo(); // 글 번호를 받아서 글 번호로 페이지 이동
}
}
board-mapper.xml
detail 부분 SQL 수정:
게시글의 상세 정보를 가져오는 데 사용되며, comment 서브쿼리를 사용하여 해당 게시글의 댓글 개수도 함께 조회
<select id="detail" resultType="boardDTO" parameterType="Integer">
SELECT b.board_no, b.board_title, b.board_content, m.mname as board_write, b.board_date, b.board_ip,
(SELECT COUNT(*) FROM comment WHERE board_no=b.board_no) AS comment
FROM board b JOIN member m ON b.mno=m.mno WHERE board_no=#{no} AND board_del ='1' <!-- mybatis 변수명 # -->
</select>
BoardController.java
sql 수정 후 콘솔에 출력되나 확인
boardcontroller의 detail if문에서 System.out.println("댓글 수 : "+ detail.getComment()); 출력문 추가해서 확인해보기.
@GetMapping("/detail")
public String detail(@RequestParam(value = "no", defaultValue = "0") String no, Model model) { // @Param : spring이 알아서 처리함
int reNo = util.str2Int(no);
if(reNo != 0) {
BoardDTO detail = boardService.detail(reNo);
model.addAttribute("detail", detail);
// 2024-02-19 psd 댓글 출력
System.out.println("댓글 수 : "+ detail.getComment());
return "detail"; // 주소창이 detail?no= 이렇게 detail이 들어감.
} else { // 0이라면 (비정상: 에러 페이지로 이동하기)
return "redirect:/error"; // controller에 있는 error매핑을 실행해 (http://localhost/error)
}
}
int reNo = util.str2Int(no);
if(reNo != 0) {
BoardDTO detail = boardService.detail(reNo);
model.addAttribute("detail", detail);
if(detail.getComment() > 0) { // 댓글이 1개 이상이면
List<CommentDTO> commentsList = boardService.commentsList(reNo);
model.addAttribute("commentsList", commentsList);
}
return "detail";
-> 위에서 만들어진 commentsList를 BoardService에 추가하기
public List<CommentDTO> commentsList(int no) {
return boardDAO.commentsList(no);
}
BoardDAO
public List<CommentDTO> commentsList(int no) {
return sqlSession.selectList("board.commentsList", no);
}
board-mapper.xml
<select id="commentsList" resultType="commentDTO" parameterType="Integer">
SELECT cno, ccomment AS comment, cdate, clike, mname, cip
FROM commentview
WHERE board_no=#{no}
</select>
CommentDTO
DTO에 cno, mname, cdate, clike, cip 추가하기
import lombok.Data;
@Data
public class CommentDTO {
private int no, cno, board_no, clike, mno;
private String comment, mid, mname, cdate, cip;
}
board-mapper.xml
<resultMap type="commentDTO" id="commentDTOmap">
<result column="cno" property="no"/>
<result column="board_no" property="board_no"/>
<result column="ccomment" property="comment"/>
<result column="cdate" property="cdate"/>
<result column="clike" property="clike"/>
<result column="mno" property="mno"/>
<result column="mid" property="mid"/>
<result column="mname" property="mname"/>
<result column="cip" property="cip"/>
</resultMap>
-> 생성한 resultMap(id = commentDTOmap)을 resultType -> resultMap으로 변경 후 resultMap에 적용하기
<select id="commentsList" parameterType="Integer" resultMap="commentDTOmap" >
SELECT cno, ccomment, cdate, clike, mid, mname, cip
FROM commentview
WHERE board_no=#{no}
</select>
detail.jsp
-> detail.jsp의 댓글출력창 입력
<!-- 댓글 출력창 20240219 -->
<c:forEach items="${commentsList }" var="c">
${c.no } / ${c.comment } / ${c.cdate } / ${c.clike } / ${c.mno } / ${c.mid } / ${c.mname } / ${c.cip } <br>
</c:forEach>
-> 댓글 출력창 css 만들기 (bootstrap)
<!-- 댓글 출력창 20240219 -->
<div class="mt-2">
<c:forEach items="${commentsList}" var="c">
<div class="card mb-3">
<div class="card-header bg-success text-white">
${c.no} / ${c.cdate} / ${c.clike} / ${c.mno} / ${c.mid} / ${c.mname}
</div>
<div class="card-body">
<p class="card-text">${c.comment}</p>
</div>
</div>
</c:forEach>
</div>
-> 게시글 디테일 부분에 아이콘 추가하기
다운받은 이미지 img 폴더에 넣기.
${detail.board_write } 뒤에 아이콘 추가하기
아이콘을 누르면 넘어가도록 onclick 기능도 추가하기. onclick="deletePost(${detail.board_no})"
<!-- 게시판 -->
<br>
<br>
<section class="page-section" id="detail">
<div class="container">
<div class="text-center">
<h2 class="section-heading text-uppercase">게시글 디테일</h2>
</div>
<div class="card mb-4" style="min-height: 500px;">
<div class="card-body">
<div class="h2">${detail.board_title }</div>
<div class="row p-2 bg-secondary">
<div class="col align-middle text-start">${detail.board_write }
<img alt="edit" src="./assets/img/pencil.png">
<img alt="delete" src="./assets/img/deletey.png" title="글 삭제" onclick="deletePost(${detail.board_no})">
</div>
<div class="col align-middle text-end">${detail.board_date }</div>
</div>
<div class="mt-4 vh -75">${detail.board_content }</div>
</div>
</div>
<button class="btn btn-warning" onclick="history.back()">게시판으로</button>
<button class="btn btn-warning" onclick="history.go(-1)">게시판으로</button>
-> function deletePost() 생성
swal.fire 사용해서 alert창 뜨도록 만들기
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script type="text/javascript">
function deletePost(){
Swal.fire({
title: "글을 삭제합니다",
//text: "post를 삭제합니다.",
icon: "warning",
showCancelButton: true,
confirmButtonText: "Yes",
cancelButtonText: "No",
}).then(result => {
if (result.isConfirmed) {
Swal.fire("삭제했습니다.","", "success");
}
});
}
</script>
'개발 공부 Today I Learned' 카테고리의 다른 글
[국비 61일차 TIL_2] 필수 파일의 대략적인 기본 로직 정리 (0) | 2024.02.20 |
---|---|
[국비 61일차 TIL] spring 글 삭제, 페이징, 로그인 (1) | 2024.02.20 |
[국비 59일차 TIL] Spring - 게시판 detail, error, 모달 창 구현 (0) | 2024.02.16 |
[국비 58일차 TIL] 스프링 다시 만들기 3 (0) | 2024.02.15 |
[국비 57일차 TIL] 스프링 설정하기 반복 (0) | 2024.02.14 |
댓글