2018-11-21 Обновление
Спасибо большим ребятам за их предложения по оптимизации в области комментариев, а также за оптимизацию дизайна и структуры кода таблицы данных в соответствии с предложениями.
Новая статья:
оригинал:
Модули комментариев доступны во многих системах,Код реки CodeRiverВ качестве платформы для общения и совместной работы, похожей на гостиницу программиста, недостатка в ней не будет.
Внешний интерфейс относится к модулю комментариев короткой книги, и специально написана статья, чтобы представить шаги реализации:
модуль vue + element-ui + scss для имитации книжного обзора
Заинтересованные могут глянуть.
адрес проекта:GitHub.com/cache Cats/ из…
код находится в根目录/java/comments-service
Статья будет разделена на три части:
- Анализ внешнего интерфейса
- Дизайн базы данных
- Реализация функции
1. Анализ внешнего интерфейса
Давайте сначала посмотрим, как выглядит внешний интерфейс.Если вы знаете, какие данные нужны внешнему интерфейсу, вы знаете, как спроектировать базу данных.
Прежде всего, предметом комментариев могут быть люди, проекты и ресурсы, поэтому должно бытьtype
Поле указывает тип данного комментария.
Возьмем, к примеру, проекты. Под одним проектом может быть несколько комментариев. Каждый комментарий на самом деле делится на два типа: один — комментарий непосредственно к проекту, называемый родительским комментарием, другой — комментарий к существующим комментариям, называемый дочерним комментарием.
Чтобы выявить взаимосвязь, каждый элемент может иметь несколько родительских комментариев, а каждый родительский комментарий может иметь несколько дочерних комментариев. Элементы имеют отношения «один ко многим» с родительскими комментариями и родительские комментарии с дочерними комментариями.
Видно, что база данных должна быть разделена на две таблицы, одну для хранения родительских комментариев и одну для хранения дочерних комментариев.
Посмотрите, какие поля нужны, и сначала проанализируйте основной комментарий. У вас должен быть идентификатор проекта, вы должны знать, кто комментирует, назовем его ownerId. Также есть аватар комментатора, никнейм, id, а также время комментария, содержание, количество лайков и т.д.
Подкомментарии имеют те же поля, что и родительские комментарии, только лайки не учитываются.
Во-вторых, дизайн базы данных
Проанализировав интерфейс и зная, какие поля нужны, приступим к проектированию базы данных.
Основная таблица комментариев (родительская таблица комментариев)
CREATE TABLE `comments_info` (
`id` varchar(32) NOT NULL COMMENT '评论主键id',
`type` tinyint(1) NOT NULL COMMENT '评论类型:对人评论,对项目评论,对资源评论',
`owner_id` varchar(32) NOT NULL COMMENT '被评论者id,可以是人、项目、资源',
`from_id` varchar(32) NOT NULL COMMENT '评论者id',
`from_name` varchar(32) NOT NULL COMMENT '评论者名字',
`from_avatar` varchar(512) DEFAULT '' COMMENT '评论者头像',
`like_num` int(11) DEFAULT '0' COMMENT '点赞的数量',
`content` varchar(512) DEFAULT NULL COMMENT '评论内容',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `owner_id` (`owner_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评论主表';
Форма ответа на комментарий (форма подкомментария)
CREATE TABLE `comments_reply` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`comment_id` varchar(32) NOT NULL COMMENT '评论主表id',
`from_id` varchar(32) NOT NULL COMMENT '评论者id',
`from_name` varchar(32) NOT NULL COMMENT '评论者名字',
`from_avatar` varchar(512) DEFAULT '' COMMENT '评论者头像',
`to_id` varchar(32) NOT NULL COMMENT '被评论者id',
`to_name` varchar(32) NOT NULL COMMENT '被评论者名字',
`to_avatar` varchar(512) DEFAULT '' COMMENT '被评论者头像',
`content` varchar(512) DEFAULT NULL COMMENT '评论内容',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `comment_id` (`comment_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='评论回复表';
3. Реализация функции
Принятие проектаSpringCloud
Микросервисная архитектура, модуль комментариев не сильно связан с другими модулями и может быть выделен как отдельная службаcomments-service
.
объект объекта данных
объект объекта данных
CommentsInfo
package com.solo.coderiver.comments.dataobject;
import lombok.Data;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.Date;
/**
* 评论表主表
*/
@Entity
@Data
@DynamicUpdate
public class CommentsInfo {
//评论主键id
@Id
private String id;
//评论类型。1用户评论,2项目评论,3资源评论
private Integer type;
//被评论者的id
private String ownerId;
//评论者id
private String fromId;
//评论者名字
private String fromName;
//评论者头像
private String fromAvatar;
//获得点赞的数量
private Integer likeNum;
//评论内容
private String content;
//创建时间
private Date createTime;
//更新时间
private Date updateTime;
}
объект объекта данных
CommentsReply
package com.solo.coderiver.comments.dataobject;
import lombok.Data;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Date;
/**
* 评论回复表
*/
@Entity
@Data
@DynamicUpdate
public class CommentsReply {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
//评论主表id
private String commentId;
//评论者id
private String fromId;
//评论者名字
private String fromName;
//评论者头像
private String fromAvatar;
//被评论者id
private String toId;
//被评论者名字
private String toName;
//被评论者头像
private String toAvatar;
//评论内容
private String content;
//创建时间
private Date createTime;
//更新时间
private Date updateTime;
}
Хранилище операций базы данных
Работа с базой данных временно используетJpa
, может быть добавлено позжеmybatis
реализация.
CommentsInfoRepository
package com.solo.coderiver.comments.repository;
import com.solo.coderiver.comments.dataobject.CommentsInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface CommentsInfoRepository extends JpaRepository<CommentsInfo, String> {
List<CommentsInfo> findByOwnerId(String ownerId);
}
CommentsReplyRepository
package com.solo.coderiver.comments.repository;
import com.solo.coderiver.comments.dataobject.CommentsReply;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface CommentsReplyRepository extends JpaRepository<CommentsReply, Integer> {
List<CommentsReply> findByCommentId(String commentId);
}
Инкапсуляция интерфейса службы
Чтобы сделать код более надежным, инкапсулируйте работу базы данных.
CommentsInfoService
package com.solo.coderiver.comments.service;
import com.solo.coderiver.comments.dataobject.CommentsInfo;
import java.util.List;
public interface CommentsInfoService {
/**
* 保存评论
* @param info
* @return
*/
CommentsInfo save(CommentsInfo info);
/**
* 根据被评论者的id查询评论列表
* @param ownerId
* @return
*/
List<CommentsInfo> findByOwnerId(String ownerId);
}
CommentsReplyService
package com.solo.coderiver.comments.service;
import com.solo.coderiver.comments.dataobject.CommentsReply;
import java.util.List;
public interface CommentsReplyService {
/**
* 保存评论回复
* @param reply
* @return
*/
CommentsReply save(CommentsReply reply);
/**
* 根据评论id查询回复
* @param commentId
* @return
*/
List<CommentsReply> findByCommentId(String commentId);
}
Класс реализации интерфейса
CommentsInfoServiceImpl
package com.solo.coderiver.comments.service.impl;
import com.solo.coderiver.comments.dataobject.CommentsInfo;
import com.solo.coderiver.comments.repository.CommentsInfoRepository;
import com.solo.coderiver.comments.service.CommentsInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CommentsInfoServiceImpl implements CommentsInfoService {
@Autowired
CommentsInfoRepository repository;
@Override
public CommentsInfo save(CommentsInfo info) {
return repository.save(info);
}
@Override
public List<CommentsInfo> findByOwnerId(String ownerId) {
return repository.findByOwnerId(ownerId);
}
}
CommentsReplyServiceImpl
package com.solo.coderiver.comments.service.impl;
import com.solo.coderiver.comments.dataobject.CommentsReply;
import com.solo.coderiver.comments.repository.CommentsReplyRepository;
import com.solo.coderiver.comments.service.CommentsReplyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CommentsReplyServiceImpl implements CommentsReplyService {
@Autowired
CommentsReplyRepository repository;
@Override
public CommentsReply save(CommentsReply reply) {
return repository.save(reply);
}
@Override
public List<CommentsReply> findByCommentId(String commentId) {
return repository.findByCommentId(commentId);
}
}
Контроллер уровня управления
Controller
Слой отправляет запрос и возвращает данные, требуемые внешним интерфейсом.
package com.solo.coderiver.comments.controller;
@RestController
@Api(description = "评论相关接口")
public class CommentsController {
@Autowired
CommentsInfoService infoService;
@Autowired
CommentsReplyService replyService;
@PostMapping("/save")
@ApiOperation("保存评论")
@Transactional
public ResultVO saveComments(@Valid CommentsInfoForm form, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
throw new CommentsException(ResultEnums.PARAMS_ERROR.getCode(), bindingResult.getFieldError().getDefaultMessage());
}
//将 CommentsInfoForm 里的数据拷贝到 CommentsInfo
CommentsInfo info = new CommentsInfo();
BeanUtils.copyProperties(form, info);
// 生成并设置评论的主键id
info.setId(KeyUtils.genUniqueKey());
CommentsInfo result = infoService.save(info);
if (result == null) {
throw new CommentsException(ResultEnums.SAVE_COMMENTS_FAIL);
}
return ResultVOUtils.success();
}
@GetMapping("/get/{ownerId}")
@ApiOperation("根据 ownerId 查询评论")
@ApiImplicitParam(name = "ownerId", value = "被评论者id")
public ResultVO getCommentsByOwnerId(@PathVariable("ownerId") String ownerId) {
List<CommentsInfo> infoList = infoService.findByOwnerId(ownerId);
//将 CommentsInfo 转换为 CommentsInfoDTO
List<CommentsInfoDTO> infoDTOS = infoList.stream().map(info -> {
CommentsInfoDTO dto = new CommentsInfoDTO();
BeanUtils.copyProperties(info, dto);
return dto;
}).collect(Collectors.toList());
return ResultVOUtils.success(infoDTOS);
}
@PostMapping("/save-reply")
@ApiOperation("保存评论回复")
@Transactional
public ResultVO saveReply(@Valid CommentsReplyForm form, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
throw new CommentsException(ResultEnums.PARAMS_ERROR.getCode(), bindingResult.getFieldError().getDefaultMessage());
}
CommentsReply reply = new CommentsReply();
BeanUtils.copyProperties(form, reply);
CommentsReply result = replyService.save(reply);
if (result == null) {
throw new CommentsException(ResultEnums.SAVE_COMMENTS_FAIL);
}
return ResultVOUtils.success();
}
@GetMapping("/get-reply/{commentId}")
@ApiOperation("通过commentId获取评论回复")
public ResultVO getReplyByCommentId(@PathVariable("commentId") String commentId) {
List<CommentsReply> replyList = replyService.findByCommentId(commentId);
//将 CommentsReply 转换为 CommentsReplyDTO
List<CommentsReplyDTO> replyDTOS = replyList.stream().map(reply -> {
CommentsReplyDTO dto = new CommentsReplyDTO();
BeanUtils.copyProperties(reply, dto);
return dto;
}).collect(Collectors.toList());
return ResultVOUtils.success(replyDTOS);
}
}
Перейдите к классу инструмента и классу перечисления в коде.github
См. исходный код выше.
Выше приведен дизайн и функциональная реализация модуля комментариев.Добро пожаловать к старшим братьям, чтобы выдвигать предложения по оптимизации кода и расти вместе~
Код из проекта с открытым исходным кодомCodeRiver
, стремится создать полноплатформенный бутик-проект с открытым исходным кодом.
coderiver Китайское название 河CODE — это платформа, на которой программисты и дизайнеры могут совместно работать над проектами. Независимо от того, являетесь ли вы разработчиком интерфейса, бэкенда или мобильного приложения, дизайнером или менеджером по продукту, вы можете публиковать проекты на платформе и сотрудничать с партнерами-единомышленниками для завершения проектов.
Coderiver River Code похож на гостиницу программиста, но его основная цель — способствовать техническому обмену между талантами в различных подобластях, расти вместе и совместно выполнять проекты. Никаких денежных операций не происходит.
Планируется, что это будет полноплатформенный проект с полным стеком, включая терминал для ПК (Vue, React), мобильный H5 (Vue, React), гибридную разработку ReactNative, родной Android, апплет WeChat и бэкэнд Java. Добро пожаловать, обратите внимание.
адрес проекта:GitHub.com/cache Cats/ из…
Ваша поддержка - самая большая движущая сила для меня, чтобы двигаться вперед, добро пожаловать, чтобы поставить лайк, добро пожаловать, чтобы отправить маленькие звездочки ✨ ~