用servlet实现无线评论功能

谁说我不能喝 提交于 2020-04-04 10:32:00

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

先上图,看功能

思路:

  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'>\n" +"<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/>\n" +
                "<div>"+result[i].commentContent+ "</div>\n" +
                "</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'>\n" +"<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/>\n" +
                "<div>"+result[i].commentContent+ "</div>\n" +
                "</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\">\n" +
        "                <input type=\"text\" name=\"userName\" placeholder=\"请输入用户姓名\" id=\"user_comment_name\">\n" +
        "                <input type=\"text\" name=\"userComment\" placeholder=\"请输入评论内容\" id=\"user_comment\">\n" +
        "                <input type=\"button\" value=\"回复\" onclick=\"ajaxResponse("+responseId+")\">\n" +
        "            </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();
        }
    }

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

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!