目录

  • 一、🐇项目场景:
  • 二、🐇数据库实现:
  • 三、🐇Java代码实现评论:
  • 四、🐇jsp代码演示:
  • 五、🐇展示页面

一、🐇项目场景:

当你做一个程序,需要实现评论功能时,如果只是单纯评论的功能,没有回复,这将会是非常简单的操作;如果需要有回复功能,那就麻烦了。在我的认知里,有回复型的评论写法有两种,一种是无限嵌套型的,它用到了递归,太消耗资源,这里不展开描述;其次就是今天要来讲的两层型。

二、🐇数据库实现:

要用到两层型的评论,表结构怎么实现呢,我看到好多人说要有两张表,一张评论表,一张回复表。其实不然,一张表就足够了,但是设置字段的时候,需要多设置一个parentId(这个初始化为-1,表示这个为父id)记录回复的评论id,方便日后寻找。就是这么简单,现在来看下表设计:

servlet实现(两层型)评论表_mysql

三、🐇Java代码实现评论:

咱们在创建好评论表的实体类之后,在持久层编写插入语句(其实就是一个插入操作),然后来到控制层,这个控制层需要写两个请求(一个是评论请求,一个是回复评论请求),评论请求和回复请求的唯一区别就是,回复评论请求比评论请求多设置了一个parentId(前面说了,评论请求parentId都设置为-1),现在咱们看代码:

评论请求:

private void addCommon(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        HttpSession session = req.getSession();
        Users users = (Users) session.getAttribute(Constants.USER_SESSION_KEY);
        if (users != null){
            String bookId = req.getParameter("bookId");
            System.out.println("书id:"+bookId);
            Result result = bookService.findBookById(Integer.valueOf(bookId));
            if (result.isFlag()){
                Book book = (Book) result.getData();
                if (book.getCommon()){
                    String content = req.getParameter("content");
                    content = new String(content.getBytes("iso-8859-1"),"utf-8");
//                    System.out.println("评论内容:"+content);
                    Common common = new Common();
                    common.setBookId(Integer.valueOf(bookId));
                    common.setuId(users.getuId());
                    common.setContent(content);
                    common.setParentId(-1);
                    System.out.println("用户id:"+users.getuId());
                    commonService.addCommon(common);
//                    req.getRequestDispatcher("/bookDetail.jsp").forward(req,resp);
                    session.setAttribute("id",bookId);
                    System.out.println(bookId);
                    resp.sendRedirect("ok.jsp");
                }else {
                    req.setAttribute(Constants.REQUEST_MSG,"该书籍主人已关闭评论模块");
                    req.getRequestDispatcher("/bookDetail.jsp").forward(req,resp);
                }
            }else {
                req.setAttribute(Constants.REQUEST_MSG,"该书不存在");
                req.getRequestDispatcher("/bookDetail.jsp").forward(req,resp);
            }

        }else {
            req.setAttribute(Constants.REQUEST_MSG,"您还未登录,请登录再评论");
            req.getRequestDispatcher("/bookDetail.jsp").forward(req,resp);
        }
    }

回复评论请求

private void addReply(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        Users users = (Users) session.getAttribute(Constants.USER_SESSION_KEY);
        if (users != null){
            String bookId = req.getParameter("bookId");
            Result result = bookService.findBookById(Integer.valueOf(bookId));
            System.out.println("------------------------i------------------------");
            if (result.isFlag()){
                Book book = (Book) result.getData();
                if (book.getCommon()){
                    String parentId = req.getParameter("parentId");
                    String content = req.getParameter("content"+parentId);
                    content = new String(content.getBytes("iso-8859-1"),"utf-8");
                    Common common = new Common();
                    common.setBookId(Integer.valueOf(bookId));
                    common.setuId(users.getuId());
                    common.setContent(content);
                    common.setParentId(Integer.valueOf(parentId));
                    commonService.addCommon(common);
//                    req.getRequestDispatcher("/bookDetail.jsp").forward(req,resp);
                    System.out.println("ninh"+bookId);
                    session.setAttribute("id",bookId);
                    resp.sendRedirect("ok.jsp");
                }else {
                    req.setAttribute(Constants.REQUEST_MSG,"该书籍主任已关闭评论模块");
                    resp.sendRedirect("bookDetail.jsp");
                }
            }else {
                req.setAttribute(Constants.REQUEST_MSG,"该书不存在");
                resp.sendRedirect("bookDetail.jsp");
            }

        }else {
            req.setAttribute(Constants.REQUEST_MSG,"您还未登录,请登录再评论");
            resp.sendRedirect("bookDetail.jsp");
        }
    }

