포트폴리오/SPRINGBOOT 옛날

3-10 수정과 삭제

서버관리자 페페 2022. 10. 10. 18:58

단 하나의 맥락

- Update / Delete 기능 구현

 

 

 


Semiflow Bundle

 

(Question Update)

- modifyDate 

- 수정 버튼

- 수정 버튼 > @GetMapping

- CSRF 토큰 수동발행

- Service에서 modify method 추가

- Controller에서 서비스의 modify 메서드 연동

 

(Question Delete)

- 삭제 버튼 

- 삭제 버튼 확인창 자바스크립트 연동

- 자바스크립트 블록 layout.html에 삽입

- QuestionService에 pubic void delete 추가

- QuestionController에 public String questiondelete 기능 구현

 

(Answer Update)

- 답변 수정 버튼 추가

- AnswerService에서 getAnswer, modify 기능 구현

- AnswerController 




자각

 

(질문 수정)

 

수정 일시를 추가

> Quesiton, Answer Entity에

 

  • private LoaclDateTIme modifyDate; 

 

 

-

 

수정 버튼 추가

> question_detail 에

 

날짜 카드 밑에

 

  • <div class="my-3"></div> 내부
  • <a th:href="@{|/question/modify/${question.id}|}"  class="btn btn-sm btn-outline-secondary"
  • sec:authorize="isAuthenticated()"
  • th:if="${question.author != null and #authentication.getPrincipal().getUsername() == question.author.username}"
  • th:text="수정"></a>

 

 

 

-

 

@GetMapping으로 수정양식 불러오기 + 양식 내부에 기존 question 내용이 들어가 있다

 

> QuestionController에

 

// import org.springframework.http.HttpStatus;

// import org.springframework.web.server.ResponseStatusException;

 

  • @PreAuthorize("isAuthenticated()")
  • @GetMapping("/modify/{id}")
  • M : public String questionModify
  • S : (QuestionForm questionForm, @PathVariable("id") Integer id, Principal principal)
  • A1 : Question question = this.questionService.getQuestion(id);
  • A2 : if (!question.getAuthor().getUsername().equals(principal.getName())) {}
    • throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "수정권한이 없습니다.");
  • A3 : questionForm.setSubject(question.getSubject);
  • A4 : questionForm.setContent(question.getContent);
  • A5 : return "question_form";

추가

 

-

 

CSRF 토큰을 수동으로 추가한다

 

> question_form.html에

 

폼 형식에

  • <form th:action="@{/question/create}"  th:object="${questionForm}"  method="post"></form>

 

를 삭제하고, 내부 에러 메세지 위

  • <input type="hidden"  th:name="${_csrf.parameterName}"  th:value="${_csrf.token}" />

 

 

-

 

> QuestionService에 modify 메서드 신규 작성

 

  • public void modify(Question question, String subject, String content)
  • A1 : question.setSubject(subject);
  • A2 : question.setContent(content);
  • A3 : question.setModifyDate(LocalDateTime.now());
  • A4 : this.questionRepository.save(question);

 

-

 

> QuestionController에 @PostMapping 추가

 

  • @PreAuthorize("isAuthenticated()")
  • @PostMapping("/modify/{id}")
  • M : public String questionModify
  • S : (@Valid QuestionForm questionForm, BindingResult bindingResult, Principal principal, @PathVariable("id") Integer id) {}
  • A1 : if(bindingResult.hasErrors())
    • { retrun "question_form";}
  • A2 : Question question = this.questionService.getQuestion(id);
  • A3 : if (!question.getAuthor().getUsername().equals(principal.getName())) 
    • {throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "수정권한이 없습니다.");}
  • A4 : this.questionService.modify(question, questionForm.getSubject()), questionForm.getContent());
  • A5 : return String.format("redirect:/question/detail/%s", id);

 

 

로컬 서버를 실행시켜, 수정 버튼이 잘 동작하는 지 확인한다

 

 

-

 

질문 삭제

 

질문 삭제 버튼을 추가하기 위해

