이전 게시글은 여기 >>
Servlet 과 JSP를 이용한(모델2 형식) 블로그 만들기(10) - DTO(Data Transfer Object)를 이용한 블로그 상세보기 만들기
이제 수정과 삭제를 만들어보자. 지금까지 했으면 매우.. 아주 쉽다.
먼저 버튼을 눌렀을 때, 수정과 삭제를 담당해줄 액션을 만들자.
- BoardController.java의 라우터 메소드
public Action router(String cmd) {
if(cmd.equals("home")) {
// 홈페이지로 이동
return new BoardHomeAction(); //Board의 목록
}else if(cmd.equals("write")) {
// 글쓰기 페이지로 이동
return new BoardWriteAction();
}else if(cmd.equals("writeProc")) {
// 글쓰기 정보 넘기기
return new BoardWriteProcAction();
}else if(cmd.equals("detail")) {
//상세보기
return new BoardDetailAction();
}else if(cmd.equals("update")) {
//수정페이지
return new BoardUpdateAction();
}else if(cmd.equals("updateProc")) {
//수정페이지
return new BoardUpdateProcAction();
}else if(cmd.equals("delete")) {
//수정페이지
return new BoardDeleteProcAction();
}
return null;
}
먼저, 버튼을 눌렀을 때 발생하는 액션을 보자.
여기서 주목해야할 점은 "수정"이라는 점이다. 생각해보자. 100만줄을 써놨는데, 수정할때마다 다시 써야한다..!
이 얼마나 빡치겠는가? 그러니 데이터베이스에서 값을 가져와서 미리 텍스트 입력 폼에 넣어줘야 한다.
그러려면 먼저 데이터베이스에서 값을 가져와야겠지?
package com.cos.blog.action.board;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.cos.blog.action.Action;
import com.cos.blog.dto.DetailResponseDto;
import com.cos.blog.repository.BoardRepository;
import com.cos.blog.util.Script;
public class BoardUpdateAction implements Action {
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(
request.getParameter("id")==null||
request.getParameter("id").equals("")
) {
Script.back("잘못된 접근입니다.", response);
return;
}
int id=Integer.parseInt(request.getParameter("id"));
BoardRepository boardRepository=BoardRepository.getInstance();
DetailResponseDto dto = boardRepository.findById(id);
if(dto!=null) {
request.setAttribute("dto", dto);
//request를 유지하기 때문에 데이터를 담고 이동할때 사용
RequestDispatcher dis=request.getRequestDispatcher("board/update.jsp");
dis.forward(request, response);
}else {
Script.back("잘못된 접근입니다.", response);
}
}
}
상세보기와 로직은 비슷하다. 값을 가져와서, DTO에 넣고, 값을 이동시킨다..!
이제 가져온 값을 value와, textarea의 태그 사이에 입력해주면 된다. 마찬가지로 el값을 이용해서 dto 내부에 가져온 값을 넣어준다.
- update.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="../include/nav.jsp"%>
<%@ include file="../include/authentication.jsp"%>
<div class="container">
<form action="/blog/board?cmd=updateProc" method="post">
<input type="hidden" value="${dto.board.id }" name="id"/>
<div class="form-group">
<label for="title">title:</label>
<input value=${dto.board.title } type="text" class="form-control" placeholder="title" id="title" name="title">
</div>
<div class="form-group">
<label for="content">content:</label>
<textarea class="form-control" rows="5" id="summernote" name="content">
${dto.board.content }
</textarea>
</div>
<button type="submit" class="btn btn-primary">수정하기</button>
</form>
</div>
<script>
$(document).ready(function() {
$('#summernote').summernote({
tabsize: 2,
height: 300
});
});
</script>
<%@ include file="../include/footer.jsp"%>
일단 수정되는 화면만 보자.
텍스트 입력창에 데이터베이스의 값이 들어온 것을 확인할 수 있다.
이제 "수정하기"를 누르면 수정되어서 값이 넘어가는걸 구현해보자.
수정하기 버튼을 누르면 updateProc가 작동하도록 구현할 것이다.
앞에 올려둔 라우터를 참조하면서 액션을 만들어보자,
package com.cos.blog.action.board;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.cos.blog.action.Action;
import com.cos.blog.model.Board;
import com.cos.blog.model.Users;
import com.cos.blog.repository.BoardRepository;
import com.cos.blog.util.Script;
public class BoardUpdateProcAction implements Action {
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 0. 세션 유효성 검사
HttpSession session = request.getSession();
if (session.getAttribute("principal") == null) {
Script.outText("잘못된 접근입니다.", response);
}
// 1. request에 title이 null인지 공백인지 확인
if (request.getParameter("id") == null ||
request.getParameter("id").equals("")||
request.getParameter("title") == null ||
request.getParameter("title").equals("")||
request.getParameter("content") == null ||
request.getParameter("content").equals("")) {
Script.back("실패하셨습니다.", response);
return;
}
// 2. request에 title 값과 content 값 받기
int id = Integer.parseInt(request.getParameter("id"));
String title = request.getParameter("title");
String content = request.getParameter("content");
// 3. title 값과 content값, pricipal.getId()을 board 오브젝트에 담기
Board board = Board.builder()
.id(id)
.title(title)
.content(content)
.build();
// 3. Repository 연결해서 save(board) 함수 호출
BoardRepository boardRepository = BoardRepository.getInstance();
int result = boardRepository.update(board);
// 4. result==1이면 성공로직(index.jsp)로 이동
if (result == 1) {
Script.href("수정 성공.", "/blog/board?cmd=detail&id="+id, response);
} else {
// 5. result != 1이면 실패로직(history.back())
Script.back("게시글 등록에 실패하셨습니다.", response);
}
}
}
수정되는 것은 블로그의 글과 내용밖에 없으므로 board에만 객체를 담아 이동해도 괜찮다.
- BoardRepository.java의 updata 메소드
public int update(Board board) {
final String SQL="Update board set title =?, content=? where id = ? ";
try {
conn=DBConn.getConnection();
pstmt = conn.prepareStatement(SQL);
//물음표 완성하기
pstmt.setString(1, board.getTitle());
pstmt.setString(2, board.getContent());
pstmt.setInt(3, board.getId());
return pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
System.out.println(TAG+"update : "+e.getMessage());
}finally {
DBConn.close(conn, pstmt);
}
return -1;
}
여기서 수정이 정상적으로 반영되었으면 executeUpdate가 1을 반환할 것이다.
이제 이 값을 가지고 정상반영되었으면 cmd=detail을 통해 수정된 페이지의 게시글 id을 출력할 것이다.
아니라면, 수정반영이 되지 않았음을 알리고 다시 수정페이지로 이동시킨다.
정말 수정되는지 확인해봅시다!
정말 내용물이 도도도도도도에서 도도도도도돗으로 제대로 수정되네요.
2. 삭제
삭제는 뭔 화면 띄워줄 필요도 없이 그냥 삭제시키면 되지 않나? (너무하나)
다만, 문제라면 delete의 경우 원래 delete방식으로 이동시켜야 하는데, 모델2 방식의 경우 post와 get 방식만 사용한다. 그러나 delete의 경우 get방식이 아닌 post의 방식을 이용해야 하기 때문에 어쩔수 없이 ajax로 수정합니다.
삭제버튼을 누르면 그냥 바로 데이터베이스를 타고 넘어가서 쿼리문으로 삭제하고 홈으로 돌아가면 끝~
라우터를 보며 액션을 만들어줍시다.
- BoardDeleteProcAction.java
package com.cos.blog.action.board;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.cos.blog.action.Action;
import com.cos.blog.repository.BoardRepository;
import com.cos.blog.util.Script;
public class BoardDeleteProcAction implements Action {
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session=request.getSession();
if(session.getAttribute("principal")==null) {
Script.outText("잘못된 접근입니다.", response);
return;
}
if(
request.getParameter("id")==null||
request.getParameter("id").equals("")
) {
Script.outText("잘못된 접근입니다.", response);
return;
}
int id=Integer.parseInt(request.getParameter("id"));
BoardRepository boardRepository=BoardRepository.getInstance();
int result = boardRepository.deleteByID(id);
PrintWriter out=response.getWriter();
out.print(result);
}
}
(임포트 코드가 길어서 그렇지 실제 코드는 길지 않습니다.)
간단합니다. 게시글 아이디를 받아 그 아이디로 게시글을 찾고, 그 게시글을 삭제만 하면 되는 아주 간단한 로직입니다.
- BoardRepository.java
public int deleteByID(int id) {
final String SQL="delete from board where id=?";
try {
conn=DBConn.getConnection();
pstmt = conn.prepareStatement(SQL);
//물음표 완성하기
pstmt.setInt(1, id);
return pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
System.out.println(TAG+"deleteByID : "+e.getMessage());
}finally {
DBConn.close(conn, pstmt);
}
return -1;
}
마지막으로, 이 url을 넘겨줄 script를 footer의 아래에 붙이면 완성
- detail.jsp의 마지막 부분(ajax)
<script>
function deleteById(boardId){
$.ajax({
type:"post",
url:"/blog/board?cmd=delete&id="+boardId,
dataType:"text"
}).done(function(result){
console.log(result);
if(result==1){
alert("삭제 성공");
location.href="/blog/index.jsp";
}else{
alert("삭제 실패");
}
}).fail(function(error){
console.log(error);
console.log(error.responseText);
console.log(error.status);
alert("서버 오류");
});
}
</script>
그럼 이제 도도도돗을 삭제시켜봅시다.
정말 204번 도도도도도돗이 사라졌습니다.
이제 이거랑 진짜 비슷한 회원수정도 해봅시다.