这样评论就弄好了,是不是很easy,其实最难搞的还是查看评论这个功能,我这个项目前端不是很会弄,我就直接把查看评论这个功能和其他的功能合并了。

private void showDetail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String id = req.getParameter("id");
        Result result = bookService.showDetail(Integer.valueOf(id));
        if (result.isFlag()){
            req.setAttribute(Constants.REQUEST_MSG,result.getMessage());
            req.setAttribute("book",(Book)result.getData());

//            获取评论信息
            List<Common> commonList = commonService.findAll(((Book) result.getData()).getBookId());
            List<Common> commons = new ArrayList<>();
            Map<Integer, List<Common>> reply = new HashMap<>();
            Map<Integer, String> userNames = new HashMap<>();
            for (Common common : commonList) {
                if(userNames.get(common.getuId()) == null) {
                    int uid=common.getuId();
                    Users users = (Users) userLoginService.showUserById(uid).getData();
                    userNames.put(uid,users.getUsername());
                }
                if(common.getParentId() == -1) {
                    commons.add(common);
                }else {
                    if (reply.get(common.getParentId())==null){
                        reply.put(common.getParentId(),new ArrayList<Common>());
                    }
                    reply.get(common.getParentId()).add(common);
                }
            }
            req.setAttribute("userNames",userNames);
            req.setAttribute("commons",commons);
            req.setAttribute("reply",reply);
            req.getRequestDispatcher("/bookDetail.jsp").forward(req,resp);
        }
    }

我这个评论功能在查看书籍详情下面直接评论(对于淘宝的点击商品页面后才能评论),先调用方法获取数据库的所有评论数据,设置三个容器(List 和Map):

List<Common> commons = new ArrayList<>();
    Map<Integer, List<Common>> reply = new HashMap<>();
    Map<Integer, String> userNames = new HashMap<>();

第一个list是装父评论(也就是parentId为-1的评论),它是所有子评论的“顶楼”,其次,reply就是装的子评论了,这个map的value是一个评论属性的List集合,就是为了装载全部的子评论,这里有一个点要注意,需要初始化List集合,我作了一个判断,如果reply.get(common.getParentId())==null,那就要初始化,第三个集合很明显就是存评论用户的username,确保每个评论前面都有用户名。

四、🐇jsp代码演示:

评论和查看评论:

<c:if test="${book.getCommon()==true}">
    <div class="contextForm">
        <form action="./common.do?flag=addCommon&bookId=${book.bookId}" method="post">
            <div class="title">留言:</div>
            <textarea rows="5" cols="200" name="content" required="required"></textarea>
            <br>
            <input type="submit" value="留言" />
<%--            <input type="hidden" >--%>
<%--            <input type="hidden" name="flag" value="showDetail">--%>
        </form>
    </div>
</c:if>
<br>
<h1>所有留言</h1>
<hr>
<c:if test="${!empty commons}">
    <c:forEach items="${commons}" var="comment">
        <div id="messDivId">
            <div class="story">
                <div class="opbtn"></div>
                <p class="story_t">${userNames.get(comment.uId)}</p>
                <p class="story_time">${comment.commonDate}</p>
                <p class="story_m">${comment.content}</p>
                <c:if test="${!empty requestScope.reply[comment.commonId]}">
                    <div class="story_hf">
                        <c:forEach items="${requestScope.reply[comment.commonId]}"
                                   var="reply">
                            <p>${requestScope.userNames[reply.uId]}: ${reply.content}</p>
                            <p class="hf_time">${reply.commonDate}</p>
                        </c:forEach>
                    </div>
                </c:if>
                <div class='reply_textarea'>
                    <form action="common.do" method='post'>
                        <input type="hidden" name="flag" value="addReply"/>
                        <input type="hidden" name="bookId" value="${book.bookId}"/>
                        <input type="hidden" name="parentId" value="${comment.commonId}"/>
                        <textarea name='content${comment.commonId}' rows='5' cols='200' required='required' ></textarea>
                        <br>
                        <input type='submit' value='回复' />
                    </form>

                </div>
            </div>
            <hr>
        </div>
    </c:forEach>
</c:if>

五、🐇展示页面

展示页面比较平平无奇,因为前端

实在是太难了,所以谅解下哈

servlet实现(两层型)评论表_mysql_02


希望可以帮到你。觉得还行的朋友麻烦给个一键三连,谢谢。