1. BoardApiController에서 @DeleteMapping("api/boards/{id}") 만들기
- 아이디 중복체크는 무조건 ajax로 해야 함!
- 아니면 적은 글이 다 날아감
- 로직이 실행이 안됨
- res에 html을 담아준다는 것은 말이 안됨 → index를 리턴하면 망함
package shop.mtcoding.blog.board; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RequiredArgsConstructor @RestController // 데이러틀 리턴 public class BoardApiController { private final BoardRepository boardRepository; // DI // 삭제하기 @DeleteMapping("api/boards/{id}") // 보드 중에 몇번을 삭제할게 public ApiUtil<?> deleteById(@PathVariable Integer id) { boardRepository.deleteById(id); return new ApiUtil<>(null); // 삭제는 데이터를 줄 것이 없음 } // 주소 만들기 @GetMapping("api/boards") // 보드 줘라는 주소, 복수는 보드들 줘, 보드들 중에 1번 줘해서 복수형을 씀 public ApiUtil<List<Board>> findAll(HttpServletResponse response) { //response.setStatus(401); List<Board> boardList = boardRepository.selectAll(); // 상태코드랑 메세지랑 같이 줘야함 return new ApiUtil<>(boardList); // MessageConverter라는 클래스가 오브젝트를 응답할때 자동 발동함 } }
2. BoardRepository에 deleteById() 만들기
package shop.mtcoding.blog.board; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.util.List; @RequiredArgsConstructor @Repository public class BoardRepository { private final EntityManager em; public List<Board> selectAll() { Query query = em.createNativeQuery("select * from board_tb order by id desc ", Board.class); List<Board> boardList = query.getResultList(); // 못찾으면 빈 컬렉션을 준다 (크기=0) return boardList; } public Board selectOne(int id) { Query query = em.createNativeQuery("select * from board_tb where id = ?", Board.class); query.setParameter(1, id); try { Board board = (Board) query.getSingleResult(); return board; } catch (Exception e) { return null; } } @Transactional public void insert(String title, String content, String author) { Query query = em.createNativeQuery("insert into board_tb(title, content, author) values(?, ?, ?)"); query.setParameter(1, title); query.setParameter(2, content); query.setParameter(3, author); query.executeUpdate(); } @Transactional public void deleteById(Integer id) { Query query = em.createNativeQuery("delete from board_tb where id = ?"); query.setParameter(1, id); query.executeUpdate(); // insert, update, delete는 커밋이 발동 } }
3. BoardApiController에 api/boards/{id}에 null일 때 셋팅하기
package shop.mtcoding.blog.board; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RequiredArgsConstructor @RestController // 데이러틀 리턴 public class BoardApiController { private final BoardRepository boardRepository; // DI // 삭제하기 @DeleteMapping("api/boards/{id}") // 보드 중에 몇번을 삭제할게 public ApiUtil<?> deleteById(@PathVariable Integer id, HttpServletResponse response) { Board board = boardRepository.selectOne(id); if (board == null) { response.setStatus(404); return new ApiUtil<>(404, "해당 데이터를 찾을 수 없습니다"); } boardRepository.deleteById(id); return new ApiUtil<>(null); // 삭제는 데이터를 줄 것이 없음 } // 주소 만들기 @GetMapping("api/boards") // 보드 줘라는 주소, 복수는 보드들 줘, 보드들 중에 1번 줘해서 복수형을 씀 public ApiUtil<List<Board>> findAll(HttpServletResponse response) { //response.setStatus(401); List<Board> boardList = boardRepository.selectAll(); // 상태코드랑 메세지랑 같이 줘야함 return new ApiUtil<>(boardList); // MessageConverter라는 클래스가 오브젝트를 응답할때 자동 발동함 } }
4. index.mustache에 del함수 추가하기
{{> layout/header}} <div class="container p-5"> <table class="table table-striped"> <thead> <tr> <th>번호</th> <th>제목</th> <th>내용</th> <th>작성자</th> <th></th> </tr> s </thead> <tbody id="board-box"> </tbody> </table> </div> <script> // 나중에 js 파일을 따로 빼서 링크를 걸게 됨 function del(boardId) { $.ajax({ url: `api/boards/${boardId}`, type: "delete" }).done((res) => { $(`#board-${boardId}`).remove(); }).fail((res) => { alert(res.responseJSON.msg); }); } // 페이지 로드될때 무조건 시작되야 도니까 밖에 있음 $.ajax({ url: "/api/boards", //서버가 같으면 8080뒤에 있는 주소는 뒤에 것만 적어도 됨 type: "get" // poset면 컨텐트타입, 데이터가 추가로 들어감 }).done((res) => { // 정상(200)이면 done->바디 데이터 console.log("통신 성공"); console.log(res); // for(board of boardList){}도 가능하나 stream api를 쓰는 것이 좋음 let boardList = res.body; boardList.forEach((board) => { $("#board-box").append(render(board)); }); }).fail((res) => { //console.log(res); alert(res.responseJSON.msg); // location.herf="/loginForm"; }); // 실패면 다 fail function render(board) { return `<tr id="board-${board.id}"> <td>${board.id}</td> <td>${board.title}</td> <td>${board.content}</td> <td>${board.author}</td> <td> <div class="d-flex"> <button onclick="del(${board.id})" class="btn btn-danger">삭제</button> <form action="/board/${board.id}/updateForm" method="get"> <button class="btn btn-warning">수정</button> </form> </div> </td> </tr>`; } </script> {{> layout/footer}}
5. 삭제 실패시 강제로 F5하기
- F5 하면서 확인하는게 폴링 기법
{{> layout/header}} <div class="container p-5"> <table class="table table-striped"> <thead> <tr> <th>번호</th> <th>제목</th> <th>내용</th> <th>작성자</th> <th></th> </tr> </thead> <tbody id="board-box"> </tbody> </table> </div> <script> // 나중에 js 파일을 따로 빼서 링크를 걸게 됨 function del(boardId) { $.ajax({ url: `api/boards/${boardId}`, type: "delete" }).done((res) => { $(`#board-${boardId}`).remove(); }).fail((res) => { alert(res.responseJSON.msg); location.reload(); // F5 강제로 해주기 }); } // 페이지 로드될때 무조건 시작되야 도니까 밖에 있음 $.ajax({ url: "/api/boards", //서버가 같으면 8080뒤에 있는 주소는 뒤에 것만 적어도 됨 type: "get" // poset면 컨텐트타입, 데이터가 추가로 들어감 }).done((res) => { // 정상(200)이면 done->바디 데이터 console.log("통신 성공"); console.log(res); // for(board of boardList){}도 가능하나 stream api를 쓰는 것이 좋음 let boardList = res.body; boardList.forEach((board) => { $("#board-box").append(render(board)); }); }).fail((res) => { //console.log(res); alert(res.responseJSON.msg); // location.herf="/loginForm"; }); // 실패면 다 fail function render(board) { return `<tr id="board-${board.id}"> <td>${board.id}</td> <td>${board.title}</td> <td>${board.content}</td> <td>${board.author}</td> <td> <div class="d-flex"> <button onclick="del(${board.id})" class="btn btn-danger">삭제</button> <form action="/board/${board.id}/updateForm" method="get"> <button class="btn btn-warning">수정</button> </form> </div> </td> </tr>`; } </script> {{> layout/footer}}
6. 푸시 서버(push server)
- 일반적으로 클라이언트 애플리케이션으로 메시지를 보내는 서버
- 푸시 알림, 채팅 메시지, 업데이트 알림 등 다양한 형태
- 주로 모바일 애플리케이션에서 사용
- 클라이언트 애플리케이션이 서버에 대한 요청 없이도 서버에서 메시지를 받을 수 있게 해줌
Share article