본문 바로가기
Spring/study

spring 23강 게시판 만들기4( 게시물 수정 )

by avvin 2019. 7. 8.

spring 23강 게시판 만들기4( 게시물 수정, 파일 첨부, 첨부파일 삭제, 게시물 삭제)




BoardContoller

//첨부파일 목록을 리턴

@RequestMapping("getAttach/{bno}")

public List<String> getAttach(@PathVariable int bno)


@RequestMapping("delete.do")

public String delete(int bno)


//게시물 내용 수정

@RequestMapping("update.do")

public String update(BoardDTO dto)


@RequestMapping("list.do") //세부적인 url pattern

public ModelAndView list( ... )


@RequestMapping("view.do")

public ModelAndView view (int bno, HttpSession session)



@RequestMapping("write.do")

public String write()


// write.jsp에서 입력한 내용들이 BoardDTO에 저장됨

@RequestMapping("insert.do")

public String insert ( ... )



BoardService

  public void deleteFile(String fullName);


public List<String> getAttach(int bno);


public void create(BoardDTO dto) 


public BoardDTO read(int bno)


public void update(BoardDTO dto) // BoardDAO의 update와 updateAttach 호출


public void delete(int bno) 


public List<BoardDTO> listAll(String search_option, String keyword,int start, int end) 


public void increaseViewcnt(int bno, HttpSession session) 


public int countArticle(String search_option, String keyword)


BoardDAO

public void deleteFile(String fullName); //첨부파일 삭제

public List<String> getAttach(int bno); //첨부파일 정보

public void addAttach(String fullName); //첨부파일 저장

public void updateAttach(String fullName, int bno);//첨부파일 수정

public void create(BoardDTO dto)  //글쓰기 

public void update(BoardDTO dto) ; //글수정 //board.update

public void delete(int bno)  //글삭제


public List<BoardDTO> listAll(String search_option, String keyword,int start, int end) //목록

public void increateViewcnt(int bno)//조회수 증가 처리

public int countArticle(String search_option, String keyword) //조회수 증가 처리

public BoardDTO read(int bno) throws Exception;//레코드 조회





파일 첨부 ( 드래그 & 드롭 )





어떤 파일이 올라왔는지 목록으로 보여주기 위해 첨부파일 테이블(attach)을 작성

:파일 이름(uuid/PK), 게시물 번호 ( reference board(bno)), 업로드 날짜


>view.jsp에서 common.js include

:이미지 파일인지 아닌지 체크하는 함수/ 파일이름, 이미지소스, 링크, 파일이름 리턴하는 함수 (AjaxUpload에 메핑된 함수 호출)


>view.jsp에서 .fileDrop 에 대한 drop 이벤트 처리의 디폴트처리를 막는다. ( e.preventDefault() )




첨부파일 테이블 작성


게시판.sql

drop table attach cascade constraints;


create table attach(


fullName varchar2(150) not null, --첨부파일 이름

bno number not null, --게시물 번호

regdate date default sysdate, --업로드 날짜

primary key(fullName) --첨부파일 이름에 uuid 사용, PK


);


--bno 컬럼에 foreign key 설정


alter table attach add constraint fk_board_attach

foreign key(bno) references board(bno);


-- board테이블의 bno를 참조하여 제약 설정


--board 테이블의 bno 컬럼을 위한 시퀀스 생성


drop sequence seq_board;


create sequence seq_board

start with 1

increment by 1;




common.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*views/include/js/common.js*/
/*이미지 파일인지 확인
/정규표현식/
*/
function checkImageType(fileName){
    var pattern=/jpg|gif|png|jpeg/;
    return fileName.match(pattern);
}
function getFileInfo(fullName){
    var fileName, imgsrc, getLink, fileLink;
    if(checkImageType(fullName)){ 
        //이미지 파일인 경우
        //(#{path}자바 파일 아니고 자바스크립트 파일이기때문에 EL문 못쓴다.)
        //AjaxUploadContoller에서 맵핑된 부분
        imgsrc="/spring02/upload/displayFile?fileName="
            +fullName;
        
        //파일의 확장자와 이름 구분
        fileLink=fullName.substr(14); //14 인덱스~끝
        var front=fullName.substr(0,12); //0~11
        var end=fullName.substr(14);
        //썸네일이미지는 's_'가 들어가도록 설정했기때문에
        // 12, 13번 인덱스를 뺀 이름을 저장해준다.
        getLink="/spring02/upload/displayFile?fileName="
                +front+end;
        
    }else//이미지가 아닌 경우
        fileLink=fullName.substr(12);
        getLink="/spring02/upload/displayFile?fileName="
                +fullName;
    }
    // uuid_filename
    fileName=fileLink.substr(fileLink.indexOf("_")+1);
    return {fileName: fileName, imgsrc: imgsrc,
            getLink: getLink, fullName:fullName };
}



이미지 타입 체크, 파일 정보 리턴하는 함수를 가진 js파일 작성



view.jsp에 common.js 등록

1
2
3
4
5
6
7
8
9
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<%@ include file="../include/header.jsp" %>
<script src="${path}/include/js/common.js"></script>






