스프링 프레임워크/스프링 MVC

# Spring MVC 게시판 예제 18 : 게시글 좋아요

edenDev 2023. 3. 15.

본 포스팅의 예제는 STS 또는 Eclipse를 사용하지 않고 Intellij를 통해 구현하고 있습니다.

그래서 기존의 STS(Spring Tool Studio)에서 생성된 Spring 프로젝트의 스프링 관련 설정 파일명과

프로젝트 구조가 약간 다를 수 있습니다.Intellij 스프링 mvc 프로젝트 생성 포스팅을 참고해주시면 감사하겠습니다.


Spring-MVC 기본 개념 및 테스트 예제 관련 포스팅 링크

순서 포스팅 제목
1 Intellij에서 Spring MVC Project 생성하기
2 Spring MVC - MariaDB 연결테스트
3 Spring MVC - Mybatis 설정 및 테스트
4 SpringMVC 구조
5 SpringMVC + Mybatis
6 Spring MVC Controller 작성 연습
7 Spring Interceptor

 

Spring-MVC 게시판 예제 이전 포스팅 링크

순서 포스팅제목
1 IntelliJ를 이용한 Spring MVC Project 생성 하기
2 Bootstrap AdminLTE Template 적용하기
3 ExceptionResovler : 예외페이지 처리
4 Spring AOP 적용하기
5 회원가입 구현하기
6 회원 유효성 검사 (Feat. JavaScript)
7 회원 유효성 검사 (Feat. Validation)
8 HttpSession을 이용한 로그인 구현하기
9 아이디 찾기 및 패스워드 찾기
10 내 프로필 페이지 및 회원정보 변경 및 탈퇴 구현
11 인터셉터 권한 체크
12 계정 복구 페이지 구현
13 자동로그인
14 게시글 목록 출력
15 게시글 작성
16 게시글 조회수 증가 및 중복 증가 방지
17 게시글 수정 및 삭제

 


1. 게시글 좋아요 구현

 

1.1 게시글 좋아요 테이블 구현

 

--  게시글 좋아요 테이블
drop table eden_board_like;
create table eden_board_like(
    like_no number primary key,
    user_no number,
    board_no number,
    like_date date default sysdate,
    constraint eden_like_userNo foreign key (user_no) references eden_user(user_no),
    constraint eden_like_boardNo foreign key (board_no) references eden_board(board_no)
);

--  게시글 좋아요 시퀸스
drop sequence eden_board_like_seq;
create sequence eden_board_like_seq;

 

1.2 게시글 좋아요 클래스 생성

 

src/기본패키지/board/domain 패키지 안에 BoardLikeVo 클래스 생성 후 아래와 같이 내용을 작성 해주세요

import java.util.Date;

public class BoardLikeVo {

    private int like_no; // 좋아요 번호
    private int user_no; // 좋아요 유저 번호
    private int board_no; // 좋아요 게시글 번호
    private Date like_date; // 좋아요 날짜

    public BoardLikeVo() {
        super();
    }

    public BoardLikeVo(int like_no, int user_no, int board_no, Date like_date) {
        this.like_no = like_no;
        this.user_no = user_no;
        this.board_no = board_no;
        this.like_date = like_date;
    }

    public int getLike_no() {
        return like_no;
    }

    public void setLike_no(int like_no) {
        this.like_no = like_no;
    }

    public int getUser_no() {
        return user_no;
    }

    public void setUser_no(int user_no) {
        this.user_no = user_no;
    }

    public int getBoard_no() {
        return board_no;
    }

    public void setBoard_no(int board_no) {
        this.board_no = board_no;
    }

    public Date getLike_date() {
        return like_date;
    }

    public void setLike_date(Date like_date) {
        this.like_date = like_date;
    }

    @Override
    public String toString() {
        return "BoardLikeVo{" +
                "like_no=" + like_no +
                ", user_no=" + user_no +
                ", board_no=" + board_no +
                ", like_date" + like_date +
                '}';
    }
}

1.3 게시글 좋아요 영속 계층 (Persistence Tire) 구현

 

src/기본패키지/board/persistence 패키지 안에 BoardDAO 인터페이스와 BoardDAOImpl 클래스 안에 아래와 같이 내용을 추가 해주세요.


//  게시글 좋아요
public void doLike(BoardLikeVo likeVo);

//  게시글 좋아요 상태
public int getMyLikeCount(BoardLikeVo likeVo);

//  게시글 좋아요 취소
public void deleteLike(BoardLikeVo likeVo);

//  게시글 좋아요 총 갯수
public int getTotalLikeCount(int board_no);

//  게시글 좋아요
@Override
@LogException
public void doLike(BoardLikeVo likeVo) {
    sqlSession.insert(NAMESPACE + ".doLike", likeVo);
}

//  게시글 좋아요 상태
@Override
@LogException
public int getMyLikeCount(BoardLikeVo likeVo) {
    return sqlSession.selectOne(NAMESPACE + ".getMyLikeCount", likeVo);
}

