zoukankan      html  css  js  c++  java
  • 用servlet实现无限评论功能

    最近在写博客功能中的无限评论,比如知乎上的,我可以给根评论进行评论,也可以给子评论进行评论,下面是我做的一个简单的例子,分享给大家,希望能帮助各位,也希望可以指出缺点。

    先上图,看功能

    思路:

    1. 点击文章,获取文章的id,例如id为1
    2. 点击以后,查找文章id为1的全部评论,进行遍历(这里用到的是递归,方便观看,如上述,黄的为根评论,回复的是文章;绿的为子评论,回复的是根评论或者是其他子评论)
    3. 一开始刚发布文章肯定没有评论,所以,在最下面是发布评论,是对文章进行评论,使其有根评论,获取其根评论的id。
    4. 在有了根评论后,点击根评论后面的回复按钮,弹出一个回复的div,填写姓名和内容
    5. 点击弹出div的回复,将回复的信息添加到数据库,在进行2步骤,重新遍历;
    6. 点击子评论,同样可以出现回复的div,添加姓名和内容,点击回复按钮,在进行2步骤,遍历。
    7. 这样的缺点:遍历的话,消耗性能比较大(但我就想出来这一种,建议各位可以看看闭包表,这种评论相当于树结构,方便查找,但我脑子笨,没咋看明白)

    评论表:

    前端页面:

    页面比较丑,我只是说功能,大家可以自己去写。

    1 //这个是回复的div
    2 <div class="response_div"></div>

    这个是在js里动态生成的,只是有个父元素去装其他子元素

     //评论的div,装根评论和子评论
    评论:
            <div class="user_comments"></div>
    //发表评论的div,为根评论
    发表评论
    <div> <form id="form" onsubmit="return false" action="###" method="post"> <input id="article_id" type="hidden" name="articleId" value="${requestScope.article.get("ArticleId")}" > <p>个人昵称:<input id="user_name" type="text" name="name"></p> <p> 通知邮箱:<input id="email" type="email" name="email"></p> <p>评论内容:<input id="content" type="text" name="content"></p> <input type="button" value="提交" onclick="ajaxSelectComment()"> </form> </div>

     其他相关在js文件中:


    首先文章里没有评论,那么我在发表评论以后,点击按钮,将评论的信息通过ajax提交到servlet中(这里一开始打算用form表单的action方法直接提交,但后来感觉用ajax好一些,个人想法)

    //发表评论,先获取输入框的内容,将值作为参数传递给servlet,然后返回所有的评论
    function ajaxSelectComment() {
        let articleId=$("#article_id").val();
        let name=$("#user_name").val();
        let email=$("#email").val();
        let content=$("#content").val();
        $.ajax({
            url:"article?action=addComment",
            type:"POST",
            dataType: "json",
            data:{articleId,name,email,content},
            success:function (result) {
                alert("提交成功");
                console.log(result);
                showRootComment(result);
            },
            error:function () {
                alert("请求失败");
            }
        });
    }

    请求后,跳到servlet中

    protected void addComment(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          //获取对应文章的id,评论的姓名,内容,以及email
            Map<String, String[]> comment = req.getParameterMap();
    //声明service层对象
    ArticleService articleService= new ArticleServicesImpl();
    //调用service层中的方法
    articleService.addComment(Integer.parseInt(comment.get("articleId")[0]),comment.get("name")[0],comment.get("content")[0],comment.get("email")[0]);
    //调用查询全部评论的方法,并将其转换成json格式(这里我将查询全部评论和转成JSON格式封装成了一个方法)
    this.returnJson(resp,this.selectUserComment(comment)); }

    //查询全部评论方法,将Map传入其中,然后获取对应文章的id
    public List<Comment> selectUserComment(Map<String, String[]> parameterMap){
    ArticleService articleService=new ArticleServicesImpl();
    return articleService.selectComment(Integer.parseInt(parameterMap.get("articleId")[0]));
    }

    //将集合转成JSON格式
    public void returnJson(HttpServletResponse resp ,Object object) throws ServletException, IOException{
    //将传过来的数组转化为JSON
    PrintWriter out = resp.getWriter();
    Gson gson=new Gson();
    String jsonComments = gson.toJson(object);//查找总的评论并且转化为数组
    System.out.println(jsonComments);
    out.write(jsonComments);
    out.flush();
    out.close();
    }

    showRootComment(result)方法:

    function showRootComment(result){
        let str="";
        console.log(result);
        $(".user_comments").empty();
        for (let i = 0; i <result.length ; i++) {
            console.log(result.length);
            if(result[i].responseId==0){//说明这个是根评论
                str="<div class='rootResponse'>
    " +"<input type='hidden' name='commentId' value="+result[i].pid+">"+
                    "#"+i+"楼"+"评论时间:"+result[i].publishTime + " | " + result[i].commentName+" <button onclick='responseDiv($(this).prev().val(),$(this).prev())'>回复<button/>
    " +
                    "<div>"+result[i].commentContent+ "</div>
    " +
                    "</div><hr>";
                $(".user_comments").append(str);
              //查询子评论
                digui(result,result[i]);
            }
        }
    }

    查询子评论方法:digui(result,result[i])

    function digui(result,comment) {
        let str='';
        console.log(result+"###"+comment);
        for (let i = 0; i <result.length ; i++) {
            console.log(comment.pid);
            if (result[i].responseId==comment.pid){//那么这个是评论的子id
                str="<div class='ziResponse'>
    " +"<input type='hidden' name='commentId' value="+result[i].pid+">"+
                    "评论时间:"+result[i].publishTime + " | " + result[i].commentName+"<button onclick='responseDiv($(this).prev().val(),$(this).prev())'>111回复<button/>
    " +
                    "<div>"+result[i].commentContent+ "</div>
    " +
                    "</div><hr>";
            //将其子评论div添加到.user_comments div中
    $(".user_comments").append(str); 
    console.log(str);
    digui(result,result[i]);
    } } }

    最后一行递归的作用:在查找到第一个子评论后,查找是否有其他子评论回复当前的子评论,如果有,则继续遍历,如果没有,则跳过


    到这的话,遍历的就ok了,下面我们看如何回复评论而不是回复文章

    每次遍历,都会有一个回复的按钮

    <button onclick='responseDiv($(this).prev().val(),$(this).prev())'>111回复<button/>

    点击回复按钮,

    $(this).prev().val()

    为获取当前元素的同胞元素的值,获取其对应的评论的id

    $(this).prev()
    获取其对应的同胞元素


    点击回复按钮,跳到 responseDiv($(this).prev().val(),$(this).prev())方法
    function responseDiv(responseId,nowElement) {
    //首先将.responsediv移除,因为在点击其他评论的回复时,其他评论的回复div将消失 $(
    ".response").remove(); let str="<div class="response"> " + " <input type="text" name="userName" placeholder="请输入用户姓名" id="user_comment_name"> " + " <input type="text" name="userComment" placeholder="请输入评论内容" id="user_comment"> " + " <input type="button" value="回复" onclick="ajaxResponse("+responseId+")"> " + " </div>"; //将这个回复div添加进这个评论的div中 nowElement.parent().append(str); }

     点击回复,跳到ajaxResponse方法中,找到回复responseId,

    function ajaxResponse(responseId) {
    //点击回复后,将回复的div移除
        $(this).prev().remove();
        //获取回复对应的文章id,回复的姓名,回复的内容
        let articleId=$("#article_id").val();
        let name=$("#user_comment_name").val();
        let content=$("#user_comment").val();
    
        $.ajax({
            url:"article?action=addUserComment",
            type:"POST",
            dataType: "json",
            data:{articleId,name,content,responseId},
            success:function (result) {
                alert("提交回复成功");
    //重新遍历
                showRootComment(result);
            },
            error:function () {
                alert("请求失败");
    
            }
        });
    }///

    servlet添加子评论的方法

      protected void addUserComment(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            Map<String, String[]> userComment = req.getParameterMap();
            articleService.addResponse(Integer.parseInt(userComment.get("articleId")[0]),userComment.get("name")[0],userComment.get("content")[0],Integer.parseInt(userComment.get("responseId")[0]));
           this.returnJson(resp,this.selectUserComment(userComment));
        }

    添加回复,首先出现一个回复的div,填写回复的信息,点击回复按钮,将回复的内容添加到数据库,然后返回所有的评论,继续遍历,思路基本上就是这样

    service层方法:

     /**
         * 添加的是根评论
         * @param articleId
         * @param name
         * @param content
         * @param email
         */
        @Override
        public void addComment(int articleId, String name, String content, String email) {
                articleDao.addComment(articleId,name,content,email);
            //先查找对应文章的评论有多少
            long commentSum=articleDao.selectCommentsSum(articleId);
            //修改对应文章中评论的数量
            articleDao.insertCommentsSum(commentSum,articleId);
    
        }
       /**
         * 查找对应文章的评论
         * @param articleId
         * @return
         */
        @Override
        public List<Comment> selectComment(int articleId) {
            return  articleDao.selectComment(articleId);
        }
     /**
         * 添加对应文章的评论,子评论
         * @param articleId
         * @param commentName
         * @param commentContent
         * @param responseId
         */
        @Override
        public void addResponse(int articleId,String commentName,String commentContent,int responseId) {
                articleDao.addUserComment( articleId, commentName, commentContent,responseId);
        }

    dao层方法:

    /**
    *查找对应文章的全部评论
    */
     public List<Comment> selectComment(int articleId) {
            List<Comment> comments=null;
            String sql= "SELECT * FROM COMMENT WHERE Article_Id=?";
            try {
                 comments = queryRunner.query(sql, new BeanListHandler<Comment>(Comment.class), articleId);
            } catch (SQLException e) {
                e.printStackTrace();
            }
    
            return comments;
        }
    /**
         * 添加根评论
         * @param articleId
         * @param name
         * @param content
         * @param email
         */
        @Override
        public void addComment(int articleId, String name, String content, String email) {
                String sql="INSERT  INTO COMMENT (Article_Id,CommentName,CommentContent,email) VALUES(?,?,?,?) ";
                Object[] parms={articleId,name,content,email};
            try {
                queryRunner.update(sql,parms);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    /**
         * 添加子评论
         * @param articleId
         * @param commentName
         * @param commentContent
         * @param responseId
         */
        @Override
        public void addUserComment(int articleId,String commentName,String commentContent,int responseId) {
            String sql="INSERT INTO COMMENT (Article_Id,CommentName,CommentContent,ResponseId) VALUES(?,?,?,?)";
            Object[] parms={articleId,commentName,commentContent,responseId};
            try {
                queryRunner.update(sql,parms);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    这就是关于评论的所有操作,如果大家有疑惑或者更好的建议,在评论区留言,看到会立即回复!

  • 相关阅读:
    ural(Timus) 1019 Line Painting
    ACMICPC Live Archive 2031 Dance Dance Revolution
    poj 3321 Apple Tree
    其他OJ 树型DP 选课
    poj 3548 Restoring the digits
    ACMICPC Live Archive 3031 Cable TV Network
    递归循环获取指定节点下面的所有子节点
    手动触发asp.net页面验证控件事件
    子级Repeater获取父级Repeater绑定项的值
    没有列名的数据绑定
  • 原文地址:https://www.cnblogs.com/BLACKJT/p/12630096.html
Copyright © 2011-2022 走看看