게시글 좋아요 기능 구현하기

꿈꾸는하늘·2024년 3월 24일

JSP

목록 보기
16/25
post-thumbnail

게시글 좋아요 기능을 구현하기 위해서는
DB에 boardlike 테이블을 생성(num:좋아요 번호(auo increment), id:좋아요를 누른 사람, bno:게시글 번호)하고 board 테이블에 좋아요 수 속성을 추가하고 board 테이블의 bno와 boardlike의 bno를 외래키관계로 추가 & member 테이블의 id와 boardlike의 id를 외래키관계로 추가해야하며,
이에 따라 boardDto 및 BoardDao 수정, LikeDao를 생성해준다.
Dto의 경우 좋아요 테이블에서 필요한 값은 id와, 게시글번호 뿐이므로(num은 auto_increment 속성이라 필요없음) 별도의 Dto 생성없이 LikeDao에서 매개변수를 직접 입력하여 사용한다.

* boardlike 테이블


* board 테이블

* BoardDto.java

package dto;

import java.text.SimpleDateFormat;
import java.util.Date;

public class BoardDto {
	private int num;
	private String title;
	private String content;
	private String id;
	private Date postDate;
	private int viewCnt;
	private String name;
	
	private int commentCnt; //댓글수
	private int likeCnt; //좋아요수
	
	public int getLikeCnt() {
		return likeCnt;
	}
	public void setLikeCnt(int likeCnt) {
		this.likeCnt = likeCnt;
	}
	public int getCommentCnt() {
		return commentCnt;
	}
	public void setCommentCnt(int commentCnt) {
		this.commentCnt = commentCnt;
	}
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public Date getPostDate() {
		return postDate;
	}
	public void setPostDate(Date postDate) {
		this.postDate = postDate;
	}
	public int getViewCnt() {
		return viewCnt;
	}
	public void setViewCnt(int viewCnt) {
		this.viewCnt = viewCnt;
	}
	public BoardDto() {
		super();
		// TODO Auto-generated constructor stub
	}
	public BoardDto(String title, String content, String id) {
		super();
		this.title = title;
		this.content = content;
		this.id = id;
	}
	

	public BoardDto(int num, String title, String content, String id) {
		super();
		this.num = num;
		this.title = title;
		this.content = content;
		this.id = id;
	}
	@Override
	public String toString() {
		return "BoardDto [num=" + num + ", title=" + title + ", content=" + content + ", id=" + id + ", postDate="
				+ postDate + ", viewCnt=" + viewCnt + ", name=" + name + ", commentCnt=" + commentCnt + ", likeCnt="
				+ likeCnt + ", sdf=" + sdf + "]";
	}
	
	
}

* BoardDao.java

package dao;

import java.sql.Date;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Map;

import javax.servlet.ServletContext;

import dto.BoardDto;
import util.JDBConnect;

public class BoardDao extends JDBConnect{
	public BoardDao(ServletContext application) {
		super(application);
	}
	
