본문 바로가기

Program/JSP

게시판 댓글 생성, 댓글 수 표시

22.08.25 - 게시판 댓글 생성, 댓글 수 표시

게시판 댓글


  • Java

      package com.aca.web0812.news;
    
      import java.io.IOException;
      import java.io.PrintWriter;
      import java.util.List;
    
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
    
      import com.aca.web0812.domain.Comments;
      import com.aca.web0812.domain.News;
      import com.aca.web0812.model.CommentsDAO;
      import com.google.gson.Gson;
    
      /*댓글 등록 요청을 처리하는 서블릿*/
      public class CommentsRegist extends HttpServlet{
          CommentsDAO commentsDAO = new CommentsDAO();
    
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              request.setCharacterEncoding("utf-8");
              String detail = request.getParameter("detail");
              String author = request.getParameter("author");
              String news_id = request.getParameter("news_id");
    
              //DTO 
              Comments comments = new Comments();//Empty 객체 생성
              comments.setDetail(detail);
              comments.setAuthor(author);
    
              //객체변수이므로 메모리에 올려야함
              News news = new News();
              news.setNews_id(Integer.parseInt(news_id));
    
              comments.setNews(news);//comments DTO안에 News DTO 넣기 자식이 부모를 has a로 보유
    
              //DAO : DAO는 테이블 별로 1:1 대응
              commentsDAO.insert(comments);
    
              //클라이언트가 비동기 방식으로 요청을 한다는 것은 전체 html 디자인을 바꾸는 것이 아니라 현재 페이지는 유지하되 
              //오직 데이터면 주고 받기 위함
              response.setContentType("text/html;charset=utf-8");
              PrintWriter out = response.getWriter();
    
              //이 뉴스기사에 딸려있는 댓글 가져오기
              List<Comments> commentsList = commentsDAO.selectAll(news.getNews_id());
    
              //클라이언트에게 등록과 동시에 지금까지 누적된 댓글 목록을 보낸다.
              //json표기를 문자열로 처리할 경우 너무 번거로우니 외부 라이브러리(GSON)를 이용한다.
    
              //목록 가져오기 
              Gson gson = new Gson();
              String json =gson.toJson(commentsList);
              out.print(json);
          }
      }
      package com.aca.web0812.model;
    
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.util.ArrayList;
      import java.util.List;
    
      import com.aca.web0812.domain.Comments;
      import com.aca.web0812.domain.News;
      import com.aca.web0812.pool.ConnectionManager;
      import com.aca.web0812.pool.PoolManager;
    
      /*
       * DAO는 테이블마다 1:1 대응하게 생성해야함 따라서 오라클에 table이 100개 라면 DAO도 100개
       * 제작시에는 시간이 좀 걸리지만, 추후 유지보수 할때는 시간이 단축된다. 
       * */
      public class CommentsDAO {
          ConnectionManager manager=PoolManager.getInstance();//다형성을 염두(코드가 유연해짐)
          //메모리에 클래스가 올라올때 생성
    
          public int insert(Comments comments) {
               Connection con =null;
               PreparedStatement pstmt = null;
               int result =0;
    
               con=manager.getConnection();
               String sql="INSERT INTO comments(comments_id, detail, author, news_id) VALUES(seq_comments.nextval, ?,?,?)";
               try {
                  pstmt=con.prepareStatement(sql);
                  pstmt.setString(1, comments.getDetail());
                  pstmt.setString(2, comments.getAuthor());
                  pstmt.setInt(3, comments.getNews().getNews_id());//News객체로 등록했기 때문에 2번 치고 들어가야함
                  result=pstmt.executeUpdate();
    
              } catch (SQLException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }finally {
                  manager.freeConnection(con,pstmt);
              }
    
               return result;
           }
    
          //모든 레코드 가져오기 (해당 뉴스 기사에 관련된 )
          public List selectAll(int news_id) {
              Connection con =null;
              PreparedStatement pstmt =null;
              ResultSet rs =null;
              List list = new ArrayList();
    
              con = manager.getConnection();
    
              String sql = "SELECT * FROM comments WHERE news_id=?";
              try {
                  pstmt=con.prepareStatement(sql);
                  pstmt.setInt(1, news_id);
                  rs=pstmt.executeQuery();
    
                  while(rs.next()) {
                      Comments comments = new Comments();
                      comments.setComments_id(rs.getInt("comments_id"));
    
                      News news = new News();
                      news.setNews_id(news_id);
                      comments.setNews(news);
    
                      comments.setDetail(rs.getString("detail"));
                      comments.setAuthor(rs.getString("author"));
                      comments.setWritedate(rs.getString("writedate"));
    
                      list.add(comments);
                  }
    
              } catch (SQLException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }finally {
                  manager.freeConnection(con,pstmt,rs);
              }
              return list;
          }
    
      }
  • JSP

      <%@page import="com.aca.web0812.domain.News"%>
      <%@page import="com.aca.web0812.news.model.NewsDAO"%>
      <%@ page contentType="text/html;charset=UTF-8"%>
      <%! NewsDAO newsDAO = new NewsDAO();%>
      <%
          int news_id = Integer.parseInt(request.getParameter("news_id"));
          News news =newsDAO.select(news_id);
      %>
      <!DOCTYPE html>
      <html>
      <head>
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <style>
      body {font-family: Arial, Helvetica, sans-serif;}
      * {box-sizing: border-box;}
    
      input[type=text], select, textarea {
        width: 100%;
        padding: 12px;
        border: 1px solid #ccc;
        border-radius: 4px;
        box-sizing: border-box;
        margin-top: 6px;
        margin-bottom: 16px;
        resize: vertical;
      }
    
      input[type=button] {
        background-color: #04AA6D;
        color: white;
        padding: 12px 20px;
        border: none;
        border-radius: 4px;
        cursor: pointer;
      }
    
      input[type=button]:hover {
        background-color: #45a049;
      }
    
      .container {
        border-radius: 5px;
        background-color: #f2f2f2;
        padding: 20px;
      }
    
      #comments-list{
          border:1px solid red;
          overflow:hidden;
      }
      #comments-list *{
          float: left;
      }
      .title-style{width:80%}
      .writer-style{width:10%}
      .regdate-style{width:10%}
      </style>
      <script>
      //댓글 목록 출력
      function showCommentsListByString(jsonArray){//댓글이 json형태로 넘겨짐
          console.log("넘겨받은 데이터의 배열크기는 ",jsonArray.lenth);
          //넘어온 데이터가 문자열이므로, 객체처럼 사용할 수 없는 상태
          var data = JSON.parse(jsonArray);
          console.log("json객체 수는",data.length);
    
          //div안의 컨텐츠를 js를 DOM을 이용하여 동적으로 출력해본다.
          var commentsList = document.getElementById("comments-list");//div
          commentsList.innerHTML="";
          //문자열로 취급하는 방법
          var tag="";
          for(var i=0; i<data.length;i++){
              tag+="<div class=\"title-style\">짜파게티 맛있엉</div>";
              tag+="<div class=\"writer-style\">리얼개미</div>";
                tag+="<div class=\"regdate-style\">리얼개미</div>"
          }
          console.log(tag);
          commentsList.innerHTML=tag;    
      }
    
      //DOM객체로 처리하는 방법
      function showCommentsListByDom(jsonArray){
    
          var data = JSON.parse(jsonArray);
          var commentsList = document.getElementById("comments-list");
    
          //출력전에 기존 요소들을 삭제
          commentsList.innerHTML="";
    
    
    for(var i=0; i<data.length;i++){
        var json = data[i];//배열에 들어있는 한건의 댓글 객체
        var div1=document.createElement("div");//title-style
        var div2=document.createElement("div");//writer-style
        var div3=document.createElement("div");//regdate-style

        //생성된 DOM 요소에 클래스 적용
        div1.className="title-style";
        div2.className="writer-style";
        div3.className="regdate-style";

        //div안의 컨텐츠 구성
        div1.innerText=json.detail;
        div2.innerText=json.author;
        div3.innerText=json.writedate.substring(0,10);

        //조립
        commentsList.appendChild(div1);//부모요소에 자식 추가
        commentsList.appendChild(div2);
        commentsList.appendChild(div3);
        //이렇게 하다가 react가 나옴    
    }
}

