Spring/게시판 만들기 프로젝트

[Spring Boot] #4_3 게시판 만들기

sujin7837 2020. 12. 23. 17:10
반응형

학습 목표

-객체 간의 관계 설정(@OneToMany, @ManyToOne 등)

 

학습 목차

4-1. 회원과 질문 간의 관계 매핑 및 리팩토링

4-2. 질문 상세보기 기능 구현

4-3. 질문 수정/삭제 기능 구현

4-4. 수정/삭제 기능에 대한 보안 처리 및 LocalDateTime 설정

4-5. 답변 추가 및 답변 목록 기능 구현

4-6. QuestionController 중복 제거 리팩토링

4-7. 원격 서버에 소스 코드 배포

 

 

//QuestionController.java

@Controller	
@RequestMapping("/questions")	
public class QuestionController {
	@Autowired	
    private QuestionRepository questionRepository;

	@GetMapping("/form")
    public String form(HttpSession session) {	
    	if(HttpSessionUtils.isLoginUser(session)) {
        	return "/users/loginForm";
        }
    	return "/qna/form";
    }
    
    @PostMapping("")
    public String create(String title, String contents, HttpSession session) {	
    	if(!HttpSessionUtils.isLoginUser(session)) {
        	return "/users/loginForm";
        }
        User sessionUser=HttpSessoinUtils.getUserFromSession(session);
        Question newQuestion=new Question(sessionUser, title, contents);		
        questionRepository.save(newQuestion);	
    	return "redirect:/";
    }
    
    @GetMapping("/{id}")
    public String show(@PathVariable Long id, Model model) {	
    	model.addAttribute("question", questionRepository.findById(id).get());
    	return "/qna/show";
    }
    
    @GetMapping("/{id}/form")
    public String updateForm(@PathVariable Long id, Model model, HttpSession session) {
    	try {	//2.
        	Question question=questionRepository.findById(id).get();
        	hasPermission(session, question);
            model.addAttribute("question", question);
            
            return "/qna/updateForm";
        } catch(IllegalStateException e) {
        	model.addAttribute("errorMessage", e.getMessage());
            return "/user/login";	//3.
        }	
    }
    
