6.1 KiB
6.1 KiB
点赞
点赞:
- 支持对帖子、评论/回复点赞
- 第 1 次点赞,第 2 次取消点赞
- 首页统计帖子的点赞数量
- 详情页统计帖子和评论/回复的点赞数量
- 详情页显示用户的点赞状态(赞过了则显示已赞)
Redis 一般不用 DAO 层,不像 MySQL
Redis 配置
导包、配置端口等
# Redis
spring.redis.database = 11
spring.redis.host = localhost
spring.redis.port = 6379
Redis 配置类
/**
* Redis 配置类
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置 key 的序列化的方式
template.setKeySerializer(RedisSerializer.string());
// 设置 value 的序列化的方式
template.setValueSerializer(RedisSerializer.json());
// 设置 hash 的 key 的序列化的方式
template.setHashKeySerializer(RedisSerializer.string());
// 设置 hash 的 value 的序列化的方式
template.setHashValueSerializer(RedisSerializer.json());
template.afterPropertiesSet();
return template;
}
}
动态生成 Redis 的 key:
我们将点赞相关信息存入 set 中。其中,key 命名为 like:entity:entityType:entityId
,value 即存储点赞用户的 id。比如 key = like:entity:2:246
value = 11
表示用户 11 对实体类型 2 即评论进行了点赞,该评论的 id 是 246
/**
* 生成 Redis 的 key
*/
public class RedisKeyUtil {
private static final String SPLIT = ":";
private static final String PREFIX_ENTITY_LIKE = "like:entity";
// 某个实体(帖子、评论/回复)的赞
// like:entity:entityType:entityId -> set(userId)
// 谁给这个实体点了赞,就将这个用户的id存到这个实体对应的集合里
public static String getEntityLikeKey(int entityType, int entityId) {
return PREFIX_ENTITY_LIKE + SPLIT + entityType + SPLIT + entityId;
}
}
Service
/**
* 点赞相关
*/
@Service
public class LikeService {
@Autowired
private RedisTemplate redisTemplate;
/**
* 点赞
* @param userId
* @param entityType
* @param entityId
*/
public void like(int userId, int entityType, int entityId) {
String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
// 判断用户是否已经点过赞了
boolean isMember = redisTemplate.opsForSet().isMember(entityLikeKey, userId);
if (isMember) {
// 如果用户已经点过赞,点第二次则取消赞
redisTemplate.opsForSet().remove(entityLikeKey, userId);
}
else {
redisTemplate.opsForSet().add(entityLikeKey, userId);
}
}
/**
* 查询某实体被点赞的数量
* @param entityType
* @param entityId
* @return
*/
public long findEntityLikeCount(int entityType, int entityId) {
String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
return redisTemplate.opsForSet().size(entityLikeKey);
}
/**
* 查询某个用户对某个实体的点赞状态(是否已赞)
* @param userId
* @param entityType
* @param entityId
* @return 1:已赞,0:未赞
*/
public int findEntityLikeStatus(int userId, int entityType, int entityId) {
String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
return redisTemplate.opsForSet().isMember(entityLikeKey, userId) ? 1 : 0;
}
}
表现层(Controller 和前端)
在首页进行查询的时候,添加对帖子点赞数量查询
HomeController
long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId());
map.put("likeCount", likeCount);
在消息列表进行查询的时候,添加点赞功能,并对帖子、评论的点赞数量以及目前登录用户的点赞状态进行查询
LikeController
/**
* 点赞
*/
@Controller
public class LikeController {
@Autowired
private HostHolder hostHolder;
@Autowired
private LikeService likeService;
@PostMapping("/like")
@ResponseBody
public 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<String, Object> map = new HashMap<>();
map.put("likeCount", likeCount);
map.put("likeStatus", likeStatus);
return CommunityUtil.getJSONString(0, null, map);
}
}
前端消息列表界面 discuss-detail.html
:
<a href="javascript:;" th:onclick="|like(this, 1, ${post.id});|" class="text-primary">
<b th:text="${likeStatus == 1 ? '已赞' : '赞'}"></b> <i th:text="${likeCount}"></i>
</a>
对应的 discuss.js
function like(btn, entityType, entityId) {
$.post(
CONTEXT_PATH + "/like",
{"entityType":entityType, "entityId":entityId},
function(data) {
data = $.parseJSON(data);
if (data.code == 0) {
$(btn).children("i").text(data.likeCount);
$(btn).children("b").text(data.likeStatus == 1 ? '已赞' : '赞');
}
else {
alert(data.msg);
}
}
)
}
对应的 DiscussPostController
:
// 点赞数量
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);