点赞
Redis缓存用于点赞功能,可以提高性能。(面向Key编程)
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;//拼的结果}}
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:没有点赞}
}
异步请求,整个页面不刷新,更新点赞数就行
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,提示,并将数据返回给页面}}
点赞是在帖子详情页面进行的,也就是说要在该处,进行修改
依赖的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);//失败传出提示}});
}
注意变量要有“$”符号
在 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
在index.html中找到首页显示赞的地方:
寒江雪 发布于 2019-04-15 15:32:18- 赞 11
- |
- 回帖 7
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
另外两个位置处理方式相似