個人部落格專案筆記_06

CherriesOvO發表於2024-04-11

Bug修正

之前Article中的commentCounts,viewCounts,weight 欄位為int,會造成更新閱讀次數的時候,將其餘兩個欄位設為初始值0。

處理辦法:將int改為Integer

package com.cherriesovo.blog.dao.pojo;

import lombok.Data;

@Data
public class Article {

    public static final int Article_TOP = 1;

    public static final int Article_Common = 0;

    private Long id;

    private String title;

    private String summary;

    private Integer commentCounts;

    private Integer viewCounts;

    /**
     * 作者id
     */
    private Long authorId;
    /**
     * 內容id
     */
    private Long bodyId;
    /**
     *類別id
     */
    private Long categoryId;

    /**
     * 置頂
     */
    private Integer weight;


    /**
     * 建立時間
     */
    private Long createDate;
}

package com.cherriesovo.blog.vo;


import lombok.Data;

import java.util.List;

@Data
public class ArticleVo {

    private Long id;

    private String title;

    private String summary;

    private Integer commentCounts;

    private Integer viewCounts;

    private Integer weight;
    /**
     * 建立時間
     */
    private String createDate;

    private String author;

    private ArticleBodyVo body;

    private List<TagVo> tags;

    private CategoryVo category;

}

1. 評論列表

CREATE TABLE `blog`.`ms_comment`  (
  `id` bigint(0) NOT NULL AUTO_INCREMENT,
  `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `create_date` bigint(0) NOT NULL,
  `article_id` int(0) NOT NULL,
  `author_id` bigint(0) NOT NULL,
  `parent_id` bigint(0) NOT NULL,
  `to_uid` bigint(0) NOT NULL,	#給誰評論
  `level` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,	#第幾層評論
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `article_id`(`article_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
package com.cherriesovo.blog.dao.pojo;

import lombok.Data;
//評論
@Data
public class Comment {

    private Long id;

    private String content;

    private Long createDate;

    private Long articleId;

    private Long authorId;

    private Long parentId;

    private Long toUid;

    private Integer level;
}

1.1 介面說明

介面url:/comments/article/{id}

請求方式:GET

請求引數:

引數名稱 引數型別 說明
id long 文章id(路徑引數)

返回資料:

{
    "success": true,
    "code": 200,
    "msg": "success",
    "data": [
        {
            "id": 53,
            "author": {
                "nickname": "李四",
                "avatar": "http://localhost:8080/static/img/logo.b3a48c0.png",
                "id": 1
            },
            "content": "寫的好",
            "childrens": [
                {
                    "id": 54,
                    "author": {
                        "nickname": "李四",
                        "avatar": "http://localhost:8080/static/img/logo.b3a48c0.png",
                        "id": 1
                    },
                    "content": "111",
                    "childrens": [],
                    "createDate": "1973-11-26 08:52",
                    "level": 2,
                    "toUser": {
                        "nickname": "李四",
                        "avatar": "http://localhost:8080/static/img/logo.b3a48c0.png",
                        "id": 1
                    }
                }
            ],
            "createDate": "1973-11-27 09:53",
            "level": 1,
            "toUser": null
        }
    ]
}

1.2 Controller

package com.cherriesovo.blog.controller;

import com.cherriesovo.blog.service.CommentsService;
import com.cherriesovo.blog.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("comments")
public class CommentsController {

    @Autowired
    private CommentsService commentsService;

    @GetMapping("article/{id}")
    public Result comments(@PathVariable("id") Long articleId){

        return commentsService.commentsByArticleId(articleId);

    }
}

1.3 Service

package com.cherriesovo.blog.service;

import com.cherriesovo.blog.vo.Result;

public interface CommentsService {

    //根據文章id查詢所有的評論列表
    Result commentsByArticleId(Long articleId);
}

private UserVo author; //作者資訊

private List<CommentVo> childrens;	//子評論

private String createDate;	//時間

private UserVo toUser;	//給誰評論
copy()中除了使用BeanUtils.copyProperties(comment,commentVo)之外,以上四個屬性需要手動編寫程式碼設定。
package com.cherriesovo.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cherriesovo.blog.dao.mapper.CommentMapper;
import com.cherriesovo.blog.dao.pojo.Comment;
import com.cherriesovo.blog.service.CommentsService;
import com.cherriesovo.blog.service.SysUserService;
import com.cherriesovo.blog.vo.CommentVo;
import com.cherriesovo.blog.vo.Result;
import com.cherriesovo.blog.vo.UserVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.joda.time.DateTime;

import java.util.ArrayList;
import java.util.List;

@Service
public class CommentsServiceImpl implements CommentsService {
    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    private SysUserService sysUserService;

	public CommentVo copy(Comment comment){
        CommentVo commentVo = new CommentVo();
        BeanUtils.copyProperties(comment,commentVo);
        //1、時間格式化
        commentVo.setCreateDate(new DateTime(comment.getCreateDate()).toString("yyyy-MM-dd HH:mm"));
        //2、作者資訊
        Long authorId = comment.getAuthorId();
        UserVo userVo = this.sysUserService.findUserVoById(authorId);
        commentVo.setAuthor(userVo);
        //3、評論的評論(子評論)
        Integer level = comment.getLevel();
        if(1 == level){
            Long id = comment.getId();
            List<CommentVo> commentVoList = findCommentsByParentId(id);
            commentVo.setChildrens(commentVoList);
        }
        //4、給誰評論
        if (level > 1) {
            Long toUid = comment.getToUid();
            UserVo toUserVo = this.sysUserService.findUserVoById(toUid);
            commentVo.setToUser(toUserVo);
        }
        return commentVo;
    }

    public List<CommentVo> copyList(List<Comment> commentList){
        List<CommentVo> commentVoList = new ArrayList<>();
        for (Comment comment : commentList) {
            commentVoList.add(copy(comment));
        }
        return commentVoList;
    }
    
    //透過父id查詢評論列表
    private List<CommentVo> findCommentsByParentId(Long id) {
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Comment::getParentId,id);
        queryWrapper.eq(Comment::getLevel,2);
        //SELECT * FROM comment WHERE parent_id = ? AND level = 2
        List<Comment> comments = this.commentMapper.selectList(queryWrapper);
        return copyList(comments);
    }

    
    @Override
    public Result commentsByArticleId(Long articleId) {
        /*
        * 1、根據文章id查詢評論列表  從coment表中查
        * 2、根據作者的id查詢作者的資訊
        * 3、判斷如果 level=1 要去查詢他有沒有子評論
        * 4、如果有,根據評論父id進行查詢(parent_id)
        * */
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Comment::getArticleId,articleId);
        queryWrapper.eq(Comment::getLevel,1);
        //SELECT * FROM comment WHERE article_id = 'articleId' AND level = 1;
        List<Comment> comments = commentMapper.selectList(queryWrapper);
        return Result.success(copyList(comments));
    }
}

