Servlet, JSP/Servlet, JSP

23-03-13 Servlet, JSP

모건이삼촌 2023. 3. 13. 18:19

※ 복습

 

1. 검색 후 2페이지로 갔을 때 검색결과가 사라지는 것 수정

1-1 criteria 수정

el을 가져올때 getter로 가져오는데 쿼리스트링을 문자열로 만들면 됨

criteria 

keyword에 null값이 아닌 초기값 추가

getQueryString 구문 추가

package com.chanyongyang.jsp.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Criteria {
	// 초기값을 주는게 좋다.	
	private int pageNum = 1;
	private int amount = 10;
	private int category = 1;
	private String[] type;
	private String keyword = "";
	
	public Criteria(int pageNum, int amount) {
		this.pageNum = pageNum;
		this.amount = amount;
	}
	public String getQueryString() {
		String str = "";
		str += "amount=" + amount + "&category=" + category;
		if(type != null) {
			for(String s : type) {
				str += "&type=" + s;
			}
			// 검색어가 있을때만 검색
			str += "&keyword=" + keyword;
		}
		return str;
	}
	
}

1-1 list.jsp의 pagination 부분 수정

page.cri.amount => criteria에 만들어놓은 page.cri.queryString으로 변경

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core"  prefix="c"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<%@ include file="../common/head.jsp" %>
</head>
<body>
<%@ include file="../common/header.jsp" %>
 <main class="container p-3 pb-5">
    <div class="card">
      <div class="card-header p-5">
        <h2>Board List</h2>
      </div>
      <div class="card-body">
        <div class="clearfix mb-3">
          <div class="float-start">
          <c:set var="amounts" value="5,10,25,50,100" />
          <select class="form-select amount">
          <c:forTokens items="${amounts}" delims="," var="amount">
            <option value="${amount}" ${page.cri.amount == amount ? 'selected' : ''}>${amount}개씩보기</option>
          </c:forTokens>
          </select>
          </div>
          <form>
          <input type="hidden" name="page" value="1">
          <input type="hidden" name="amount" value="${page.cri.amount}">
          <input type="hidden" name="category" value="${page.cri.category}">
          <div class="float-start mx-5 row">
			<div class="col">
				<input class="form-check-input" type="checkbox" id="check1" name="type" value="title" checked>
				<label class="form-check-label" for="check1">제목</label>
				<input class="form-check-input" type="checkbox" id="check2" name="type" value="content">
				<label class="form-check-label" for="check2">내용</label>
				<input class="form-check-input" type="checkbox" id="check3" name="type" value="writer">
				<label class="form-check-label" for="check3">작성자</label>
			</div>
            <div class="input-group mb-3 col">
              <input type="text" class="form-control" placeholder="Search" name="keyword" value="${page.cri.keyword}">
              <button class="btn btn-success" type="submit"><i class="fas fa-search"></i></button>
            </div>
          </div>
          </form>
          <a href="write" class="float-end btn btn-primary">write</a>
        </div>

        <div class="card">
        <c:forEach var="board" items="${boards}" varStatus="stat">
          <a href="view?bno=${board.bno}" class="text-decoration-none">
            <div class="container card-body ${stat.last ? '': 'border-bottom'}">
              <div class="mb-4 text-truncate">${board.title}</div>
              <div class="row text-muted small">
                <div class="col-7">${board.writer}</div>
                <div class="col text-end small"><span class="mx-3">${board.regdate}</span> <span>조회수 ${board.hitcount}</span></div>
              </div>
            </div>
          </a>
          </c:forEach>
       </div>
        <ul class="pagination mt-3 justify-content-center">
        <c:if test="${page.doublePrev}">
          <li class="page-item"><a class="page-link" href="list?pageNum=${page.startPage - 1}&${page.cri.queryString}"><i class="fas fa-angle-double-left"></i></a></li>
        </c:if>
        <c:if test="${page.prev}">
          <li class="page-item"><a class="page-link" href="list?pageNum=${page.cri.pageNum - 1}&${page.cri.queryString}"><i class="fas fa-angle-left"></i></a></li>
        </c:if>
        <c:forEach begin="${page.startPage}" end="${page.endPage}" var="i">
          <li class="page-item"><a class="page-link ${page.cri.pageNum == i ? 'active' : ''}" href="list?pageNum=${i}&${page.cri.queryString}">${i}</a></li>
		</c:forEach>
        <c:if test="${page.next}">
          <li class="page-item"><a class="page-link" href="list?pageNum=${page.cri.pageNum + 1}&amount=${page.cri.amount}"><i class="fas fa-angle-right"></i></a></li>
        </c:if>
        <c:if test="${page.doubleNext}">
          <li class="page-item"><a class="page-link" href="list?pageNum=${page.endPage + 1}&amount=${page.cri.amount}"><i class="fas fa-angle-double-right"></i></a></li>
        </c:if>
        </ul>
      </div>
    </div>
  </main>
 <%@ include file="../common/footer.jsp" %>
</body>
<script>
	$(".amount").change(function() {
		// console.log($(this).val());
		
		
		let page = '${page.cri.pageNum}'; // 텍스트 형태로 js가 인식
		let amount = $(this).val();
		let obj = {pageNum:page, amount:amount};
		location.search = $.param(obj);
	})
</script>
</html>
      <!-- 게시판에 table을 안쓰는게 좋음 / ul, li 사용 -->

* PropertyNotFoundException 발생

 page.queryString =>  page.cri.queryString 으로 변경... 한심..

 

 

 

게시글에서 목록으로 눌렀을 때 게시판 초기화면으로 넘어가는것 수정

 

2. ?? 개씩 보기 수정

jsp로 동작해서 아주 불편함.

