【黑马点评学习笔记 | 实战篇 】| 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);  
}

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

相关推荐
心静财富之门34 分钟前
Flask 详细讲解 + 实战实例(零基础可学)
后端·python·flask
大鸡腿同学8 小时前
【成长类】《只有偏执狂才能生存》读书笔记:程序员的偏执型成长地图
后端
0xDevNull8 小时前
MySQL数据冷热分离详解
后端·mysql
一定要AK8 小时前
Spring 入门核心笔记
java·笔记·spring
AI成长日志8 小时前
【Agentic RL】1.1 什么是Agentic RL:从传统RL到智能体学习
人工智能·学习·算法
AI袋鼠帝8 小时前
OpenClaw(龙虾)最强开源对手!Github 40K Star了,又一个爆火的Agent..
后端
_李小白9 小时前
【OSG学习笔记】Day 38: TextureVisitor(纹理访问器)
android·笔记·学习
新知图书9 小时前
搭建Spring Boot开发环境
java·spring boot·后端
杨云龙UP9 小时前
从0到1快速学会Linux操作系统(基础),这一篇就够了!
linux·运维·服务器·学习·ubuntu·centos·ssh
宸津-代码粉碎机9 小时前
Spring Boot 4.0虚拟线程实战调优技巧,最大化发挥并发优势
java·人工智能·spring boot·后端·python