12.2_黑马Redis实战篇达人探店好友关注

目录

实战篇03

thinking :提取公共部分为一个方法的快捷键?

thinking:redis中的ismember?

thinking:BooleanUtil.isTrue?

实战篇04

thinking:zscore的用法?

thinking:stream().map().collect?

thinking:引用静态方法?JAVA中的双冒号? 

thinking:StringUtils.join的用法?

thinking:StrUtil.join()?

实战篇05

实战篇06

thinking:在redis中求交集?  用inersect。

实战篇07

实战篇08

thinking:System.currentTimeMillis()?

​编辑 thinking:时间戳?​编辑

实战篇09

实战篇10

​编辑 thinking:JAVA中的long和int有什么区别?

thinking:为什么long类型的变量需要加上L?float类型的变量要加上F?


实战篇03

thinking :提取公共部分为一个方法的快捷键?

ctrl + alt + m

thinking:redis中的ismember?

redis五大集合之一(Set集合常用命令)_redis set ismember-CSDN博客

可以简化为:

thinking:BooleanUtil.isTrue?

hutool工具包快速入门_beanutil.fillbeanwithmap-CSDN博客

package com.hmdp.service.impl;

import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hmdp.dto.Result;
import com.hmdp.entity.Blog;
import com.hmdp.entity.User;
import com.hmdp.mapper.BlogMapper;
import com.hmdp.service.IBlogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.service.IUserService;
import com.hmdp.utils.SystemConstants;
import com.hmdp.utils.UserHolder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {
    @Resource
    private IUserService userService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Override
    public Result queryHotBlog(Integer current) {
        // 根据用户查询
        Page<Blog> page = query()
                .orderByDesc("liked")
                .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
        // 获取当前页数据
        List<Blog> records = page.getRecords();
        // 查询用户
        records.forEach(blog -> {
            this.queryBlogUser(blog);
            this.isBlockLiked(blog);
        });
        return Result.ok(records);
    }

    @Override
    public Result queryBlogById(Long id) {
        //1. 查询blog
        Blog blog  =getById(id);
        if(blog == null){
            return Result.fail("笔记不存在!");
        }
        //2. 查询blog有关的用户
        queryBlogUser(blog);
        //3.查询blog是否被点赞
        isBlockLiked(blog);
        return Result.ok(blog);
    }

    private void isBlockLiked(Blog blog) {
        //1.判断当前登录用户
        Long userId = UserHolder.getUser().getId();
        //2.判断当前登录用户是否已经点赞
        String key ="blog:liked:"+blog.getId();
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
        blog.setIsLike(BooleanUtil.isTrue(isMember));

    }

    @Override
    public Result likeBlog(Long id) {
        //1.判断当前登录用户
        Long userId = UserHolder.getUser().getId();
        //2.判断当前登录用户是否已经点赞
        String key ="blog:liked:"+id;
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
        if(BooleanUtil.isFalse(isMember)) {
            //3.如果未点赞,可以点赞
            //3.1数据库点赞数 +1
            boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();
            //3.2保存用户到Redis的set集合
            if (isSuccess) {
                stringRedisTemplate.opsForSet().add(key, userId.toString());
            }
        }else {
            //4如果已点赞,取消点赞
            //4.1数据库点赞数 -1
            boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();
            //4.2把用户从Redis的set集合移除
            if (isSuccess) {
                stringRedisTemplate.opsForSet().remove(key, userId.toString());
            }
        }
        return Result.ok();
    }

    private void queryBlogUser(Blog blog) {
        Long userId = blog.getUserId();
        User user = userService.getById(userId);
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
    }
}

实战篇04

thinking:zscore的用法?

Redis zrangebylex的使用 | Redis sorted_set不可不知的秘密_血煞长虹的博客-CSDN博客

thinking:stream().map().collect?

thinking:引用静态方法?JAVA中的双冒号? 

当时看黑马上下部的时候一直没有搞懂的内容之一。现在来恶补一下。

方法引用-02-引用静态方法_哔哩哔哩_bilibili

 

 

 

接着判断它是否符合以下三个要求

接着,我们来看看视频中的例子

Java中Long::valueOf是什么意思_long.valueof-CSDN博客

 有几篇讲JAVA双冒号的文章也挺好的,可以看看。

深入理解Java双冒号(::)运算符的使用(*)_java 双冒号_Firm陈的博客-CSDN博客

