servlet实现(两层型)评论表

简介: servlet实现(两层型)评论表

一、项目场景:

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


二、数据库实现:

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

2018122814580746.png


三、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>


五、展示页面

2018122814580746.png

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

相关文章
|
算法 计算机视觉
【MATLAB 】 VMD 信号分解+希尔伯特黄变换+边际谱算法
【MATLAB 】 VMD 信号分解+希尔伯特黄变换+边际谱算法
1209 0
|
机器学习/深度学习 人工智能 安全
回望现阶段人工智能招聘岗位和条件
【7月更文挑战第4天】AI公司招聘涉及多个机器学习角色:所有职位都强调尖端ML技术和对用户体验的改进。
645 4
回望现阶段人工智能招聘岗位和条件
|
7月前
|
设计模式 存储 程序员
六大设计原则
本文介绍了六大设计原则,包括单一职责、开闭原则、里氏替换、接口隔离、依赖倒置和迪米特法则。每项原则均通过定义、设计要点及代码示例进行说明。单一职责强调类的功能应单一;开闭原则提倡对扩展开放、对修改封闭;里氏替换要求子类能无缝替换父类;接口隔离主张拆分专用接口;依赖倒置鼓励面向抽象编程;迪米特法则减少类间依赖。掌握这些原则有助于编写高质量、可维护的代码,并为学习23种设计模式奠定基础。
198 0
|
安全 Oracle Java
Java 中的运算符重载
Java 中的运算符重载
202 19
|
12月前
|
监控 Devops Linux
推荐类似宝塔的开源面板工具
本文介绍了几款类似于宝塔面板的开源服务器管理工具,包括Websoft9、1Panel、Webmin和Cockpit。这些工具在易用性、功能性和安全性方面各有千秋,能够满足不同用户的需求,从一键部署应用到高级服务器管理,提供了丰富的选择。
1683 1
推荐类似宝塔的开源面板工具
|
11月前
|
搜索推荐 数据挖掘 双11
淘宝运营进阶秘籍:从业余到专业
淘宝运营涉及市场分析、产品定位、店铺装修、营销推广、客户服务、数据分析等多环节。要脱颖而出,需掌握进阶秘籍。本文从精准定位、店铺装修、定价策略、流量获取、客户服务、数据分析及跨平台合作七大方面深入探讨,助商家实现从平凡到卓越的蜕变。通过目标受众分析、优化店铺形象、合理定价、多种促销手段、提升客户体验、利用数据反馈调整策略以及拓展销售渠道,商家可逐步提升运营能力,在竞争激烈的电商环境中取得成功。
1394 4
|
前端开发 JavaScript Java
基于spring+jsp+mysql实现的Java web论坛系统【源码+数据库+指导运行】
基于spring+jsp+mysql实现的Java web论坛系统【源码+数据库+指导运行】
473 0
|
C++ 开发者
类和对象一封装一c++中class和struct的区别
类和对象一封装一c++中class和struct的区别
95 0
|
机器学习/深度学习 算法 计算机视觉
多目标跟踪 | 评测指标
多目标跟踪器的性能需要某些指标来进行度量,目前使用比较广泛的评测指标主要有 Bernardin 等人定义的 CLEAR MOT 指标、Ristani 等人定义的 ID scores 指标以及最新的 Luiten 等人定义的HOTA 指标。
2821 2
|
JSON JavaScript Go
Tree资源树的实战研究
最近小编在做项目的时候,遇到了一个动态添加资源树的问题,经过几番实践,终于实现了最终的结果,下面我会将自己的经历一点点抛给大家,希望读者尽情享受这顿盛宴。