返回的資料:

package com.cherriesovo.blog.vo;

import lombok.Data;

import java.util.List;

@Data
public class CommentVo  {

    private Long id;

    private UserVo author;

    private String content;

    private List<CommentVo> childrens;

    private String createDate;

    private Integer level;

    private UserVo toUser;
}

package com.cherriesovo.blog.vo;

import lombok.Data;

@Data
public class UserVo {

    private String nickname;

    private String avatar;

    private Long id;
}

在SysUserService中提供 查詢使用者資訊的服務:

UserVo findUserVoById(Long authorId);
@Override
    public UserVo findUserVoById(Long authorId) {
        SysUser sysUser = sysUserMapper.selectById(authorId);
        if (sysUser == null){
            sysUser = new SysUser();
            sysUser.setId(1L);
            sysUser.setAvatar("/static/img/logo.b3a48c0.png");
            sysUser.setNickname("碼神之路");
        }
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(sysUser,userVo);
        return userVo;
    }

2. 評論

2.1 介面說明

介面url:/comments/create/change

請求方式:POST

請求引數:

引數名稱 引數型別 說明
articleId long 文章id
content string 評論內容
parent long 父評論id
toUserId long 被評論的使用者id

返回資料:

{
    "success": true,
    "code": 200,
    "msg": "success",
    "data": null
}

2.2 加入到登入攔截器中

確保評論的時候使用者已經登入。

WebMVCConfig:

@Override
    public void addInterceptors(InterceptorRegistry registry) {
        //當請求路徑匹配到 /test 或 /comments/create/change 時,會觸發 loginInterceptor 攔截器的攔截操作。
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/test")
            	.addPathPatterns("/comments/create/change");
    }

2.3 Controller

將評論請求的引數封裝為一個類:

package com.cherriesovo.blog.vo.params;

import lombok.Data;

@Data
public class CommentParam {

    private Long articleId;

    private String content;

    private Long parent;

    private Long toUserId;
}

CommentsController:

	@PostMapping("create/change")
    public Result comment(@RequestBody CommentParam commentParam){
        return commentsService.comment(commentParam);
    }

2.4 Service

CommentsServiceImpl只幹兩件事:

  1. 獲取以上欄位
  2. 儲存到資料庫
  public interface CommentsService {
    Result comment(CommentParam commentParam);
}

@Service
public class CommentsServiceImpl implements CommentsService {
    @Override
    public Result comment(CommentParam commentParam) {
        //UserThreadLocal 是一個基於 ThreadLocal 實現的工具類,用於在當前執行緒中儲存和獲取使用者資訊
        SysUser sysUser = UserThreadLocal.get();    //拿到登入使用者
        Comment comment = new Comment();
        //1、設定文章id
        comment.setArticleId(commentParam.getArticleId());
        //2、設定作者id
        comment.setAuthorId(sysUser.getId());
        //3、設定評論內容
        comment.setContent(commentParam.getContent());
        //4、設定評論時間
        comment.setCreateDate(System.currentTimeMillis());
        Long parent = commentParam.getParent();
        //5、設定評論等級
        if (parent == null || parent == 0) {
            comment.setLevel(1);
        }else{
            comment.setLevel(2);
        }
        //6、設定父id,如果 parent 是 null,則將父級ID設定為 0,否則將其設定為 parent 的值
        comment.setParentId(parent == null ? 0 : parent);
        //7、設定給誰評論
        Long toUserId = commentParam.getToUserId();
        comment.setToUid(toUserId == null ? 0 : toUserId);
        //最後把comment儲存到資料庫
        this.commentMapper.insert(comment);
        return Result.success(null);
    }
}

處理由於使用者id過長導致前端無法解析造成跟評失敗的bug

@Data
public class CommentVo  {
    //防止前端 精度損失 把id轉為string
// 分散式id 比較長,傳到前端 會有精度損失,必須轉為string型別 進行傳輸,就不會有問題了
    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;

    private UserVo author;

    private String content;

    private List<CommentVo> childrens;

    private String createDate;

    private Integer level;

    private UserVo toUser;
}

Caused by: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Out of range value for column 'article_id' at row 1

解決方法:將資料庫中的ms_comment表中的article_id型別修改為bigint

相關文章