function regist(){
    //비동기
    var xhttp=new XMLHttpRequest();

    var detail = document.getElementsByName("detail")[0];//text자체
    var author = document.getElementsByName("author")[0];//text자체
    xhttp.onreadystatechange=function(){
        if(this.readyState==4 && this.status==200){
            console.log("서버가 보낸 json 문자열은",this.responseText);
            showCommentsListByDom(this.responseText);//출력함수로 정의
        }
    }

    xhttp.open("POST","/comments/regist");
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send("detail="+detail.value+"&author="+author.value+"&news_id=<%=news_id%>");//파라미터명=값&파라미터명=값

}
</script>
</head>
<body>

<h3>뉴스기사 상세보기</h3>

<div class="container">
  <form name="form1">
    <input type="text" name="title" value="<%=news.getTitle()%>">
    <input type="text"name="writer" value="<%=news.getWriter()%>">
    <textarea name="content" style="height:200px"><%=news.getContent() %></textarea>

    <input type="button" value="등록" onClick="regist()">
    <input type="button" value="목록" onClick="location.href='/news/list.jsp'">
  </form>

  <form name="form2">
      <input type="text" name="detail" placeholder="댓글 내용" style="width:60%">
      <input type="text" name="author" placeholder="작성자" style ="width:10%">
      <input type="button" value="댓글등록" onClick="regist()">
  </form>
  <!-- 댓글 목록 -->

  <div id="comments-list">
  <!-- 
      <div class="title-style">짜파게티 맛있엉</div>
      <div class="writer-style">리얼개미</div>
      <div class="regdate-style">리얼개미</div>
      -->
  </div>