list.jsp의 script 부분 추가

	$(".amount").change(function() {
		// console.log($(this).val());
		
		let page = '${page.cri.pageNum}'; // 텍스트 형태로 js가 인식
		let amount = $(this).val();
		let category = '${page.cri.category}';
		// amount를 뺀 나머지 문자열이 필요
		let type = '${page.cri.typeStr}'
		
		let obj = {pageNum:page, amount:amount, category:category};
		location.search = $.param(obj) + type;
	})

BoardDao 수정

package com.chanyongyang.jsp.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import com.chanyongyang.jsp.domain.Board;
import com.chanyongyang.jsp.domain.Criteria;
import com.chanyongyang.jsp.domain.Member;
import com.chanyongyang.jsp.util.DBConn;

public class BoardDao {

		private Connection conn;
		private PreparedStatement pstmt;
		private ResultSet rs;
		
		public int insert(Board board) {
			conn = DBConn.getConnection();
			int result = 0;
			// 처리할 sql구문, 지정타입에 맞춰서 ? 로 바꿀수 있음 
			String sql = "insert into tbl_board (title, content, writer) values (?, ?, ?)";
			try {
				// 문장 생성
				pstmt = conn.prepareStatement(sql);
				pstmt.setString(1, board.getTitle());
				pstmt.setString(2, board.getContent());
				pstmt.setString(3, board.getWriter());
				
				// 문장 처리
				result = pstmt.executeUpdate();
				close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return result;
		}
		public Board selectOne(Long bno) {
			conn = DBConn.getConnection();
			// 반환 예정 객체
			Board board = null;
			// 처리할 sql구문
			String sql = "select * from tbl_board where bno = ?";
			try {
				// 문장 생성 conn으로부터 문장생성 객체를 만듬
				pstmt = conn.prepareStatement(sql);
				pstmt.setLong(1, bno);
				// 결과집합 반환
				rs = pstmt.executeQuery();
				
				// 결과집합을 자바객체로 만듬
				if(rs.next()) {
					int idx = 1;
					// 객체 생성 후 값 바인딩
					
					board = new Board(
							rs.getLong(idx++),
							rs.getString(idx++),
							rs.getString(idx++),
							rs.getString(idx++),
							rs.getDate(idx++),
							rs.getString(idx++),
							rs.getInt(idx++), rs.getInt(idx++));
				}
				close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			// 결과 반환
			return board;
		}
		
		
		public List<Board> selectList(Criteria cri) {
			conn = DBConn.getConnection();
			// 반환 예정 객체
			List<Board> boards = new ArrayList<Board>();
			// 처리할 sql구문
			String sql =""; 
			sql += "select * from tbl_board where category = ?";
			// 검색
			sql += getSearchSqlBy(cri);
			sql += " order by bno desc limit ? offset ?";
			System.out.println(sql);
			try {
				// 문장 생성 conn으로부터 문장생성 객체를 만듬
				pstmt = conn.prepareStatement(sql);
				int idx = 1;
				pstmt.setInt(idx++, cri.getCategory());
//				if(cri.getType() != null && cri.getKeyword() != null) {
//					pstmt.setString(idx++, cri.getKeyword());
//				}
				pstmt.setInt(idx++, cri.getAmount());
				pstmt.setInt(idx++, (cri.getPageNum() - 1) * cri.getAmount());
				// 결과집합 반환
				rs = pstmt.executeQuery();
				
				// 결과집합을 자바객체로 만듬
				while(rs.next()) {
					idx = 1;
					// 객체 생성 후 값 바인딩
					
					Board board = new Board(
							rs.getLong(idx++),
							rs.getString(idx++),
							rs.getString(idx++),
							rs.getString(idx++),
							rs.getDate(idx++),
							rs.getString(idx++),
							rs.getInt(idx++), rs.getInt(idx++));
					boards.add(board);
				}
				close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			// 결과 반환
			return boards;
		}
		public int selectListCount(Criteria cri) {
			conn = DBConn.getConnection();
			// 반환 예정 객체
			int count = 0;
			// 처리할 sql구문
			String sql = "select count(*) from tbl_board where category = ?";
			sql += getSearchSqlBy(cri);
			
			try {
				// 문장 생성 conn으로부터 문장생성 객체를 만듬
				pstmt = conn.prepareStatement(sql);
				pstmt.setLong(1, cri.getCategory());
				// 결과집합 반환
				rs = pstmt.executeQuery();
				
				// 결과집합을 자바객체로 만듬
				while(rs.next()) {
					int idx = 1;
					// 객체 생성 후 값 바인딩
					count = rs.getInt(1);
				}
				close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			// 결과 반환
			return count;
		}
		
		public void update(Board board) {
			conn = DBConn.getConnection();
			// 처리할 sql구문
			String sql = "update tbl_board set\r\n"
					+ "	title = ?,\r\n"
					+ "	content = ?,\r\n"
					+ "	updatedate = now()\r\n"
					+ "where bno = ?";
//			System.out.println(sql);
			try {
				// 문장 생성
				pstmt = conn.prepareStatement(sql);
				pstmt.setString(1, board.getTitle());
				pstmt.setString(2, board.getContent());
				pstmt.setLong(3, board.getBno());
				
				// 문장 처리
				pstmt.executeUpdate();
				close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		public void delete(Long bno) {
			conn = DBConn.getConnection();
			// 처리할 sql구문
			String sql = "delete from tbl_board where bno = ?";
//			System.out.println(sql);
			try {
				// 문장 생성
				pstmt = conn.prepareStatement(sql);
				pstmt.setLong(1, bno);
				
				// 문장 처리
				pstmt.executeUpdate();
				close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		// 자원반환
		public void close() {
			if(conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {}
			}
			if(pstmt != null) {
				try {
					pstmt.close();
				} catch (SQLException e) {}
			}
			if(rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {}
			}
		}
		private String getSearchSqlBy(Criteria cri) {
			String sql ="";
			
//			if(cri.getType() != null && cri.getKeyword() != null) {
			if(cri.getType() != null && cri.getKeyword() != null && String.join("", cri.getType()).length() > 0) {
				sql += " and ( ";
							
				List<String> list = Arrays.asList(cri.getType());
				// T C W
				List<String> typeList = list.stream().map(s->" " + s + " like '%" + cri.getKeyword() + "%' ").collect(Collectors.toList());
				sql += String.join(" or ", typeList);
							
				sql += ")";
			}
			
			return sql;
		}
		
		public static void main(String[] args) {
//			new BoardDao().selectList(1).forEach(System.out::println);
//			BoardDao dao = new BoardDao();
//			Board board = dao.selectOne(5L);
//			System.out.println(dao.selectListCount(1));
//			board.setTitle("java에서 수정한 내용");
//			board.setContent("java에서 수정한 내용");
			
//			dao.update(board);
//			dao.delete(5L);
//			System.out.println(dao.selectOne(5L));
			
			String str = "12345";
			String[] result = str.split("");
			System.out.println(result.length);
			String result2 = String.join(" or ", result);
			System.out.println(result2);
		}

}

Criteria 수정

package com.chanyongyang.jsp.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Criteria {
	// 초기값을 주는게 좋다.	
	private int pageNum = 1;
	private int amount = 10;
	private int category = 1;
	private String[] type = new String[0];
	private String keyword = "";
	
	public Criteria(int pageNum, int amount) {
		this.pageNum = pageNum;
		this.amount = amount;
	}
	public String getQueryString() {
		String str = "";
		str += "amount=" + amount + "&category=" + category;
		str += getTypeStr();
		return str;
	}
	public String getTypeStr() {
		String str = "";
		if(type != null) {
			for(String s : type) {
				str += "&type=" + s;
			}
			// 검색어가 있을때만 검색
			str += "&keyword=" + keyword;
		}
		return str;
	}
	
}

 

※ 게시글 내용을 볼때 기존에 있던 쿼리스트링을 가져가지않고 bno만 가져오는 상황 발생

이로인해 게시글 내용 보고 목록으로 갔을 때 게시판의 첫페이지를 가져오게됨

 

1. 게시글 클릭시 글번호만 가져오는게 아닌 나머지값도 전에 있던 쿼리스트링 전체를 가져와야함

2. list.jsp의 a태그 수정

<a href="view?bno=${board.bno}" class="text-decoration-none">
↓
<a href="view?bno=${board.bno}&${page.cri.fullQueryString}" class="text-decoration-none">

3. view 컨트롤러에 크리테리아 바인딩

package com.chanyongyang.jsp.board.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.chanyongyang.jsp.domain.Criteria;
import com.chanyongyang.jsp.service.BoardService;
import com.chanyongyang.jsp.service.BoardServiceImpl;
import com.chanyongyang.jsp.util.ParamSolver;

@WebServlet("/board/view")
public class BoardViewController extends HttpServlet {
	private BoardService boardService = new BoardServiceImpl();
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		Criteria cri = ParamSolver.getParams(req, Criteria.class);
//		view.jsp에서도 cri로 호출 가능
		req.setAttribute("cri", cri);
		req.setAttribute("board", boardService.get(Long.valueOf(req.getParameter("bno"))));
		req.getRequestDispatcher("/WEB-INF/jsp/board/view.jsp").forward(req, resp);
	}
	
}

4. view.jsp a태그(수정, 삭제, 목록으로) 경로 추가 

       		<div class="text-center">
       		 	<a href="modify?bno=${board.bno}&${cri.fullQueryString}" class="btn btn-warning">수정</a>
       		 	<a href="remove?bno=${board.bno}&${cri.fullQueryString}" class="btn btn-danger btn-remove">삭제</a>
       		 	<a href="list?${cri.fullQueryString}" class="btn btn-outline-primary">목록으로</a>
        	</div>

5. remove 컨트롤러 수정

package com.chanyongyang.jsp.board.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.chanyongyang.jsp.domain.Criteria;
import com.chanyongyang.jsp.service.BoardService;
import com.chanyongyang.jsp.service.BoardServiceImpl;
import com.chanyongyang.jsp.util.ParamSolver;

@WebServlet("/board/remove")
public class BoardRemoveController extends HttpServlet {
	private BoardService boardService = new BoardServiceImpl();
	
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		Criteria cri = ParamSolver.getParams(req, Criteria.class);
		boardService.remove(Long.valueOf(req.getParameter("bno")));
		// 삭제시 쿼리스트링을 달고다님
		resp.sendRedirect("list" + "?" + cri.getFullQueryString());
	}
	
}

6. modify 컨트롤러 에 크리테리아 값 바인딩

package com.chanyongyang.jsp.board.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.chanyongyang.jsp.domain.Board;
import com.chanyongyang.jsp.domain.Criteria;
import com.chanyongyang.jsp.service.BoardService;
import com.chanyongyang.jsp.service.BoardServiceImpl;
import com.chanyongyang.jsp.util.ParamSolver;

@WebServlet("/board/modify")
public class BoardModifyController extends HttpServlet {
	private BoardService boardService = new BoardServiceImpl();
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		if(req.getSession().getAttribute("member") == null) {
			resp.sendRedirect(req.getContextPath() + "/member/login");
			return;
		}
		req.setAttribute("cri", ParamSolver.getParams(req, Criteria.class));
		req.setAttribute("board", boardService.get(Long.valueOf(req.getParameter("bno"))));
		req.getRequestDispatcher("/WEB-INF/jsp/board/modify.jsp").forward(req, resp);
	}

	@Override //글작성 주로 나오는 오류는 네임값오류이다. 이름이 맞는지 getParameter에 네임값이 맞는지 꼭 확인하자!
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
//		Board board = new Board(req.getParameter("title"), req.getParameter("content"), req.getParameter("writer"));
//		board.setBno(Long.valueOf(req.getParameter("bno")));
		
		Board board = ParamSolver.getParams(req, Board.class);
		boardService.modify(board);
		resp.sendRedirect("view?bno=" + board.getBno());
	}
	
	
	
}

6-1 modify.jsp 구문 삽입 및 수정

       		<div class="text-center">
       		<input type="hidden" name="bno" value="${board.bno}">
       		<input type="hidden" name="pageNum" value="${cri.pageNum}">
       		<input type="hidden" name="amount" value="${cri.amount}">
       		<input type="hidden" name="category" value="${cri.category}">
       		<c:if test="${not empty cri.type}">
       			<c:forEach items="${cri.type}" var="type">
       				<input type="hidden" name="type" value="${type}">
       			</c:forEach>
       			<input type="hidden" name="keyword" value="${cri.keyword}">
       		</c:if>
       		 	<button class="btn btn-warning">수정</button>
       		 	<a href="list?${cri.fullQueryString}" class="btn btn-outline-warning">목록</a>
        	</div>

 

7. 게시글 수정시 쿼리스트링을 가져와야함 그래야 목록으로 갔을시 쿼리스트링을 확인하여 그 목록으로 넘어감

 7-1. modify 컨트롤러 doPost 크리테리아 바인딩 및 코드 수정

package com.chanyongyang.jsp.board.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.chanyongyang.jsp.domain.Board;
import com.chanyongyang.jsp.domain.Criteria;
import com.chanyongyang.jsp.service.BoardService;
import com.chanyongyang.jsp.service.BoardServiceImpl;
import com.chanyongyang.jsp.util.ParamSolver;

@WebServlet("/board/modify")
public class BoardModifyController extends HttpServlet {
	private BoardService boardService = new BoardServiceImpl();
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		if(req.getSession().getAttribute("member") == null) {
			resp.sendRedirect(req.getContextPath() + "/member/login");
			return;
		}
		req.setAttribute("cri", ParamSolver.getParams(req, Criteria.class));
		req.setAttribute("board", boardService.get(Long.valueOf(req.getParameter("bno"))));
		req.getRequestDispatcher("/WEB-INF/jsp/board/modify.jsp").forward(req, resp);
	}

	@Override //글작성 주로 나오는 오류는 네임값오류이다. 이름이 맞는지 getParameter에 네임값이 맞는지 꼭 확인하자!
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
//		Board board = new Board(req.getParameter("title"), req.getParameter("content"), req.getParameter("writer"));
//		board.setBno(Long.valueOf(req.getParameter("bno")));
		Criteria cri = ParamSolver.getParams(req, Criteria.class);
		Board board = ParamSolver.getParams(req, Board.class);
		boardService.modify(board);
		resp.sendRedirect("view?bno=" + board.getBno() + "&" + cri.getFullQueryString());
	}
	
	
	
}

 

 

* 게시글 수정 완료시 쿼리스트링에 type이 2번붙음

http://localhost/member_board/board/list?pageNum=4&amount=10&category=1&type=title&type=title&type=title&type=title&keyword=

원인 : 배열 및 여러 문제

formaction = 원래하던 액션을 안쓰고 자기 액션을 쓰겠다

해결 1

<button class="btn btn-warning"">수정</button>
↓ 로 수정
<button class="btn btn-warning" formaction="modify">수정</button>

해결 2 

js에서 해결

 

위에까지 게시판에 대한 CRUD는 끝

 

※ 댓글(비동기처리, JS작업이 많이 들어감 (VSCODE랑 왔다갔다 해야함))

1. 테이블 생성

 

2. 단독글이 아닌 종속형태의 게시글 (게시글이 잇어야만 댓글 작성 가능)

2-1. 회원과 댓글에 대한 외래키 필요 (회원제 게시판일경우)

 

3. 댓글의 정렬순서 (최신글을 맨 밑으로)

 

4. 페이징처리 안함 (스프링가서 작업할것)

 

5. 수정기능x 작성, 삭제만 가능하게

 

6. 댓글에 대한 목록조회

 

7. 댓글을 삭제하기 위해 작성자확인

 

※ 댓글 구현

1. 테이블 생성

create table tbl_reply (
	rno bigint primary key auto_increment,
	content text,
	regdate datetime default now(),
	writer varchar(750) references tbl_member(id),
	bno bigint references tbl_board
);

 

2. VO 생성

 

3. DAO 생성

boardDao를 복붙해서 Reply를 만들고 쓸

package com.chanyongyang.jsp.domain;

import java.util.Date;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Reply {
	private Long rno;
	private String Content;
	private Date regDate;
	private String writer;
	private Long bno;
	
}

4. service 생성

 

5. controller 생성

package com.chanyongyang.jsp.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.chanyongyang.jsp.domain.Reply;
import com.chanyongyang.jsp.service.ReplyService;
import com.chanyongyang.jsp.service.ReplyServiceImpl;

@WebServlet("/reply")
public class ReplyController extends HttpServlet {
	private ReplyService service = new ReplyServiceImpl();
	
	@Override
	protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 삭제
		// TODO Auto-generated method stub
		super.doDelete(req, resp);
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 조회
		// 목록을 가져와야함 (bno값 필요)
		Long bno = Long.valueOf(req.getParameter("bno"));
		List<Reply> replies = service.list(bno);
		System.out.println(replies);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

	}
	// Http Method
	// GET, POST, PUT(PATCH), DELETE
	
	
}

http://localhost/member_board/reply?bno=515

* xml or json으로 응답해야 비동기로 처리됨

 

6. application.json

https://mvnrepository.com/artifact/com.google.code.gson/gson/2.8.9 

2.8.9 버전 jar 파일 다운로드 후 라이브러리 폴더에 추가

빨간색으로 칠해진 버전은 보안이슈가 있던 친구들이니 사용을 가급적이면 안하는게 좋다.

 

json의 문자열은 toJson이다.

위 예제 수정

	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 조회
		// 목록을 가져와야함 (bno값 필요)
		Long bno = Long.valueOf(req.getParameter("bno"));
		List<Reply> replies = service.list(bno);
		System.out.println(replies);
		Gson gson = new Gson();
		String json = gson.toJson(replies); // String type으로 반환
		System.out.println(json);

toJson 출력

한글이 깨진다. 코드 재수정

	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 조회
		// 목록을 가져와야함 (bno값 필요)
		Long bno = Long.valueOf(req.getParameter("bno"));
		List<Reply> replies = service.list(bno);
		System.out.println(replies);
		Gson gson = new Gson();
		String json = gson.toJson(replies); // String type으로 반환
		System.out.println(json);
		resp.setContentType("application/json; charset=utf8");
		resp.getWriter().print(json);
	}

 

