需求:
- 同一个用户只能点赞一次,再次点击则取消点赞
- 查询某篇文章的信息,包括点赞数,以及是否点赞
实现步骤:
- 给Blog类中添加一个字段,标示是否被当前用户点赞
- 利用Redis的set集合判断是否点赞过
- 未点赞过则点赞数+1,并将点赞标识设置为true,并在redis的set集合中保存该信息
- 已点赞过则点赞数-1,并将点赞标识设置为false,并在redis的set集合中删除该信息
效果展示
用户发表博客
用户查看博客
用户点赞博客
再次查看博客,点赞数应该加1
取消点赞
再次查看博客,点赞数应该减1
代码实现
bean&vo
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 博客
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Blog implements Serializable {
private Long id;
private String content;
private Integer likes;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BlogVO {
private Long id;
private String content;
private Integer likes;
private Boolean likeFlag = false;
}
核心业务
import cn.hutool.core.bean.BeanUtil;
import com.issa.seckill.bean.Blog;
import com.issa.seckill.common.PathConstant;
import com.issa.seckill.service.BlogService;
import com.issa.seckill.util.RedisUtil;
import com.issa.seckill.vo.BlogVO;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
/**
* 博客发布、查看、点赞
*/
@RestController
@RequestMapping(value = PathConstant.Business.BUSINESS)
@RequiredArgsConstructor
public class BusinessController {
private final StringRedisTemplate stringRedisTemplate;
private final BlogService blogService;
private final RedisUtil redisUtil;
/**
* 点赞/取消点赞
*
* @param blog 博客ID
* @return -
*/
@PutMapping("/likes")
public ResponseEntity<Boolean> like(@RequestBody Blog blog, HttpServletRequest request) {
// 默认为true,表示已经点了赞
boolean likeFlag = true;
String user = request.getHeader("user");
// 获取文章ID
Long id = blog.getId();
String preKey = user + ":" + "likes";
// 从redis获取该用户是否点赞过
Boolean member = stringRedisTemplate.opsForSet().isMember(preKey, String.valueOf(id));
// 如果点赞过,则取消点赞,并在数据库将该文章的点赞-1
boolean equals = Boolean.TRUE.equals(member);
Integer likes = blog.getLikes();
if (likes == null) {
likes = blogService.getById(id).getLikes();
}
if (equals) {
likeFlag = false;
blog.setLikes(likes - 1);
boolean update = blogService.updateById(blog);
if (update) {
stringRedisTemplate.opsForSet().remove(preKey, String.valueOf(id));
}
} else {
// 反之,增加点赞,在数据库+1
blog.setLikes(likes + 1);
boolean update = blogService.updateById(blog);
if (update) {
stringRedisTemplate.opsForSet().add(preKey, String.valueOf(id));
}
}
// blogService.update().setSql("likes = likes +1").eq("id", id).update();
return ResponseEntity.ok(likeFlag);
}
/**
* 获取博客详情
*
* @param id 博客ID
* @return 博客的详细信息:点赞数等
*/
@GetMapping("/{id}")
public ResponseEntity<BlogVO> getBlogDetail(@PathVariable Long id, HttpServletRequest request) {
String user = request.getHeader("user");
String preKey = user + ":" + "likes";
Blog blogDetail = blogService.getById(id);
BlogVO blogVO = BeanUtil.toBean(blogDetail, BlogVO.class);
// 从redis获取该用户是否点赞过
Boolean member = stringRedisTemplate.opsForSet().isMember(preKey, String.valueOf(id));
boolean equals = Boolean.TRUE.equals(member);
if (equals) {
blogVO.setLikeFlag(true);
}
return ResponseEntity.ok(blogVO);
}
/**
* 发表博客
*
* @param blog 博客
* @return 博客ID
*/
@PostMapping
public ResponseEntity<Long> pushBlog(@RequestBody Blog blog) {
Long id = redisUtil.id("blog");
blog.setId(id);
boolean save = blogService.save(blog);
if (save) {
return ResponseEntity.ok(id);
}
return ResponseEntity.status(400).build();
}
}