✔ BoardController.java
package edu.example.ex.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import edu.example.ex.service.BoardService; import edu.example.ex.vo.BoardVO; import lombok.extern.slf4j.Slf4j; @Slf4j // 로그 @Controller @RequestMapping("/jboard/*") public class BoardController { @Autowired private BoardService boardService; @GetMapping("/list") public String view_list(Model model) { log.info("view_list() .."); model.addAttribute("boards", boardService.getList()); return "/board/list"; } @GetMapping("/content_view") public String content_view(BoardVO boardVO, Model model) { log.info("content_view() .."); int bid = boardVO.getBid(); boardVO = boardService.get(bid); model.addAttribute("content_view", boardVO); return "/board/content_view"; } @PostMapping("/modify") public String modify(BoardVO boardVO, Model model) { log.info("modify() .."); int rn = boardService.modify(boardVO); log.info("modify() .. result number::" + rn); return "redirect:list"; } @GetMapping("/delete") public String delete(BoardVO boardVO, Model model) { log.info("delete() .."); int rn = boardService.delete(boardVO); return "redirect:list"; } @GetMapping("/write_view") public String write_view() { return "/board/write_view"; } @PostMapping("/write") public String write(BoardVO boardVO) { log.info("write() .."); int rn = boardService.write(boardVO); return "redirect:list"; } @GetMapping("/reply_view") public String reply_view(BoardVO boardVO, Model model) { log.info("reply_view().."); model.addAttribute("reply_view", boardService.get(boardVO.getBid())); return "/board/reply_view"; } @GetMapping("/reply") public String reply(BoardVO boardVO) { log.info("reply() .."); boardService.registerReply(boardVO); return "redirect:list"; // 로직 수행 후 list로 redirect 함 } }
✔ BoardService.java
package edu.example.ex.service; import java.util.List; import edu.example.ex.vo.BoardVO; public interface BoardService { public List<BoardVO> getList(); // 리스트 public BoardVO get(int bno); // 글 보기 int modify(BoardVO board); // 글 수정 int delete(BoardVO board); // 글 삭제 int write(BoardVO board); // 글 등록 void registerReply(BoardVO board); // 댓글 등록 }
✔ BoardServiceImpl.java
package edu.example.ex.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import edu.example.ex.mapper.BoardMapper; import edu.example.ex.vo.BoardVO; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j @Service @RequiredArgsConstructor // +@Autowired 하면 생성자 주입 (없으면 필드 주입) public class BoardServiceImpl implements BoardService { @Autowired private final BoardMapper mapper; @Override public List<BoardVO> getList() { log.info("getList() .."); return mapper.getList(); } @Override public BoardVO get(int bid) { log.info("get(int bid) .."); return mapper.read(bid); } @Override public int modify(BoardVO board) { log.info("modify() .."); return mapper.update(board); } @Override public int delete(BoardVO board) { log.info("delete() .."); return mapper.remove(board); } @Override public int write(BoardVO board) { log.info("write() .."); return mapper.insert(board); } @Transactional @Override public void registerReply(BoardVO board) { log.info("registerReply() .."); mapper.updateShape(board); mapper.insertReply(board); } }
✔ BoardMapper.java
package edu.example.ex.mapper; import java.util.List; import org.apache.ibatis.annotations.Mapper; import edu.example.ex.vo.BoardVO; @Mapper // mybatis에 사용할 거라는 것을 알려주는 애너테이션 public interface BoardMapper { public List<BoardVO> getList(); public BoardVO read(int bid); // 파라미터는 url로 넘어오는 bid값을 의미 public int update(BoardVO board); // ServiceImpl.java에서의 update 정의해주기 (글 수정) public int remove(BoardVO board); public int insert(BoardVO board); void updateShape(BoardVO board); // 답글 위치 void insertReply(BoardVO board); // 답글 등록 }
✔ 🔎BoardMapper.xml
<?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 namespace="edu.example.ex.mapper.BoardMapper"> <select id="getList" resultType="edu.example.ex.vo.BoardVO"> <!-- id는 함수이름 resultType은 BoardVO --> <![CDATA[ select * from mvc_board order by bGroup desc, bStep asc ]]> </select> <select id="read" resultType="edu.example.ex.vo.BoardVO"> <![CDATA[ select * from mvc_board where bid = #{bid} ]]> <!-- content_view 부분 / #{bid}는 파라미터를 넘기는 과정 --> </select> <update id="update"> <![CDATA[ update mvc_board set bname=#{bname}, btitle=#{btitle}, bcontent=#{bcontent} where bid =#{bid} ]]> <!-- modify 부분 / bname=#{getBname()}과 같은 의미 --> </update> <delete id="remove"> <![CDATA[ delete from mvc_board where bid = #{bid} ]]> </delete> <insert id="insert"> <![CDATA[ insert into mvc_board (bid, bname, btitle, bcontent, bhit, bgroup, bstep, bindent) values (mvc_board_seq.nextval, #{bname}, #{btitle}, #{bcontent}, 0, mvc_board_seq.currval, 0, 0) ]]> </insert> <!--댓글을 하나씩 미뤄서 정렬을 해줘야 하기 때문에 세로 정렬을 bstep에 +1로 한칸씩 미뤄내줘야한다. --> <update id="updateShape"> <![CDATA[ update mvc_board set bstep = bstep + 1 where bgroup =#{bgroup} and bstep > #{bstep} ]]> </update> <insert id="insertReply" > <![CDATA[ insert into mvc_board (bid, bname, btitle, bcontent, bgroup, bstep, bindent) values (mvc_board_seq.nextval, #{bname}, #{btitle},#{bcontent}, #{bgroup}, #{bstep}+1, #{bindent}+1) ]]> </insert> </mapper>
✔ list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <table width="500" cellpadding="0" cellspacing="0" border="1"> <tr> <td>번호</td> <td>이름</td> <td>제목</td> <td>날짜</td> <td>히트</td> </tr> <c:forEach var="board" items="${boards}"> <tr> <td>${board.bid}</td> <td>${board.bname}</td> <td><c:forEach begin="1" end="${board.bindent}">-</c:forEach> <a href="${pageContext.request.contextPath}/jboard/content_view?bid=${board.bid}">${board.btitle}</a></td> <td>${board.bdate}</td> <td>${board.bhit}</td> </tr> </c:forEach> <tr> <td colspan="5"><a href="write_view">글작성</a></td> </tr> </table> </body> </html>
- 결과
✔ content_view.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript"> $(document).ready(function (){ $('#a-delete').click(function(event){ //prevendDefault()는 href로 연결해 주지 않고 단순히 click에 대한 처리를 하도록 해준다. event.preventDefault(); console.log("ajax 호출전"); $.ajax({ type : "DELETE", url : "${pageContext.request.contextPath}/restful/board/" + "${content_view.bid}", data:{"bid":"${content_view.bid}"}, success: function (result) { console.log(result); if(result == "SUCCESS"){ //getList(); } }, error: function (e) { console.log(e); } }) }); }); </script> </head> <body> <table id="list-table" width="500" cellpadding="0" cellspacing="0" border="1"> <form action="modify" method="post"> <input type="hidden" name="bid" value="${content_view.bid}"> <tr> <td> 번호 </td> <td> ${content_view.bid} </td> </tr> <tr> <td> 히트 </td> <td> ${content_view.bhit} </td> </tr> <tr> <td> 이름 </td> <td> <input type="text" name="bname" value="${content_view.bname}"></td> </tr> <tr> <td> 제목 </td> <td> <input type="text" name="btitle" value="${content_view.btitle}"></td> </tr> <tr> <td> 내용 </td> <td> <textarea rows="10" name="bcontent" >${content_view.bcontent}</textarea></td> </tr> <tr > <td colspan="2"> <input type="submit" value="수정"> <a href="list">목록보기</a> <a href="delete?bid=${content_view.bid}">삭제</a> <a href="reply_view?bid=${content_view.bid}">답변</a></td> </tr> </form> </table> </body> </html>
- 결과
✔ write_view.jsp
<%@ page language="java" contentType="text/html;charset=utf-8" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <html> <head> <title>write_view</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script type="text/javascript"> $(document).ready(function() { $("#updateForm").submit(function(event) { //prevendDefault()는 href로 연결해 주지 않고 //단순히 click에 대한 처리를 하도록 해준다. event.preventDefault(); let bname = $("#input_bname").val(); let btitle = $("#input_btitle").val(); let bcontent = $("#input_bcontent").val(); let form = { bname : bname, btitle : btitle, bcontent : bcontent }; /* $.ajax({ type : `http method type`, url : `url`, data : `서버에 전송할 데이터`, contentType : "전송할 데이터 타입", //기본 값 : "application / x-www-form-urlencoded; charset = UTF-8" dataType : '서버로 부터 수신할 데이터 타입', //아무것도 지정하지 않으면 jQuery는 응답의 MIME 유형을 기반으로 해석을 시도 error : `에러 발생시 수행할 함수`, success : `성공시 수행할 함수` }); */ console.log(JSON.stringify(form)); $.ajax({ type : "POST", url : "/boards/", cashe : false, contentType : 'application/json; charset=utf-8', data : JSON.stringify(form), success : function(result) { console.log(result); //location.href = "/list"; //$(location).attr('href', '/rest_board.html'); $(location).attr('href', '/list2'); }, error : function(e) { console.log(e); } }); }); }); </script> </head> <body> <table width="500" cellpadding="0" cellspacing="0" border="1"> <form action="write" method="post"> <tr> <td>이름</td> <td><input id="input_bname" type="text" name="bname" size="50"> </td> </tr> <tr> <td>제목</td> <td><input id="input_btitle" type="text" name="btitle" size="50"></td> </tr> <tr> <td>내용</td> <td><textarea id="input_bcontent" name="bcontent" rows="10"></textarea> </td> </tr> <tr> <td colspan="2"><input type="submit" value="입력"> <a href="list">목록보기</a></td> </tr> </form> </table> </body> </html>
- 결과
✔ reply_view.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <table width="500" cellpadding="0" cellspacing="0" border="1"> <form action="reply" method="get"> <input type="hidden" name="bid" value="${reply_view.bid}"> <input type="hidden" name="bgroup" value="${reply_view.bgroup}"> <input type="hidden" name="bstep" value="${reply_view.bstep}"> <input type="hidden" name="bindent" value="${reply_view.bindent}"> <tr> <td>번호</td> <td>${reply_view.bid}</td> </tr> <tr> <td>히트</td> <td>${reply_view.bhit}</td> </tr> <tr> <td>이름</td> <td><input type="text" name="bname" value="${reply_view.bname}"></td> </tr> <tr> <td>제목</td> <td><input type="text" name="btitle" value="${reply_view.btitle}"></td> </tr> <tr> <td>내용</td> <td><textarea rows="10" name="bcontent">${reply_view.bcontent}</textarea></td> </tr> <tr> <td colspan="2"><input type="submit" value="답변"> <a href="list">목록</a></td> </tr> </form> </table> </body> </html>
- 결과