이제 준비를 다 했으니 view.jsp에서 비동기로 가져올 수 있게 되었다.

 

view.jsp script 수정

 	$(".btn-remove").click(function() {
 		return confirm("정말 삭제 하시겠습니까?");
 	});
	let contextPath = '${pageContext.request.contextPath}'
	let replyPath = contextPath + "/reply"
	let bno = '${board.bno}';
	$.ajax({
		url : replyPath,
		data : {bno:bno},
		success : function(data) {
			console.log(data);
		}
	})

이제 댓글이 있는 글에 가서 f12 버튼을 누르면 댓글이 보이게 된다.

 

원래 없는것에 대한 동적처리를 해야함 (화면구성)

 

view.html 생성

댓글이 있는 페이지의 소스를 긁어와 복붙해준다.

fontawesome에서 적절한 아이콘 찾아 배치

댓글 작성폼 만들기

singleLineText

<!DOCTYPE html>
<html lang="ko">

<head>

  <meta charset='utf-8'>
  <meta http-equiv='X-UA-Compatible' content='IE=edge'>
  <title>Page Title</title>
  <meta name='viewport' content='width=device-width, initial-scale=1'>
  <link rel="shortcut icon" href="/member_board/img/fav.ico">
  <link rel='stylesheet' href='	https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css'>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"
    integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ=="
    crossorigin="anonymous" referrerpolicy="no-referrer" />
  <script src='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js'></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/js/all.min.js"
    integrity="sha512-Tn2m0TIpgVyTzzvmxLNuqbSJH3JP8jm+Cy3hvHrW7ndTDcJ1w5mBiksqDBb8GpE2ksktFvDB/ykZ0mDpsZj20w=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js"
    integrity="sha512-pumBsjNRGGqkPzKHndZMaAG+bir374sORyzM3uulLV14lN5LyykqNk8eEeUlUkB3U0M4FApyaHraT65ihJhDpQ=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>

