【黑马点评学习笔记 | 实战篇 】| 7-达人探店

Bug如山勤为径,代码似海苦作舟。友友们好,这里是苦瓜大王。今天学习的是黑马点评项目实战篇------达人探店部分的学习,进行了一系列秒杀优化之后,终于进入到相对轻松的章节啦!今天我们将完成达人探店功能。笔记如下,后续会一直更新黑马点评学习过程中的笔记、问题等,请多多支持哦!

文章目录

一、发布探店笔记

  • 表分析
  • 接口分析
  • 修改一下保存文件的位置,改成自己的目录,比如我的是D:\nginx-pro\nginx-hmdp-1.18.0\html\hmdp\imgs

二、查看探店笔记

  • 接口分析
  • 给Blog类加上两个属性
java 复制代码
/**  
 * 用户图标  
 */  
@TableField(exist = false) //代表这个属性不属于数据库
private String icon;  
/**  
 * 用户姓名  
 */  
@TableField(exist = false)  
private String name;
  • BlogController代码
java 复制代码
------------------------------------BlogController---------------------------------------
@GetMapping("/hot")  
public Result queryHotBlog(@RequestParam(value = "current", defaultValue = "1") Integer current) {  
    return blogService.queryHotBlog(current);  
}  
@GetMapping("/{id}")  
public Result queryBlogById(@PathVariable("id") Long id) {  
    return blogService.queryBlogById(id);  
}
  • BlogServiceImpl代码
java 复制代码
------------------------------------BlogServiceImpl--------------------------------------
@Resource  
private IUserService userService;  
/**  
 * 查询博文详情  
 * @param id  
 * @return  
 */  
public Result queryBlogById(Long id) {  
    //1.查询blog  
    Blog blog = getById(id);  
    if(blog==null)  
        return Result.fail("该Blog不存在!");  
    queryBlogUser(blog);  
    return Result.ok(blog);  
}  
 /**
  * 查询热点博文
 * @param current  
 * @return 
 **/ 
@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(this::queryBlogUser);  
    return Result.ok(records);  
}  
  
/**  
 * 查询blog用户并封装属性进blog  
 * @param blog  
 */  
private void queryBlogUser(Blog blog) {  
    Long userId = blog.getUserId();  
    User user =  userService.getById(userId);  
    blog.setName(user.getNickName());  
    blog.setIcon(user.getIcon());  
}

三、点赞功能

1.业务思路

2.具体实现

(1)给Blog添加一个isLike字段

java 复制代码
/**  
 * 是否点赞过了  
 */  
@TableField(exist = false)  
private Boolean isLike;

(2)利用Redis的set集合修改点赞功能

java 复制代码
-------------------------------------BlogServiceImpl-------------------------------------
@Resource  
private StringRedisTemplate stringRedisTemplate;
/**  
 * 点赞博文  
 * @param id  
 * @return  
 */  
public Result likeBlog(Long id) {  
    //1.获取登录用户  
    Long userId= UserHolder.getUser().getId();  
    //2.判断当前登录用户是否已经点赞  
    String key = BLOG_LIKED_KEY + 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集合中  
        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集合中移除用户信息  
        if(isSuccess){  
            stringRedisTemplate.opsForSet().remove(key,userId.toString());  
        }  
    }  
    return Result.ok();  
}

(3)修改两个查询Blog的业务,判断赋值isLike字段

  • 增加判断是否点赞过方法
java 复制代码
/**  
 * 判断是否点赞过  
 */  
public void  isLikedBlog(Blog blog){  
    //1.获取登录用户  
    Long userId= UserHolder.getUser().getId();  
    //2.判断当前登录用户是否已经点赞  
    String key = BLOG_LIKED_KEY +blog.getId();  
    Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());  
    blog.setIsLike(BooleanUtil.isTrue(isMember));  
}
  • 修改查询Blog的业务
java 复制代码
/**  
 * 查询博文详情  
 * @param id  
 * @return  
 */  
public Result queryBlogById(Long id) {  
    //1.查询blog  
    Blog blog = getById(id);  
    if(blog==null)  
        return Result.fail("该Blog不存在!");  
    queryBlogUser(blog);  
    islIkeBlog(blog);  
    return Result.ok(blog);  
}  
  
