Java Spring JSP웹페이지 만들기7 (댓글 달기, 첨부파일 다운로드 기능)

호연지기·2023년 5월 26일
0
post-thumbnail

📌 게시글 기능 추가하기 (댓글 기능, 첨부파일 다운로드)

게시글에 파일을 첨부했을 경우 클릭하면 pc에 다운로드 되도록 하는 기능과 댓글 기능이 필요하다.

✏ 작업 순서

  1. 첨부파일이 있는 게시글에서 파일을 클릭했을 때 파일이 pc에 다운로드 되도록 한다.
    ( BoardService , BfileDto )

  2. 댓글 기능 추가 ( BoardContents , BoardController , BoardService , ReplyDto , BoardDao )
    댓글 달면 데이터에 저장되고 화면에도 노출되도록 표현

서버에 업로드 한 파일 저장 방식

1) 내용과 파일을 함께 저장
    BLOB 타입으로 파일을 2진 바이너리 데이터로 처리하여 글 내용과 같이 저장.
    (문서 중간에 파일이 들어간 형태)
    예) 블로그 같은 형식.
    이 방식을 처리하기 위한 에디터가 필요(naver smart editor 등)
2) 내용과 파일을 따로 저장
    내용은 DB로, 파일은 파일 서버나 특정 폴더로 저장.
    파일의 정보를 저장할 DB 테이블(컬럼)이 필요.

참고) WYSIWYG(What You See Is What You Get) : 보이는대로 얻는(처리한)다.
    한컴 워드, MS-word, 웹용 에디터 등
    내용과 다양한 파일(이미지, 영상, 음성 등)을 함께 저장/편집할 수 있는 방식.

💫 첨부파일을 다운로드 하자!

💻 BfileDto 소스

@Data
public class BfileDto {
    private int bf_bnum;
    private String bf_oriname;
    private String bf_sysname;
}

파일 데이터 처리용 Dto를 생성한다.
bf_oriname 은 파일의 원본 이름이고, bf_sysname 은 데이터베이스에 저장된 변경된 이름이다.

⛔ 파일 저장 시 파일의 이름을 왜 변경해야 할까?

  • 한 사람이 자신만의 파일을 업로드하는 것이 아니라,
    여러 사람이 제각각 파일을 업로드하는데 이때 파일명이 동일한 경우도 발생한다.
    그럼 나중에 업로드한 파일만 존재하고, 이전 파일은 덮어써서 없어지게 됨. (해결방법) ➡ 이름을 변경하여 저장.
  • 파일 이름에는 시간(밀리초)을 사용.
    파일 정보를 저장할 때 함께 저장하는 데이터(비파일)의 키값이 외래키로 저장되어야 한다.

💻 BoardService 소스

public ResponseEntity<Resource> fileDownload(BfileDto bfile, HttpSession session)
throws IOException {
    log.info("fileDownload()");
    //파일 저장 경로
    String realpath = session.getServletContext().getRealPath("/");
    realpath += "upload/" + bfile.getBf_sysname();

    //실제 파일이 저장된 하드디스크까지 경로를 수립.
    InputStreamResource fResource = new InputStreamResource(new FileInputStream(realpath));

    //파일명이 한글인 경우의 처리(UTF-8로 인코딩)
    String fileName = URLEncoder.encode(bfile.getBf_oriname(), "UTF-8");
    return ResponseEntity.ok().contentType(MediaType.APPLICATION_OCTET_STREAM)
            .cacheControl(CacheControl.noCache())
            .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName)
            .body(fResource);
}

💫 댓글 기능을 만들자!

<input type="button" value="댓글 전송" class="btn-write" onclick="replyInsert()" style="width: 100%; margin-bottom: 30px;">

이 부분에서 작동하는 replyInsert() 함수의 스크립트

💻 BoardContents 소스

function replyInsert(){
const replyForm = $("#rform").serialize();
console.log(replyForm);

//controller에 전송(ajax)
$.ajax({
  url:"replyInsert",
  type:"post",
  data:replyForm,
  success:function (res) {
    console.log(res);
    let str = "";
    str += "<tr>"
        + "<td class='p-20'>" + res.r_id + "</td>"
        + "<td class='p-50'>" + res.r_contents + "</td>"
        + "<td class='p-30'>" + res.r_date + "</td>"
        + "</tr>";

    $("#rtable").prepend(str);
    $("#comment").val(""); //댓글입력창의 내용 지우기
  },
  error:function (err) {
    console.log(err);
    alert("댓글 저장 실패");
    $("#comment").val(""); //댓글입력창의 내용 지우기
    $("#comment").focus();
  }
});
}

댓글 전송을 위해 데이터를 boardContents 에서 BoardController로 넘기고 컨트롤러는 BoardService 로 처리를 넘긴다.
BoardService 에서는 ReplyDto에서 값을 받아 BoardDao를 활용해 쿼리를 전송한다.

💻 BoardController 소스

@PostMapping("replyInsert")
@ResponseBody
public ReplyDto replyInsert(ReplyDto reply){
    log.info("replyInsert()");
    reply = bServ.replyInsert(reply);
    return reply;
}

💻 ReplyDto 소스

@Data
public class ReplyDto {
    private int r_num; //기본키(댓글 번호)
    private int r_bnum; //외래키(게시글번호)
    private String r_contents;
    private String r_id;//작성자 id
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
    private Timestamp r_date;
}
//댓글 데이터는 ajax에서 json 객체로 처리됨
//DTO에서 날짜 형식을 지정해야 함.

ajax는 클라이언트와 서버 간의 데이터 교환을 위해 사용되며, 페이지 전체를 새로고침하지 않고도 웹 페이지의 일부분을 업데이트하거나 데이터를 동적으로 로드할 수 있다.

💻 BoardService 소스

public ReplyDto replyInsert(ReplyDto reply){
    log.info("replyInsert()");
    try{
        bDao.insertReply(reply);//댓글 저장
        //저장된 댓글 가져오기
        reply = bDao.selectLastReply(reply.getR_num());
    } catch (Exception e) {
        e.printStackTrace();
        reply = null;
    }
    return reply;
}

💻 BoardDao.java 소스

@Mapper
public interface BoardDao {
    //댓글 저장 메소드 선언
    void insertReply(ReplyDto reply);
    //추가한 댓글 1개 가져오는 메소드 선언
    ReplyDto selectLastReply(Integer r_num);
}

💻 BoardDao.xml 소스

//댓글 저장 쿼리문
<insert id="insertReply" parameterType="replyDto" useGeneratedKeys="true" keyProperty="r_num">
    <selectKey keyProperty="r_num" resultType="Integer" order="AFTER">
        select last_insert_id()
    </selectKey>
    insert into reply
    values (null,#{r_bnum},#{r_contents},#{r_id},default)
</insert>

//추가한 댓글 1개 가져오는 쿼리문
<select id="selectLastReply" resultType="ReplyDto" parameterType="Integer">
    select * from rlist where r_num=#{r_num}
</select>

댓글 내용을 입력 후 댓글 전송 버튼을 누르면 댓글이 등록된다.

ajax 기능으로 화면이 전환되지 않고 바로 댓글이 등록된 모습!

📅 DATE

2023.05.26 작성

profile
사람의 마음에 차 있는 너르고 크고 올바른 기운

0개의 댓글