<body>

  <header class="container-fluid bg-warning">
    <div class="container">
      <div class="pt-3">
        <a href="/member_board" class="text-decoration-none">
          <h1><span class="fs-2">더조은 아카데미</span> <span class="fs-6">AWS 클라우드 기반 자바&스프링&리액트 풀스택 개발자 양성</span></h1>
        </a>
      </div>
      <nav class="navbar navbar-expand-sm">
        <!-- Links -->
        <ul class="navbar-nav">
          <li class="nav-item">
            <a class="nav-link" href="/member_board">홈</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="/member_board/board/list">게시판</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">갤러리</a>
          </li>
        </ul>
      </nav>
    </div>
  </header>
  <main class="container p-3 pb-5">
    <div class="card">
      <div class="card-header p-5">
        <h2>Board View</h2>
      </div>
      <div class="card-body">
        <form method="post">
          <div class="mb-3 mt-3">
            <label for="title" class="form-label"><i class="fas fa-heading"></i> title</label>
            <input type="text" class="form-control" id="email" placeholder="Enter title" name="title" readonly
              value="23-03-13 첫글">
          </div>
          <div class="mb-3">
            <label for="content" class="form-label"><i class="fas fa-align-left"></i> content</label>
            <textarea class="form-control" id="content" placeholder="Enter content" name="content" rows="10"
              readonly>뭐 왜</textarea>
          </div>
          <div class="mb-3">
            <label for="writer" class="form-label"><i class="fas fa-user-edit"></i> writer</label>
            <input type="text" class="form-control" id="writer" placeholder="Enter writer" name="writer" value="id1"
              readonly>
          </div>
          <div class="text-center">
            <a href="modify?bno=515&pageNum=1&amount=10&category=1" class="btn btn-warning"><i class="far fa-edit"></i> 수정</a>
            <a href="remove?bno=515&pageNum=1&amount=10&category=1" class="btn btn-danger btn-remove"><i class="far fa-trash-alt"></i> 삭제</a>
            <a href="list?pageNum=1&amount=10&category=1" class="btn btn-outline-primary">목록으로</a>
          </div>
          <div class="mb-3">
            <p class="form-label mb-4 border-bottom pb-3"><i class="far fa-comment-dots"></i> replies</p>
            <div class="px-5 row mb-5">
              <textarea class="form-control mb-2" id="commentArea" placeholder="Enter comments" rows="3"></textarea>
              <button class="btn btn-primary opacity-75">댓글 작성</button>
            </div>
            <ul class="container">
              <li class="list-unstyled px-4">
                <div class="row">
                  <a class="text-muted small mb-3 col text-decoration-none" href="">
                    <span class="fs-6 fw-bold">id1</span>
                    <span class="mx-5">2023-03-08 16:18:56</span>
                  </a>
                  <div class="col text-end"><a href="" class="text-danger"><i class="fas fa-times"></i></a></div>
                </div>
                <div class="mb-4 small">
                  <p>java dao에서 테스트</p>
                </div>
              </li>
            </ul>
          </div>
        </form>
      </div>
    </div>
  </main>

  <footer class="container-fluid bg-warning p-5 text-center">
    <address>copyright @ TJ academy</address>
  </footer>
  <script>
    $(".btn-remove").click(function () {
      return confirm("정말 삭제 하시겠습니까?");
    });
    let contextPath = '/member_board'
    let replyPath = contextPath + "/reply"
    let bno = '515';
    $.ajax({
      url: replyPath,
      data: { bno: bno },
      success: function (data) {
        console.log(data);
      }
    })
  </script>
