一、🐇项目场景:
当你做一个程序,需要实现评论功能时,如果只是单纯评论的功能,没有回复,这将会是非常简单的操作;如果需要有回复功能,那就麻烦了。在我的认知里,有回复型的评论写法有两种,一种是无限嵌套型的,它用到了递归,太消耗资源,这里不展开描述;其次就是今天要来讲的两层型。
二、🐇数据库实现:
要用到两层型的评论,表结构怎么实现呢,我看到好多人说要有两张表,一张评论表,一张回复表。其实不然,一张表就足够了,但是设置字段的时候,需要多设置一个parentId(这个初始化为-1,表示这个为父id)记录回复的评论id,方便日后寻找。就是这么简单,现在来看下表设计:
三、🐇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>
五、🐇展示页面
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/143172.html