# tensquare_parent **Repository Path**: sinclairdong/tensquare_parent ## Basic Information - **Project Name**: tensquare_parent - **Description**: 黑马十次方项目实战课程 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2023-07-28 - **Last Updated**: 2023-07-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 黑马十字方课程 ## 技术选型 后端:springboot + springcloud + mybatis plus + mysql5.7 前端:nodejs + NUXT + elementUI + vue ## 分布式ID生成器 使用snowflake (雪花)算法(twitter出品)生成 的主键值 注册到启动类去使用 ~~~java @Bean public IdWorker createIdWorker() { return new IdWorker(1, 1); } ~~~ ## 多环境切换 在大型开发系统中,伴随着测试、生产、开发多种环境下,一个配置文件来回更换里面的配置显然对于开发者极其不便。所以springboot自带切换的功能 ~~~yml spring: profiles: active: dev ~~~ 在resources目录下创建`application-dev.yml`,他会自动识别并切换!properties同理! ## 分页条件查询 `两个知识点做一起讲了` mybatisplus集成分页功能 ~~~java import com.baomidou.mybatisplus.plugins.PaginationInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyBatisPlusConfig { @Bean public PaginationInterceptor createPaginationInterceptor() { return new PaginationInterceptor(); } } ~~~ 设置分页,`selectPage` ~~~java //设置分页参数 Page
pageData = new Page<>(page, size); //第一个是分页参数,第二个是查询条件 List
list = articleDao.selectPage(pageData, wrapper); ~~~ 条件查询 使用核心类`EntityWrapper`,泛型是对应的实体类!这里有一点要说明的就是逻辑判断的问题,当传入参数为空时,mybatis有个if标签可以判断,而在mp当中这里可以自己使用if来判断,但是这样我们会觉得很麻烦。mp内部自己给我们重载了一个方法,来简化这个操作! ~~~java public Wrapper eq(boolean condition, String column, Object params) { if (condition) { this.sql.WHERE(this.formatSql(String.format("%s = {0}", column), params)); } return this; } ~~~ 本示例: ~~~java EntityWrapper
wrapper = new EntityWrapper<>(); Set keys = map.keySet(); for (String key : keys) { wrapper.eq(map.get(key) != null, key, map.get(key)); } ~~~ 从前端传入的map里获取到key,然后遍历key,一边遍历,一边去判断传入的value是否为空,如果是空,则省略,所以他等价于下面的写法 ~~~java // if (map.get(key) != null) { // wrapper.eq(key, map.get(key)); // } ~~~ ## 用户点赞评论 需求:当用户点赞时,给当前评论的点赞数加一 注意:需要保证每个用户不能重复点赞! 使用mongo inc自增特性,使用redis做唯一性判断! ~~~java public void thumbup(String commentId) { //点赞功能优化 //封装修改的条件 Query query = new Query(); query.addCriteria(Criteria.where("_id").is(commentId)); //封装修改的数值 Update update = new Update(); //使用inc列值增长 update.inc("thumbup", 1); //直接修改数据 //第一个参数是修改的条件 //第二个参数是修改的数值 //第三个参数是MongoDB的集合名称 mongoTemplate.updateFirst(query, update, "comment"); } ~~~ mongdb的使用比较像JPA,他的条件构造也是使用的`Query`,inc是他的默认函数,在当前基础增加,自增在方法里设置是1,`updateFirst`里面的参数分别是修改条件,修改值,集合名! > 这里就会出现我们一开始讨论的问题了,用户重复点赞怎么办呢?怎么去保证每个用户只点一次,我们第一想到的就是redis! 首先我们要协定好一个key,用户每次点赞的成功之后要把这个key,存入redis!这样,每次访问接口的时候先去判断redis里面有没有这个key,如果有那么就说明他应该点过赞了,就返回重复提示~~ ~~~java //PUT /comment/thumbup/{commentId} 根据评论id点赞评论 @RequestMapping(value = "thumbup/{commentId}", method = RequestMethod.PUT) public Result thumbup(@PathVariable String commentId) { //把用户点赞信息保存到Redis中 //每次点赞之前,先查询用户点赞信息 //如果没有点赞信息,用户可以点赞 //如果有点赞信息,用户不能重复点赞 //模拟用户id String userId = "123"; //查询用户点赞信息,根据用户id和评论id Object flag = redisTemplate.opsForValue().get("thumbup_" + userId + "_" + commentId); //判断查询到的结果是否为空 if (flag == null) { //如果为空,表示用户没有点过赞,可以点赞 commentService.thumbup(commentId); //点赞成功,保存点赞信息 redisTemplate.opsForValue().set("thumbup_" + userId + "_" + commentId, String.valueOf(1)); return new Result(true, StatusCode.OK, "点赞成功"); } //如果不为空,表示用户点过赞,不可以重复点赞 return new Result(false, StatusCode.REPERROR, "不能重复点赞"); } ~~~