Java 中的双冒号“::”_java ::_JFS_Study的博客-CSDN博客  

 发现很多知识点当时很难理解,一段时间之后就突然开窍。

遂决定明年暑假前把JAVA基础篇再二刷一遍。

thinking:StringUtils.join的用法?

StringUtils.join的用法_stringutils.join用法-CSDN博客

thinking:StrUtil.join()?

Hutool Java开发工具包_strutil.join-CSDN博客

 Hutool,轻松玩转字符串操作, 都是案例,值得收藏!_hutool 字符串拼接-CSDN博客

package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.Blog;
import com.hmdp.entity.User;
import com.hmdp.mapper.BlogMapper;
import com.hmdp.service.IBlogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.service.IUserService;
import com.hmdp.utils.SystemConstants;
import com.hmdp.utils.UserHolder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.hmdp.utils.RedisConstants.BLOG_LIKED_KEY;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {
    @Resource
    private IUserService userService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Override
    public Result queryHotBlog(Integer current) {
        // 根据用户查询
        Page<Blog> page = query()
                .orderByDesc("liked")
                .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
        // 获取当前页数据
        List<Blog> records = page.getRecords();
        // 查询用户
        records.forEach(blog -> {
            this.queryBlogUser(blog);
            this.isBlockLiked(blog);
        });
        return Result.ok(records);
    }

    @Override
    public Result queryBlogById(Long id) {
        //1. 查询blog
        Blog blog  =getById(id);
        if(blog == null){
            return Result.fail("笔记不存在!");
        }
        //2. 查询blog有关的用户
        queryBlogUser(blog);
        //3.查询blog是否被点赞
        isBlockLiked(blog);
        return Result.ok(blog);
    }

    private void isBlockLiked(Blog blog) {
        //1.获取登录用户
        UserDTO user = UserHolder.getUser();
        if(user == null){
            //用户未登录,无需查询是否点赞
            return;
        }
        //1.判断当前登录用户
        Long userId = UserHolder.getUser().getId();
        //2.判断当前登录用户是否已经点赞
        String key ="blog:liked:"+blog.getId();
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        blog.setIsLike(score != null);

    }

    @Override
    public Result likeBlog(Long id) {
        //1.判断当前登录用户
        Long userId = UserHolder.getUser().getId();
        //2.判断当前登录用户是否已经点赞
        String key =BLOG_LIKED_KEY+id;
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        if(score == null) {
            //3.如果未点赞,可以点赞
            //3.1数据库点赞数 +1
            boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();
            //3.2保存用户到Redis的set集合
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().add(key, userId.toString(),System.currentTimeMillis());
            }
        }else {
            //4如果已点赞,取消点赞
            //4.1数据库点赞数 -1
            boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();
            //4.2把用户从Redis的set集合移除
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().remove(key, userId.toString());
            }
        }
        return Result.ok();
    }

    @Override
    public Result queryBlogLikes(Long id) {
        String key =BLOG_LIKED_KEY + id;
        //1.查询top5的点赞用户 zrange key 0 4
        Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);
        if(top5 ==null || top5.isEmpty()){
            return  Result.ok(Collections.emptyList());
        }
        //2.解析出其中的用户id
        List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());
        String idStr = StrUtil.join(",", ids);
        //3.根据用户id查询用户
        List<UserDTO> userDTOS = userService.query()
                .in("id",ids)
                .last("ORDER BY FIELD(id,"+idStr + ")").list()
                .stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());
        //4.返回
        return Result.ok(userDTOS);
    }

    private void queryBlogUser(Blog blog) {
        Long userId = blog.getUserId();
        User user = userService.getById(userId);
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
    }
}

实战篇05

package com.hmdp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hmdp.dto.Result;
import com.hmdp.entity.Follow;
import com.hmdp.mapper.FollowMapper;
import com.hmdp.service.IFollowService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.utils.UserHolder;
import org.springframework.stereotype.Service;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow> implements IFollowService {

    @Override
    public Result follow(Long followUserId, Boolean isFollow) {
        //1.获取登录用户
        Long userId = UserHolder.getUser().getId();
        //1.判断到底是关注还是取关
        if(isFollow){
            //2.关注,新增数据
            Follow follow = new Follow();
            follow.setUserId(userId);
            follow.setFollowUserId(followUserId);
            save(follow);
        }
        else{
            //3.取关,删除
            remove(new QueryWrapper<Follow>()
                    .eq("user_id",userId)
                    .eq("follow_user_id",followUserId));
        }
        return Result.ok();
    }

    @Override
    public Result isFollow(Long followUserId) {
        //1.获取登录用户
        Long userId = UserHolder.getUser().getId();
        //2.查询是否关注
        Integer count = query().eq("user_id", userId)
                .eq("follow_user_id", followUserId).count();
        return Result.ok(count > 0 );
    }
}