</body>

</html>
<!-- 게시판에 table을 안쓰는게 좋음 / ul, li 사용 -->

 

 

이벤트 부여

script구문 추가

1. 댓글작성시 이벤트

2. 댓글 삭제시 이벤트

   $(".btn-remove").click(function () {
      return confirm("정말 삭제 하시겠습니까?");
    });
    let contextPath = '/member_board'
    let replyPath = contextPath + "/reply"
    let bno = '515';
    
    // 임시 주석
    // $.ajax({
    //   url: replyPath,
    //   data: { bno: bno },
    //   success: function (data) {
    //     console.log(data);
    //   }
    // })

    let jsonStr = '[{"rno":9,"content":"댓글댓글","regDate":"3월 13, 2023","writer":"id1","bno":515}, {"rno":10,"content":"댓글댓글","regDate":"3월 13, 2023","writer":"id1","bno":515}]'
    let replies = JSON.parse(jsonStr);
    console.log(replies);
    let str = "";
    for(let i in replies) {
      let r = replies[i];
      console.log(r.rno, r.content, r.regDate, r.writer, r.bno);
      
       str += `
      <li class="list-unstyled px-4" data-rno="${r.rno}">
        <div class="row">
          <a class="text-muted small mb-3 col text-decoration-none" href="">
            <span class="fs-6 fw-bold">${r.writer}</span>
            <span class="mx-5">${r.regDate}</span>
            </a>
            <div class="col text-end"><a href="" class="text-danger"><i class="fas fa-times"></i></a></div>
            </div>
            <div class="mb-4 small">
              <p>${r.content}</p>
              </div>
              </li>
    `;
  }
  $(".replies").html(str);

  // 댓글 작성
  $("#commentArea").next().click(function() {
    console.log($("#commentArea").val());
  })


  // 댓글 삭제
  $(".replies").on("click", "li a.text-danger", function() {
    event.preventDefault();
    console.log($(this).closest("li").data("rno"));
  })

 

 * script 작성시 에러상황

  for문 콘솔로 출력시 날짜, 글번호를 제외하고 undefined 출력

 해결방법

  - vo작성시 변수 선언할 때 content를 Content로 작업했다. 소문자로 변경 후 에러 해결

 

 