/**  
 * 查询热点博文  
 * @param current  
 * @return  
 */  
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.islIkeBlog(blog);  
    });  
    return Result.ok(records);  
}

小贴士:

  • 要记得修改拦截器配置,把blog/hot拦截了,不然线程不会保存请求的user

四、点赞排行

  • 用查分数的形式,查到就说明存在,查不到就说明不存在

1.用sortedSet改造点赞

(1)改造点赞业务

  • 保存进sortSet
java 复制代码
stringRedisTemplate.opsForZSet().add(key,userId.toString(),System.currentTimeMillis());
  • 删除
java 复制代码
stringRedisTemplate.opsForZSet().remove(key,userId.toString());
  • 查是否存在
java 复制代码
Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
if(score==null) {}
  • 优化后点赞功能整体代码
java 复制代码
/**  
 * 点赞博文  
 * @param id  
 * @return  
 */  
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保存用户信息到sortedSet集合中  
        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集合中移除用户信息  
        if(isSuccess){  
            stringRedisTemplate.opsForZSet().remove(key,userId.toString());  
        }  
    }  
    return Result.ok();  
}

(2)改造查询业务

java 复制代码
Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());  
blog.setIsLike(score!=null);
  • 判断是否点赞过代码
java 复制代码
/**  
 * 判断是否点赞过  
 */  
public void  isLikedBlog(Blog blog){  
    //1.获取登录用户  
    Long userId= UserHolder.getUser().getId();  
    //2.判断当前登录用户是否已经点赞  
    String key = BLOG_LIKED_KEY +blog.getId();  
    Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());  
    blog.setIsLike(score!=null);  
}

2.点赞排行的实现

  • 排行榜的顺序反了,是因为数据库查询的时候用了IN
  • 需要手动指定顺序
  • 对查询继续进行改造
java 复制代码
-----------------------------------queryBlogLikes----------------------------------------
List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());  
String idStr = StrUtil.join(",", ids);  
// 3.根据用户id查询用户 WHERE id IN ( 5 , 1 ) ORDER BY FIELD(id, 5, 1)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());
  • 这里还发现一个小bug,用户在首页没有登陆的时候无需查看是否点过赞
  • 修改isLikedBlog代码
java 复制代码
/**  
 * 判断是否点赞过  
 */  
public void  isLikedBlog(Blog blog){  
    //1.获取登录用户  
    UserDTO userDTO= UserHolder.getUser();  
    if(userDTO==null)  
        //用户未登录,无需查询是否点过赞  
        return;  
    Long userId = userDTO.getId();   
    //2.判断当前登录用户是否已经点赞  
    String key = BLOG_LIKED_KEY +blog.getId();  
    Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());  
    blog.setIsLike(score!=null);  
}
  • 完整代码如下:
java 复制代码
-----------------------------------BlogController----------------------------------------
@GetMapping("/likes/{id}")  
public Result queryBlogLikes(@PathVariable("id") Long id) {  
    return blogService.queryBlogLikes(id);  
}
----------------------------------BlogServiceImpl----------------------------------------
/**  
 * 查询博文点赞排行  
 * @param id  
 * @return  
 */  
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查询用户 WHERE id IN ( 5 , 1 ) ORDER BY FIELD(id, 5, 1)    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);  
}

以上就是黑马点评实战篇------达人探店部分的学习笔记,仅供参考,多多支持!🌹

相关推荐
AI-Ming2 小时前
注意力机制拓展-大模型知识点(程序员转行AI大模型学习)
人工智能·学习
大树学长2 小时前
【QT开发】Redis通信相关(一)
redis·qt
ADHD多动联盟2 小时前
多动症孩子的运动干预是什么?主要有怎样的方法?
学习·学习方法·玩游戏
炽烈小老头2 小时前
【每天学习一点算法 2026/03/20】单词搜索
学习·算法
xiaoxiaoxiaolll2 小时前
最新《Nature Communications》:多元素共生策略为金属材料穿上“抗疲劳铠甲”
学习
weixin_458872612 小时前
东华复试OJ二刷复盘14
学习
元契2 小时前
英语基础语法学习0
学习
常利兵2 小时前
Spring Boot缓存新玩法:一键切换,租户无忧
spring boot·后端·缓存
想你的液宝2 小时前
Spring Boot @RestControllerAdvice:统一异常处理的利器
后端