view.jsp 첨부파일 부분

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    $(".fileDrop").on("dragenter dragover",function(e){
        //기본 효과 막음
        e.preventDefault();
    });
    $(".fileDrop").on("drop",function(e){
        e.preventDefault();
        //첫번째 첨부파일
        var files=e.originalEvent.dataTransfer.files;
        var file=files[0];
        //폼 데이터에 첨부파일 추가
        var formData=new FormData();
        formData.append("file",file);
        $.ajax({
            url: "${path}/upload/uploadAjax",
            data: formData,
            dataType: "text",
            processData: false,
            contentType: false,
            type: "post",
            success: function(data){
                //console.log(data);
                //data : 업로드한 파일 정보와 Http 상태 코드
                var fileInfo=getFileInfo(data);
                //console.log(fileInfo);
                var html="<a href='"+fileInfo.getLink+"'>"+
                    fileInfo.fileName+"</a><br>";
                html += "<input type='hidden' class='file' value='"
                    +fileInfo.fullName+"'>";
                $("#uploadedList").append(html);
            }
        });
    });




dataTransfer는 드래그앤드롭시 드래그된 데이터를 보관하는데에 사용되는 개체


( 드래그된 파일 중 첫번째 파일만 폼데이터에 append시키는데  왜???<<< )


첨부파일 이름 정보를 포함한 input type='hidden' 태그를 uploadedLsit에 추가  


AjaxUploadController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
    //uploadAjax에서 받은 데이터를 post방식으로 명시하여 실행
    // 업로드한 파일은 MultipartFile 변수에 저장됨
 
    @ResponseBody // json 형식으로 리턴
    @RequestMapping(value = "/upload/uploadAjax"
    method = RequestMethod.POST, produces = "text/plain;charset=utf-8")
 
    public ResponseEntity<String> uploadAjax(MultipartFile file) throws Exception {
 
        // 업로드한 파일 정보와 Http 상태 코드를 함께 리턴
        return new ResponseEntity<String>(
                UploadFileUtils.uploadFile(uploadPath, file.getOriginalFilename(), file.getBytes()), HttpStatus.OK);
    }




위 리턴되는 ResponseEntity 객체가 success : function( data )  data(메시지와 상태코드)로 넘어옴






게시물 수정


view.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    //수정 버튼
    $("#btnUpdate").click(function(){
        //첨부파일 이름들을 폼에 추가
        var str="";
        $("#uploadedList .file").each(function(i){
            str+=
                "<input type='hidden' name='files["+i+"]' value='"
                +$(this).val()+"'>";
        });
        //첨부파일 이름들을 폼에 추가해서 BoardController의 update.do로 보낸다.
        //update.do로 가서 dto의 files(String[]타입)에 쌓인다.
        $("#form1").append(str);
        document.form1.action="${path}/board/update.do";
        document.form1.submit();
    });




id가 uploadedList이고 class가 file인 태그들(드래그앤드롭시 uploadedList에 append시킨 태그) 

각각 처리 ( $( this ).val( )는 현재태그의 값)

 

처리한 데이터를 form1에 추가하여 BoardController의 update.do로 보낸다.


1
2
3
4
5
6
7
8
9
10
11
12
//게시물 내용 수정    
    @RequestMapping("update.do")
    public String update(BoardDTO dtothrows Exception {
        System.out.println("dto:"+dto);
        if(dto != null) {
            boardService.update(dto); //레코드 수정
        }
        // 수정 완료 후 목록으로 이동
        //return "redirect:/board/list.do";
        // 상세 화면으로 되돌아감
        return "redirect:/board/view.do?bno="+dto.getBno();
    }



update.do에 매핑된 메서드에서 BoardDTO에 파일 이름이 쌓이고 (DTO의 String[]타입 files에 쌓인다)


BoardServiceImpl의 update메서드에 @Transactional 이 붙어야한다.


레코드 추가는 성공했는데 파일 첨부에 실패한다면 rollback 시켜야하기때문


BoardServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
    @Transactional //트랜잭션 처리 method
    @Override
    public void update(BoardDTO dtothrows Exception {
        boardDao.update(dto); //board 테이블 수정
        //attach 테이블 수정
        String[] files=dto.getFiles();
        if(files==nullreturn;
        for(String name : files) {
            System.out.println("첨부파일 이름:"+name);
            boardDao.updateAttach(namedto.getBno()); 
        }
    }



> DAO의 update메서드 호출하여 board테이블 수정

> DAO의 updateAttach메서드를 호출해 파일이름과 게시글번호를 넘김

BoardDAO.java
1
2
3
4
5
//레코드 수정    
    @Override
    public void update(BoardDTO dto) throws Exception {
        sqlSession.update("board.update", dto); 
    }



1
2
3
4
5
6
7
8
9
10
11
//첨부파일 정보 수정
    @Override
    public void updateAttach(String fullNameint bno) { 
 
        Map<String,Object> map=new HashMap<>();
 
        map.put("fullName", fullName); //첨부파일 이름
        map.put("bno", bno); //게시물 번호
 
        sqlSession.insert("board.updateAttach", map);  
    }



넘어온 값들을 map으로 묶어 boardMapper로

boardMapper.xml
1
2
3
4
5
6
<!-- 게시물 내용 수정 -->
    <update id="update">
        update board
        set title=#{title}, content=#{content}
        where bno=#{bno}
    </update>
cs

1
2
3
4
5
<!-- 새로운 첨부파일 추가 -->    
    <insert id="updateAttach">
        insert into attach (fullName, bno) values
        ( #{fullName}#{bno} )
    </insert>