※ 수신 테스트를 위한 확장프로그램 설치 및 사용방법

설치 후 크롬 우측 상단에 있는 확장프로그램을 눌러 실행

★ tomcat server가 켜져있어야함

 

 * 수신 테스트 (replyController => doDelete, doPost 구문 추가) 

package com.chanyongyang.jsp.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.chanyongyang.jsp.domain.Reply;
import com.chanyongyang.jsp.service.ReplyService;
import com.chanyongyang.jsp.service.ReplyServiceImpl;
import com.chanyongyang.jsp.util.ParamSolver;
import com.google.gson.Gson;

@WebServlet("/reply")
public class ReplyController extends HttpServlet {
	private ReplyService service = new ReplyServiceImpl();
	

	@Override
	protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 삭제
		System.out.println(req.getParameter("rno"));
		System.out.println("doDelete()");
		service.remove(Long.valueOf(req.getParameter("rno")));
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		Reply reply = ParamSolver.getParams(req, Reply.class);
		System.out.println(reply);
		System.out.println("doPost()");
		service.register(reply);

	}
	// Http Method
	// GET, POST, PUT(PATCH), DELETE
	
	
}

 

1) 추가 (댓글번호, 내용, 작성자 입력)

2) 조회 (댓글이 달린 글번호 입력)

3) 삭제 (댓글번호 입력)

주로 테스트 용도로 사용된다.

 

※ 새로

 

마지막 view.html 코드

<!DOCTYPE html>
<html lang="ko">

<head>

  <meta charset='utf-8'>
  <meta http-equiv='X-UA-Compatible' content='IE=edge'>
  <title>Page Title</title>
  <meta name='viewport' content='width=device-width, initial-scale=1'>
  <link rel="shortcut icon" href="/member_board/img/fav.ico">
  <link rel='stylesheet' href='	https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css'>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"
    integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ=="
    crossorigin="anonymous" referrerpolicy="no-referrer" />
  <script src='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js'></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/js/all.min.js"
    integrity="sha512-Tn2m0TIpgVyTzzvmxLNuqbSJH3JP8jm+Cy3hvHrW7ndTDcJ1w5mBiksqDBb8GpE2ksktFvDB/ykZ0mDpsZj20w=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js"
    integrity="sha512-pumBsjNRGGqkPzKHndZMaAG+bir374sORyzM3uulLV14lN5LyykqNk8eEeUlUkB3U0M4FApyaHraT65ihJhDpQ=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>