//  게시글 좋아요 취소
@Override
@LogException
public void deleteLike(BoardLikeVo likeVo) {
    sqlSession.delete(NAMESPACE + ".deleteLike", likeVo);
}

//  게시글 좋아요 총 갯수
@Override
@LogException
public int getTotalLikeCount(int board_no) {
    return sqlSession.selectOne(NAMESPACE + ".getTotalLikeCount", board_no);
}

/resources/mappers/board 패키지 안에 BoardSQLMapper.xml 파일 안에 아래와 같이 내용을 추가 해주세요.


<!-- 게시글 좋아요 -->
<insert id="doLike">
    insert into eden_board_like (like_no, user_no, board_no)
    values (eden_board_like_seq.nextval,
            #{user_no},
            #{board_no})
</insert>

<!-- 게시글 좋아요 상태 확인 -->
<select id="getMyLikeCount" resultType="int">
    select count(*) from eden_board_like where board_no = #{board_no} and user_no = #{user_no}
</select>

<!-- 게시글 좋아요 취소 -->
<delete id="deleteLike">
    delete from eden_board_like where board_no = #{board_no} and user_no = #{user_no}
</delete>

<!-- 게시글 좋아요 총 갯수 -->
<select id="getTotalLikeCount" resultType="int">
    select count(*) from eden_board_like where board_no = #{board_no}
</select>

1.4 게시글 좋아요 비지니스 계층 (Business Tire) 구현

 

src/기본패키지/board/service 패키지 안에 BoardService 인터페이스와 BoardServiceImpl 클래스 안에 아래와 같이 내용을 추가 해주세요.

 


//  게시글 좋아요
public void doLike(BoardLikeVo likeVo);

//  게시글 좋아요 상태
public int getMyLikeCount(BoardLikeVo likeVo);

//  게시글 좋아요 총 갯수
public int getTotalLikeCount(int board_no);
//  게시글 목록

	@Override
	@LogException
	public ArrayList<HashMap<String, Object>> getBoardList(int category_no) {

    ArrayList<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();

    List<BoardVo> boardVoList;

    if (category_no != 0) {
        boardVoList = boardDAO.getBoardByCategoryList(category_no);
    } else {
        boardVoList = boardDAO.getBoardList();
    }

    for (BoardVo boardVo : boardVoList) {
        int userNo = boardVo.getUser_no();
        UserVo userVo = userDAO.getUserByNo(userNo);
        CategoryVo categoryVo = boardDAO.getCategoryByNo(boardVo.getCategory_no());
        int totalLikeCount = boardDAO.getTotalLikeCount(boardVo.getBoard_no());

        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("boardVo", boardVo);
        map.put("userVo", userVo);
        map.put("categoryVo", categoryVo);
        map.put("totalLikeCount", totalLikeCount);

        data.add(map);
    }
    return data;
}

    //  게시글 상세보기
    @Override
    @LogException
    public HashMap<String, Object> getBoard(int board_no) {

        BoardVo boardVo = boardDAO.getBoardByNo(board_no);
        UserVo userVo = userDAO.getUserByNo(boardVo.getUser_no());
        int totalLikeCount = boardDAO.getTotalLikeCount(board_no);

        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("userVo", userVo);
        map.put("boardVo", boardVo);
        map.put("totalLikeCount", totalLikeCount);

        return map;
    }
    
    
    //  게시글 좋아요
    @Override
    @LogException
    public void doLike(BoardLikeVo likeVo) {
        if (getMyLikeCount(likeVo) < 1) {
            boardDAO.doLike(likeVo);
        } else {
            boardDAO.deleteLike(likeVo);
        }
    }

    //  게시글 좋아요 상태
    @Override
    @LogException
    public int getMyLikeCount(BoardLikeVo likeVo) {
        return boardDAO.getMyLikeCount(likeVo);
    }

    //  게시글 좋아요 총 갯수
    @Override
    @LogException
    public int getTotalLikeCount(int board_no) {
        return boardDAO.getTotalLikeCount(board_no);
    }

1.5 게시글 좋아요 컨트롤러 구현

 

src/기본패키지/board/controller 패키지 안에 RestBoardController 클래스 안에 아래와 같이 내용을 추가 해주세요.


//  게시글 좋아요 및 좋아요 취소
@PostMapping(value = "doLike")
@LogException
public HashMap<String, Object> doLike(BoardLikeVo param, HttpSession session) {
    UserVo sessionUser = (UserVo) session.getAttribute("sessionUser");

    if (sessionUser == null) {
        data.put("result", "error");
        data.put("reason", "로그인이 필요합니다.");
        return data;
    }

    int myLikeCount = boardService.getMyLikeCount(param);

    data.put("result", "success");

    if (myLikeCount > 0) {
        data.put("status", "like");
    } else {
        data.put("status", "unlike");
    }

    int userNo = sessionUser.getUser_no();
    param.setUser_no(userNo);

    boardService.doLike(param);

    data.put("result", "success");

    return data;
}

//  게시글 좋아요 상태
@PostMapping("getMyLikeStatus")
@LogException
public HashMap<String, Object> getMyLikeStatus(BoardLikeVo param, HttpSession session) {
    HashMap<String, Object> data = new HashMap<>();

    UserVo sessionUser = (UserVo) session.getAttribute("sessionUser");
    if (sessionUser == null) {
        data.put("result", "error");
        data.put("reason", "로그인이 필요합니다.");
        return data;
    }

    param.setUser_no(sessionUser.getUser_no());

    int myLikeCount = boardService.getMyLikeCount(param);

    data.put("result", "success");

    if (myLikeCount > 0) {
        data.put("status", "like");
    } else {
        data.put("status", "unlike");
    }

    return data;
}

//  게시글 좋아요 총 갯수
@PostMapping(value = "getTotalLikeCount")
@LogException
public HashMap<String, Object> getTotalLikeCount(int board_no){
    HashMap<String, Object> data = new HashMap<String, Object>();

    int totalLikeCount = boardService.getTotalLikeCount(board_no);
    data.put("totalLikeCount", totalLikeCount);
    return data;
}

1.6 게시글 좋아요 JSP 파일 구현

 

web-inf/views/board 패키지 안에 detailsPosting.jsp 파일의 내용을 아래와 같이 수정 해주세요.


<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ include file="../include/head.jsp" %>
<%@ include file="../include/user_menu.jsp" %>

<html>
<body class="hold-transition skin-green-light sidebar-mini" oncopy="return false" oncut="return false"
      onpaste="return false">
<div class="wrapper">

    <%@ include file="../include/top_menu.jsp" %>

    <%@ include file="../include/left_menu.jsp" %>

    <div class="content-wrapper">
        <section class="content container-fluid">

            <div class="col-lg-12">


                <%--게시글 내용 영역--%>
                <div class="box box-primary">

                    <%--게시글 제목 영역--%>
                    <div class="box-header with-border">
                        <h3 class="box-title">글제목 : ${data.boardVo.board_title}</h3>
                        <ul class="list-inline pull-right">
                            <li><a href="#" class="link-black text-lg" id="likeCount">좋아요 수(${data.totalLikeCount})</a>
                            </li>
                            <li><span><i class="fa fa-eye"></i>조회수
                                (${data.boardVo.board_view_count})</span></li>
                        </ul>
                    </div>

                    <%--게시글 내용 영역--%>
                    <div class="box-body" style="height: 700px">
                        ${fn:replace(fn:replace(fn:escapeXml(data.boardVo.board_content), newLine, "<br/>") , " ", "&nbsp;")}
                    </div>

                    <%--작성자 정보 영역--%>
                    <div class="box-footer">
                        <div class="user-block">
                            <ul class="navbar-custom-menu">
                                <li class="dropdown messages-menu">
                                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                                        <img class="img-circle img-bordered-sm"
                                             src="${path}/resources/dist/img/profile/${data.userVo.user_image}" alt="user image">
                                        <span>${data.userVo.user_nickname}</span>
                                        <span class="description"><fmt:formatDate pattern="yyyy-MM-dd a HH:mm"
                                                                                  value="${data.boardVo.board_write_date}"/></span>
                                    </a>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">작성 글보기</a></li>
                                    </ul>
                                </li>
                            </ul>
                        </div>
                    </div>

                    <div class="box-footer">
                        <form role="form" method="post">
                            <input type="hidden" id="boardNo" name="board_no" value="${data.boardVo.board_no}">
                            <input type="hidden" id="userNo" name="user_no" value="${sessionUser.user_no}">
                            <input type="hidden" id="categoryNo" name="category_no" value="${data.boardVo.category_no}">
                        </form>
                        <button class="btn btn-primary" onclick="postingList(${data.boardVo.category_no})"><i
                                class="fa fa-list"></i> 목록
                        </button>
                        <c:if test="${!empty sessionUser}">
                            <button type="button" class="btn btn-info boardLike"><i class="fa-regular fa-thumbs-up"
                                                                                    id="like"></i> 좋아요
                            </button>
                        </c:if>
                        <c:if test="${sessionUser.user_no == data.boardVo.user_no}">
                            <div class="pull-right">
                                <button type="button" class="btn btn-warning modBtn"><i class="fa fa-edit"></i> 수정
                                </button>
                                <button type="button" class="btn btn-danger delBtn"><i class="fa fa-trash"></i> 삭제
                                </button>
                            </div>
                        </c:if>
                    </div>
                </div>
            </div>
        </section>
    </div>

    <%@ include file="../include/footer.jsp" %>

</div>

<%@ include file="../include/plugin_js.jsp" %>
</body>
</html>

1.7 게시글 좋아요 화면 확인


2. 정리

 

이번에는 게시글 좋아요 기능을 구현 해 보았습니다. 다음 시간에는 게시글 스크랩(북마크) 기능을 구현 해보도록 하겠습니다.

댓글