十次方后端笔记三:吐槽微服务和文章评论功能
使用 MongoDB 完成吐槽微服务以及文章评论功能

吐槽微服务

吐槽微服务项目创建(省略)

准备工作

  1. 引入依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <?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>tensquare_parent</artifactId>
    <groupId>com.tensquare</groupId>
    <version>1.0.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>tensquare_spit</artifactId>

    <dependencies>
    <dependency>
    <groupId>com.tensquare</groupId>
    <artifactId>tensquare_common</artifactId>
    <version>${tensquare.version}</version>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    </dependencies>
    </project>
  2. 编写application.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    spring:
    data:
    mongodb:
    host: 192.168.136.104
    port: 27017
    database: spit
    application:
    name: tensquare-spit
    server:
    port: 9006
  3. 编写启动类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    package com.tensquare.spit;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import util.IdWorker;

    @SpringBootApplication
    public class SpitApplication {
    public static void main(String[] args) {
    SpringApplication.run(SpitApplication.class, args);
    }

    @Bean
    public IdWorker idWorker(){
    return new IdWorker(1, 6);
    }
    }
  4. 创建吐槽实体类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    package com.tensquare.spit.pojo;

    import lombok.Data;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.mongodb.core.mapping.Document;

    import java.io.Serializable;
    import java.util.Date;

    @Data
    public class Spit implements Serializable {

    @Id
    private String _id;
    private String content;
    private Date publishtime;
    private String userid;
    private String nickname;
    private Integer visits;
    private Integer thumbup;
    private Integer share;
    private Integer comment;
    private String state;
    private String parentid;
    }

CRUD实现

SpitController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package com.tensquare.spit.controller;

import com.tensquare.spit.pojo.Spit;
import com.tensquare.spit.service.SpitService;
import entity.Result;
import entity.StatusCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@CrossOrigin
@RestController
@RequestMapping("/spit")
public class SpitController {

@Autowired
private SpitService spitService;

/**
* 查询全部数据
*
* @return
*/
@RequestMapping(method = RequestMethod.GET)
public Result findAll() {
return new Result(true, StatusCode.OK, "查询成功", spitService.findAll());
}

/**
* 根据ID查询
*
* @param id ID
* @return
*/
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Result findOne(@PathVariable String id) {
return new Result(true, StatusCode.OK, "查询成功", spitService.findById(id));
}

/**
* 增加
*
* @param spit
*/
@RequestMapping(method = RequestMethod.POST)
public Result add(@RequestBody Spit spit) {
spitService.add(spit);
return new Result(true, StatusCode.OK, "增加成功");
}

/**
* 修改
* @param spit
*/
@RequestMapping(value="/{id}",method=RequestMethod.PUT)
public Result update(@RequestBody Spit spit,@PathVariable String id )
{
spit.set_id(id);
spitService.update(spit);
return new Result(true,StatusCode.OK,"修改成功");
}
/**
* 删除
* @param id
*/
@RequestMapping(value="/{id}",method=RequestMethod.DELETE)
public Result deleteById(@PathVariable String id ){
spitService.deleteById(id);
return new Result(true,StatusCode.OK,"删除成功");
}

}

SpitService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.tensquare.spit.service;

import com.tensquare.spit.pojo.Spit;
import com.tensquare.spit.repository.SpitRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import util.IdWorker;

import java.util.List;

@Service
public class SpitService {

@Autowired
private SpitRepository spitRepository;

@Autowired
private IdWorker idWorker;

/**
* 查询全部记录
*
* @return
*/
public List<Spit> findAll() {
return spitRepository.findAll();
}

/**
* 根据主键查询实体
*
* @param id
* @return
*/
public Spit findById(String id) {
Spit spit = spitRepository.findById(id).get();
return spit;
}

/**
* 增加
*
* @param spit
*/
public void add(Spit spit) {
spit.set_id(idWorker.nextId() + ""); //主键值
spitRepository.save(spit);
}

/**
* 修改
*
* @param spit
*/
public void update(Spit spit) {
spitRepository.save(spit);
}
/**
* 删除
* @param id
*/
public void deleteById(String id) {
spitRepository.deleteById(id);
}
}

SpitRepository

1
2
3
4
5
6
7
package com.tensquare.spit.repository;

import com.tensquare.spit.pojo.Spit;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface SpitRepository extends MongoRepository<Spit, String> {
}

根据上级ID查询吐槽列表

SpitController新增方法

1
2
3
4
5
6
7
8
9
10
11
/**
* 根据上级ID查询吐槽分页数据
*/
@RequestMapping(value = "/comment/{parentId}/{page}/{size}", method = RequestMethod.GET)
public Result findByParentid(@PathVariable String parentId,
@PathVariable int page,
@PathVariable int size) {
Page<Spit> pageList = spitService.findByParentid(parentId, page, size);
return new Result(true, StatusCode.OK, "查询成功", new
PageResult<>(pageList.getTotalElements(), pageList.getContent()));
}

SpitService新增方法

1
2
3
4
5
6
7
8
9
10
11
/**
* 根据上级ID查询吐槽分页数据
*
* @param parentId 上级ID
* @param page 当前页码
* @param size 当前页记录数
* @return
*/
public Page<Spit> findByParentid(String parentId, int page, int size) {
return spitRepository.findByParentid(parentId, PageRequest.of(page, size));
}

SpitRepository新增方法

1
Page<Spit> findByParentid(String parentId, Pageable pageable);

吐槽点赞

SpitController新增方法

1
2
3
4
5
6
7
8
/**
* 点赞
*/
@RequestMapping(value = "/thumbup/{id}", method = RequestMethod.PUT)
public Result updateThumbup(@PathVariable String id) {
spitService.updateThumbup(id);
return new Result(true, StatusCode.OK, "点赞成功");
}