<body>

  <header class="container-fluid bg-warning">
    <div class="container">
      <div class="pt-3">
        <a href="/member_board" class="text-decoration-none">
          <h1><span class="fs-2">더조은 아카데미</span> <span class="fs-6">AWS 클라우드 기반 자바&스프링&리액트 풀스택 개발자 양성</span></h1>
        </a>
      </div>
      <nav class="navbar navbar-expand-sm">
        <!-- Links -->
        <ul class="navbar-nav">
          <li class="nav-item">
            <a class="nav-link" href="/member_board">홈</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="/member_board/board/list">게시판</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">갤러리</a>
          </li>
        </ul>
      </nav>
    </div>
  </header>
  <main class="container p-3 pb-5">
    <div class="card">
      <div class="card-header p-5">
        <h2>Board View</h2>
      </div>
      <div class="card-body">
        <form method="post">
          <div class="mb-3 mt-3">
            <label for="title" class="form-label"><i class="fas fa-heading"></i> title</label>
            <input type="text" class="form-control" id="email" placeholder="Enter title" name="title" readonly
              value="23-03-13 첫글">
          </div>
          <div class="mb-3">
            <label for="content" class="form-label"><i class="fas fa-align-left"></i> content</label>
            <textarea class="form-control" id="content" placeholder="Enter content" name="content" rows="10"
              readonly>뭐 왜</textarea>
          </div>
          <div class="mb-3">
            <label for="writer" class="form-label"><i class="fas fa-user-edit"></i> writer</label>
            <input type="text" class="form-control" id="writer" placeholder="Enter writer" name="writer" value="id1"
              readonly>
          </div>
          <div class="text-center">
            <a href="modify?bno=515&pageNum=1&amount=10&category=1" class="btn btn-warning"><i class="far fa-edit"></i> 수정</a>
            <a href="remove?bno=515&pageNum=1&amount=10&category=1" class="btn btn-danger btn-remove"><i class="far fa-trash-alt"></i> 삭제</a>
            <a href="list?pageNum=1&amount=10&category=1" class="btn btn-outline-primary">목록으로</a>
          </div>
          <div class="mb-3">
            <p class="form-label mb-4 border-bottom pb-3"><i class="far fa-comment-dots"></i> replies</p>
            <div class="px-5 row mb-5">
              <textarea class="form-control mb-2" id="commentArea" placeholder="Enter comments" rows="3"></textarea>
              <button type="button" class="btn btn-primary opacity-75">댓글 작성</button>
            </div>
            <ul class="container replies">
              <li class="list-unstyled px-4">
                <!-- <div class="row">
                  <a class="text-muted small mb-3 col text-decoration-none" href="">
                    <span class="fs-6 fw-bold">id1</span>
                    <span class="mx-5">2023-03-08 16:18:56</span>
                  </a>
                  <div class="col text-end"><a href="" class="text-danger"><i class="fas fa-times"></i></a></div>
                </div> -->
                <div class="mb-4 small text-center">
                  <p>댓글이 없습니다</p>
                </div>
              </li>
            </ul>
          </div>
        </form>
      </div>
    </div>
  </main>

  <footer class="container-fluid bg-warning p-5 text-center">
    <address>copyright @ TJ academy</address>
  </footer>
  <script>
    $(".btn-remove").click(function () {
      return confirm("정말 삭제 하시겠습니까?");
    });
    let contextPath = '/member_board'
    let replyPath = contextPath + "/reply"
    let bno = '515';
    // $.ajax({
    //   url: replyPath,
    //   data: { bno: bno },
    //   success: function (data) {
    //     console.log(data);
    //   }
    // })


    // 댓글 조회
    function list() {
      let jsonStr = '[{"rno":9,"content":"댓글댓글","regDate":"3월 13, 2023","writer":"id1","bno":515}, {"rno":10,"content":"댓글댓글","regDate":"3월 13, 2023","writer":"id1","bno":515}]'
      let replies = JSON.parse(jsonStr);
      console.log(replies);
      let str = "";
      for(let i in replies) {
        let r = replies[i];
        console.log(r.rno, r.content, r.regDate, r.writer, r.bno);
        
        str += `
        <li class="list-unstyled px-4" data-rno="${r.rno}">
          <div class="row">
            <a class="text-muted small mb-3 col text-decoration-none" href="">
              <span class="fs-6 fw-bold">${r.writer}</span>
              <span class="mx-5">${r.regDate}</span>
              </a>
              <div class="col text-end"><a href="" class="text-danger"><i class="fas fa-times"></i></a></div>
              </div>
              <div class="mb-4 small">
                <p>${r.content}</p>
                </div>
                </li>
        `;
      }
      // json 분석 (db에 저장된 댓글 출력)
      $(".replies").html(str);
    }
    list();


  // 댓글 작성
  $("#commentArea").next().click(function() {
    console.log($("#commentArea").val());
  })


  // 댓글 삭제
  $(".replies").on("click", "li a.text-danger", function() {
    event.preventDefault();
    console.log($(this).closest("li").data("rno"));
  })
  </script>
</body>

</html>
<!-- 게시판에 table을 안쓰는게 좋음 / ul, li 사용 -->

