728x90
반응형
SMALL

수정 및 삭제 기능 추가

수정 일시 추가하기

게시판의 질문과 답변을 수정하거나 삭제 기능을 추가하기 전에 언제 수정되었는지 확인할 수 있도록 속성을 추가하자.

/question/Question.java

package com.mysite.sbb.question;

import java.time.LocalDateTime;
import java.util.List;

import com.mysite.sbb.answer.Answer;
import com.mysite.sbb.user.SiteUser;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Entity
public class Question {
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	
	@Column(length = 200)
	private String subject;
	
	@Column(columnDefinition = "TEXT")
	private String content;
	
	private LocalDateTime createDate;
	
	//관계주입
	@OneToMany(mappedBy = "question", cascade = CascadeType.REMOVE)
	private List<Answer> answerList;
	
	//관계주입
	@ManyToOne
	private SiteUser author;
	
	private LocalDateTime modifyDate;
}

 

/answer/Answer.java

package com.mysite.sbb.answer;

import java.time.LocalDateTime;

import com.mysite.sbb.question.Question;
import com.mysite.sbb.user.SiteUser;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Entity
public class Answer {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	
	@Column(columnDefinition = "TEXT")
	private String content;
	
	private LocalDateTime createDate;
	
	//관계주입
	@ManyToOne
	private Question question;
	
	//관계주입
	@ManyToOne
	private SiteUser author;
	
	private LocalDateTime modifyDate;
}
Question과 Answer모두 동일하게 수정일시를 추가한 후, 다시 H2콘솔에 접속해보면 열이 추가된 것을 확인할 수 있다.

 

질문 수정 기능 생성하기

질문 수정 버튼 만들기

/templates/question_detail.html

...
<!--수정 버튼-->
<div class="my-3">
	<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>
</div>
<!--수정 버튼 끝-->
...

수정 버튼이 로그인한 사용자가 글쓴이가 동일한 경우에만 보여야 하므로 th:if로 조건을 주었다.

 

질문 컨트롤러 수정하기(1)

위의 <a>태그를 통해 GET방식으로  @{|/question/modify/${question.id}|} url이 추가되었으므로 이 링크가 정상 작동하도록 수정해야 한다.

 /question/QuestionController.java

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

유효성 검사를 위해 QuestionForm을 선언해두었다.

먼저 해당하는 question객체를 가져오고

그에 해당하는 제목과 내용으로 QuestionForm을 세팅해준다. 이 내용들을 가지고 qeustion_form화면으로 이동한다.

 

질문 등록 템플릿 수정하기

질문을 등록하는 화면이나 수정하는 화면은 내용 기입하는 곳이 동일하므로 같은 템플릿을 사용한다.

/templates/question_form.html

<html layout:decorate="~{layout}">
<div layout:fragment="content" class="container">
	<h5 class="my-3 border-bottom pb-2">질문등록</h5>
	<form th:object="${questionForm}" method="post">
		<input type="hidden" th:name="${_csrf.parameterName}"
		th:value="${_csrf.token}">
		<div th:replace="~{form_errors :: formErrorsFragment}"></div>
		<div class="mb-3">
			<label for="subject" class="form-label">제목</label>
			<input type="text" th:field="*{subject}" class="form-control">		
		</div>
		<div class="mb-3">
			<label for="content" class="form-label">내용</label>
			<textarea th:field="*{content}" class="form-control" rows="10"></textarea>
		</div>
		<input type="submit" value="저장하기" class="btn btn-primary my-2">
	</form>
</div>
</html>

 

먼저 기존에 있던 form태그의 action속성을 삭제한다. 그러면 CSRF값이 자동생성되지 않아 input태그의 hidden타입으로 직접 추가해주어야 한다. 그러지 않으면 접근 거부가 나타난다.

여기서 action속성없이 submit하게되면 자동으로 여기 화면으로 접근하게된 경로를 갖고 있으므로

/question/cretae URL로 GET방식으로 접근했다면 submit할 시 자동으로 POST방식으로 /question/cretae가 action속성으로 잡힌다. 수정시에는 /question/modify/2와 같은 URL로 접근했기 때문에 POST방식으로 자동으로 /question/modify/2로 설정된다.

 

질문 서비스 수정하기

/qeustion/QuestionService.java

public void modify(Question question, String subject, String content) {
		question.setSubject(subject);
		question.setContent(content);
		question.setModifyDate(LocalDateTime.now());
		this.questionRepostiory.save(question);
	}

수정된 질문이 처리되도록 서비스를 수정했다.

 

질문 컨트롤러 수정하기(2)

내용 변경 후 저장 버튼을 클릭하게 되면 action이 /question/modify/{id}로 자동 생성되고 POST방식으로 전달할 것이다.

이를 처리하기 위해 컨트롤러를 수정하자.

/question/QuestionController.java

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

유효성 검사를 통해 만약 오류가 있다면 다시 question_form 으로 돌아가고

작성자와 동일한지도 검사한다.

이상이 없다면 위의 Service에서 만들었던 modify메서드를 호출하여 question객체와 수정된 제목과 내용을 넘겨 수정하게 한다.

이후에는 상세화면으로 돌아가게끔 했다.

 

수정 기능 확인하기

로그인 했을 경우 내가 작성한 글에서만 수정 버튼 활성화.
내용 변경 후 저장하기 버튼 클릭
내용이 변경된 것을 확인

728x90
반응형
LIST

+ Recent posts