SpitController新增方法

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 点赞
*
* @param id 吐槽ID
*/
public void updateThumbup(String id) {
Optional<Spit> optionalSpit = spitRepository.findById(id);
if (optionalSpit.isPresent()) {
Spit spit = optionalSpit.get();
spit.setThumbup(spit.getThumbup() == null ? 0 : spit.getThumbup() + 1);
}
}

控制不能重复点赞

根据用户ID和吐槽Id进行存储,放在redis中,每次点赞前先判断是否存在该key,如果存在说明已经点过赞了,不存在执行点赞逻辑。

引入Redis依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置Redis

1
2
3
4
spring:
redis:
host: 192.168.136.104
port: 6379

SpitController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 吐槽点赞
*
* @param id
* @return
*/
@RequestMapping(value = "/thumbup/{id}", method = RequestMethod.PUT)
public Result updateThumbup(@PathVariable String id) {
//判断用户是否点过赞
String userid = "2023";// 后边我们会修改为当前登陆的用户
if (redisTemplate.opsForValue().get("thumbup_" + userid + "_" + id) != null) {
return new Result(false, StatusCode.REPERROR, "你已经点过赞了");
}
spitService.updateThumbup(id);
redisTemplate.opsForValue().set("thumbup_" + userid + "_" + id, "1");
return new Result(true, StatusCode.OK, "点赞成功");
}

也可以把这些逻辑放在Service中处理。

发布吐槽逻辑修改

修改SpitService#add方法逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 发布吐槽(或吐槽评论)
*
* @param spit
*/
public void add(Spit spit) {
spit.set_id(idWorker.nextId() + "");
spit.setPublishtime(new Date());//发布日期
spit.setVisits(0);//浏览量
spit.setShare(0);//分享数
spit.setThumbup(0);//点赞数
spit.setComment(0);//回复数
spit.setState("1");//状态
if (spit.getParentid() != null && !"".equals(spit.getParentid())) {//
// 如果存在上级ID,评论
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(spit.getParentid()));
Update update = new Update();
update.inc("comment", 1);
mongoTemplate.updateFirst(query, update, "spit");
}
spitRepository.save(spit);
}

文章微服务 - 评论功能

表结构分析

评论的数据非常多,而且价值相对较低,所有这里仍然采用MongoDB进行存储。

字段名称 字段含义 字段类型 备注
_id ID 文本
articleid 文章ID 文本
content 评论内容 文本
userid 评论人ID 文本
parentid 评论ID 文本 如果为0表示文章的顶级评论
publishdate 评论日期 日期

准备工作

文章评论功能是属于之前的文章微服务,所以这里我们回到文章微服务继续开发。

引入依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

配置MongoDB

1
2
3
4
5
6
Spring: 
data:
mongodb:
host: 192.168.136.104
port: 27017
database: commentdb

创建评论实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.tensquare.article.pojo;

import lombok.Data;

import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;

@Data
public class Comment implements Serializable {
@Id
private String _id;
private String articleid;
private String content;
private String userid;
private String parentid;
private Date publishdate;
}

新增评论

CommentController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.tensquare.article.controller;

import com.tensquare.article.pojo.Comment;
import com.tensquare.article.service.CommentService;
import entity.Result;
import entity.StatusCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@CrossOrigin
@RequestMapping("/comment")
public class CommentController {

@Autowired
private CommentService commentService;

@RequestMapping(method= RequestMethod.POST)
public Result save(@RequestBody Comment comment){
commentService.add(comment);

return new Result(true, StatusCode.OK, "提交成功 ");
}
}

CommentService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.tensquare.article.service;

import com.tensquare.article.dao.CommentDao;
import com.tensquare.article.pojo.Comment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import util.IdWorker;

@Service
public class CommentService {

@Autowired
private CommentDao commentDao;

@Autowired
private IdWorker idWorker;

public void add(Comment comment) {
comment.setId(idWorker.nextId() + "");
commentDao.save(comment);
}

}

实体类如果是使用lombok@Data注解的话,因为是_id所以set方法也是set_id,我这里只所以是setId是因为我重写了_id的getter和setter方法。

CommentDao

1
2
3
4
5
6
7
package com.tensquare.article.dao;

import com.tensquare.article.pojo.Comment;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface CommentDao extends MongoRepository<Comment, String> {
}

查询指定文章的所有评论

CommentController新增方法

1
2
3
4
5
@RequestMapping(value="/article/{articleid}",method= RequestMethod.GET)
public Result findByArticleid(@PathVariable String articleid){
return new Result(true, StatusCode.OK, "查询成功",
commentService.findByArticleid(articleid));
}

CommentService新增方法

1
2
3
4
5
6
7
8
9
/**
* 查询指定文章评论
*
* @param articleid 文章ID
* @return 评论
*/
public List<Comment> findByArticleid(String articleid){
return commentDao.findByArticleid(articleid);
}

CommentDao新增方法

1
List<Comment> findByArticleid(String articleid);

删除评论

CommentController新增方法

1
2
3
4
5
@RequestMapping(value="/{commentId}",method= RequestMethod.DELETE)
public Result delete(@PathVariable String commentId){
commentService.deleteById(commentId);
return Result.ok("删除成功");
}

CommentService新增方法

1
2
3
public void deleteById(String commentId) {
commentDao.deleteById(commentId);
}
文章作者: imxushuai
文章链接: https://www.imxushuai.com/2002/01/02/3.十次方后端笔记三:吐槽微服务和文章评论功能/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 imxushuai
支付宝打赏
微信打赏