实战篇06

thinking:在redis中求交集?  用inersect。

package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.Follow;
import com.hmdp.mapper.FollowMapper;
import com.hmdp.service.IFollowService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.service.IUserService;
import com.hmdp.utils.CacheClient;
import com.hmdp.utils.UserHolder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow> implements IFollowService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private IUserService userService;
    @Override
    public Result follow(Long followUserId, Boolean isFollow) {
        //1.获取登录用户
        Long userId = UserHolder.getUser().getId();
        String key ="follows:" + userId;
        //1.判断到底是关注还是取关
        if(isFollow){
            //2.关注,新增数据
            Follow follow = new Follow();
            follow.setUserId(userId);
            follow.setFollowUserId(followUserId);
            boolean isSuccess = save(follow);
            if(isSuccess){
                //把关注用户的id,放入redis的set集合
                stringRedisTemplate.opsForSet().add(key,followUserId.toString());
            }
        } else{
            //3.取关,删除
            boolean isSuccess = remove(new QueryWrapper<Follow>()
                    .eq("user_id", userId)
                    .eq("follow_user_id", followUserId));
            if (isSuccess) {
                //把关注用户的id从Redis集合中移除
                stringRedisTemplate.opsForSet().remove(key, followUserId.toString());
            }
        }
        return Result.ok();
    }

    @Override
    public Result isFollow(Long followUserId) {
        //1.获取登录用户
        Long userId = UserHolder.getUser().getId();
        //2.查询是否关注
        Integer count = query().eq("user_id", userId)
                .eq("follow_user_id", followUserId).count();
        return Result.ok(count > 0 );
    }

    @Override
    public Result followCommons(Long id) {
        //1.获取当前用户
        Long userId = UserHolder.getUser().getId();
        String key = "follows:"+userId;
        //2.求交集
        String key2 = "follows"+ id;
        Set<String> intersect = stringRedisTemplate.opsForSet().intersect(key, key2);
        if(intersect == null || intersect.isEmpty()){
            //无交集
            return Result.ok(Collections.emptyList());
        }
        //3.解析id集合
        List<Long> ids = intersect.stream().map(Long::valueOf).collect(Collectors.toList());
        //4.查询用户
        List<UserDTO> users = userService.listByIds(ids)
                .stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());

        return Result.ok(users);
    }
}

实战篇07

实战篇08

对于数据经常发生变化的,用sortset处理分页问题 

thinking:System.currentTimeMillis()?

System.currentTimeMillis()用法及其计算方式与时间的单位转换_Tan.]der的博客-CSDN博客

Java获取当前系统时间-CSDN博客

 thinking:时间戳?

 获取系统时间以及时间戳的理解与使用_系统时间戳-CSDN博客

