4-3:点赞功能
创始人
2024-03-07 13:55:39
0次

点赞

点赞

  • 支持对帖子、评论点赞。
  • 第1次点赞,第2次取消点赞。
    首页点赞数量
  • 统计帖子的点赞数量。
    详情页点赞数量
  • 统计点赞数量。
  • 显示点赞状态。

Redis缓存用于点赞功能,可以提高性能。(面向Key编程)

1.建立RedisKeyUtil.java

package com.nowcoder.community.util;public class RedisKeyUtil {private static final String SPLIT = ":";private static final String PREFIX_ENTITY_LIKE = "like:entity";// 生成某个实体的赞// like:entity:entityType:entityId -> set(userId),用id集合表示赞,不用整数,防止后面需求发生变化,集合中装载UserId,public static String getEntityLikeKey(int entityType, int entityId) {return PREFIX_ENTITY_LIKE + SPLIT + entityType + SPLIT + entityId;//拼的结果}}
  1. 开发业务组件LikeService.java
package com.nowcoder.community.service;import com.nowcoder.community.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;@Service
public class LikeService {@Autowiredprivate RedisTemplate redisTemplate;//注入Redis模板// 点赞public void like(int userId, int entityType, int entityId) {String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);boolean isMember = redisTemplate.opsForSet().isMember(entityLikeKey, userId);if (isMember) {//判断用户是否点过赞,用户id在集合中,就是点过赞。redisTemplate.opsForSet().remove(entityLikeKey, userId);} else {redisTemplate.opsForSet().add(entityLikeKey, userId);}}// 查询某实体被点赞的数量public long findEntityLikeCount(int entityType, int entityId) {String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);return redisTemplate.opsForSet().size(entityLikeKey);}// 查询某人对某实体的点赞状态public int findEntityLikeStatus(int userId, int entityType, int entityId) {String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);return redisTemplate.opsForSet().isMember(entityLikeKey, userId) ? 1 : 0;//返回整数,可以表现更多的状态,如踩等。1:点赞,0:没有点赞}
}

3. 表现层

异步请求,整个页面不刷新,更新点赞数就行

package com.nowcoder.community.controller;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.util.CommunityUtil;
import com.nowcoder.community.util.HostHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;import java.util.HashMap;
import java.util.Map;@Controller
public class LikeController {@Autowiredprivate LikeService likeService;@Autowiredprivate HostHolder hostHolder;@RequestMapping(path = "/like", method = RequestMethod.POST)//处理异步请求的方法@ResponseBodypublic String like(int entityType, int entityId) {User user = hostHolder.getUser();// 点赞likeService.like(user.getId(), entityType, entityId);// 数量long likeCount = likeService.findEntityLikeCount(entityType, entityId);// 状态int likeStatus = likeService.findEntityLikeStatus(user.getId(), entityType, entityId);// 返回的结果:统一传递给页面Map map = new HashMap<>();map.put("likeCount", likeCount);map.put("likeStatus", likeStatus);return CommunityUtil.getJSONString(0, null, map);//返回Json格式的数据:正确返回0,提示,并将数据返回给页面}}

4.discuss-detail

点赞是在帖子详情页面进行的,也就是说要在该处,进行修改


在这里插入图片描述
依赖的JS文件

function like(btn, entityType, entityId) {$.post(//POST请求,将点赞key拼接CONTEXT_PATH + "/like",{"entityType":entityType,"entityId":entityId},function(data) {//转存服务器返回的数据data = $.parseJSON(data);if(data.code == 0) {//判断请求是否成功$(btn).children("i").text(data.likeCount);//获取btn节点的子节点,改变它的内容。$(btn).children("b").text(data.likeStatus==1?'已赞':"赞");//赞成功了显示“已赞”。} else {alert(data.msg);//失败传出提示}});
}

5. 重启服务器,判断一下结果

在这里插入图片描述
在这里插入图片描述
注意变量要有“$”符号

5首页显示的点赞的数量要一致

在 HomeController.java中,将likeService注入
方法修改如下:

public String getIndexPage(Model model, Page page) {// 方法调用钱,SpringMVC会自动实例化Model和Page,并将Page注入Model.// 所以,在thymeleaf中可以直接访问Page对象中的数据.page.setRows(discussPostService.findDiscussPostRows(0));page.setPath("/index");List list = discussPostService.findDiscussPosts(0, page.getOffset(), page.getLimit());List> discussPosts = new ArrayList<>();if (list != null) {for (DiscussPost post : list) {Map map = new HashMap<>();map.put("post", post);User user = userService.findUserById(post.getUserId());map.put("user", user);long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId());map.put("likeCount", likeCount);discussPosts.add(map);}}model.addAttribute("discussPosts", discussPosts);return "/index";}

在index.html中找到首页显示赞的地方:

寒江雪 发布于 2019-04-15 15:32:18
  • 赞 11
  • |
  • 回帖 7

5帖子详情页面显示的点赞的数量和状态也要一致

DiscussPostController.java中将likeService注入,在方法内部进行处理

 public String getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model, Page page) {// 帖子DiscussPost post = discussPostService.findDiscussPostById(discussPostId);model.addAttribute("post", post);// 作者User user = userService.findUserById(post.getUserId());model.addAttribute("user", user);// 点赞数量long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, discussPostId);model.addAttribute("likeCount", likeCount);//将状态传到页面// 点赞状态int likeStatus = hostHolder.getUser() == null ? 0 :likeService.findEntityLikeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_POST, discussPostId);//判断用户是否登录,没登录也可以看model.addAttribute("likeStatus", likeStatus);......

完整:

public String getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model, Page page) {// 帖子DiscussPost post = discussPostService.findDiscussPostById(discussPostId);model.addAttribute("post", post);// 作者User user = userService.findUserById(post.getUserId());model.addAttribute("user", user);// 点赞数量long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, discussPostId);model.addAttribute("likeCount", likeCount);// 点赞状态int likeStatus = hostHolder.getUser() == null ? 0 :likeService.findEntityLikeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_POST, discussPostId);model.addAttribute("likeStatus", likeStatus);// 评论分页信息page.setLimit(5);page.setPath("/discuss/detail/" + discussPostId);page.setRows(post.getCommentCount());// 评论: 给帖子的评论// 回复: 给评论的评论// 评论列表List commentList = commentService.findCommentsByEntity(ENTITY_TYPE_POST, post.getId(), page.getOffset(), page.getLimit());// 评论VO列表List> commentVoList = new ArrayList<>();if (commentList != null) {for (Comment comment : commentList) {// 评论VOMap commentVo = new HashMap<>();// 评论commentVo.put("comment", comment);// 作者commentVo.put("user", userService.findUserById(comment.getUserId()));// 点赞数量likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, comment.getId());//评论的点赞状态,数量commentVo.put("likeCount", likeCount);// 点赞状态likeStatus = hostHolder.getUser() == null ? 0 :likeService.findEntityLikeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId());commentVo.put("likeStatus", likeStatus);//装到VO中// 回复列表List replyList = commentService.findCommentsByEntity(ENTITY_TYPE_COMMENT, comment.getId(), 0, Integer.MAX_VALUE);// 回复VO列表List> replyVoList = new ArrayList<>();if (replyList != null) {for (Comment reply : replyList) {Map replyVo = new HashMap<>();// 回复replyVo.put("reply", reply);// 作者 replyVo.put("user", userService.findUserById(reply.getUserId()));// 回复目标User target = reply.getTargetId() == 0 ? null : userService.findUserById(reply.getTargetId());replyVo.put("target", target);// 点赞数量likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, reply.getId());replyVo.put("likeCount", likeCount);// 点赞状态likeStatus = hostHolder.getUser() == null ? 0 :likeService.findEntityLikeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId());//回复的处理也是类似的。replyVo.put("likeStatus", likeStatus);replyVoList.add(replyVo);}}commentVo.put("replys", replyVoList);// 回复数量int replyCount = commentService.findCommentCount(ENTITY_TYPE_COMMENT, comment.getId());commentVo.put("replyCount", replyCount);commentVoList.add(commentVo);}}model.addAttribute("comments", commentVoList);return "/site/discuss-detail";}}

6:帖子详情页面也要更改

在这里插入图片描述
另外两个位置处理方式相似
在这里插入图片描述
在这里插入图片描述

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...