1 评论
1.1 编写实体类
一条评论的基本要素,包括了评论本身的id、用户的昵称、email、内容、头像等要显示的信息,还有创建时间、在哪一条新闻下评论的。比较重要的是1.父评论(一个)2.子评论(一个列表)
@Entity
@Table(name = "t_comment")
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String nickname;
private String email;
private String content;
private String avatar;
@Temporal(TemporalType.TIMESTAMP)
private Date createTime;
@ManyToOne
private News news;
@OneToMany(mappedBy = "parentComment")
private List<Comment> replyComments=new ArrayList<>();
@ManyToOne
private Comment parentComment;
private boolean adminComment;
1.2 编写dao接口
我们要做的就是评论的增加和显示。增加评论比较简单,就是增加一条记录,显示评论则有些技巧,需要将评论的层级关系显示出来。在数据库层面考虑的话,取同一级的所有评论需要的就是评论的文章和父评论。
public interface CommentRepository extends JpaRepository<Comment,Long> {
List<Comment> findByNewsIdAndParentCommentNull(Long newId, Sort sort);
}
1.3 编写Service
根据上述两个需求,写出service接口:
public interface CommentService {
List<Comment> listCommentByNewId(Long newId);
Comment saveComment(Comment comment);
}
实现保存新评论:
比较简单,也就是获取评论,根据评论的父评论id设定它的父评论对象,接着设置创建时间,然后存放到数据库中。
@Override
public Comment saveComment(Comment comment) {
Long parentCommentId=comment.getParentComment().getId();
if(parentCommentId!=-1){
comment.setParentComment(commentRepository.findById(parentCommentId).orElse(null));
}else{
comment.setParentComment(null);
}
comment.setCreateTime(new Date());
return commentRepository.save(comment);
}
实现列举评论
主要是要获取评论的所有子评论,由于评论又有自己的子评论,所以有一个递归调用的过程。
@Override
public List<Comment> listCommentByNewId(Long newId) {
Sort sort=Sort.by("createTime");
List<Comment> comments=commentRepository.findByNewsIdAndParentCommentNull(newId,sort);
return eachComment(comments);
}
private List<Comment> eachComment(List<Comment> comments){
List<Comment> commentView=new ArrayList<>();
for(Comment comment:comments){
Comment c=new Comment();
BeanUtils.copyProperties(comment,c);
commentView.add(c);
}
//合并评论的各层子代到第一级子代集合
combineChildren(commentView);
return commentView;
}
private void combineChildren(List<Comment> comments){
for(Comment comment:comments){
List<Comment> replys1=comment.getReplyComments();
for(Comment reply1:replys1){
//循环迭代,找出子代,存放在tempReplys里
recursively(reply1);
}
comment.setReplyComments(tempReplys);
//清除temp
tempReplys=new ArrayList<>();
}
}
private List<Comment> tempReplys=new ArrayList<>();
private void recursively(Comment comment){
tempReplys.add(comment);//顶节点
if(comment.getReplyComments().size()>0){
List<Comment> replys =comment.getReplyComments();
for(Comment reply:replys){
tempReplys.add(reply);
if(reply.getReplyComments().size()>0){
recursively(reply);
}
}
}
}
1.4 编写Controller
Get请求用于获取所有评论列表。Post请求将新添加的评论根据当前的用户信息添加到数据库中。
@Controller
public class CommentController {
@Autowired
private CommentService commentService;
@Autowired
private NewService newService;
private String avatar="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1596010448468&di=907ebbe0a67751f8c93d79da1c9a2c6a&imgtype=0&src=http%3A%2F%2Fattachments.gfan.com%2Fforum%2F201608%2F04%2F2339412b3z30zbd2j6k652.jpg";
@GetMapping("/comments/{newId}")
private String comments(@PathVariable Long newId, Model model){
model.addAttribute("comments",commentService.listCommentByNewId(newId));
return "new::commentList";
}
@PostMapping("/comments")
private String post(Comment comment, HttpSession session){
Long newId=comment.getNews().getId();
comment.setNews(newService.getNew(newId));
User user=(User) session.getAttribute("user");
if(user!=null){//是管理员,因为只有管理员能登录
comment.setAdminComment(true);
comment.setAvatar(avatar);
}else{
comment.setAvatar(avatar);
}
commentService.saveComment(comment);
//System.out.println(commentService.saveComment(comment));
return "redirect:/comments/"+newId;
}
}
2 分类和标签显示
主要是显示当前所有的标签和分类,并且点击不同的标签和分类可以分别显示属于它们的新闻。
由于Service基本已经有显示标签和种类的方法了,接下来主要是写两个Controller方法来回应前端的请求。
Tag回应前端的get请求。构造pageable,返回所有的标签的列表和分页显示的新闻,以及当前查看的tag。
@Controller
public class TagShowController {
@Autowired
private NewService newService;
@Autowired
private TagService tagService;
@GetMapping("/tags/{id}")
public String tags(@PageableDefault(size=8,sort = {"updateTime"},direction = Sort.Direction.DESC) Pageable pageable,
@PathVariable Long id, Model model){
List<Tag> tags=tagService.listTagTop(20);
if(id==-1){
id=tags.get(0).getId();
}
NewQuery newQuery=new NewQuery();
newQuery.setTypeId(id);
model.addAttribute("tags",tags);
model.addAttribute("page",newService.listNew(id,pageable));
model.addAttribute("activeTagId",id);
return "tags";
}
}
同理可以写出Type的Controller:
@Controller
public class TypeShowController {
@Autowired
private TypeService typeService;
@Autowired
private NewService newService;
@GetMapping("/types/{id}")
public String types(@PageableDefault(size=8,sort = {"updateTime"},direction = Sort.Direction.DESC)Pageable pageable,
@PathVariable Long id, Model model){
List<Type> types=typeService.listTypeTop(20);
if(id==-1){
id=types.get(0).getId();
}
NewQuery newQuery=new NewQuery();
newQuery.setTypeId(id);
model.addAttribute("types",types);
model.addAttribute("page",newService.listNew(pageable,newQuery));
model.addAttribute("activeTypeId",id);
return "types";
}
}
3 测试