package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.Blog;
import com.hmdp.entity.Follow;
import com.hmdp.entity.User;
import com.hmdp.mapper.BlogMapper;
import com.hmdp.service.IBlogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.service.IFollowService;
import com.hmdp.service.IUserService;
import com.hmdp.utils.SystemConstants;
import com.hmdp.utils.UserHolder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.hmdp.utils.RedisConstants.BLOG_LIKED_KEY;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {
    @Resource
    private IUserService userService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private IFollowService followService;
    @Override
    public Result queryHotBlog(Integer current) {
        // 根据用户查询
        Page<Blog> page = query()
                .orderByDesc("liked")
                .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
        // 获取当前页数据
        List<Blog> records = page.getRecords();
        // 查询用户
        records.forEach(blog -> {
            this.queryBlogUser(blog);
            this.isBlockLiked(blog);
        });
        return Result.ok(records);
    }

    @Override
    public Result queryBlogById(Long id) {
        //1. 查询blog
        Blog blog  =getById(id);
        if(blog == null){
            return Result.fail("笔记不存在!");
        }
        //2. 查询blog有关的用户
        queryBlogUser(blog);
        //3.查询blog是否被点赞
        isBlockLiked(blog);
        return Result.ok(blog);
    }

    private void isBlockLiked(Blog blog) {
        //1.获取登录用户
        UserDTO user = UserHolder.getUser();
        if(user == null){
            //用户未登录,无需查询是否点赞
            return;
        }
        //1.判断当前登录用户
        Long userId = UserHolder.getUser().getId();
        //2.判断当前登录用户是否已经点赞
        String key ="blog:liked:"+blog.getId();
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        blog.setIsLike(score != null);

    }

    @Override
    public Result likeBlog(Long id) {
        //1.判断当前登录用户
        Long userId = UserHolder.getUser().getId();
        //2.判断当前登录用户是否已经点赞
        String key =BLOG_LIKED_KEY+id;
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        if(score == null) {
            //3.如果未点赞,可以点赞
            //3.1数据库点赞数 +1
            boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();
            //3.2保存用户到Redis的set集合
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().add(key, userId.toString(),System.currentTimeMillis());
            }
        }else {
            //4如果已点赞,取消点赞
            //4.1数据库点赞数 -1
            boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();
            //4.2把用户从Redis的set集合移除
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().remove(key, userId.toString());
            }
        }
        return Result.ok();
    }

    @Override
    public Result queryBlogLikes(Long id) {
        String key =BLOG_LIKED_KEY + id;
        //1.查询top5的点赞用户 zrange key 0 4
        Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);
        if(top5 ==null || top5.isEmpty()){
            return  Result.ok(Collections.emptyList());
        }
        //2.解析出其中的用户id
        List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());
        String idStr = StrUtil.join(",", ids);
        //3.根据用户id查询用户
        List<UserDTO> userDTOS = userService.query()
                .in("id",ids)
                .last("ORDER BY FIELD(id,"+idStr + ")").list()
                .stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());
        //4.返回
        return Result.ok(userDTOS);
    }

    @Override
    public Result saveBlog(Blog blog) {
        //1 获取登录用户
        UserDTO user = UserHolder.getUser();
        blog.setUserId(user.getId());
        //2 保存探店笔记
        boolean isSuccess = save(blog);
        if (!isSuccess){
            return Result.fail("新增笔记失败!");
        }
        //3 查询笔记作者的所有粉丝
        List<Follow> follows = followService.query().eq("follow_user_id", user.getId()).list();
        //4 推送笔记id给所有粉丝
        for(Follow follow : follows){
            //4.1 获取粉丝id
            Long userId = follow.getUserId();
            //4.2推送
            String key = "feed:" + userId;
            stringRedisTemplate.opsForZSet().add(key,blog.getId().toString(),System.currentTimeMillis());
        }
        //5 返回id
        return Result.ok(blog.getId());
    }

    private void queryBlogUser(Blog blog) {
        Long userId = blog.getUserId();
        User user = userService.getById(userId);
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
    }
}

实战篇09

实战篇10

 thinking:JAVA中的long和int有什么区别?

 java long 区别_java中long和int的区别-CSDN博客

thinking:为什么long类型的变量需要加上L?float类型的变量要加上F?

运算符-04-05-隐式转换和强制转换_哔哩哔哩_bilibili

意思就是说:30本身是int类型,可是你现在想要它变成long类型。

而JAVA中的隐形转化,会自动将int类型转化未long类型。

因此,JAVA把你想做的事情帮你做了。因此,long num1 = 30 才可以成立

而1111111111111111111超过了int的取值范围,就已经出bug了。无法再帮你转long类型了

而double的取值范围最大,就无法自动转化了。得自己手动转化才可以。 

为什么定义long类型跟float类型的变量时要加L和F_java中long类型为什么要加l_Cristo_Li的博客-CSDN博客

【Java】double|float 区别_java float和double-CSDN博客

 

listByIds 无法保证在数据库中按照一定的顺序进行查找,因此要用自定义sql语句才可以完成这个操作。

