第一次在项目中使用redis,我写的点赞功能因为使用频率高,所以我选择使用了redis。这是我痛苦的开始,我以为点赞功能很好写的结果这么麻烦,因为存到redis里的key值的问题,我想了很久,最终解决了。但是我发现帖子的点赞,帖子的收藏,专辑的点赞,专辑的收藏,这些都差不多。后面写的也快了很多。
使用redis遇到了一些问题。
因为刚开始没有给redis加密码,而且在root用户上运行,导致攻击端口的行为出现,然后我的6379端口被封禁了一天。于是我改了个端口号,在另一个用户上运行。但是…,因为没给另一个用户足够的权限,总是频频报错。最终还是解决了。
把这次解决思路redis点赞的代码展示一下。
首先需要一个RedisKeyUtils,得到存在redis里的key值
public class RedisKeyUtils {
//保存用户点赞数据的key
public static final String MAP_KEY_USER_LIKED = "MAP_USER_LIKED";
//保存用户被点赞数量的key
public static final String MAP_KEY_USER_LIKED_COUNT = "MAP_USER_LIKED_COUNT";
//保存热门推荐帖子
/**
* 拼接被点赞的帖子id和点赞的人的id作为key。格式 222222::333333
* @param likedUserId 点赞的人id
* @param likedPostId 点赞的帖子的id
* @return
*/
public static String getLikedKey(String likedUserId, String likedPostId){
StringBuilder builder = new StringBuilder();
builder.append(likedPostId);
builder.append("::");
builder.append(likedUserId);
return builder.toString();
}
用户点赞的实体类UserLike :
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class UserLike {
/**
* id
*/
private int id;
/**
* 点赞人的id
*/
private Integer userId;
/**
* 点赞帖子的id
*/
private Integer postId;
/**
* 时间
*/
private String time;
/**
* 点赞状态
*/
private Integer status;
public UserLike(Integer userId,Integer postId,Integer status){
this.userId = userId;
this.status = status;
this.postId = postId;
}
}
点赞数量实体类LikedCountDTO :
package future.image.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class LikedCountDTO {
/**
* 帖子id
*/
private String id;
/**
* 点赞收藏数量
*/
private int count;
}
一个redis的service,里面定义点赞需要的方法。
import future.image.pojo.*;
import future.image.utils.Result;
import java.util.List;
/**
* @author zrl
*/
public interface RedisService {
/**
* 点赞。状态为1
* @param likedUserId
* @param likedPostId
*/
void saveLiked2Redis(String likedUserId, String likedPostId);
/**
* 取消点赞。将状态改变为0
* @param likedUserId
* @param likedPostId
*/
void unlikeFromRedis(String likedUserId, String likedPostId);
/**
* 从Redis中删除一条点赞数据
* @param likedUserId
* @param likedPostId
*/
void deleteLikedFromRedis(String likedUserId, String likedPostId);
/**
* 该用户的点赞数加1
* @param likedPostId
*/
void incrementLikedCount(String likedPostId);
/**
* 该用户的点赞数减1
* @param likedPostId
*/
void decrementLikedCount(String likedPostId);
/**
* 获取Redis中存储的所有点赞数据
* @return
*/
List<UserLike> getLikedDataFromRedis();
/**
* 获取Redis中存储的所有点赞数量
* @return
*/
List<LikedCountDTO> getLikedCountFromRedis();
/**
* 点赞数量
*/
Result getThumbUpCount(Integer postId);
}
以及它的是实现类RedisServiceImpl
import future.image.dao.CollectMapper;
import future.image.dao.ForumMapper;
import future.image.pojo.*;
import future.image.service.LikedService;
import future.image.service.RedisService;
import future.image.utils.RedisKeyUtils;
import future.image.utils.RedisUtil;
import future.image.utils.Result;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author zrl
*/
@Service("redisService")
public class RedisServiceImpl implements RedisService {
@Resource
RedisTemplate redisTemplate;
@Resource
LikedService likedService;
@Resource
ForumMapper forumMapper;
@Resource
RedisUtil redisUtil;
@Override
public void saveLiked2Redis(String likedUserId, String likedPostId) {
String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId);
redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED, key, LikedStatusEnum.LIKE.getCode());
}
@Override
public void unlikeFromRedis(String likedUserId, String likedPostId) {
String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId);
redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED, key, LikedStatusEnum.UNLIKE.getCode());
}
@Override
public void deleteLikedFromRedis(String likedUserId, String likedPostId) {
String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId);
redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);
}
@Override
public void incrementLikedCount(String likedPostId) {
boolean flag = redisTemplate.opsForHash().hasKey(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT,likedPostId);
if(flag){
redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedPostId, 1);
}else{
int count = forumMapper.getThumbUpCount(Integer.parseInt(likedPostId));
redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedPostId, count+1);
}
}
@Override
public void decrementLikedCount(String likedPostId) {
redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedPostId, -1);
}
@Override
public void decrementCollectForumCount(String postId) {
boolean flag = redisTemplate.opsForHash().hasKey(RedisKeyUtils.MAP_KEY_COLLECT_FORUM_COUNT,postId);
if(flag){
redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_COLLECT_FORUM_COUNT, postId, -1);
}else{
int count = collectMapper.getCollectForumCount(Integer.parseInt(postId));
redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_COLLECT_FORUM_COUNT, postId, count-1);
}
}
@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 likedPostId = split[0];
String likedUserId = split[1];
Integer value = (Integer) entry.getValue();
//组装成 UserLike 对象
UserLike userLike = new UserLike(Integer.parseInt(likedUserId), Integer.parseInt(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;
}
@Override
public Result getThumbUpCount(Integer postId) {
boolean flag = redisTemplate.opsForHash().hasKey(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT,String.valueOf(postId));
if(flag){
Object hget = redisUtil.hget(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, String.valueOf(postId));
return Result.success(hget);
}else{
int count = forumMapper.getThumbUpCount(postId);
redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, String.valueOf(postId), count);
return Result.success(count);
}
}
用户点赞的service LikedService:
package future.image.service;
import future.image.pojo.UserLike;
import future.image.utils.Result;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.util.List;
public interface LikedService {
/**
* 保存点赞记录
* @param userLike
* @return
*/
Result saveUserLike(UserLike userLike);
/**
* 根据被点赞人的id查询点赞列表(即查询都谁给这个人点赞过)
* @param postId pageSize pageNum
* @return Result
*/
Result getLikedListByPostId(Integer postId, Integer pageSize,Integer pageNum);
/**
* 通过被点赞人和点赞人id查询是否存在点赞记录
* @param likedUserId
* @param likedPostId
* @return
*/
UserLike getByLikedUserIdAndLikedPostId(Integer likedUserId, Integer likedPostId);
/**
* 将Redis里的点赞数据存入数据库中
*/
void transLikedFromRedis2DB();
/**
* 将Redis中的点赞数量数据存入数据库
*/
void transLikedCountFromRedis2DB();
/**
* 点赞
* */
Result thumbUpForum(@Param("userId")Integer userId, @Param("postId")Integer postId);
/**
* 得到用户点赞状态
*/
Result likeStatus(Integer postId,Integer userId);
}
及likedServiceImpl:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import future.image.dao.ForumMapper;
import future.image.dao.LikedMapper;
import future.image.dao.UserMapper;
import future.image.pojo.*;
import future.image.service.LikedService;
import future.image.service.RedisService;
import future.image.utils.RedisKeyUtils;
import future.image.utils.RedisUtil;
import future.image.utils.Result;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service("likedService")
public class LikedServiceImpl implements LikedService {
@Resource
RedisService redisService;
@Resource
LikedMapper likedMapper;
@Resource
UserMapper userMapper;
@Resource
ForumMapper forumMapper;
@Resource
RedisUtil redisUtil;
@Override
public Result saveUserLike(UserLike userLike) {
int f = likedMapper.savaUserLike(userLike);
if(f != 1){
return Result.fail("保存失败");
}
return Result.success();
}
@Override
public Result getLikedListByPostId(Integer postId,Integer pageSize,Integer pageNum) {
PageHelper.startPage(pageNum, pageSize);
List<UserLike> list = likedMapper.getLikedListByPostId(postId);
return Result.success(list);
}
@Override
public UserLike getByLikedUserIdAndLikedPostId(Integer likedUserId, Integer likedPostId) {
UserLike userlike = likedMapper.getByLikedUserIdAndLikedPostId(likedUserId,likedPostId);
return userlike;
}
@Override
public void transLikedFromRedis2DB() {
List<UserLike> list = redisService.getLikedDataFromRedis();
for (UserLike like : list) {
UserLike ul = getByLikedUserIdAndLikedPostId(like.getUserId(), like.getPostId());
if (ul == null){
//没有记录,直接存入
saveUserLike(like);
}else{
//有记录,需要更新
ul.setStatus(like.getStatus());
likedMapper.updateUserLike(ul);
}
}
}
@Override
public void transLikedCountFromRedis2DB() {
List<LikedCountDTO> list = redisService.getLikedCountFromRedis();
if(list.size() == 0){
return;
}
for (LikedCountDTO dto : list) {
//点赞数量属于无关紧要的操作,出错无需抛异常
Integer likeNum = dto.getCount();
//更新点赞数量
forumMapper.updateForumThumbUp(Integer.parseInt(dto.getId()),likeNum);
}
}
@Override
public Result thumbUpForum(Integer userId, Integer postId) {
Object hget = redisUtil.hget(RedisKeyUtils.MAP_KEY_USER_LIKED, postId + "::" + userId);
if(hget == null){
redisService.saveLiked2Redis(String.valueOf(userId),String.valueOf(postId));
redisService.incrementLikedCount(String.valueOf(postId));
return Result.success(1);
}else if("1".equals(hget.toString())){
redisService.unlikeFromRedis(String.valueOf(userId),String.valueOf(postId));
redisService.decrementLikedCount(String.valueOf(postId));
return Result.success(0);
}else{
redisService.saveLiked2Redis(String.valueOf(userId),String.valueOf(postId));
redisService.incrementLikedCount(String.valueOf(postId));
return Result.success(1);
}
}
@Override
public Result likeStatus(Integer postId, Integer userId) {
Object hget = redisUtil.hget(RedisKeyUtils.MAP_KEY_USER_LIKED, postId + "::" + userId);
if(hget == null){
Integer like = likedMapper.getUserLikeStatus(postId,userId);
if(like == null){
return Result.success(0);
}
redisService.saveLiked2Redis(String.valueOf(postId),String.valueOf(userId));
return Result.success(like);
}else if("1".equals(hget.toString())){
return Result.success(1);
}else{
return Result.success(0);
}
}
}
还有点赞功能的mapper,对数据库的操作LikedMapper:
import future.image.pojo.UserLike;
import java.util.List;
/**
* @author zrl
*/
public interface LikedMapper {
/**
* 点赞保存
*/
int savaUserLike(UserLike userLike);
int saveAllUserLike(List<UserLike> userLike);
int updateUserLike(UserLike userLike);
List<UserLike> getLikedListByPostId(Integer likedUserId);
UserLike getByLikedUserIdAndLikedPostId(Integer userId,Integer postId);
Integer getUserLikeStatus(Integer postId,Integer userId);
}
总结:
每次考核都是对自己技术的提升,也对之前学习的东西有了实战经验,记忆更加深刻。在考核中锻炼自己的能力。

3759

被折叠的 条评论
为什么被折叠?