    private boolean hasPermission(HttpSession session, Question question) {	//1.
    	if(!HttpSessionUtils.isLoginUser(session) {
        	throw new IllegalStateException("로그인이 필요합니다.");
        }
        
        User loginUser=HttpSessionUtils.getUserFromSession(session);
        if(question.isSameWriter(loginUser)) {
        	throw new IllegalStateException("자신이 쓴 글만 수정, 삭제가 가능합니다.");
        }
        return true;
    }
    
    @PutMapping("/{id}")	
    public String update(@PathVariable Long id, String title, String contents, Model model, HttpSession session) {
    	try {	//2.
        	Question question=questionRepository.findById(id).get();
        	hasPermission(session, question);
            question.update(title, contents);
        	questionRepository.save(question);
    		return String.format("redirect:/questions/%d", id);
        } catch(IllegalStateException e) {
        	model.addAttribute("errorMessage", e.getMessage());
            return "/user/login";	//3.
        }	
    }
    
    @DeleteMapping("/{id}")	
    public String delete(@PathVariable Long id, Model model, HttpSession session) {	
    	try {	//2.
        	Question question=questionRepository.findById(id).get();
        	hasPermission(session, question);
            questionRepository.delete(id);
        	return "redirect:/";
        } catch(IllegalStateException e) {
        	model.addAttribute("errorMessage", e.getMessage());
            return "/user/login";	//3.
        }	
    }
}

1. 중복 코드를 없애주기 위해 hasPermission 메소드를 만들어줍니다.

 

2. try catch문과 hasPermission 메소드를 이용해서 코드를 리팩토링 해줍니다.

 

3. return 주소를 잘못 설정해줌(/user/login으로 변경하기)

 

<!--login.html-->

<div class="container" id="main">
   <div class="col-md-6 col-md-offset-3">
      <div class="panel panel-default content-main">
      	  {{#errorMessage}}	<!--1.-->
      	  <div class="alert alert-danger" role="alert">{{this}}</div>	<!--1.-->
      	  {{/errorMessage}}	<!--1.-->
          <form name="question" method="post" action="/users/login">
              <div class="form-group">
                  <label for="userId">사용자 아이디</label>
                  <input class="form-control" id="userId" name="userId" placeholder="User ID">
              </div>
              <div class="form-group">
                  <label for="password">비밀번호</label>
                  <input type="password" class="form-control" id="password" name="password" placeholder="Password">
              </div>
              <button type="submit" class="btn btn-success clearfix pull-right">로그인</button>
              <div class="clearfix" />
          </form>
        </div>
    </div>
</div>

1. 에러 메시지를 연결해줍니다.

{{this}}: 자기 자신을 불러줌

 

//Result.java

public class Result {
	private boolean valid;
    
    private String errorMessage;
    
    private Result(boolean valid, String errorMessage) {
    	this.valid=valid;
        this.errorMessage=errorMessage;
    }
    
    public boolean isValid() {
    	return valid;
    }
    
    public String getErrorMessage() {
    	return errorMessage;
    }
    
    public static Result ok() {
    	return new Result(true, null);
    }
    
    public static Result fail(String errorMessage) {
    	return new Result(false, errorMessage);
    }
}

Result.java는 hasPermission 메소드 대신 사용해줄  수 있는 클래스입니다.

 

//QuestionController.java

@Controller	
@RequestMapping("/questions")	
public class QuestionController {
	@Autowired	
    private QuestionRepository questionRepository;

	@GetMapping("/form")
    public String form(HttpSession session) {	
    	if(HttpSessionUtils.isLoginUser(session)) {
        	return "/users/loginForm";
        }
    	return "/qna/form";
    }
    
    @PostMapping("")
    public String create(String title, String contents, HttpSession session) {	
    	if(!HttpSessionUtils.isLoginUser(session)) {
        	return "/users/loginForm";
        }
        User sessionUser=HttpSessoinUtils.getUserFromSession(session);
        Question newQuestion=new Question(sessionUser, title, contents);		
        questionRepository.save(newQuestion);	
    	return "redirect:/";
    }
    
    @GetMapping("/{id}")
    public String show(@PathVariable Long id, Model model) {	
    	model.addAttribute("question", questionRepository.findById(id).get());
    	return "/qna/show";
    }
    
    @GetMapping("/{id}/form")
    public String updateForm(@PathVariable Long id, Model model, HttpSession session) {
    	Question question=questionRepository.findById(id).get();	//2.
        Result result=valid(session, question);	//2.
        if(!result.isValid) {	//3.
        	model.addAttribute("errorMessage", result.getErrorMessage());
            return "/user/login";	
        }
            model.addAttribute("question", question);
            return "/qna/updateForm";
    }
    
    private Result valid(HttpSession session, Question question) {	//1.
    	if(!HttpSessionUtils.isLoginUser(session) {
        	return Result.fail("로그인이 필요합니다.");
        }
        
        User loginUser=HttpSessionUtils.getUserFromSession(session);
        if(question.isSameWriter(loginUser)) {
        	return Result.fail("자신이 쓴 글만 수정, 삭제가 가능합니다.");
        }
        return Result.ok();
    }
    
    private boolean hasPermission(HttpSession session, Question question) {	
    	if(!HttpSessionUtils.isLoginUser(session) {
        	throw new IllegalStateException("로그인이 필요합니다.");
        }
        
        User loginUser=HttpSessionUtils.getUserFromSession(session);
        if(question.isSameWriter(loginUser)) {
        	throw new IllegalStateException("자신이 쓴 글만 수정, 삭제가 가능합니다.");
        }
        return true;
    }
    
    @PutMapping("/{id}")	
    public String update(@PathVariable Long id, String title, String contents, Model model, HttpSession session) {
    	Question question=questionRepository.findById(id).get();	//2.
        Result result=valid(session, question);	//2.
        if(!result.isValid) {	//3.
        	model.addAttribute("errorMessage", result.getErrorMessage());
            return "/user/login";	
        }
        question.update(title, contents);
       	questionRepository.save(question);
    	return String.format("redirect:/questions/%d", id);
    }
    
    @DeleteMapping("/{id}")	
    public String delete(@PathVariable Long id, Model model, HttpSession session) {	
    	Question question=questionRepository.findById(id).get();	//2.
        Result result=valid(session, question);	//2.
        if(!result.isValid) {	//3.
        	model.addAttribute("errorMessage", result.getErrorMessage());
            return "/user/login";	
        }
        questionRepository.delete(id);
        return "redirect:/";
    }
}

1. Result의 메소드를 만들어줍니다.

 

2. valid의 인자로 question이 필요하기 때문에 먼저 선언해줍니다.

Result 클래스를 이용해서 로그인 정보가 유효한지 확인합니다.

 

3. hasPermission을 대신해서 Result를 이용하여 리팩토링 합니다.

반응형