본문 바로가기

Programming/Framework

DAY 164. Spring MVC - 게시글 수정하기

 

01. update.jsp 준비

 

 

02.  BoardController.java

- URL 요청에 대해 받을 수 있게 GET 메소드에 대한 @GetMapping 메소드 작성

 

▼완성코드

// ▼ 게시글 수정
@GetMapping("/update")
public ModelAndView update(
        @SessionAttribute("loginMember") Member loginMember,
        ModelAndView model, @RequestParam("no") int no) {

    Board board = service.findBoardByNo(no);

    if(loginMember.getNo() == board.getWriterNo()) {

        // ▼ model : 컨트롤러에서 처리한 결과를 jsp에게 전달하는 객체
        // 서비스를 통해 조회해온 board 객체를 jsp에게 포워딩한다.
        model.addObject("board", board);
        model.setViewName("board/update");
    } else {
        model.addObject("msg", "잘못된 접근입니다.");
        model.addObject("location", "/board/list");
        model.setViewName("common/msg");
    }

    return model;
}

 

- 로그인체크인터셉터를 탈 수 있도록 해보자

 

 

03. Servlet-context.xml

<mapping path="/board/update"/>

 

- 로그인 체크 적용되도록 위처럼 작성

 

 

04.  BoardController.java

 

- 지금 상태에서는 작성된 글 관련 정보(제목, 작성자 첨부파일, 내용 등)가 불러와지지 않은 상태이기 때문에 이 부분을 수정해보자.

 

- HOW? 게시글에 대한 PK 값인 no값을 이용해서 조회한다. -> 컨트롤러에서 데이터를 조회해서 Model 객체에 담아서 .jsp 에 포워딩 시키면 된다.

 

- 데이터베이스에 실제 있는(값이 저장되고 있는) 컬럼이랑 현재 계정의 NO 값이 동일하면 본인이 작성한 글이다.

 

- 또한, URL에서 바로 pk값을 파라미터로 넘겨버려서 특정 글 번호를 입력해버리면, 본인이 작성한 게시물이 아니여도 글 수정 페이지로 들어갈 수 있기 때문에 걸러주는 로직이 필요하다.

 

- 로그인 멤버는 Session 영역에서 가져올 수 있다. @SessionAttribute 파라미터에서 이용해보자.

 

(이 실습에서는 쿼리문들에서 WRITER_NO에 대한 매핑이 빠져있기 때문에, 해당하는 쿼리문에 컬럼들을 추가했다. 에러가 발생했을 때는 toString으로 값도 찍어보고 쿼리문도 뒤져보자.)

 

- 글을 수정하고 '수정하기(<input type="submit" value="수정">)' 버튼을 누르면 /board/update로 POST 요청을 보내게 될 것이다. 아직 POST 처리 요청에 대한 컨트롤러 메소드가 없어서 405 에러가 발생한다.

 

- POST 요청 받을 수 있는 핸들러를 컨트롤러에 만들자.

 

@PostMapping("/update")
public ModelAndView update(ModelAndView model,
			@ModelAttribute Board board, @RequestParam("upfile") MultipartFile upfile,
            @SessionAttribute("loginMember") Member loginMember){
	
    int result;
	
    if(loginMember.getId().equals(board.getWriterId))){
    	result = servie.save(board);
        
        if(result > 0){
    		model.addObject("msg", "게시글 수정 성공");
       		model.addObject("location", "/board/view?no=" + board.getNo());
    	} else {
        	model.addObject("msg", "게시글 수정 실패");
        	model.addObject("location", "/board/update?no=" + board.getNo());
    	}
    
    } else {
    	model.addObject("msg", "잘못된 접근입니다.");
        model.addObject("location", "/board/list");
    }

    model.setViewName("common/msg");

	return model;
}

 

- 사용자가 전달하는 데이터를 몽땅 받아오고 싶기때문에 즉, 객체로 받기 위해서 @ModelAttribute 이용

 

- @ModelAttribute로 원하는 타입의 객체 Board board 를 지정한다. 그러면 기본 생성자로 Board 객체를 만든다. Board 객체의 필드명과 사용자가 보내주는 파라미터의 name  속성이랑 동일한 것들이 있으면 자동으로 값을 set 해준다.

 

 

05.  BoardServiceImpl.java

 

- save() 메소드에서 update가 수행될 수 있도록 로직 완성해보자.

@Override
@Transactional 
public int save(Board board) {
    int result = 0;

    if(board.getNo() != 0) {
        // update
        result = mapper.updateBoard(board);
    } else {
        // insert
        result = mapper.insertBoard(board);
    }

    return result;
}

- board-mapper.xml에 id가 updateBoard인 쿼리문 준비

 

 

06.  BoardMapper.java

int updateBoard(Board board);

 

- 추상 메소드 작성

 

 


 

++) 업로드된 파일이 있는 경우 처리할 로직을 추가하자.

 

- 먼저 사용자가 파일을 업로드 했는지? 확인

 

- renamedFileName이 null이 아니면 originalFilename과 renamedFileName을 얻어와서 새로 board에 set 해보자.

 

- 그런데 실제 물리적인 위치에 원래 원본 파일이 남아있기 때문에, (실무에서는 바로 지우지 않고 임시 폴더에 옮겼다가 일정 기간 지나고 일괄 삭제 하거나 한다.) 이걸 지우는 로직을 추가해보자.

 

 

 

@PostMapping("/update")
public ModelAndView update(ModelAndView model,
	    @ModelAttribute Board board, @RequestParam("upfile") MultipartFile upfile,
            @SessionAttribute("loginMember") Member loginMember){
	
    int result;
	
    if(loginMember.getId().equals(board.getWriterId))){
    
    	if(upfile != null && !upfile.isEmpty()){
        
	    String renamedFileName = null; 
            String location = null;
            
            try{
            	location = resourceLoader.getResource("resources/upload/board").getFile().getPath();
                
               	if(board.getRenamedFileName() != null) {
		    FileProcess.delete(location + "/" + board.getRenamedFileName());
	        }	
                
                renamedFileName = FileProcess.save(upfile, location);
                
                if(renamedFileName != null){
                    board.setOriginalFileName(upfile.getOriginalFileName());
                    board.setRenamedFileName(renamedFileName);
                }
                
                
            } catch (IOException e){
            	e.printStackTrace();
            }
        
        }
    	result = servie.save(board);
        
        if(result > 0){
    		model.addObject("msg", "게시글 수정 성공");
       		model.addObject("location", "/board/view?no=" + board.getNo());
    	} else {
        	model.addObject("msg", "게시글 수정 실패");
        	model.addObject("location", "/board/update?no=" + board.getNo());
    	}
    
    } else {
    	model.addObject("msg", "잘못된 접근입니다.");
        model.addObject("location", "/board/list");
    }

    model.setViewName("common/msg");

	return model;
}

 

 

 

07.  FilePorcess.java

public static void delete(String location) {

    File file = new File(location);

    if(file.exists()) {
        file.delete();
    }

}

- 범용으로 사용할 수 있도록 FilePorcess에 delete() 메소드 작성 

 

- 전달받은 location 정보로 새로운 파일 객체 만들고 File 객체의 delete() 메소드로 지운다.