评论功能的实现与Article展示页的修改
本章主要实现了博客的评论功能的实现,包括增删改查等功能。并且,由于权限不同,之前将文章页面分为了两个页面。其实是没有必要的,这次修改将两个页面合二为一。
1.数据库的建立
评论主要应该包括评论的作者、评论的内容、评论所在的文章id
数据库结构如下:
其中comment_id是自增的主键
article_id是与文章编号关联的外键(删改联动)
2.数据库对应的pojo
这里的int类型最好写成它的包装类Integer,不然可能会出现一些问题。
数据的命名是比较重要的,最好不要出现驼峰命名,而是用"_"来分开两个词。
package com.zhz.f.provider.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import tk.mybatis.mapper.annotation.KeySql;import javax.persistence.Id;@Data
@AllArgsConstructor
@NoArgsConstructor
public class ArticleComments {@Id@KeySql(useGeneratedKeys = true)//自增键回填Integer comment_id;String comment_owner;String comment_contents;Integer article_id;public ArticleComments(String comment_owner, String comment_contents, int article_id) {this.comment_owner = comment_owner;this.comment_contents = comment_contents;this.article_id = article_id;}
}
3.server层和dao层的实现
这次采用了一个不同的顺序,首先设计好api的接口,实现可能需要的增删改查的功能。而不是像之前一样,等需要什么功能的时候再来写dao层。
MyData.java中增加的接口
//评论:
Boolean createAnArticleComment(String comment_owner, String comment_contents, Integer article_id);
Boolean deleteAnArticleComment(int comment_id);
Boolean updateAnArticleComment(int comment_id, String comment_contents);
Map<Integer, Map<String, String>> getAllCommentsByArticleID(int article_id);
*** 后续修改:之前因为嫌不好放在服务器上,不使用类传递数据而使用map套map的方法,现在感觉这个太垃圾所以又改了过来。***
//Map<Integer, Map<String, String>> getAllCommentsByArticleID(int article_id);
ArrayList<CommonArticleComments> getAllCommentsByArticleID(int article_id);
这个CommonArticleComments放在common包下:
package com.zhz.f.common.classes;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
// 需要传输的类必须支持序列化
public class CommonArticleComments implements Serializable {public Integer commentID;public String commentOwner;public String commentContent;
}
它们的实现:
@Override
public Boolean createAnArticleComment(String comment_owner, String comment_contents, Integer article_id) {commentsMapper.insert(new ArticleComments(comment_owner, comment_contents, article_id));return null;
}
@Override
public Boolean deleteAnArticleComment(int comment_id) {commentsMapper.deleteByPrimaryKey(comment_id);return null;
}
@Override
public Boolean updateAnArticleComment(int comment_id, String comment_contents) {commentsMapper.updateAnArticleComment(comment_id, comment_contents);return null;
}
/*@Override
public Map<Integer, Map<String, String>> getAllCommentsByArticleID(int article_id) {//用一个嵌套的map存数据返回。其实应该直接传一个类的数据是最好的,将类的定义放在comment里面。// 但是我不知道怎么将这种分布式的项目很好的去打包上传到服务器运行。为了之后可以在服务器上跑,这里就用了一个笨方法了。Map<Integer, Map<String, String>> result = new HashMap<>();List<Integer> commentsIDs = commentsMapper.selectAllCommentsIDsByArticleID(article_id);for (Integer comment_id : commentsIDs) {//使用通用mapper的话这里传的必须是comment_idArticleComments ac = commentsMapper.selectByPrimaryKey(comment_id);Map<String, String> ccm = new HashMap<>();ccm.put(ac.getComment_owner(), ac.getComment_contents());result.put(comment_id, ccm);}return result;*/@Overridepublic ArrayList<CommonArticleComments> getAllCommentsByArticleID(int article_id) {List<Integer> commentsIDs = commentsMapper.selectAllCommentsIDsByArticleID(article_id);ArrayList<CommonArticleComments> result = new ArrayList<>();for (Integer comment_id : commentsIDs) {//使用通用mapper的话这里传的必须是comment_idArticleComments ac = commentsMapper.selectByPrimaryKey(comment_id);result.add(new CommonArticleComments(ac.getComment_id(),ac.getComment_owner(),ac.getComment_co ntents()));}return result;}
}
dao层主要是调用了通用mapper的简单方法和自己写的一些方法。由于比较简单就不放上来
4.控制层和前端的联调
评论的功能应该是嵌入在文章页面的,所以需要修改之前的前端页面。
由于权限不同,之前将文章页面分为了两个页面。其实是没有必要的,可以加上一个thymeleaf的if语句判断即可。修改后并加上评论功能的article前端页面如下:
这里涉及到了很多的前后端的数据传输,看起来有些复杂,但其实很多都是一些判断条件,获得文章的各种信息和评论的各种信息和用户信息等。
article.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title th:text="${articleOwnerName}">的博文</title><!--判断文章是否属于该用户--><div th:if="${articleOwnerAccount} eq ${userAccount}"><form action="/zhz/editArticle"><input type="text" name="articleTitle" th:value="${articleTitle}" hidden><input type="submit" value="修改该文章"></form><form action="/zhz/deleteArticle"><input type="text" name="articleTitle" th:value="${articleTitle}" hidden><input type="submit" value="删除该文章"></form></div>
</head>
<body><h2><div th:text="${articleTitle}"></div>
</h2>
<h4>作者:<strong th:text="${articleOwnerName}"> </strong>作者账号:<strong th:text="${articleOwnerAccount}"></strong></h4><!--该标签<pre>可以有格式的输出对应的字符串-->
<textarea name="newContent" rows="50" cols="80" th:utext="${content}" readonly></textarea><h3>看看大家的精彩评论吧</h3>
<ol><li th:each="ac:${articleComments}"><form action="/zhz/editAndDeleteArticleComments" method="post"><strong th:text="${ac.commentOwner}" th:colspan="10"></strong>:<textarea name="articleCommentContents" th:text="${ac.commentContent}" style="overflow: visible"readonly></textarea><input name="articleCommentID" th:value="${ac.commentID}" hidden><input name="articleTitle" th:value="${articleTitle}" hidden><div th:if="${userAccount} eq ${ac.commentOwner}"><strong>如果需要修评论,则修改后点击提交</strong><br/><textarea name="newArticleCommentContents" th:text="${ac.commentContent}"style="overflow: visible"></textarea><!--articleID作为从public进入的标识符,必须要有--><input name="articleID" th:value="${articleID}" hidden><input type="submit" value="修改评论" name="editComment"></div></form></li>
</ol><h3>写下您的评论</h3>
<form action="/zhz/writeArticleComments" method="post"><textarea name="writeArticleComments" placeholder="请在此输入您的精彩评论"></textarea><input name="articleTitle" th:value="${articleTitle}" hidden><input name="articleOwnerAccount" th:value="${articleOwnerAccount}" hidden><!--articleID作为从public进入的标识符,必须要有--><input name="articleID" th:value="${articleID}" hidden><input type="submit" value="提交评论">
</form></body>
</html>
ToArticleController :
package com.zhz.f.client.controller.articles;import com.zhz.f.api.service.MyData;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;@Controller
public class ToArticleController {@DubboReferenceMyData myData;@RequestMapping("/zhz/toArticle")public String toArticle(HttpServletRequest request, HttpSession session, Model model) {String articleID = request.getParameter("articleID");if ("".equals(articleID)) articleID = null;String articleOwnerAccount = null;String userAccount = (String) session.getAttribute("userAccount");if (articleID != null) {//id不为空,说明是从public界面进来的articleOwnerAccount = myData.getUserAccountByArticleID(Integer.parseInt(articleID));} else {//id为空,说明是从用户主页进来的,直接获取本用户的用户账号articleOwnerAccount = (String) session.getAttribute("userAccount");}//获取文章信息String articleOwnerName = myData.getUserNameByAccount(articleOwnerAccount);String articleTitle = request.getParameter("articleTitle");String content = myData.getUserArticleByAccountAndArticleName(articleOwnerAccount, articleTitle);//获取评论信息Map<Integer, Map<String, String>> allComments = null;if (articleID != null) {//publicallComments = myData.getAllCommentsByArticleID(Integer.parseInt(articleID));} else {//userallComments = myData.getAllCommentsByArticleID(myData.getArticleIDByAccountAndArticleName(articleOwnerAccount, articleTitle));}//获取评论信息ArrayList<CommonArticleComments> articleComments = new ArrayList<>();if (articleID != null) {//publicarticleComments = myData.getAllCommentsByArticleID(Integer.parseInt(articleID));} else {//userarticleComments = myData.getAllCommentsByArticleID(myData.getArticleIDByAccountAndArticleName(articleOwnerAccount, articleTitle));}/*//读取数据,转化为ArticleComments类型。哎,要是直接传类多方便,真是自作自受List<ArticleComments> articleComments = new ArrayList<>();for (Integer cID : allComments.keySet()) {Map<String, String> stringStringMap = allComments.get(cID);for (String cOwner : stringStringMap.keySet()) {String cContents = stringStringMap.get(cOwner);articleComments.add(new ArticleComments(cID,cOwner,cContents));}}*///添加到显示model.addAttribute("articleComments",articleComments);model.addAttribute("articleOwnerAccount", articleOwnerAccount);model.addAttribute("articleOwnerName", articleOwnerName);model.addAttribute("userAccount", userAccount);model.addAttribute("articleTitle", articleTitle);model.addAttribute("content", content);model.addAttribute("articleID", articleID);// if (articleID != null) return "/articles/article";return "/articles/article";}/*@Data@AllArgsConstructor@NoArgsConstructorpublic class ArticleComments{public int commentID;public String commentOwner;public String commentContent;}*/
}
EditAndDeleteArticleCommentsController
处理删除评论和修改评论的controller,本来想将删改两个功能放在两个controller里,但是前端遍历的时候两个按钮都在一个form表单中。不知道大佬们有没有什么方法可以将这两个功能分开。
虽然这样也挺好用的,但层次和功能清楚的代码还是更优质的。
package com.zhz.f.client.controller.articleComments;import com.zhz.f.api.service.MyData;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;@Controller
public class EditAndDeleteArticleCommentsController {@DubboReferenceMyData myData;@RequestMapping("/zhz/editAndDeleteArticleComments")public String editAndDeleteArticleComments(HttpServletRequest request){String deleteComment = request.getParameter("deleteComment");String editComment = request.getParameter("editComment");String articleCommentID = request.getParameter("articleCommentID");if ("删除评论".equals(deleteComment)){myData.deleteAnArticleComment(Integer.parseInt(articleCommentID));}else if ("修改评论".equals(editComment)){String newArticleCommentContents = request.getParameter("newArticleCommentContents");myData.updateAnArticleComment(Integer.parseInt(articleCommentID),newArticleCommentContents);}//主要需要输入articleID(如果有),articleTitlereturn "forward:/zhz/toArticle";}
}
WriteArticleCommentsController
主要实现读取前端数据和将读取到的评论写入数据库的功能。
package com.zhz.f.client.controller.articleComments;import com.zhz.f.api.service.MyData;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;@Controller
public class WriteArticleCommentsController {@DubboReferenceMyData myData;@RequestMapping("/zhz/writeArticleComments")public String writeArticleComments(HttpServletRequest request, HttpSession session){String userAccount = (String) session.getAttribute("userAccount");String writeArticleComments = request.getParameter("writeArticleComments");String articleOwnerAccount = request.getParameter("articleOwnerAccount");String articleTitle = request.getParameter("articleTitle");int articleID = myData.getArticleIDByAccountAndArticleName(articleOwnerAccount, articleTitle);myData.createAnArticleComment(userAccount,writeArticleComments,articleID);return "forward:/zhz/toArticle";}}
总结
至此就基本实现了评论的功能。
前端页面不是很美观,没有学javaScript和Ajax等前端的东西,做其前端还是很简陋的。