</div>

</body>
</html>
```

게시글 제목에 댓글 수 표시


  • 코드

      package com.aca.web0812.news.model;
    
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.util.ArrayList;
      import java.util.List;
    
      import com.aca.web0812.domain.News;
      import com.aca.web0812.pool.ConnectionManager;
      import com.aca.web0812.pool.PoolManager;
    
      /*
       * 기존 코드방식에서랑은 다르게, Connection 객체는 커넥션 풀을 이용한다
       * 우리가 사용하는 커넥션풀은 Tomcat 서버가 제공하는 풀을 이용하되, JNDI로 자원에 접근할 예정
       */
      public class NewsDAO {
          ConnectionManager manager;//웹이건 응용이건 둘다 포함 할수 있는 객체
    
          public NewsDAO(){
              //manager = new PoolManager();//웹용으로 생성 
              manager = PoolManager.getInstance();//위의 코드를 싱글톤으로 받아옴
    
          }
          //Create
          public int insert(News news) {
              Connection con=null;
              int result=0;
              PreparedStatement pstmt=null;
              try {
                  con=manager.getConnection();//다형성: 자료형은 ConnectionManager이지만, 
                  //호출되는 메서드 동작은 각각 틀리게 동작할 수 있다. ConnectionManger가 어떤 때는 PoolManager로 동작 DBManager로 동작할 수 있다.
                  String sql="insert into news(news_id, title, writer, content) values(seq_news.nextval,?,?,?)";
                  pstmt=con.prepareStatement(sql);
                  pstmt.setString(1, news.getTitle());
                  pstmt.setString(2, news.getWriter());
                  pstmt.setString(3, news.getContent());
    
                  result= pstmt.executeUpdate();//DML 수행
    
    
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            manager.freeConnection(con, pstmt);
        }
        return result;
    }
    //Read
    public List selectAll() {
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs=null;
        List<News> list = new ArrayList<News>();

        con=manager.getConnection();
        String sql = "";
        sql+="SELECT news_id, title ,writer ,regdate ,hit, COUNT(news_id) as cnt";  
        sql+=" FROM"; 
        sql+="(";
        sql+="SELECT title ,writer ,regdate ,hit, c.news_id  AS news_id"; 
        sql+=    " FROM news n LEFT OUTER JOIN  comments c"; 
        sql+=    " ON n.news_id =c.news_id";
        sql+=") GROUP BY news_id, title ,writer, regdate ,hit";
        System.out.println(sql);

        try {
            pstmt=con.prepareStatement(sql);
            rs=pstmt.executeQuery();
            while(rs.next()) {
                News news = new News();
                news.setNews_id(rs.getInt("news_id"));
                news.setTitle(rs.getString("title"));
                news.setWriter(rs.getString("writer"));
                news.setRegdate(rs.getString("regdate"));
                news.setHit(rs.getInt("hit"));
                news.setHit(rs.getInt("cnt"));

                list.add(news);
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            manager.freeConnection(con,pstmt,rs);
        }
        return list;
    }
    public News select(int news_id) {
        Connection con =null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        News news=null;//return 하려고

        con = manager.getConnection();
        String sql="select * from news where news_id=?";
        try {
            pstmt=con.prepareStatement(sql);
            pstmt.setInt(1, news_id);
            rs= pstmt.executeQuery();

            if(rs.next()) {//레코드가 있다면
                news = new News();
                news.setNews_id(rs.getInt("news_id"));
                news.setTitle(rs.getString("title"));
                news.setWriter(rs.getString("writer"));
                news.setContent(rs.getString("content"));
                news.setRegdate(rs.getString("regdate"));
                news.setHit(rs.getInt("hit"));
            }

        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            manager.freeConnection(con, pstmt, rs);
        }
        return news;
    }
    //update
    public void update() {
        String sql="update news set title=?, writer?, content=? where news_id=?";
    }
    //delete
    public void delete() {
        String sql="delete news where news_id=?";
    }
}
```

