第十一章 app端评论系统开发
目标
- 能够完成对mongodb的环境搭建
- 能够掌握mongodb的基本使用
- 能够完成app端评论的查询、发表、点赞等功能
- 能够完成app端评论回复的查询,发表、点赞功能
1 Mongodb
1.1Mongodb简介
MongoDB是一个开源、高性能、无模式的文档型数据库
应用场景:
-
支持文本查询
-
不需要支持事务,不存在复杂的多表查询
-
存储数据可持久化
-
需要TB甚至 PB 级别数据存储
-
需求变化较快,数据模型无法确认,预计使用快速迭代开发形式
-
需要至少2000以上的读写QPS【高性能】
-
能支持快速水平扩展【高扩展】
-
99.999%高可用【高可用】
1.2 Mongodb安装
1.2.1 拉取镜像
docker pull mongo
1.2.2 创建容器
docker run -di --name mongo-service -p 27017:27017 -v ~/data/mongodata:/data mongo
1.2.3 可视化工具
studio3t是mongodb优秀的客户端工具。官方地址在https://studio3t.com/
下载studio3t
同学不用下载,可以使用资料文件夹中提供好的软件安装即可。
安装并启动
创建连接
注意:以上的链接的ip地址以及端口以自己实际的服务器的ip地址和端口为准
连接成功:
2 app端评论-发表评论
2.1 需求分析
- 文章详情页下方可以查看评论信息,按照点赞数量倒序排列,展示评论内容、评论的作者、点数数、回复数、时间,默认查看10条评论,如果想查看更多,可以点击加载更多进行分页
- 可以针对当前文章发布评论
- 可以针对于某一条评论进行点赞操作
2.2 思路分析
(1)需要将数据存储到mongodb中,所以先创建两个pojo ,他们之间关系如下
思路分析
根据文章id发表评论,输入内容发表评论,评论内容不能超过140字,评论内容需要做文本垃圾检测(暂时不做),将数据存储到mongodb中。
需要搭建一个评论微服务,实现相关的功能。
2.3 搭建评论微服务
(1)创建项目itheima-leadnews-service-comment
(2)微服务中pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>itheima-leadnews</artifactId>
<groupId>com.itheima</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>itheima-leadnews-service-comment</artifactId>
<dependencies>
<dependency>
<groupId>com.itheima</groupId>
<artifactId>itheima-leadnews-comment-api</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.itheima</groupId>
<artifactId>itheima-leadnews-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
</project>
(3)application.yml
spring:
profiles:
active: dev
---
server:
port: 9007
spring:
application:
name: leadnews-comment
profiles: dev
cloud:
nacos:
server-addr: 192.168.211.136:8848
discovery:
server-addr: ${spring.cloud.nacos.server-addr}
data:
mongodb:
host: 192.168.211.136
port: 27017
database: leadnews-comment
---
server:
port: 9007
spring:
application:
name: leadnews-user
profiles: pro
cloud:
nacos:
server-addr: 192.168.211.136:8848
discovery:
server-addr: ${spring.cloud.nacos.server-addr}
data:
mongodb:
host: 192.168.211.136
port: 27017
database: leadnews-comment
---
server:
port: 9007
spring:
application:
name: leadnews-user
profiles: test
cloud:
nacos:
server-addr: 192.168.211.136:8848
discovery:
server-addr: ${spring.cloud.nacos.server-addr}
data:
mongodb:
host: 192.168.211.136
port: 27017
database: leadnews-comment
数据库其实可以暂时不用。我们先放到这。链接上去。
(4)启动类
package com.itheima;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class CommentApplication {
public static void main(String[] args) {
SpringApplication.run(CommentApplication.class, args);
}
}
(5)配置mongodb(已经配置好了)
(6)创建POJO 映射到mongdb中:
package com.itheima.comment.document;
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
import java.time.LocalDateTime;
@Data
@Document("ap_comment")//定义集合(表)的名称
public class Comment {
/**
* id 主键
*/
private String id;
/**
* 评论人的ID
*/
private Integer userId;
/**
* 评论人的昵称
*/
private String nickName;
/**
* 评论人的头像
*/
private String headImage;
/**
* 文章id
*/
private Long articleId;
/**
* 文章所属的频道ID
*/
//private Integer channelId;
/**
* 评论人写的内容
*/
private String content;
/**
* 总的点赞数
*/
private Integer likes;
/**
* 总的回复数
*/
private Integer replys;
/* *//**
* 经度
*//*
private BigDecimal longitude;
*//**
* 维度
*//*
private BigDecimal latitude;
*/
/**
* 评论时间
*/
private LocalDateTime createdTime;
/**
* 更新时间
*/
private LocalDateTime updatedTime;
}
@Data
@Document("comment_like")
public class CommentLike {
/**
* id
*/
private String id;
/**
* 点赞人的ID
*/
private Integer userId;
/**
* 被点赞的评论id
*/
private String commentId;
//取消点赞就是 删除评论点赞记录
}
基本的CURD操作mongodb 回顾:
新版本的springboot 不需要写RunWith
package com.itheima;
import com.itheima.comment.document.Comment;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import java.util.List;
/**
* @author ljh
* @version 1.0
* @date 2021/12/9 09:06
* @description 标题
* @package com.itheima
*/
@SpringBootTest
public class MongoTest {
@Autowired
private MongoTemplate mongoTemplate;
//相同的CRUD的操作
@Test
public void insert(){
Comment comment = new Comment();
comment.setUserId(2);
comment.setLikes(20);
mongoTemplate.insert(comment);
}
@Test
public void testFindOne() {
Comment apComment = mongoTemplate.findById("5f7012e03ea2da5788227a6f", Comment.class);
System.out.println(apComment);
}
@Test
public void testQuery() {
//Query query = Query.query(Criteria.where("_id").is("5f7012e03ea2da5788227a6f"));
Query query = Query.query(Criteria.where("likes").gt(8)); // select *from xxx where likes >20
// query.with(Sort.by(Sort.Direction.DESC, "likes"));
List<Comment> apComments = mongoTemplate.find(query, Comment.class);
System.out.println(apComments);
}
@Test
public void testDelete() {
//delete from xxx where id=?
mongoTemplate.remove(Query.query(Criteria.where("_id").is("5f7012e03ea2da5788227a6f")), Comment.class);
}
@Test
public void testUpdate() {
// update xxx set yy=? where id=?
Query query = Query.query(Criteria.where("_id").is("5f7015e63ea2da1618d173eb"));
Update update = new Update().set("content", "itcast");
mongoTemplate.updateMulti(query, update, Comment.class);
}
}
方式二:创建Repository
/**
* @Repository @service @controller
*
* <Comment,String> comment 用于指定 要操作的POJO 对应的collection; String 指定 主键的数据类型
* @author ljh
* @version 1.0
* @date 2021/12/9 09:19
* @description 标题
* @package com.itheima.comment.repository
*/
public interface CommentRepository extends MongoRepository<Comment,String> {
//我要根据userId=2的值进行查询 select * from xx where userId=2 order by likes desc
public List<Comment> findByUserIdOrderByLikesDesc(Integer userId);
}
test2:
package com.itheima;
import com.itheima.comment.document.Comment;
import com.itheima.comment.repository.CommentRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import java.util.List;
/**
* @author ljh
* @version 1.0
* @date 2021/12/9 09:06
* @description 标题
* @package com.itheima
*/
@SpringBootTest
public class Mongo2Test {
@Autowired
private CommentRepository commentRepository;
//相同的CRUD的操作
@Test
public void save(){
Comment entity = new Comment();
entity.setUserId(46);
entity.setLikes(89);
commentRepository.save(entity);
}
//查询
@Test
public void findAll(){
List<Comment> all = commentRepository.findAll();
for (Comment comment : all) {
System.out.println(comment.getLikes());
}
}
//删除
@Test
public void delete(){
Comment contition = new Comment();
contition.setId("61b158bc38dd626fbad93e48");
contition.setUserId(2);
// delete from xxx where id=? and userId=?
commentRepository.delete(contition);
}
//条件查询
@Test
public void find(){
List<Comment> byUserIdOrderByLikesDesc = commentRepository.findByUserIdOrderByLikesDesc(2);
for (Comment comment : byUserIdOrderByLikesDesc) {
System.out.println(comment);
}
}
}
2.4 功能实现
2.4.1 需求分析
实现发表评论
APP端 点击按钮 --》输入文字 点击提交即可
后台接收之后,进行保存到mongodb即可
发表评论:CommentSaveDto
@Data
public class CommentSaveDto {
/**
* 文章id
*/
private Long articleId;
/**
* 评论内容
*/
private String content;
}
2.4.2 controller
//保存文章评论 注意该评论保存到 mongodb中。
@Autowired
private CommentService commentService;
/**
* 发表评论
*/
@PostMapping("/saveToMongo")
public Result saveToMongo(@RequestBody CommentSaveDto commentSaveDto) throws LeadNewsException {
commentService.saveToMongo(commentSaveDto);
return Result.ok();
}
2.4.3 service层
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private CommentRepository commentRepository;
// 发表评论
@Override
public void saveToMongo(CommentSaveDto commentSaveDto) throws LeadNewsException {
//1.获取当前用户判断是否为匿名用户
if (RequestContextUtil.isAnonymous()) {
//2.如果是抛出异常
throw new LeadNewsException("不能发表评论");
}
UserTokenInfoExp userInfo = RequestContextUtil.getRequestUserTokenInfo();
//3.添加数据到mongo即可
Comment entity = new Comment();
entity.setUserId(userInfo.getUserId().intValue());
entity.setLikes(0);//点赞数为0
entity.setNickName(userInfo.getNickName());
entity.setHeadImage(userInfo.getHeadImage());
entity.setCreatedTime(LocalDateTime.now());
entity.setContent(commentSaveDto.getContent());
entity.setArticleId(commentSaveDto.getArticleId());
entity.setReplys(0);//发表评论 的是默认是0 回复
entity.setUpdatedTime(LocalDateTime.now());
commentRepository.save(entity);
}
2.4.4 网关进行配置
spring:
profiles:
active: dev
---
server:
port: 6003
spring:
application:
name: leadnews-app-gateway
profiles: dev
cloud:
nacos:
server-addr: 192.168.211.136:8848
discovery:
server-addr: ${spring.cloud.nacos.server-addr}
gateway:
globalcors:
cors-configurations:
'[/**]': # 匹配所有请求
allowedOrigins: "*" #跨域处理 允许所有的域
allowedHeaders: "*"
allowedMethods: # 支持的方法
- GET
- POST
- PUT
- DELETE
routes:
# 文章微服务
- id: article
uri: lb://leadnews-article
predicates:
- Path=/article/**
filters:
- StripPrefix= 1
# app用户微服务
- id: user
uri: lb://leadnews-user
predicates:
- Path=/user/**
filters:
- StripPrefix= 1
- id: behaviour
uri: lb://leadnews-behaviour
predicates:
- Path=/behaviour/**
filters:
- StripPrefix= 1
- id: comment
uri: lb://leadnews-comment
predicates:
- Path=/comment/**
filters:
- StripPrefix= 1
---
server:
port: 6003
spring:
application:
name: leadnews-app-gateway
profiles: test
cloud:
nacos:
server-addr: 192.168.211.136:8848
discovery:
server-addr: ${spring.cloud.nacos.server-addr}
gateway:
globalcors:
cors-configurations:
'[/**]': # 匹配所有请求
allowedOrigins: "*" #跨域处理 允许所有的域
allowedHeaders: "*"
allowedMethods: # 支持的方法
- GET
- POST
- PUT
- DELETE
routes:
# 文章微服务
- id: article
uri: lb://leadnews-article
predicates:
- Path=/article/**
filters:
- StripPrefix= 1
# app用户微服务
- id: user
uri: lb://leadnews-user
predicates:
- Path=/user/**
filters:
- StripPrefix= 1
- id: behaviour
uri: lb://leadnews-behaviour
predicates:
- Path=/behaviour/**
filters:
- StripPrefix= 1
- id: comment
uri: lb://leadnews-comment
predicates:
- Path=/comment/**
filters:
- StripPrefix= 1
---
server:
port: 6003
spring:
application:
name: leadnews-app-gateway
profiles: pro
cloud:
nacos:
server-addr: 192.168.211.136:8848
discovery:
server-addr: ${spring.cloud.nacos.server-addr}
gateway:
globalcors:
cors-configurations:
'[/**]': # 匹配所有请求
allowedOrigins: "*" #跨域处理 允许所有的域
allowedHeaders: "*"
allowedMethods: # 支持的方法
- GET
- POST
- PUT
- DELETE
routes:
# 文章微服务
- id: article
uri: lb://leadnews-article
predicates:
- Path=/article/**
filters:
- StripPrefix= 1
# app用户微服务
- id: user
uri: lb://leadnews-user
predicates:
- Path=/user/**
filters:
- StripPrefix= 1
- id: behaviour
uri: lb://leadnews-behaviour
predicates:
- Path=/behaviour/**
filters:
- StripPrefix= 1
- id: comment
uri: lb://leadnews-comment
predicates:
- Path=/comment/**
filters:
- StripPrefix= 1
3 app端评论-点赞评论
3.1 需求分析
用户点赞,可以增加点赞数量,点赞后不仅仅要增加点赞数,需要记录当前用户对于当前评论的数据记录
点赞评论 就添加一条数据 ,如果取消点赞 就删除一条数据即可
3.2 功能实现
3.2.1 dto创建
用户点赞:CommentLikeDto
@Data
public class CommentLikeDto {
/**
* 评论id
*/
private String commentId;
/**
* 1:点赞
* 0:取消点赞
*/
private Integer operation;
}
3.2.2 controller
//点赞评论或者取消点赞
@PostMapping("/like")
public Result like(@RequestBody CommentLikeDto commentLikeDto) throws LeadNewsException{
commentService.like(commentLikeDto);
return Result.ok();
}
3.2.3 service
@Override
public void like(CommentLikeDto commentLikeDto) throws LeadNewsException {
if (RequestContextUtil.isAnonymous()) {
//2.如果是抛出异常
throw new LeadNewsException("不能发表评论");
}
UserTokenInfoExp userTokenInfo = RequestContextUtil.getRequestUserTokenInfo();
//点赞 需要向点赞记录表中添加一条记录
//如果是点赞 就insert
if (commentLikeDto.getOperation() == 1) {
//先查询 如果有点赞记录 不用点赞了 select * from commentLIke where commentId=? and userId=?
Query query1 = Query.query(Criteria.where("userId")
.is(userTokenInfo.getUserId().intValue())
.and("commentId").is(commentLikeDto.getCommentId()));
List<CommentLike> commentLikes = mongoTemplate.find(query1, CommentLike.class);
if (commentLikes != null && commentLikes.size() > 0) {
throw new LeadNewsException("不能发表评论");
}
CommentLike commentLike = new CommentLike();
commentLike.setCommentId(commentLikeDto.getCommentId());
commentLike.setUserId(userTokenInfo.getUserId().intValue());
mongoTemplate.insert(commentLike);
//点赞数量 需要+ 1 找到这个评论 将其数量+1
Query query = Query.query(Criteria.where("_id").is(commentLikeDto.getCommentId()));
Update update = new Update();
update.inc("likes");//+1
mongoTemplate.findAndModify(query, update, Comment.class);
} else {
//如果是取消点赞 就delete from xx where userId=? and commentId=?
Query query = Query.query(Criteria.where("userId")
.is(userTokenInfo.getUserId().intValue())
.and("commentId").is(commentLikeDto.getCommentId()));
mongoTemplate.remove(query, CommentLike.class);
//点赞数 -1
Query query2 = Query.query(Criteria.where("_id").is(commentLikeDto.getCommentId()));
Update update = new Update();
update.inc("likes", -1);//-1
mongoTemplate.findAndModify(query2, update, Comment.class);
}
}
3.2.4 测试
使用postmen来测试
4 app端评论-评论列表
4.1 需求分析
查询评论列表,根据当前文章id进行检索,按照发布评论的时间进行倒序排列,分页查询(默认10条数据)
可以参考这个:https://www.cnblogs.com/linhan/p/4248679.html
1.每次查询10条数据 限制
2.下一页的时候,传递最后一个评论数据的 【时间】 根据时间查询数据 并限制10条 即可
4.2 功能实现
4.2.1 VO定义
由于返回列表数据需要标记该评论是否被点赞过,之前的POJO没有该标记,所以现在添加一个字段进行展示
@Data
public class CommentVo extends Comment {
//1标识被当前用户点赞了 0 标识 该评论没有被当前用点赞
private Integer operation=0;
}
查询评论列表:CommentDto
@Data
public class CommentDto {
/**
* 文章id
*/
private Long articleId;
// 最小时间
private LocalDateTime minDate;
}
4.2.2 controller
//展示评论的列表 返回值 参数
@PostMapping("/loadPage")
public Result<List<CommentVo>> loadPage(@RequestBody CommentDto commentDto) {
List<CommentVo> voList = commentService.loadPage(commentDto);
return Result.ok(voList);
}
4.2.3 service层
@Override
public List<CommentVo> loadPage(CommentDto commentDto) {
//select * from comment where creatitme < 你传递过来的时间 and articleId=? order by creattime desc limit 10;
//匿名用户 可以看 但是 不能点赞 也就是点赞的状态为非点赞的状态
//如果是以第一次过来查询 那么传递一个null时间即可
if (commentDto.getMinDate() == null) {
commentDto.setMinDate(LocalDateTime.now());
}
//查询条件1
Query query = Query.query(
Criteria.where("articleId").is(commentDto.getArticleId())
.and("createdTime").lt(commentDto.getMinDate())
);
//排序条件2
Sort sort = Sort.by(Sort.Direction.DESC, "createdTime");
query.with(sort);
//限制条件3
query.limit(10);
List<Comment> comments = mongoTemplate.find(query, Comment.class);
List<CommentVo> commentVos = JSON.parseArray(JSON.toJSONString(comments), CommentVo.class);
//判断 如果是匿名用户 直接返回
if (RequestContextUtil.isAnonymous()) {
return commentVos;
}
List<String> ids = comments.stream().map(p -> p.getId()).collect(Collectors.toList());
Integer userId = RequestContextUtil.getUserId();
//查询 select * from commentLike where userId=? and commentId in (?) ?从上面的评论列表中来 查询出来的值(一定是点赞过的) 永远 <=10
Query query2 = Query.query(
Criteria.where("userId").is(userId)
.and("commentId").in(ids)
);
List<CommentLike> commentLikes = mongoTemplate.find(query2, CommentLike.class);
//查询到之后 进行循环遍历 执行判断 并修改状态值即可
for (CommentVo commentVo : commentVos) {
for (CommentLike commentLike : commentLikes) {
if (commentLike.getCommentId().equals(commentVo.getId())) {
commentVo.setOperation(1);
}
}
}
return commentVos;
}
4.2.4 测试
略
5 app端评论回复-发表回复、点赞回复、回复列表
5.1 需求分析
-
当用户点击了评论中的回复就可以查看所有评论回复内容
-
可以针对当前评论进行回复,需要更新评论的回复数量
-
可以对当前评论回复列表进行点赞操作,同时记录当前回复评论点赞信息
5.2 思路分析
(1)数据实体
操作数据实体为mongodb中的集合,评论回复集合是ap_comment_reply
package com.itheima.comment.document;
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@Document("ap_comment_reply")
public class Reply {
/**
* id
*/
private String id;
/**
* 写下回复的 用户的ID
*/
private Integer userId;
/**
* 写下回复的 用户的昵称
*/
private String nickName;
/**
* 头像
*/
private String headImage;
/**
* 针对的是哪条 评论id 进行回复
*/
private String commentId;
/**
* 回复的内容
*/
private String content;
/**
* 点赞数(回复本身的点赞数量)
*/
private Integer likes;
/**
* 创建时间
*/
private LocalDateTime createdTime;
/**
* 更新时间
*/
private LocalDateTime updatedTime;
}
回复的点赞信息记录
package com.itheima.comment.document;
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
@Data
@Document("ap_comment_reply_like")
public class ReplyLike {
/**
* id
*/
private String id;
/**
* 点赞了回复的用户ID
*/
private Integer userId;
/**
* 点赞了哪一条回复
*/
private String replyId;
//点赞 就是有记录 取消点赞 就是删除记录即可
/* *//**
* 1:点赞
* 0:取消点赞
*//*
private Integer operation;*/
}
(2)思路分析:
1,用户点击回复,根据当前评论id查询对应的所有回复进行展示
2,用户针对于当前的评论进行了回复,需要保存数据,同时需要更新当前评论的回复数
3,可以对回复列表进行点赞操作
5.3 功能实现
(1)dto创建
CommentReplySaveDto
@Data
public class CommentReplySaveDto {
//回复内容
private String content;
//针对哪一个评论进行回复
private String commentId;
}
CommentReplyLikeDto:
@Data
public class CommentReplyLikeDto {
/**
* 针对 回复的ID 为该回复进行点赞或者取消点赞
*/
private String commentReplyId;
/**
* 1:点赞
* 0:取消点赞
*/
private Integer operation;
}
CommentRelyDto
/**
* 回复列表查询 传递最后一条回复的时间
*/
@Data
public class CommentRelyDto {
/**
* 评论的ID
*/
private String commentId;
// 最小时间
private LocalDateTime minDate;
}
(2)controller
package com.itheima.comment.controller;
import com.itheima.comment.dto.CommentRelyDto;
import com.itheima.comment.dto.CommentReplyLikeDto;
import com.itheima.comment.dto.CommentReplySaveDto;
import com.itheima.comment.service.ReplyService;
import com.itheima.comment.vo.ReplyVo;
import com.itheima.common.pojo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author ljh
* @version 1.0
* @date 2021/12/9 11:59
* @description 标题
* @package com.itheima.comment.controller
*/
@RestController
@RequestMapping("/reply")
public class ReplyController {
@Autowired
private ReplyService replyService;
//发表回复
@PostMapping("/saveReply")
public Result saveReply(@RequestBody CommentReplySaveDto commentReplySaveDto) throws Exception{
replyService.saveReply(commentReplySaveDto);
return Result.ok();
}
//点赞回复
@PostMapping("/replyLike")
public Result replyLike(@RequestBody CommentReplyLikeDto commentReplyLikeDto) throws Exception{
replyService.replyLike(commentReplyLikeDto);
return Result.ok();
}
//获取回复列表
@PostMapping("/loadPage")
public Result<List<ReplyVo>> loadPage(@RequestBody CommentRelyDto commentRelyDto){
List<ReplyVo> commentReplyVoList = replyService.loadPage(commentRelyDto);
return Result.ok(commentReplyVoList);
}
}
加载评论回复列表数据封装类
package com.itheima.comment.vo;
import com.itheima.comment.document.Reply;
import lombok.Data;
/**
* @author ljh
* @version 1.0
* @date 2021/12/9 14:35
* @description 标题
* @package com.itheima.comment.vo
*/
@Data
public class ReplyVo extends Reply {
private Integer operation=0;
}
(3)service
package com.itheima.comment.service.impl;
import com.alibaba.fastjson.JSON;
import com.itheima.comment.document.Comment;
import com.itheima.comment.document.CommentLike;
import com.itheima.comment.document.Reply;
import com.itheima.comment.document.ReplyLike;
import com.itheima.comment.dto.CommentRelyDto;
import com.itheima.comment.dto.CommentReplyLikeDto;
import com.itheima.comment.dto.CommentReplySaveDto;
import com.itheima.comment.repository.ReplyRepository;
import com.itheima.comment.service.ReplyService;
import com.itheima.comment.vo.ReplyVo;
import com.itheima.common.exception.LeadNewsException;
import com.itheima.common.util.RequestContextUtil;
import com.itheima.common.util.au.UserTokenInfoExp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author ljh
* @version 1.0
* @date 2021/12/9 12:01
* @description 标题
* @package com.itheima.comment.service.impl
*/
@Service
public class ReplyServiceImpl implements ReplyService {
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private ReplyRepository replyRepository;
@Override
public void saveReply(CommentReplySaveDto replyDto) throws LeadNewsException {
//就是发表回复
//获取当前用户的信息 判断是否匿名用户 如果是匿名用户 返回错误
if (RequestContextUtil.isAnonymous()) {
throw new LeadNewsException("不能点赞");
}
UserTokenInfoExp userTokenInfo = RequestContextUtil.getRequestUserTokenInfo();
Reply entity = new Reply();
entity.setCommentId(replyDto.getCommentId());
entity.setContent(replyDto.getContent());
entity.setCreatedTime(LocalDateTime.now());
entity.setHeadImage(userTokenInfo.getHeadImage());
entity.setLikes(0);
entity.setNickName(userTokenInfo.getNickName());
entity.setUpdatedTime(LocalDateTime.now());
entity.setUserId(userTokenInfo.getUserId().intValue());
replyRepository.save(entity);
//找到这个评论 将回复数量+1 update xxx set replays=replays+1 where id=?
Query query = Query.query(Criteria.where("_id").is(replyDto.getCommentId()));
Update update = new Update();
update.inc("replys");
mongoTemplate.findAndModify(query, update, Comment.class);
}
@Override
public void replyLike(CommentReplyLikeDto ReplyLikeDto) throws LeadNewsException {
if (RequestContextUtil.isAnonymous()) {
//2.如果是抛出异常
throw new LeadNewsException("不能点赞回复");
}
UserTokenInfoExp userTokenInfo = RequestContextUtil.getRequestUserTokenInfo();
//点赞 需要向点赞记录表中添加一条记录
//如果是点赞 就insert
if (ReplyLikeDto.getOperation() == 1) {
//先查询 如果有点赞记录 不用点赞了 select * from replyLike where replyId=? and userId=?
Query query1 = Query.query(Criteria.where("userId")
.is(userTokenInfo.getUserId().intValue())
.and("replyId").is(ReplyLikeDto.getReplyId()));
List<ReplyLike> replyLikes = mongoTemplate.find(query1, ReplyLike.class);
if (replyLikes != null && replyLikes.size() > 0) {
throw new LeadNewsException("不能点赞已经有点赞记录了");
}
ReplyLike replyLike = new ReplyLike();
replyLike.setReplyId(ReplyLikeDto.getReplyId());
replyLike.setUserId(userTokenInfo.getUserId().intValue());
mongoTemplate.insert(replyLike);
//回复中的点赞数量 需要+ 1 找到这个评论 将其数量+1
Query query = Query.query(Criteria.where("_id").is(ReplyLikeDto.getReplyId()));
Update update = new Update();
update.inc("likes");//+1
mongoTemplate.findAndModify(query, update, Reply.class);
} else {
//如果是取消点赞 就delete from xx where userId=? and commentId=?
Query query = Query.query(Criteria.where("userId")
.is(userTokenInfo.getUserId().intValue())
.and("replyId").is(ReplyLikeDto.getReplyId()));
mongoTemplate.remove(query, ReplyLike.class);
//点赞数 -1
Query query2 = Query.query(Criteria.where("_id").is(ReplyLikeDto.getReplyId()));
Update update = new Update();
update.inc("likes", -1);//-1
mongoTemplate.findAndModify(query2, update, Reply.class);
}
}
@Override
public List<ReplyVo> loadPage(CommentRelyDto commentRelyDto) {
//select * from reply where commentId=? and createdTime<? order by creattime desc limit 10;
if(commentRelyDto.getMinDate()==null){
commentRelyDto.setMinDate(LocalDateTime.now());
}
Query query =Query.query(
Criteria.where("commentId").is(commentRelyDto.getCommentId())
.and("createdTime").lt(commentRelyDto.getMinDate())
);
Sort sort=Sort.by(Sort.Direction.DESC,"createdTime");
query.with(sort);
query.limit(10);
List<Reply> replies = mongoTemplate.find(query, Reply.class);
List<ReplyVo> replyVos = JSON.parseArray(JSON.toJSONString(replies), ReplyVo.class);
//如果是匿名用户 直接返回列表
if(RequestContextUtil.isAnonymous()){
return replyVos;
}
List<String> ids = replies.stream().map(p -> p.getId()).collect(Collectors.toList());
//replyVos 数据都是没点赞回复的 回复数据列表
//select * from reply_like where userId=? and relyId in (?) ? 就是上边查询到的所有的回复ID的值 查询到的一定是点赞了的 而且<=10
Query query2 = Query.query(
Criteria.where("userId").is(RequestContextUtil.getUserId())
.and("replyId").in(ids)
);
List<ReplyLike> replyLikes = mongoTemplate.find(query2, ReplyLike.class);
for (ReplyVo replyVo : replyVos) {
for (ReplyLike replyLike : replyLikes) {
if(replyLike.getReplyId().equals(replyVo.getId())){
replyVo.setOperation(1);
}
}
}
return replyVos;
}
}
(3)repository:
package com.itheima.comment.repository;
import com.itheima.comment.document.Reply;
import org.springframework.data.mongodb.repository.MongoRepository;
/**
* @Repository @service @controller
*
*
* @author ljh
* @version 1.0
* @date 2021/12/9 09:19
* @description 标题
* @package com.itheima.comment.repository
*/
public interface ReplyRepository extends MongoRepository<Reply,String> {
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步