springboot如何实现点赞功能

编程

在资讯类的项目中,我们常常遇到文章评论和点赞等功能实现。但是这些功能再项目中是高频出现的,如果直接操作数据库的话,对数据库压力太大。那遇到这个问题怎么解决?

redis缓存

首先我们想到的就是添加缓存处理机制。用户点赞可以放在Redis中,然后持久化到数据库中。

点赞、取消点赞是高频次的操作,若每次都读写数据库,大量的操作会影响数据库性能,所以需要做缓存

实战

知道了解决方案,我们就要去测试效果。

redis安装不用介绍了,大家都可以安装运行。下面来讲springboot怎么解决这个问题。

导入依赖

在启动类中添加缓存注解 @EnableCaching

接下来我们需要配置redis

@Configuration

public class RedisConfig {

@Bean

@ConditionalOnMissingBean(name = "redisTemplate")

public RedisTemplate<String, Object> redisTemplate(

RedisConnectionFactory redisConnectionFactory)

throws UnknownHostException {

Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);

ObjectMapper om = new ObjectMapper();

om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

jackson2JsonRedisSerializer.setObjectMapper(om);

RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();

template.setConnectionFactory(redisConnectionFactory);

template.setKeySerializer(jackson2JsonRedisSerializer);

template.setValueSerializer(jackson2JsonRedisSerializer);

template.setHashKeySerializer(jackson2JsonRedisSerializer);

template.setHashValueSerializer(jackson2JsonRedisSerializer);

template.afterPropertiesSet();

return template;

}

@Bean

@ConditionalOnMissingBean(StringRedisTemplate.class)

public StringRedisTemplate stringRedisTemplate(

RedisConnectionFactory redisConnectionFactory)

throws UnknownHostException {

StringRedisTemplate template = new StringRedisTemplate();

template.setConnectionFactory(redisConnectionFactory);

return template;

}

}

这样基本环境搭建完成,我们需要做的就是redis的工具类了。

redis存储格式

现在知道了redis缓存,但是我们怎么把点赞存储到redis中。redis支持数据格式很多,我们需要把点赞人和被点赞人,点赞状态都给记录下来。

由于需要记录点赞人和被点赞人,还有点赞状态(点赞、取消点赞),还要固定时间间隔取出 Redis 中所有点赞数据,分析了下 Redis 数据格式中 Hash 最合适。

hash的存储方式我们确定了,接下来就是模仿用户点赞存储数据。

如果用户点赞,存储的键为:likedUserId::likedPostId,对应的值为 1 。取消点赞,存储的键为:likedUserId::likedPostId,对应的值为 0 。取数据时把键用 :: 切开就得到了两个id,也很方便。

现在主要的实现方法就是从redis中定时从缓存中持久化到数据库中。

@Override

public List<UserLike> getLikedDataFromRedis() {

Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED, ScanOptions.NONE);

List<UserLike> list = new ArrayList<>();

while (cursor.hasNext()){

Map.Entry<Object, Object> entry = cursor.next();

String key = (String) entry.getKey();

//分离出 likedUserId,likedPostId

String[] split = key.split("::");

String likedUserId = split[0];

String likedPostId = split[1];

Integer value = (Integer) entry.getValue();

//组装成 UserLike 对象

UserLike userLike = new UserLike(likedUserId, likedPostId, value);

list.add(userLike);

//存到 list 后从 Redis 中删除

redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);

}

return list;

}

@Override

public List<LikedCountDTO> getLikedCountFromRedis() {

Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, ScanOptions.NONE);

List<LikedCountDTO> list = new ArrayList<>();

while (cursor.hasNext()){

Map.Entry<Object, Object> map = cursor.next();

//将点赞数量存储在 LikedCountDT

String key = (String)map.getKey();

LikedCountDTO dto = new LikedCountDTO(key, (Integer) map.getValue());

list.add(dto);

//从Redis中删除这条记录

redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, key);

}

return list;

}

这二个方法就可以实现点赞记录和点赞次数的统计到数据库中。其实,redis主要就是实现点赞和点赞次数直接的一个缓存的作用。

但是问题来了,如果客户在点赞后,刷新了页面,此时redis没有持久化到数据库中,用户就会觉得点赞失效,继续点赞。导致可以体验不好。因为有定时器的影响,就会带来这种麻烦。大家有更好的解决办法分享一下。

以上内容皆为本人观点,欢迎大家提出批评和指导,我们一起探讨!

以上是 springboot如何实现点赞功能 的全部内容, 来源链接: utcz.com/z/512329.html

回到顶部