view.jsp을 view.html기반으로 코드 수정 및 댓글작성 적용

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core"  prefix="c"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<%@ include file="../common/head.jsp" %>
</head>
<body>
<%@ include file="../common/header.jsp" %>
 <main class="container p-3 pb-5">
    <div class="card">
      <div class="card-header p-5">
        <h2>Board View</h2>
      </div>
      <div class="card-body">
 		<form method="post">
 			<div class="mb-3 mt-3">
  				<label for="title" class="form-label">title</label>
   				<input type="text" class="form-control" id="email" placeholder="Enter title" name="title" readonly value="${board.title}">
 			</div>
 			<div class="mb-3">
   	 			<label for="content" class="form-label">content</label>
   		 		<textarea class="form-control" id="content" placeholder="Enter content" name="content" rows="10" readonly>${board.content}</textarea>
  			</div>
  			<div class="mb-3">
    			<label for="writer" class="form-label">writer</label>
    			<input type="text" class="form-control" id="writer" placeholder="Enter writer" name="writer" value="${board.writer}" readonly>
  			</div>
       		<div class="text-center">
       		 	<a href="modify?bno=${board.bno}&${cri.fullQueryString}" class="btn btn-warning">수정</a>
       		 	<a href="remove?bno=${board.bno}&${cri.fullQueryString}" class="btn btn-danger btn-remove">삭제</a>
       		 	<a href="list?${cri.fullQueryString}" class="btn btn-outline-primary">목록으로</a>
        	</div>
        	
        	<div class="mb-3">
            <p class="form-label mb-4 border-bottom pb-3"><i class="far fa-comment-dots"></i> replies</p>
            <div class="px-5 row mb-5">
              <textarea class="form-control mb-2" id="commentArea" placeholder="Enter comments" rows="3"></textarea>
              <button type="button" class="btn btn-primary opacity-75">댓글 작성</button>
            </div>
            <ul class="container replies">
              <li class="list-unstyled px-4">
                <div class="mb-4 small text-center">
                  <p>댓글이 없습니다</p>
                </div>
              </li>
            </ul>
          </div>
		</form>
      </div>
    </div>
  </main>
 <%@ include file="../common/footer.jsp" %>
 <script>
 	$(".btn-remove").click(function() {
 		return confirm("정말 삭제 하시겠습니까?");
 	});
	let contextPath = '${pageContext.request.contextPath}';
	let replyPath = contextPath + "/reply"
	let bno = '${board.bno}';
	// 댓글작성과 이어짐
	let writer = '${member.id}';
	
	// ajax를 function으로 묶어줘야 새로고침을 안함
	showList();
	function showList() {
		$.ajax({
			url : replyPath,
			data : {bno:bno},
			success : list
		});
	}
	
	// 댓글 목록
	function list(replies) {
    //  let jsonStr = '[{"rno":9,"content":"댓글댓글","regDate":"3월 13, 2023","writer":"id1","bno":515}, {"rno":10,"content":"댓글댓글","regDate":"3월 13, 2023","writer":"id1","bno":515}]'
    //  let replies = JSON.parse(jsonStr);
      console.log(replies);
      let str = "";
      for(let i in replies) {
        let r = replies[i];
        console.log(r.rno, r.content, r.regDate, r.writer, r.bno);
        
        // el 문법에 escape처리 해야 적용됨
        str += `
        <li class="list-unstyled px-4" data-rno="\${r.rno}">
          <div class="row">
            <a class="text-muted small mb-3 col text-decoration-none" href="">
              <span class="fs-6 fw-bold">\${r.writer}</span>
              <span class="mx-5">\${r.regDate}</span>
              </a>
              <div class="col text-end"><a href="" class="text-danger"><i class="fas fa-times"></i></a></div>
              </div>
              <div class="mb-4 small">
                <p>\${r.content}</p>
                </div>
                </li>
        `;
      }
      // json 분석 (db에 저장된 댓글 출력)
      $(".replies").html(str);
    }

	// 댓글 작성
    $("#commentArea").next().click(function() {
      //console.log($("#commentArea").val()); //session 체크가 필요함
      let content = $("#commentArea").val();
      if(!writer) {
    	  alert("로그인 후 작성하세요");
    	  return;
      }
      else if(!content) {
    	  alert("댓글 내용을 입력하세요");
    	  return;
      }
      // 비동기처리
      $.ajax ({
    	url : replyPath,
    	data : {bno:bno, content:content, writer:writer},
    	method : "POST",
    	success : function(data) {
    		alert("댓글이 성공적으로 작성되었습니다");
    		showList();
    	}
      })
    })


    // 댓글 삭제
    $(".replies").on("click", "li a.text-danger", function() {
      event.preventDefault();
      console.log($(this).closest("li").data("rno"));
    })
    
 </script>
</body>
</html>
      <!-- 게시판에 table을 안쓰는게 좋음 / ul, li 사용 -->

 

 

* 서버가 터졌을때 대처방법

 1. 가장 좋은방법은 이사가는 방법이다.

 2. 이사라 함은 dynamic web project를 새로 만들어서

 3. 내가 어느부분까지 정확히 동작했는지 확인 하고 코드를 하나씩 복사해서 붙여넣는다.

 4. 코드를 복사하여 하나씩 실행해보고 어느부분에서 에러가 나는지 확인한다.

 

DELETE 구현

    // 댓글 삭제
    $(".replies").on("click", "li a.text-danger", function() {
      event.preventDefault();
      console.log($(this).closest("li").data("rno"));
      let rno = $(this).closest("li").data("rno");
      $.ajax ({
      	url : replyPath,
      	data : {rno:rno},
      	method : "DELETE",
      	success : function(data) {
      		alert("댓글이 성공적으로 삭제되었습니다");
      		showList();
      	}
        })
    })

numberFormatException 발생

아래코드로 수정

    // 댓글 삭제
    $(".replies").on("click", "li a.text-danger", function() {
      event.preventDefault();
      console.log($(this).closest("li").data("rno"));
      let rno = $(this).closest("li").data("rno");
      $.ajax ({
      	url : replyPath + "?rno=" + rno,
      	data : {rno:rno},
      	method : "DELETE",
      	success : function(data) {
      		alert("댓글이 성공적으로 삭제되었습니다");
      		showList();
      	}
        })
    })

 

23-03-14

댓글 마무리작업

파일첨부 작업

'Servlet, JSP > Servlet, JSP' 카테고리의 다른 글

23-03-15 Servlet, JSP  (0) 2023.03.15
23-03-09 (1) Servlet, JSP  (0) 2023.03.09
23-03-07(1) Servlet, JSP  (0) 2023.03.07
23-03-06 (1) servlet, jsp  (0) 2023.03.06