> question_detail.html 에서

 

  • <a href="javascript:void(0)" 
  • th:data-uri="@{|/question/delete/${question.id}|}" 
  • class="delete btn btn-sm btn-outline-secondary" 
  • sec:authorize="isAuthenticated()"
  • th:if="${question.author !=null and #authentication.getPrincipal().getUsername() == question.quthor.username}"
  • th:text="삭제"></a>

수정버튼 하단에 작성

 

 

-

 

자바스크립트 블록을 추가하기 위해

 

> layout.html 에서

 

화면 렌더링이 완료된 후에 작동할 수 있도록 바디 태그 바로 위에 삽입하고

 

  • <!-- JS Start -->
  • <th:block layout:fragment="script"></th:block>
  • <!-- JS End -->

 

> question_detail.html 에서

 

  • <div layout:fragment="content"  class="container my-3"></div>

 

하단에 

 

  • <script layout:fragment="script"  type='text/javascript'></script>  내부
  • const delete_elements = documents.getElementsByClassName("delete");
  • Array.from(delete_elements).forEach(function(element)) {
    • element.addEventListener('click', function()) {
      • if (confirm("정말로 삭제하시겠습니까?")) {
      • location.href = this.dataset.uri;
      •  };
    • });
  • });

 

를 작성한다

 

 

-

 

> QuestionService 에 질문 삭제 기능을 추가한다

 

  • public void delete(Question question) {}
    • this.quesitonRepository.delete(question);

 

 

-

 

> QuestionController에

 

삭제 메서드를 추가한다

 

  • @PreAuthorize("isAuthenticated()")
  • @GetMapping("/delete/{id}")
  • M : public String questionDelete
  • S : (Principal principal, @PathVariable("id") Integer id) {}
  • A1 : Question question = this.questionService.getQuestion(id);
  • A2 : if (!question.getAuthor.getUsername().equals(princiapl.getName())) {
    • throw new ReponseStatusException(HttpStatus.BAD_REQUEST, "삭제권한이 없습니다."); }
  • A3 : this.questionService.delete(question);
  • A4 : return "redirect:/";

 

 

-

 

 

 

답변 수정

 

> question_detail.html 에서

답변 수정 버튼을 추가한다

 

답변 카드 내부, 답변 작성자와 답변 시각이 담긴 뱃지 하단에

 

  • <div class="my-3"></div> 내부
  • <a th:href="@{|/answer/modify/${answer.id}|}" 
  • class="btn btn-sm btn-outline-secondary"
  • sec:authorize="isAuthenticated()"
  • th:if="${answer.author != null  and  #authentiaction.getPrincipal().getUsername() == answer.author.username}"
  • th:text="수정"></a> 

로 버튼 작성

 

-

 

> AnswerService에 답변 조회와 답변 수정 기능 구현

 

// import java.util.Optional;

// import com.mysite.sbb.DataNotFoundException;

 

  • public Answer getAnswer(Integer id) {}
    • A1 : Optional<Answer> answer = this.answerRepository.findById(id);
    • A2 :
      • if (answer.isPresent)) 
        • return answer.get(); 
      • } else {
        • throw new DataNotFoundException("answer not found"); }

 

  • public void modify(Answer answer, String content)
    • A1 : answer.setContent(content);
    • A2 : answer.setModifyDate(LocalDateTime.now());
    • A3 : this.answerRepository.save(answer);

 

 

> AnswerController에 서비스의 답변조회와 수정기능을 구현

 

// import org.springframework.http.HttpStatus;

// import org.springframework.web.bind.annotation.GetMapping;

// import org.springframework.web.server.ResponseStatusException;

 

  • @PreAuthorize("isAuthenticated()")
  • @GetMapping("/modify/{id}")
  • M : public String answerModify
  • S : (AnswerForm answerForm, @PathVariable("id") Integer id, Principal principal) 
    • A1: Answer answer = this.answerService.getAnswer(id);
    • A2 : if (!anwer.getAuthor().getUsername().equals(principal.getName())) {}
      • throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "수정권한이 없습니다.");
    • A3 : answerForm.setContent(answer.getContent());
    • A4 : return "answer_form";

 

 

-

 

> answer_form.html 신규 작성

 

 

  • <html layout:decorate="~{layout}"></html> 내부
  • <div layout:fragment="content"  class="container"></div>

 