	//selectCount - 게시물 개수(int 반환)
	public int selectCount(Map<String, String> map) {
		//1) 반환값 저장할 변수 선언
		int totalCnt = 0;
		
		try {
			//2) 쿼리문 작성
			String sql = "select count(*) from board ";
			if(map.get("searchWord")!=null) {
				sql+="where " + map.get("searchField") + " like '%" + map.get("searchWord") + "%' ";
			}
			//3) stmt 객체 생성
			stmt = con.createStatement();
			//4) 쿼리문 실행(psmt : 객체 생성시에 sql문을 매개값으로 넣어주고 실행시에 매개값을 주지 않았으나 stmt는 매개값없이 생성 후
			// 실행시에 sql문을 매개값으로 넣어줌
			rs = stmt.executeQuery(sql);
			if(rs.next()) {
				totalCnt = rs.getInt(1);
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return totalCnt;
	}
	
	public ArrayList<BoardDto> selectList(Map<String, String> map){
		//1) 반환값 저장할 변수 선언
		ArrayList<BoardDto> blist = new ArrayList<BoardDto>();
		
		try {

			String sql = "select * from board ";
			if(map.get("searchWord")!=null) {
				sql += "where " + map.get("searchField") + " like '%" + map.get("searchWord") + "%' ";
			}
			sql += "order by num desc ";
			sql += "limit "+map.get("offset")+" , "+map.get("pageSize");
			
			stmt = con.createStatement();
			rs = stmt.executeQuery(sql);
			
			while(rs.next()) {
				BoardDto dto = new BoardDto();
				dto.setNum(rs.getInt(1));
				dto.setTitle(rs.getString(2));
				dto.setContent(rs.getString(3));
				dto.setId(rs.getString(4));
				dto.setPostDate(rs.getTimestamp(5));
				dto.setViewCnt(rs.getInt(6));
				dto.setCommentCnt(rs.getInt(7));
				dto.setLikeCnt(rs.getInt(8));
				
				blist.add(dto);
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return blist;
	}
	
	public int post(BoardDto b) {
		int res = 0;
		try {
			String sql = "insert into board (title, content, id) values (?, ?, ?)";
			psmt = con.prepareStatement(sql);
			psmt.setString(1,  b.getTitle());
			psmt.setString(2, b.getContent());
			psmt.setString(3, b.getId());
			
			res = psmt.executeUpdate();
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return res;
	}
	
	public BoardDto selectNum(int num) {
		BoardDto dto = null;
		try {
			String sql = "select B.*, M.name from board B inner join member M "
					+"on B.id = M.id where num = ?";
			psmt = con.prepareStatement(sql);
			psmt.setInt(1, num);
			
			rs = psmt.executeQuery();
			if(rs.next()) {
				dto = new BoardDto();
				dto.setNum(rs.getInt(1));
				dto.setTitle(rs.getString(2));
				dto.setContent(rs.getString(3));
				dto.setId(rs.getString(4));
				dto.setPostDate(rs.getTimestamp(5));
				dto.setViewCnt(rs.getInt(6));
				dto.setCommentCnt(rs.getInt(7));
				dto.setLikeCnt(rs.getInt(8));
				dto.setName(rs.getString(9));
			};
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return dto;
	}
	
	public int updateViewCnt(int num) {
		int res = 0;
		
		try {
			String sql = "update board set viewCnt = viewCnt+1 where num=?";
			psmt = con.prepareStatement(sql);
			psmt.setInt(1, num);
			res = psmt.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return res;
	}
	
	public int edit(BoardDto b) {
		int res = 0;
		try {
			String sql = "update board set title=?, content=? where num=?";
			psmt=con.prepareStatement(sql);
			psmt.setString(1, b.getTitle());
			psmt.setString(2, b.getContent());
			psmt.setInt(3, b.getNum());
			
			res = psmt.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return res;
	}
	
	public int delete(int num, String id) {
		int res = 0;
		try {
			String sql = "delete from board where id=? and num=?";
			psmt = con.prepareStatement(sql);
			psmt.setString(1, id);
			psmt.setInt(2, num);
			res = psmt.executeUpdate();
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return res;
	}
	
	//게시물 번호에 해당하는 댓글 수를 1 증가 or 감소
	public int updateCommentCnt(String num, int commentCnt) {
		int res=0;
		try {
			String sql = "update board set commentCnt = commentCnt+? where num=?";
			psmt=con.prepareStatement(sql);
			psmt.setInt(1, commentCnt);
			psmt.setString(2, num);
			res = psmt.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return res;
	}
	
	//게시물 번호에 해당하는 좋아요 수를 1 증가 or 감소
	public int updateLikeCnt(String num, int likeCnt) {
		int res=0;
		try {
			String sql = "update board set likeCnt = likeCnt+? where num=?";
			psmt=con.prepareStatement(sql);
			psmt.setInt(1, likeCnt);
			psmt.setString(2, num);
			res = psmt.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return res;
	}

}

* LikeDao.java

package dao;

import java.sql.SQLException;

import javax.servlet.ServletContext;

import util.JDBConnect;

public class LikeDao extends JDBConnect{
	public LikeDao(ServletContext application) {
		super(application);
	}
	
	//좋아요 누르기
	public int insert(String id, String bno) {
		int res = 0;
		try {
			String sql = "insert into boardlike (id, bno) values(?,?)";
			psmt=con.prepareStatement(sql);
			psmt.setString(1, id);
			psmt.setString(2, bno);
			res = psmt.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return res;
	}
	
	
	//좋아요 해제
	public int delete(String id, String bno) {
		int res = 0;
		try {
			String sql = "delete from boardlike where id=? and bno=?";
			psmt=con.prepareStatement(sql);
			psmt.setString(1, id);
			psmt.setString(2, bno);
			res = psmt.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return res;
	}
	
	//해당 게시물을 사용자(로그인 id)가 좋아요를 눌렀는지 안눌렀는지 확인(게시글 view에 사용) 
	public int selectLike(String id, String bno) {
		int res =0;
		try {
			String sql = "select count(*) from boardlike where id=? and bno=?";
			psmt=con.prepareStatement(sql);
			psmt.setString(1, id);
			psmt.setString(2, bno);
			
			rs = psmt.executeQuery();
			if(rs.next()) {
				res = rs.getInt(1);
			}
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return res;
	}
	
	//해당 게시물의 전체 좋아요 수 확인(글 목록에 사용)
	public int selectAll(String bno) {
		int res =0;
		try {
			String sql = "select count(*) from boardlike where bno=?";
			psmt=con.prepareStatement(sql);
			psmt.setString(1, bno);
			
			rs = psmt.executeQuery();
			if(rs.next()) {
				res = rs.getInt(1);
			}
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return res;
	}
}

* BoardView.jsp

<%@page import="util.JSFunction"%>
<%@page import="dto.BoardDto"%>
<%@page import="dao.BoardDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판</title>
<style>
*{box-sizing: border-box;
margin : 0;
}
form {
    width : 700px;
    height: 600px;
    margin : 0 auto;
            
    }
#container{
	border : 1px solid grey;
    padding : 10px;
}
button{
    margin : 3px;
    background-color : white;
    border : 1px solid green;
    }
h2{text-align : center;
	margin : 20px;
}
#viewInfo{
	font-size : 12px;}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<link rel="stylesheet" href="css/HeaderAndNav.css">
<body>
<%@ include file = "HeaderAndNav.jsp" %>

<h2>상세보기(View)</h2>

<form action="./edit">
	<div id="container">
		<input type="hidden" name = "num" value="${dto.num }">
		<input type="hidden" name = "pageNum" value="${pageNum }">
		<div id="like">
			<c:choose>
				<c:when test="${like ==1}"><button type="button" name = "likeBtn" value="unlike">💚</button>
				</c:when>
				<c:otherwise><button type="button" name = "likeBtn" value="like">🤍</button>
				</c:otherwise>
			</c:choose>
		</div>
		<div><h3>${dto.title }</h3></div>
		<div id="viewInfo">
			<span>작성자 : ${dto.name } </span>
			<span> / 작성일 : ${dto.postDate } </span>
			<span> / 조회수 : ${dto.viewCnt } </span>
			<span id="cmt"> / 댓글 수 : ${dto.commentCnt }</span>
			<span id="likeNum"> / 좋아요 수 : ${dto.likeCnt }</span>
		</div>
		
		<br>
		<div><h4>내용</h4>${dto.content }</div>
	</div>
	<c:if test="${dto.id eq sessionScope.id}">
		<button>수정</button> <button type="button" onclick="deleteBoard()">삭제</button>
	</c:if>
		<button type="button" onclick="location.href='list?pageNum=${pageNum }'">목록</button>

</form>
<script>
	bno = "${param.bno}";
		
	function deleteBoard(){
		let check = confirm("정말로 삭제하시겠습니까?");
		if(check){
			location.href="delete?num=${dto.num }";
		}
	}
	
	$(document).ready(function(){
		let bno= "${param.num}";
	    $("#like>button").click(function(){
			let mode =$("#like>button").val();
			console.log(mode);
			let btn = $(this);
	        $.ajax({
	        	type:'post',       // 요청 메서드 (post 방식)
	            url: './like?',  // 요청 URI 
	            /* type:'get',       // 요청 메서드 (get 방식)
	            url: './like?mode='+mode+'&num='+bno,  // 요청 URI */	
	            data : { mode:mode , num:bno } ,// 전달 데이터(post 방식에서만 필요)
	            success : function(result){ // 요청이 성공일 때 실행되는 이벤트
	            	console.log(result.res);
	            	console.log("mode : " + result.mode);
	            	if(result.mode == "unlike"){
	            		btn.val("unlike");
	            		btn.text("💚");
	            	}else{
	            		btn.val("like");
	            		btn.text("🤍");
	            	}
	            	$("#likeNum").text(" /  좋아요 수 : "+result.res) 
	            },
	            error: function(request, status, error){ alert("code:"+request.status+"\n"+"message:"+request.responseText+"\n"+"error:"+error) } // 에러가 발생했을 때, 호출될 함수
	        }); // $.ajax()
    	});
	})
</script>
<%@include file = "Comment.jsp" %>
</body>
</html>

* LikeController.java

package controller;

import java.io.IOException;
import java.io.PrintWriter;

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 org.json.simple.JSONObject;

import dao.BoardDao;
import dao.LikeDao;

@WebServlet("/like")
public class LikeController extends HttpServlet{

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String num = req.getParameter("num");
		String mode = req.getParameter("mode");

		LikeDao dao = new LikeDao(getServletContext());
		BoardDao bdao = new BoardDao(req.getServletContext());
		JSONObject object = new JSONObject();
		
		int res = 0;
		
		resp.setContentType("application/json; charset=UTF-8");
		PrintWriter out = resp.getWriter();

		if("unlike".equals(mode)) {
			res = dao.delete(req.getSession().getAttribute("id")+"", num);
			if(res ==1 ) {
				res = bdao.updateLikeCnt(num, -1);
				object.put("mode", "like");
			}
			
		}else {
			res = dao.insert(req.getSession().getAttribute("id")+"", num);
			if(res ==1 ) {
				res = bdao.updateLikeCnt(num, 1);
				object.put("mode", "unlike");
			}
			
		}
		int cnt = dao.selectAll(num);
		object.put("res", cnt+"");
		dao.close();
		
		out.println(object.toJSONString());
		
		//resp.sendRedirect("view?num="+num);
		
		
	}
	
	
}

0개의 댓글