package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hmdp.dto.Result;
import com.hmdp.dto.ScrollResult;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.Blog;
import com.hmdp.entity.Follow;
import com.hmdp.entity.User;
import com.hmdp.mapper.BlogMapper;
import com.hmdp.service.IBlogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.service.IFollowService;
import com.hmdp.service.IUserService;
import com.hmdp.utils.SystemConstants;
import com.hmdp.utils.UserHolder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.hmdp.utils.RedisConstants.BLOG_LIKED_KEY;
import static com.hmdp.utils.RedisConstants.FEED_KEY;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {
    @Resource
    private IUserService userService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private IFollowService followService;
    @Override
    public Result queryHotBlog(Integer current) {
        // 根据用户查询
        Page<Blog> page = query()
                .orderByDesc("liked")
                .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
        // 获取当前页数据
        List<Blog> records = page.getRecords();
        // 查询用户
        records.forEach(blog -> {
            this.queryBlogUser(blog);
            this.isBlockLiked(blog);
        });
        return Result.ok(records);
    }

    @Override
    public Result queryBlogById(Long id) {
        //1. 查询blog
        Blog blog  =getById(id);
        if(blog == null){
            return Result.fail("笔记不存在!");
        }
        //2. 查询blog有关的用户
        queryBlogUser(blog);
        //3.查询blog是否被点赞
        isBlockLiked(blog);
        return Result.ok(blog);
    }

    private void isBlockLiked(Blog blog) {
        //1.获取登录用户
        UserDTO user = UserHolder.getUser();
        if(user == null){
            //用户未登录,无需查询是否点赞
            return;
        }
        //1.判断当前登录用户
        Long userId = UserHolder.getUser().getId();
        //2.判断当前登录用户是否已经点赞
        String key ="blog:liked:"+blog.getId();
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        blog.setIsLike(score != null);

    }

    @Override
    public Result likeBlog(Long id) {
        //1.判断当前登录用户
        Long userId = UserHolder.getUser().getId();
        //2.判断当前登录用户是否已经点赞
        String key =BLOG_LIKED_KEY+id;
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        if(score == null) {
            //3.如果未点赞,可以点赞
            //3.1数据库点赞数 +1
            boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();
            //3.2保存用户到Redis的set集合
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().add(key, userId.toString(),System.currentTimeMillis());
            }
        }else {
            //4如果已点赞,取消点赞
            //4.1数据库点赞数 -1
            boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();
            //4.2把用户从Redis的set集合移除
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().remove(key, userId.toString());
            }
        }
        return Result.ok();
    }

    @Override
    public Result queryBlogLikes(Long id) {
        String key =BLOG_LIKED_KEY + id;
        //1.查询top5的点赞用户 zrange key 0 4
        Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);
        if(top5 ==null || top5.isEmpty()){
            return  Result.ok(Collections.emptyList());
        }
        //2.解析出其中的用户id
        List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());
        String idStr = StrUtil.join(",", ids);
        //3.根据用户id查询用户
        List<UserDTO> userDTOS = userService.query()
                .in("id",ids)
                .last("ORDER BY FIELD(id,"+idStr + ")").list()
                .stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());
        //4.返回
        return Result.ok(userDTOS);
    }

    @Override
    public Result saveBlog(Blog blog) {
        //1 获取登录用户
        UserDTO user = UserHolder.getUser();
        blog.setUserId(user.getId());
        //2 保存探店笔记
        boolean isSuccess = save(blog);
        if (!isSuccess){
            return Result.fail("新增笔记失败!");
        }
        //3 查询笔记作者的所有粉丝
        List<Follow> follows = followService.query().eq("follow_user_id", user.getId()).list();
        //4 推送笔记id给所有粉丝
        for(Follow follow : follows){
            //4.1 获取粉丝id
            Long userId = follow.getUserId();
            //4.2推送
            String key = "feed:" + userId;
            stringRedisTemplate.opsForZSet().add(key,blog.getId().toString(),System.currentTimeMillis());
        }
        //5 返回id
        return Result.ok(blog.getId());
    }

    @Override
    public Result queryBlogOfFollow(Long max, Integer offset) {
        //1.获取当前用户
        Long userId = UserHolder.getUser().getId();
        //2.查询收件箱
        String key = FEED_KEY + userId;
        Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate
                .opsForZSet()
                .reverseRangeByScoreWithScores(key, 0, max, offset, 2);
        //3.非空判断
        if(typedTuples == null || typedTuples.isEmpty()){
            return Result.ok();
        }
        //4.解析数据 :blogId minTime(时间戳) offset
        List<Long> ids =new ArrayList<>(typedTuples.size());
        long minTime =0;
        int os = 1;
        for(ZSetOperations.TypedTuple<String> tuple : typedTuples){
            //4.1 获取id
            ids.add(Long.valueOf(tuple.getValue()));
            //4.2 获取分数(时间戳)
            long time = tuple.getScore().longValue();
            if(time == minTime){
                os++;
            }else{
                minTime = time ;
                os = 1 ;
            }
        }
        //5.根据id查询blog
        String idStr = StrUtil.join(",",ids);
        List<Blog> blogs = query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list();
        for (Blog blog : blogs) {
            //5.1 查询blog有关的用户
            queryBlogUser(blog);
            //5.2 查询blog是否被点赞
            isBlockLiked(blog);
        }

        //6 封装并返回
        ScrollResult r = new ScrollResult();
        r.setList(blogs);
        r.setOffset(os);
        r.setMinTime(minTime);

        return Result.ok(r);

    }

    private void queryBlogUser(Blog blog) {
        Long userId = blog.getUserId();
        User user = userService.getById(userId);
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/211437.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

centos7 yum安装redis

1.安装epel源 yum install epel-release -y 2.安装 参数-y是遇到yes/no时 自动yes yum install redis -y 3.查看redis安装的位置 whereis redis 4.打开配置文件 vim /etc/redis.config 5.修改密码 在打开的文件中输入 /requirepass 后按下确认键&#xff0c;(找下一个关…

JVM虚拟机:JVM参数之标配参数

本文重点 本文我们将学习JVM中的标配参数 标配参数 从jdk刚开始就有的参数&#xff0c;比如&#xff1a; -version -help -showversion

[笔记]dubbo发送接收

公司需要使用java技术栈接入一套自定义的通讯协议&#xff0c;所以参考下dubbo的实现原理。 consumer 主要使用ThreadlessExecutor实现全consumer的全双工通讯。consumer创建本次请求的requestId用于将response和request匹配。 然后分以下几步完成一次请求发送并接收结果&…

试用 Windows Terminal 中的 Terminal Chat 功能

文章目录 1. 引言2. 设置 Terminal Chat2.1 安装 Windows Terminal Canary2.2 设置服务地址和密钥 3. 使用 Terminal Chat3.1 打开聊天3.2 对话使用 4. 最后 1. 引言 最近&#xff0c;Windows Terminal Canary 推出了一项名为 Terminal Chat 的新功能&#xff0c;它允许用户在…

c语言常见面试题(持续更新)

八股文的意义在于&#xff0c;如果你真正理解这些八股&#xff0c;那么你的编程语言才达到了入门级别&#xff0c;如果你不懂&#xff0c;你绝对还没有入门编程语言&#xff0c;也就是说在接下来的工作中&#xff0c;受限于基础的薄弱&#xff0c;你的工作进展会非常的慢&#…

在cmd下查看mysql表的结构信息

我提前已经在mysql数据库中创建了一个表&#xff1a; 在cmd下&#xff0c;登录mysql以后&#xff0c;使用命令describe 表名、或者explain 表名可以查看表结构信息。但在实践中&#xff0c;查看表结构&#xff0c;多用describe命令&#xff0c;而查看执行计划用explain。 例…

linux 手动安装移植 haveged,解决随机数初始化慢的问题

文章目录 1、问题描述2、安装 haveged3、问题解决4、将安装好的文件跟库移植到开发板下 Haveged是一个软件工具&#xff0c;用于生成高质量的熵&#xff08;Entropy&#xff09;源&#xff0c;以供计算机系统使用。熵在计算机科学中指的是一种随机性或不可预测性的度量&#xf…

服装行业中小企业零售数字化转型的工作目标和主要实施路径|徐礼昭

目标1&#xff1a;实现“人、货、场”的在线化和经营数字化 实施路径&#xff1a;中小企业可以选择商派的微信小程序商城系统&#xff0c;结合导购助手小程序&#xff0c;实现业务在线化&#xff0c;导购在线化&#xff0c;通过微信公众号、企微社群和视频号&#xff0c;开展私…

阿里云域名解析到非默认端口处理方式

1.需配置两条解析记录&#xff0c;如下图 2.第一条配置A记录&#xff0c;ip指向部署服务器 3.第二条配置隐形记录&#xff0c;指向第一条的网址&#xff0c;并附带端口号&#xff0c;最终访问第二条的网址就不用带非默认端口号了。 4.最终浏览器访问

<软考>软件设计师-1计算机组成与结构(总结)

(一)计算机系统基础知识 1 计算机硬件组成 计算机的基本硬件系统由运算器、控制器、存储器、输入设备 和 输出设备 5大部件组成。 1 运算器、控制器等部件被集成在一起统称为中央处理单元(CPU) 。CPU是硬件系统的核心&#xff0c;用于数据的加工处理&#xff0c;能完成各种算…

第十五篇红队笔记-百靶精讲之Nullbyte-exiftool图片-hydra表单-john md5-sql大小马-CVE-2021-4034

nmap信息收集 web渗透 目录爆破 源码无发现&#xff0c;下载静态资源look 可能是ssh密码&#xff0c;可能是mysql密码&#xff0c;最后是web路由 hydra暴力破解web表单 确定是需要的登陆和不需要验证码的表单 SQL注入 数据库猜解-布尔类型 手动 测试字段个数 数据库…

基于 Python+flask 构建态势感知系统(附完整源码)

一、开发 一个基于linux的态势感知系统&#xff0c;基于python和flask框架开发&#xff0c;项目文件目录如下&#xff1a; admin -核心算法 charts -图表生成 model -类 app.py -主文件 config.py -配置文件 install.py -安装文件 二、安装 1、配置 数据库密码默认设…

c++异常介绍

一 . C语言传统的处理错误的方式 1. 终止程序&#xff0c;如assert&#xff0c;缺陷&#xff1a;用户难以接受。如发生内存错误&#xff0c;除0错误时就会终止程序。2. 返回错误码&#xff0c;缺陷&#xff1a;需要程序员自己去查找对应的错误。 二 . C异常概念及使用 当一个…

Redis--11--Redis事务的理解

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Redis事务事务回滚机制Redis 事务是不支持回滚的&#xff0c;不像 MySQL 的事务一样&#xff0c;要么都执行要么都不执行&#xff1b; Redis的事务原理 Redis事务 …

【Python表白系列】制作一个无法拒绝的表白界面(完整代码)

运行时弹出界面 当点击“不要”时弹出 当点击“”时弹出 文章目录 环境需求完整代码详细分析系列文章 环境需求 python3.11.4PyCharm Community Edition 2023.2.5pyinstaller6.2.0&#xff08;可选&#xff0c;这个库用于打包&#xff0c;使程序没有python环境也可以运行&…

【开源存储】glusterfs分布式文件系统部署实践

文章目录 一、前言1、介绍说明2、术语说明3、冗余模式3.1、复制卷&#xff08;Replication&#xff09;3.2、纠删卷&#xff08;Erasure Code&#xff09; 二、部署说明1、软件安装2、集群部署2.1、前置准备2.2、部署过程a、添加节点b、配置存储c、创建glusterfs卷d、客户端挂载…

【同济大学主办】第七届先进算法与控制工程国际学术会议(ICAACE 2024)

第七届先进算法与控制工程国际学术会议&#xff08;ICAACE 2024&#xff09; 2024 7th International Conference on Advanced Algorithms and Control Engineering 第七届先进算法与控制工程国际学术会议&#xff08;ICAACE 2024&#xff09;定于2024年1月26-28日在中国上…

Android12蓝牙框架

参考&#xff1a; https://evilpan.com/2021/07/11/android-bt/ https://source.android.com/docs/core/connect/bluetooth?hlzh-cn https://developer.android.com/guide/topics/connectivity/bluetooth?hlzh-cn https://developer.android.com/guide/components/intents-fi…

适用于 Windows的U盘/硬盘数据恢复软件前 10 名列表

您是否正在寻找适用于 Windows 的最佳笔式驱动器数据恢复软件&#xff1f;是这样吗&#xff0c;那么这里我们列出了 10 款 USB 恢复工具&#xff0c;用于从 USB 闪存驱动器中检索丢失的数据。有多种工具可以帮助用户从笔式驱动器或 USB 闪存驱动器恢复永久删除、丢失、损坏和格…

Beta冲刺随笔-DAY6-橘色肥猫

这个作业属于哪个课程软件工程A这个作业要求在哪里团队作业–站立式会议Beta冲刺作业目标记录Beta冲刺Day6团队名称橘色肥猫团队置顶集合随笔链接Beta冲刺笔记-置顶-橘色肥猫-CSDN博客 文章目录 SCRUM部分站立式会议照片成员描述 PM报告项目程序&#xff0f;模块的最新运行图片…