```html
<%@page import="java.util.List"%>
<%@page import="com.aca.web0812.news.model.NewsDAO"%>
<%@page import="com.aca.web0812.domain.News"%>
<%@page import="javax.print.attribute.HashPrintRequestAttributeSet"%>
<%@ page contentType="text/html;charset=UTF-8"%>
<%!
    NewsDAO newsDAO = new NewsDAO();
%>
<%
    List<News> newsList = newsDAO.selectAll();

    int totalRecord=newsList.size();  //모든 레코드 수
    int pageSize=10;  //한 페이지당 보여질 레코드 수
    int totalPage=(int)Math.ceil((float)totalRecord/pageSize);
    int blockSize=7;  //한 블럭당 보여질 페이지 수
    int currentPage=1;
    if(request.getParameter("currentPage")!=null){
        currentPage=Integer.parseInt(request.getParameter("currentPage"));
    }
    int firstPage=currentPage-(currentPage-1)%blockSize;
    int lastPage=firstPage+blockSize-1;
    int curPos=(currentPage-1)*pageSize;//페이지당 list의 시작 index
    int num=totalRecord- curPos;//페이지당 시작 번호
%>
<%="totalRecord는 "+totalRecord+"<br>" %>
<%="pageSize는 "+pageSize+"<br>" %>
<%="totalPage는 "+totalPage+"<br>" %>
<%="blockSize는 "+blockSize+"<br>" %>
<%="currentPage는 "+currentPage+"<br>" %>
<%="firstPage는 "+firstPage+"<br>" %>
<%="lastPage는 "+lastPage+"<br>" %>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
table {
    border-collapse: collapse;
    border-spacing: 0;
    width: 100%;
    border: 1px solid #ddd;
}

th, td {
    text-align: left;
    padding: 16px;
}

tr:nth-child(even) {
    background-color: #f2f2f2;
}

.page-style{
    font-size:20px;
    font-weight:bold;
    color:red;
}
</style>
</head>
<body>

    <table>
        <tr>
            <th width="5%">No</th>
            <th width="75%">기사제목</th>
            <th width="5%">작성자</th>
            <th width="10%">작성일</th>
            <th width="5%">조회수</th>
        </tr>
        <!-- 하나의 페이지에 너무 많은 데이터가 있을 경우, 원하는 크기로 분리하여 보여주는 기법을 페이징(Paging) 처리라
        페이징 처리는 결국 데이터에 대한 산수계산이므로, 개발자마다 본인 스스로 로직을 개발해야함 -->
        <%for(int i =1; i<=pageSize; i++){%>
        <%if(num<1)break; %>
        <%
            News news =newsList.get(curPos++);
        %>
        <tr>
            <td><%=num--%></td>
            <td><a href="/news/content.jsp?news_id=<%=news.getNews_id()%>"><%= news.getTitle() %></a>
            [<%=news.getCnt() %>]</td>
            <td><%= news.getWriter() %></td>
            <td><%= news.getRegdate().substring(0,10) %></td>
            <td><%= news.getHit() %></td>
        </tr>
        <%} %>
        <tr>
            <td colspan="5" style="text-align:center">
                <%if(firstPage-1>0){ %>
                <a href="/news/list.jsp?currentPage=<%=firstPage-1%>">◀</a>
                <%}else{ %>
                <a href="javascript:alert('이전 페이지가 없습니다');">◀</a>
                <%} %>
                <%for(int i=firstPage; i<=lastPage; i++) {%>
                    <%if(i>totalPage)break; %>
                    <a href="/news/list.jsp?currentPage=<%=i%>"<%if(i==currentPage){ %> class="page-style"<%} %>>[<%=i%>]</a>
                <%} %>
                <%if(lastPage+1<=totalPage){ %>
                <a href="/news/list.jsp?currentPage=<%=lastPage+1%>">▶</a>
                <%}else{ %>
                <a href="javascript:alert('마지막 페이지입니다');">▶</a>
                <%} %>
            </td>
        </tr>
        <tr>
            <td colspan="5"><button onClick="location.href='/news/regist.jsp';">뉴스작성</button></td>
        </tr>
    </table>

</body>
</html>
```