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>
```'Program > JSP' 카테고리의 다른 글
| MyBatis, 대형 어플리케이션 구조, Maven 사용, Mapper 생성, Lombok (0) | 2022.12.27 |
|---|---|
| 대댓글 만들기 (0) | 2022.12.27 |
| Connection Manager, DBManager, PoolManager (0) | 2022.12.25 |
| 페이징, Connection Pool(중립용) (0) | 2022.12.25 |
| 등록 요청 서블릿, 데이터 목록 서블릿, 데이터 가져오는 서블릿, DAO (0) | 2022.12.25 |