틀 내부 최상단에 제목

  • <h5 class="my-3 border-bottom pb-2">답변 수정</h5>

 

제목 아래 폼 작성

  • <form th:object="${answerForm}"  method="post"></form>

 

폼 내부

 

  • 1 : <input type="hidden"  th:name="${_csrf.parameterName}"  th:value="${_csrt.token}" />
  • 2 : <div th:replace="form_errors :: formErrorsFragment"></div>
  • 3 :
    • <div class="mb-3"></div> 내부
    • <label for="content"  class="form-label">내용</label>
    • <textarea th:field="*{content}"  class="form-control"  rows="10"></textarea>
  • 4 : <input type="submit"  value="저장하기"  class="btn btn-primary my-2">

 

-

 

> AnswerController에서 

 

  • @PreAuthorize("isAuthenticated()")
  • @PostMapping("/modify/{id}")
  • M : public String answerModify
  • S : (@Valid AnswerForm answerForm, BindingResult bindingResult, @PathVariable("id") Integer id, Principal principal)
    • A1 : if (bindingResult.hasErrors())
      • return "answer_form";
    • A2 : Answer answer = this.answerService.getAnswer(id);
    • A3 : if (!answer.getAuthor().getUsername().equals(principal.getName()))
      • throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "수정권한이 없습니다");
    • A4 : this.answerService.modify(answer, answerForm.getContent());
    • R : return String.format("redirect:/question/detail/%s", answer.getQuestion().getId());

-

 

답변 수정 동작 확인

 

 

-

 

 

답변 삭제 

 

-

 

> question_detail.html

수정 버튼 하단에 답변 삭제 버튼을 추가한다

 

  • <a href="javascript:void(0);"
  • th:data-uri="@{|/answer/delete/${answer.id}|}"
  • class="delete btn btn-sm btn-outline-secondary"
  • sec:authorize="isAuthenticated()"
  • th:if="${answer.author != null and #authentication.getPrincipal().getUsername() == answer.author.username}"
  • th:text="삭제"></a>

 

-

 

> AnswerService에

답변 삭제 메서드 추가

 

  • public void delete(Answer answer) {}
    • this.answerRespository.delete(answer);

 

-

 

> AnswerController에

 

  • @PreAuthorize("isAuthenticated()")
  • @GetMapping("/delete/{id}")
  • M : public String answerDelete
  • S : (Principal principal, @PathVariable("id") Integer id)
    • A1 : Answer answer = this.answerService.getAnswer(id);
    • A2 : if (!answer.getAuthor().getUsername().equals(principal.getName()))
      • throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "삭제권한이 없습니다");
    • A3 : this.answerService.delete(answer);
    • R : return String.format("redirect:/question/detatil/%s", answer.getQuestion().getId());

 

-

 

로컬 서버 켜서 삭제 버튼 확인

 

 

수정일시 표시하기

 

> question_detail.html 에서

 

동일 "d-flex justify-contend-end" 클래스 내부, 질문 작성자 및 작성일시 뱃지 위에

 

  • <div th:if="${question.modifyDate != null}" 
  • class="badge bg-light text-dark p-2 text-start"></div> 로 뱃지를 잡고
  • <div class="mb-2">modified at</div>
  • <div th:text="${#temporals.format(question.modifyDate, 'yyyy-MM-dd HH:mm')}"></div>

로 내용 기재

 

동일 "d-flex justify-contend-end" 클래스 내부, 답변 작성자 및 작성일시 뱃지 위에

  • <div th:if="${answer.modifyDate != null}" 
  • class="badge bg-light text-dark p-2 text-start"></div> 로 뱃지를 잡고
  • <div class="mb-2">modified at</div>
  • <div th:text="${#temporals.format(question.modifyDate, 'yyyy-MM-dd HH:mm')}"></div>

 

'포트폴리오 > SPRINGBOOT 옛날' 카테고리의 다른 글

3-11 : 추천  (0) 2022.10.13
03 : GetMapping과 PostMapping  (0) 2022.10.13
3 - 09 : 글쓴이 표시  (0) 2022.10.10
3-08 : entity에 author 추가하기  (0) 2022.10.10
3-07 : 로그인과 로그아웃  (0) 2022.10.09