当前位置: 首页 > news >正文

南通网站建设技术支持vs手表官网

南通网站建设技术支持,vs手表官网,wordpress主页文章页,微信网站建设报价​​​​​​​Springboot仿抖音app开发之粉丝业务模块后端复盘及相关业务知识总结 Springboot仿抖音app开发之用短视频务模块后端复盘及相关业务知识总结 Springboot仿抖音app开发之用户业务模块后端复盘及相关业务知识总结 用户发表评论并显示评论总数 1. 控制层 (Comment…​​​​​​​Springboot仿抖音app开发之粉丝业务模块后端复盘及相关业务知识总结 Springboot仿抖音app开发之用短视频务模块后端复盘及相关业务知识总结 Springboot仿抖音app开发之用户业务模块后端复盘及相关业务知识总结 用户发表评论并显示评论总数 1. 控制层 (CommentController) PostMapping(create) public GraceJSONResult create(RequestBody Valid CommentBO commentBO)throws Exception {CommentVO commentVO commentService.createComment(commentBO);return GraceJSONResult.ok(commentVO); }控制层的主要职责 提供REST API接口 /comment/createPOST请求接收前端传来的JSON数据并绑定到CommentBO对象使用Valid注解进行参数校验调用服务层方法处理业务逻辑将处理结果包装成统一响应格式返回 2. 服务层 (CommentServiceImpl) Override public CommentVO createComment(CommentBO commentBO) {String commentId sid.nextShort();Comment comment new Comment();comment.setId(commentId);comment.setVlogId(commentBO.getVlogId());comment.setVlogerId(commentBO.getVlogerId());comment.setCommentUserId(commentBO.getCommentUserId());comment.setFatherCommentId(commentBO.getFatherCommentId());comment.setContent(commentBO.getContent());comment.setLikeCounts(0);comment.setCreateTime(new Date());commentMapper.insert(comment);// redis操作评论总数的累加redis.increment(REDIS_VLOG_COMMENT_COUNTS : commentBO.getVlogId(), 1);// 留言后的最新评论需要返回给前端进行展示CommentVO commentVO new CommentVO();BeanUtils.copyProperties(comment, commentVO);// 系统消息相关代码被注释掉了return commentVO; }服务层的主要职责 生成唯一评论ID (sid.nextShort())将前端数据(CommentBO)转换为数据库实体(Comment)设置额外信息点赞数初始化为0、创建时间等调用Mapper层将评论保存到数据库在Redis中增加视频的评论计数将数据库实体(Comment)转换为视图对象(CommentVO)返回给前端(注释掉的部分)创建系统消息通知视频作者有新评论 3. 数据访问层 (CommentMapper) 使用commentMapper.insert(comment)将评论数据插入到数据库 4. 数据模型 业务对象 (CommentBO) 包含用户提交的评论信息vlogerId, fatherCommentId, vlogId, commentUserId, content使用注解实现参数验证如NotBlank, Length等 数据库实体 (Comment) 映射到数据库表的实体类包含完整的评论信息id, vlogerId, fatherCommentId, vlogId, commentUserId, content, likeCounts, createTime 视图对象 (CommentVO) 返回给前端的数据对象包含额外信息commentUserNickname, commentUserFace, replyedUserNickname, isLike等 评论总数显示 非常容易理解吧 从redis中获取之前存储的评论总数 GetMapping(counts)public GraceJSONResult counts(RequestParam String vlogId) {String countsStr redis.get(REDIS_VLOG_COMMENT_COUNTS : vlogId);if (StringUtils.isBlank(countsStr)) {countsStr 0;}return GraceJSONResult.ok(Integer.valueOf(countsStr));} 为什么要Integer.valueOf(countsStr) Integer.valueOf(countsStr) 的作用是将字符串类型的数字转换为 Integer 对象。这在这段代码中非常重要原因如下 数据类型一致性 Redis 中存储的评论数是字符串类型即使存储的是数字从 Redis 获取时也是字符串前端或调用方期望接收的是数值类型Integer而不是字符串 统一响应格式 GraceJSONResult.ok() 方法接收各种数据类型并将其包装成统一的响应格式返回 Integer 类型更符合 API 的语义因为评论数就是一个整数 避免前端处理 如果直接返回字符串 0前端在进行数值运算时可能需要额外的转换返回 Integer 类型让前端可以直接使用这个数值无需自行转换 确保类型安全 Java 是强类型语言通过明确的类型转换可以避免隐式转换带来的潜在问题Integer.valueOf() 比 Integer.parseInt() 更优因为它可以重用常用整数的缓存 这段代码的完整逻辑是 从 Redis 获取指定视频的评论数字符串格式如果 Redis 中没有该数据默认为 0将字符串转换为 Integer 对象将转换后的 Integer 对象包装在统一响应格式中返回 这种处理方式体现了 RESTful API 设计的最佳实践确保返回的数据类型与其语义一致并减轻了客户端的处理负担。 实现查询评论列表与联调 1. 控制层实现 (CommentController) GetMapping(list) public GraceJSONResult list(RequestParam String vlogId,RequestParam(defaultValue ) String userId,RequestParam Integer page,RequestParam Integer pageSize) {return GraceJSONResult.ok(commentService.queryVlogComments(vlogId,userId,page,pageSize)); }控制层职责 提供REST API接口 /comment/listGET请求接收前端传来的参数视频ID、用户ID、页码、每页数量为userId设置默认值为空字符串处理可选参数调用服务层方法查询评论列表将查询结果包装成统一响应格式返回 2. 服务层实现 (CommentServiceImpl) Override public PagedGridResult queryVlogComments(String vlogId,String userId,Integer page,Integer pageSize) {MapString, Object map new HashMap();map.put(vlogId, vlogId);PageHelper.startPage(page, pageSize);ListCommentVO list commentMapperCustom.getCommentList(map);return setterPagedGrid(list, page); }服务层职责 创建参数Map用于传递查询条件设置vlogId作为查询条件使用PageHelper进行分页设置调用Mapper查询评论列表将结果封装为分页对象返回 3. 数据访问层实现 (CommentMapperCustom) 接口定义 public ListCommentVO getCommentList(Param(paramMap) MapString, Object map);SQL查询实现 select idgetCommentList parameterTypemap resultTypecom.imooc.vo.CommentVOSELECTc.id as commentId,c.vlog_id as vlogId,u.id as vlogerId,u.nickname as commentUserNickname,u.face as commentUserFace,c.father_comment_id as fatherCommentId,c.comment_user_id as commentUserId,c.content as content,c.like_counts as likeCounts,fu.nickname as replyedUserNickname,c.create_time as createTime FROMcomment as c LEFT JOINusers as u ONc.comment_user_id u.id LEFT JOINcomment as fc ONc.father_comment_id fc.id LEFT JOINusers as fu ONfc.comment_user_id fu.id WHEREc.vlog_id #{paramMap.vlogId} ORDER BYc.like_counts DESC,c.create_time DESC/select 评论列表查询SQL的设计详解 SQL整体设计思路 这段SQL是为了实现短视频平台的评论列表功能需要展示评论内容及相关的用户信息并支持评论回复的层级关系。整体设计采用了多表关联查询的方式将评论数据与用户数据整合在一起。 表结构及关系设计 该查询涉及到两个主要数据表 comment表存储评论的基本信息users表存储用户的基本信息 在SQL中这些表以不同的别名出现形成了四个逻辑实体 c主评论表包含当前查询的评论数据u评论作者表包含评论作者的信息fc父评论表用于处理回复关系fu父评论作者表包含被回复者的信息 关联关系详解 1. 评论与评论作者关联 LEFT JOIN users as u ON c.comment_user_id u.id这个关联将评论与发表评论的用户连接起来 关联条件评论表的comment_user_id与用户表的id使用LEFT JOIN确保即使用户信息缺失评论数据也能返回查询目的获取评论者的昵称和头像 2. 评论与父评论关联 LEFT JOIN comment as fc ON c.father_comment_id fc.id这个关联实现了评论的层级结构 关联条件当前评论的father_comment_id与父评论的id表的自关联comment表自己与自己关联通过不同别名区分设计意图支持评论回复功能建立评论之间的父子关系使用LEFT JOIN允许一级评论存在father_comment_id可能为null或0 3. 父评论与父评论作者关联 LEFT JOIN users as fu ON fc.comment_user_id fu.id这个关联获取被回复者的信息 关联条件父评论的comment_user_id与用户表的id设计目的获取被回复者的昵称以便显示回复某人的效果使用LEFT JOIN即使父评论作者信息缺失也不影响结果返回 删除评论功能的实现分析  1. 控制层实现 (CommentController) DeleteMapping(delete) public GraceJSONResult delete(RequestParam String commentUserId,RequestParam String commentId,RequestParam String vlogId) {commentService.deleteComment(commentUserId,commentId,vlogId);return GraceJSONResult.ok(); }控制层职责 提供REST API接口 /comment/deleteDELETE请求接收三个关键参数评论者ID、评论ID和视频ID调用服务层方法执行删除逻辑返回统一的成功响应格式 设计特点 使用HTTP DELETE方法符合RESTful设计规范参数通过RequestParam接收表明这些是必填项返回标准化的响应格式 2. 服务层实现 (CommentServiceImpl) Override public void deleteComment(String commentUserId,String commentId,String vlogId) {Comment pendingDelete new Comment();pendingDelete.setId(commentId);pendingDelete.setCommentUserId(commentUserId);commentMapper.delete(pendingDelete);// 评论总数的累减redis.decrement(REDIS_VLOG_COMMENT_COUNTS : vlogId, 1); }服务层职责 构建待删除的评论对象设置评论ID和评论者ID作为删除条件调用Mapper执行数据库删除操作在Redis中减少视频的评论计数 设计特点 同时验证评论ID和评论者ID确保用户只能删除自己的评论数据库操作与缓存操作结合保持数据一致性使用Redis计数器维护评论数避免频繁查询数据库 3. 数据访问层实现 虽然代码片段中没有显示commentMapper.delete()的具体实现但根据通用Mapper的使用方式这是一个条件删除操作 // MyBatis通用Mapper的典型实现 public interface CommentMapper extends MapperComment {// delete方法会根据非空字段作为条件// 等价于 DELETE FROM comment WHERE id #{id} AND comment_user_id #{commentUserId} }数据访问层职责 执行SQL删除操作根据提供的条件评论ID和评论者ID定位要删除的记录 评论点赞与取消点赞功能分析 1. 点赞功能实现 PostMapping(like) public GraceJSONResult like(RequestParam String commentId,RequestParam String userId) {// 故意犯错bigkeyredis.incrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);// // 改为每个评论单独一个 Key// String key REDIS_VLOG_COMMENT_LIKED_COUNTS : commentId;// redis.increment(key, 1);redis.setHashValue(REDIS_USER_LIKE_COMMENT, userId : commentId, 1);// // 改为每个用户评论组合一个 Key// String key REDIS_USER_LIKE_COMMENT : userId : commentId;// redis.set(key, 1);// redis.hset(REDIS_USER_LIKE_COMMENT, userId, 1);return GraceJSONResult.ok(); }功能逻辑 接收评论ID和用户ID作为参数在Redis中增加评论的点赞数记录用户对该评论的点赞状态返回成功响应 2. 取消点赞功能实现 PostMapping(unlike) public GraceJSONResult unlike(RequestParam String commentId,RequestParam String userId) {redis.decrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);redis.hdel(REDIS_USER_LIKE_COMMENT, userId : commentId);return GraceJSONResult.ok(); }功能逻辑 接收评论ID和用户ID作为参数在Redis中减少评论的点赞数删除用户对该评论的点赞状态记录返回成功响应 3. 设计问题分析 3.1 Redis Bigkey问题 代码中注释部分明确指出故意犯错bigkey这表明当前实现存在Redis性能问题 // 故意犯错bigkey redis.incrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);问题描述 使用单个hash结构REDIS_VLOG_COMMENT_LIKED_COUNTS存储所有评论的点赞数随着评论数增长这个hash会变得非常大成为bigkey大型hash会导致Redis性能下降甚至可能导致服务不稳定 更好的方案代码中已注释 String key REDIS_VLOG_COMMENT_LIKED_COUNTS : commentId; redis.increment(key, 1);这种方案为每个评论创建独立的key避免了单个hash过大的问题。 3.2 用户点赞记录存储问题 同样的bigkey问题也存在于用户点赞记录的存储中 redis.setHashValue(REDIS_USER_LIKE_COMMENT, userId : commentId, 1);问题描述 使用单个hashREDIS_USER_LIKE_COMMENT存储所有用户的所有点赞记录该hash将随用户数和评论数的增长而迅速膨胀对大型hash的操作会变得越来越慢 更好的方案代码中已注释 String key REDIS_USER_LIKE_COMMENT : userId : commentId; redis.set(key, 1);这种方案为每个用户对每个评论的点赞创建独立的key避免了hash结构过大。 Redis BigKey 问题解析  什么是 BigKey 问题 BigKey 指的是 Redis 中存储的某个 Key 对应的 Value 过大通常表现为 一个 String 类型的 Value 过大超过 10KB一个 Hash/List/Set/ZSet 类型的元素过多比如 Hash 有数千个字段 当前代码中的 BigKey 问题 1. REDIS_VLOG_COMMENT_LIKED_COUNTS Hash 结构问题 redis.incrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);这种方式将所有视频评论的点赞数都存储在一个 Hash 中 随着评论数量增加这个 Hash 会变得非常庞大每次操作都需要加载整个 Hash 到内存可能导致内存占用过高、操作延迟增加 2. REDIS_USER_LIKE_COMMENT Hash 结构问题 redis.setHashValue(REDIS_USER_LIKE_COMMENT, userId : commentId, 1);这种方式将所有用户对评论的点赞关系存储在一个 Hash 中 用户和评论数量增加时这个 Hash 会变得极其庞大每个用户点赞一个评论就增加一个字段可能导致内存爆炸性增长 改进方案注释中的正确做法 1. 为每个评论单独创建 Key String key REDIS_VLOG_COMMENT_LIKED_COUNTS : commentId; redis.increment(key, 1);优点 每个评论的点赞数独立存储避免单个 Key 过大操作更高效 2. 为每个用户评论组合创建 Key String key REDIS_USER_LIKE_COMMENT : userId : commentId; redis.set(key, 1);优点 每个点赞关系独立存储避免 Hash 结构无限增长更容易管理和清理 BigKey 的危害 内存不均导致 Redis 内存使用不平衡可能引发内存不足阻塞风险操作大 Key 可能导致 Redis 阻塞网络拥塞传输大 Key 消耗更多带宽持久化问题AOF 重写和 RDB 保存时效率降低迁移困难集群环境下数据迁移更困难 最佳实践建议 避免使用单个 Key 存储大量数据合理拆分数据结构如示例中的改进方案对于计数器类需求考虑使用多个 Key 而不是单个 Hash定期监控 Redis 的 Key 大小分布对大 Key 进行拆分或使用其他存储方案 Redis Hash 数据结构详解  Redis Hash 的三层结构 Redis 的 Hash 数据结构实际上是三层结构 外层 Key - Hash 结构的名称如 REDIS_VLOG_COMMENT_LIKED_COUNTS内层 Field - Hash 内部的字段名如 commentIdValue - 字段对应的值点赞数 所以完整结构是Key → (Field → Value) 对比普通 Key-Value 结构类型示例说明普通 Key-ValueSET comment:1001:likes 5直接键值对Hash 结构HSET comment_likes comment:1001 5两层映射关系 您的代码具体解析 redis.incrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);对应关系 外层 KeyREDIS_VLOG_COMMENT_LIKED_COUNTS所有评论点赞数的容器FieldcommentId具体是哪个评论Value点赞数通过参数1实现原子递增 为什么这样设计 组织相关数据可以把相关联的多个字段放在一个Hash中 例如用户信息user:1001 → {name:张三, age:25, email:xxxx.com} 减少Key数量避免为每个小数据都创建独立Key 原子操作可以单独操作Hash中的某个字段 用户是否点赞评论与评论总数展示  主要是在查询接口中添加业务逻辑 Overridepublic PagedGridResult queryVlogComments(String vlogId,String userId,Integer page,Integer pageSize) {MapString, Object map new HashMap();map.put(vlogId, vlogId);PageHelper.startPage(page, pageSize);ListCommentVO list commentMapperCustom.getCommentList(map);for (CommentVO cv:list) {String commentId cv.getCommentId();// 当前短视频的某个评论的点赞总数String countsStr redis.getHashValue(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId);Integer counts 0;if (StringUtils.isNotBlank(countsStr)) {counts Integer.valueOf(countsStr);}cv.setLikeCounts(counts);// 判断当前用户是否点赞过该评论String doILike redis.hget(REDIS_USER_LIKE_COMMENT, userId : commentId);if (StringUtils.isNotBlank(doILike) doILike.equalsIgnoreCase(1)) {cv.setIsLike(YesOrNo.YES.type);}}return setterPagedGrid(list, page);} 1. 基础评论数据查询 MapString, Object map new HashMap(); map.put(vlogId, vlogId); PageHelper.startPage(page, pageSize); ListCommentVO list commentMapperCustom.getCommentList(map);创建参数Map设置视频ID作为查询条件使用PageHelper设置分页参数调用自定义Mapper查询评论列表得到包含基本评论信息的VO对象列表 2. 为每条评论添加点赞数 for (CommentVO cv:list) {String commentId cv.getCommentId();// 当前短视频的某个评论的点赞总数String countsStr redis.getHashValue(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId);Integer counts 0;if (StringUtils.isNotBlank(countsStr)) {counts Integer.valueOf(countsStr);}cv.setLikeCounts(counts);// ... }遍历评论列表从Redis的hash结构中获取每条评论的点赞数若点赞数不存在则默认为0将点赞数设置到评论VO对象中 3. 判断当前用户是否点赞过评论 // 判断当前用户是否点赞过该评论 String doILike redis.hget(REDIS_USER_LIKE_COMMENT, userId : commentId); if (StringUtils.isNotBlank(doILike) doILike.equalsIgnoreCase(1)) {cv.setIsLike(YesOrNo.YES.type); }构造用户点赞记录的key格式为userId:commentId从Redis的hash结构中查询该记录是否存在如果记录存在且值为1则设置评论VO对象的isLike属性为YES 4. 封装分页结果返回 return setterPagedGrid(list, page);将处理后的评论列表封装成统一的分页响应对象返回
http://www.dnsts.com.cn/news/280273.html

相关文章:

  • 山东网站定制策划计算机网页设计培训
  • 防制网站怎么做企业网站管理系统如何使用说明
  • 一个网站的建设流程有哪些资料雷军做的网站
  • 北京企业网站建设费用wordpress 老是被挂马
  • 成都网站改版公司wp_localize_script wordpress
  • 做学术论文的网站中国建设银行国际互联网网站
  • 企业网站建设中存在的问题分析南宁快速建站模板
  • 营销专业网站网上开店能赚钱吗
  • 360建筑网简历电话怎么修改深圳最好的外贸seo培训
  • 营销网站优化推广国外优质网站
  • 做仿站如何获取网站源码做网站要哪些人员
  • wordpress会员期限优化网站建设
  • 阜宁网站制作具体报价山东潍坊建设银行招聘网站
  • 免费的企业黄页网站大同格泰网站建设
  • 站牛网湖北网站建设
  • 贪玩手游官方网站陕西网站建设推广
  • 用电脑做服务器的建一个网站如何通过建立网站赚钱
  • 西昌网站建设公司一个网站如何产生流量
  • 南京做网站公司哪家好wordpress猜你喜欢插件
  • 惠民县建设局官方网站外汇跟单网站建设
  • iis网站找不到网页seo提权软件
  • 专门 做鞋子团购的网站有哪些个人建网站要花多少钱
  • 手机端网站界面如何做做竞品分析的网站
  • 企业网站建设方式企业网站怎样优化
  • 网站开发人员 怎么保存制作app免费网站模板下载
  • 合肥网站营销通信管理局网站备案
  • 网站编辑字体字号江门制作手机网站
  • 运营是做什么的工作广州外贸seo优化
  • 科技公司网站模板下载广州网站建设代理
  • 大浪网站建设 优帮云手机微信网站开发教程