【黑马头条】-day09用户行为-点赞收藏关注阅读不喜欢-数据回显-精度丢失解决



1 long类型精度丢失问题

在这里插入图片描述

在数据库与网络传输的long类型的id传输中,long类型的id发生了精度丢失

1.1 解决

在这里插入图片描述

  • 当后端响应给前端的数据中包含了id或者特殊标识(可自定义)的时候,把当前数据进行转换为String类型
  • 当前端传递后后端的dto中有id或者特殊标识(可自定义)的时候,把当前数据转为Integer或Long类型。

特殊标识类说明:

IdEncrypt 自定义注解 作用在需要转换类型的字段属性上,用于非id的属性上 在model包下

1.2 导入jackson序列化工具

将jackson序列化工具导入heima-leadnews-common模块下的com.heima.common.jackson

在这里插入图片描述

因为是外来复制进来的,要想让spring进行管理,就需要将配置类导入src/main/resources/META-INF/spring.factories中

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.heima.common.exception.ExceptionCatch,\
  com.heima.common.aliyun.GreenTextScan,\
  com.heima.common.aliyun.GreenImageScan,\
  com.heima.common.tess4j.Tess4jClient,\
  com.heima.common.redis.CacheService,\
  com.heima.common.jackson.InitJacksonConfig

1.3 自定义注解

将配置导入spring后,发现有个注解找不到

在这里插入图片描述

需要导入自定义注解

导入自定义注解到heima-leadnews-model模块中的com.heima.model.common.annotation.IdEncrypt

@JacksonAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
public @interface IdEncrypt {
}

1.4 原理

在heima-leadnews-common模块下的com.heima.common.jackson.ConfusionSerializerModifier类中

public class ConfusionSerializerModifier extends BeanSerializerModifier {

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
                                                     BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
        List<BeanPropertyWriter> newWriter = new ArrayList<>();
        for(BeanPropertyWriter writer : beanProperties){
            String name = writer.getType().getTypeName();
            if(null == writer.getAnnotation(IdEncrypt.class) && !writer.getName().equalsIgnoreCase("id")){
                newWriter.add(writer);
            } else {
                writer.assignSerializer(new ConfusionSerializer());
                newWriter.add(writer);
            }
        }
        return newWriter;
    }
}

if(null == writer.getAnnotation(IdEncrypt.class) && !writer.getName().equalsIgnoreCase("id"))

如果是被IdEncrypt注解标注的或者为id字段的则被自动转为字符串序列化。

1.5 测试

重启heima-leadnews-artcile微服务

在这里插入图片描述

id已经加上双引号,转为字符串也就不会有精度丢失了。

2 用户行为要求

  • 所有的行为数据,都存储到redis中
  • 点赞、阅读、不喜欢需要专门创建一个微服务来处理数据,新建模块:heima-leadnews-behavior
  • 关注需要在heima-leadnews-user微服务中实现
  • 收藏与文章详情数据回显在heima-leadnews-article微服务中实现

3 创建微服务behavior

3.1 微服务创建

创建微服务heima-leadnews-behavior

在这里插入图片描述

3.2 添加启动类

@SpringBootApplication
public class BehaviorAppliction {
    public static void main(String[] args) {
        SpringApplication.run(BehaviorAppliction.class, args);
    }
}

3.3 创建bootstrap.yml

创建bootstrap.yml配置nacos

server:
  port: 51806
spring:
  application:
    name: leadnews-behavior
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.204.129:8848
      config:
        server-addr: 192.168.204.129:8848
        file-extension: yml

3.4 在nacos中配置redis

在nacos中创建leadnews-behavior配置中心,配置redis

因为文章相应的点赞收藏需要操作数据库,所以也需要配置数据库信息。

spring:
  redis:
    host: 192.168.204.129
    password: leadnews
    port: 6379
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/leadnews_admin?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
    username: root
    password: 123sjbsjb
minio:
  accessKey: minio
  secretKey: minio123
  bucket: leadnews
  endpoint: http://192.168.204.129:9000
  readPath: http://192.168.204.129:9000

3.5 引入redis依赖

为heima-leadnews-behavior模块引入redis依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis依赖commons-pool 这个依赖一定要添加 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

因为在之间已经将redis的工具类CacheService放入heima-leadnews-common的com.heima.common.redis下,并且交由spring管理,所以其他微服务可以直接注入CacheService使用redis。

3.6 更新minio

因为要进行回显,所以需要对静态html的文件在每次更新后进行重新生成静态文件。

在heima-leadnews-article模块中的com.heima.article.test中编写一个ArticleFreemarkerTest测试类,用于重新加载所有文件的minio的静态地址

@SpringBootTest(classes= ArticleApplication.class)
@RunWith(SpringRunner.class)
public class ArticleFreemarkerTest {
    @Autowired
    private ApArticleContentMapper apArticleContentMapper;
    @Autowired
    private Configuration configuration;
    @Autowired
    private FileStorageService fileStorageService;
    @Autowired
    private ApArticleService apArticleService;
    @Test
    public void testAllFreemarker() throws Exception {
        //1.获取所有文章id
        ApArticle apArticle = new ApArticle();
        List<ApArticle> apArticles = apArticleService.list();
        for (ApArticle article : apArticles) {
            //2.获取文章内容
            ApArticleContent apArticleContent = apArticleContentMapper
                    .selectOne(Wrappers
                            .<ApArticleContent>lambdaQuery()
                            .eq(ApArticleContent::getArticleId, article.getId()));
            if(apArticleContent!=null&& StringUtils.isNotBlank(apArticleContent.getContent())){
                //3.文章内容通过freemarker生成静态html页面
                Template template = configuration.getTemplate("article.ftl");
                //3.1 创建模型
                Map<String,Object> content=new HashMap();
                content.put("content", JSONArray.parseArray(apArticleContent.getContent()));
                //3.2 输出流
                StringWriter writer = new StringWriter();
                //3.3 合成方法
                template.process(content,writer);
                //4.把静态页面上传到minio
                //4.1 文件流
                InputStream inputStream = new ByteArrayInputStream(writer.toString().getBytes());
                String path = fileStorageService.uploadHtmlFile("",apArticleContent.getArticleId()+".html",inputStream);
                //5.把静态页面的路径保存到数据库
                apArticleService.update(Wrappers
                        .<ApArticle>lambdaUpdate()
                        .eq(ApArticle::getId,apArticleContent.getArticleId())
                        .set(ApArticle::getStaticUrl,path));
            }
        }
    }
}

在这里插入图片描述

4 点赞

接口地址:/api/v1/likes_behavior

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueLikesBehaviorDtoLikesBehaviorDto
  articleId文章idfalselong
  operation0 点赞 1 取消点赞falseshort
  type0文章 1动态 2评论falseshort

4.1 实体类LikesBehaviorDto

在heima-leadnews-model中创建com.heima.model.behavior.dtos.LikesBehaviorDto类

@Data
public class LikesBehaviorDto {


    // 文章、动态、评论等ID
    Long articleId;
    /**
     * 喜欢内容类型
     * 0文章
     * 1动态
     * 2评论
     */
    Short type;

    /**
     * 喜欢操作方式
     * 0 点赞
     * 1 取消点赞
     */
    Short operation;
}

4.2 Redis的Hash值

在heima-leadnew-common中创建com.heima.common.constants.BehaviorConstants类,用于保存key

public class BehaviorConstants {

    public static final String LIKE_BEHAVIOR="LIKE-BEHAVIOR-";
    public static final String UN_LIKE_BEHAVIOR="UNLIKE-BEHAVIOR-";
    public static final String COLLECTION_BEHAVIOR="COLLECTION-BEHAVIOR-";
    public static final String READ_BEHAVIOR="READ-BEHAVIOR-";
    public static final String APUSER_FOLLOW_RELATION="APUSER-FOLLOW-";
    public static final String APUSER_FANS_RELATION="APUSER-FANS-";
}

4.3 用拦截器保存获取当前用户

在heima-leadnews-behavior中创建com.heima.behavior.interceptor.AppTokenInterceptor类

public class AppTokenInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String userId = request.getHeader("userId");
        if(userId != null){
            //存入到当前线程中
            ApUser apUser = new ApUser();
            apUser.setId(Integer.valueOf(userId));
            AppThreadLocalUtil.setUser(apUser);

        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        AppThreadLocalUtil.clear();
    }
}

创建com.heima.behavior.config.WebMvcConfig将拦截器AppTokenInterceptor加入当前拦截器注册器里

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AppTokenInterceptor()).addPathPatterns("/**");
    }
}

4.4 Controller

在heima-leadnews-behavior中创建com.heima.behavior.controller.v1.ApLikesBehaviorController

@RestController
@RequestMapping("/api/v1/likes_behavior")
public class ApLikesBehaviorController {

    @Autowired
    private ApLikesBehaviorService apLikesBehaviorService;

    @PostMapping
    public ResponseResult like(@RequestBody LikesBehaviorDto dto) {
        return apLikesBehaviorService.like(dto);
    }
}

4.5 Serivce

接口

public interface ApLikesBehaviorService {

    /**
     * 存储喜欢数据
     * @param dto
     * @return
     */
    public ResponseResult like(LikesBehaviorDto dto);
}

实现

@Service
@Transactional
@Slf4j
public class ApLikesBehaviorServiceImpl implements ApLikesBehaviorService {

    @Autowired
    private CacheService cacheService;

    @Override
    public ResponseResult like(LikesBehaviorDto dto) {

        //1.检查参数
        if (dto == null || dto.getArticleId() == null || checkParam(dto)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2.是否登录
        ApUser user = AppThreadLocalUtil.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //3.点赞  保存数据
        if (dto.getOperation() == 0) {
            Object obj = cacheService.hGet(BehaviorConstants.LIKE_BEHAVIOR + dto.getArticleId().toString(), user.getId().toString());
            if (obj != null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "已点赞");
            }
            // 保存当前key
            log.info("保存当前key:{} ,{}, {}", dto.getArticleId(), user.getId(), dto);
            cacheService.hPut(BehaviorConstants.LIKE_BEHAVIOR + dto.getArticleId().toString(), user.getId().toString(), JSON.toJSONString(dto));
        } else {
            // 删除当前key
            log.info("删除当前key:{}, {}", dto.getArticleId(), user.getId());
            cacheService.hDelete(BehaviorConstants.LIKE_BEHAVIOR + dto.getArticleId().toString(), user.getId().toString());
        }


        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);

    }

    /**
     * 检查参数
     *
     * @return
     */
    private boolean checkParam(LikesBehaviorDto dto) {
        if (dto.getType() > 2 || dto.getType() < 0 || dto.getOperation() > 1 || dto.getOperation() < 0) {
            return true;
        }
        return false;
    }
}

4.6 测试

启动微服务

在这里插入图片描述

先登录获取token

在这里插入图片描述

获取token为

eyJhbGciOiJIUzUxMiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAADWLQQqAMAwE_5KzhcZGI_4mpRUrCIVUUMS_Gw_uaYdhbthagRkWsiUUF8kvjqbRuzhycP3UJ-JMiAmhgyINZmQMyJ6H0IEe0Wq9tOX986qGay67GMmRjKRW-_msf0nhK4s5el4Gao0hgAAAAA.GnAVSmGCq388UxNUJVSr87uSfrQ6QSD0RmRtfeDDvhMecu5Ylj_KSOAR29H40rFi5L-Fzhd2kRkj5ZxQTBpyEQ

找一个文章点赞

在这里插入图片描述

点赞一下这个文章吧 id 1778978497432260609

请求地址http://localhost:51601/behavior/api/v1/likes_behavior

请求体:0是点赞

{
    "articleId": 1778978497432260609,
    "operation": 0,
    "type": 0
}

把刚刚的token添加到headers中

在这里插入图片描述

发送post请求

在这里插入图片描述

请求成功,查看redis

在这里插入图片描述

成功保存

5 阅读

接口地址:/api/v1/read_behavior

请求方式:POST

参数名称参数说明in是否必须
dtodtobodytrue
  articleId文章idlongfalse
  count阅读次数intfalse

5.1 实体类ReadBehaviorDto

在heima-leadnews-model中创建com.heima.model.behavior.dtos.ReadBehaviorDto类

@Data
public class ReadBehaviorDto {

    // 文章、动态、评论等ID
    Long articleId;

    /**
     * 阅读次数
     */
    Short count;
}

5.2 Controller

在heima-leadnews-behavior中创建com.heima.behavior.controller.v1.ApReadBehaviorController

@RestController
@RequestMapping("/api/v1/read_behavior")
public class ApReadBehaviorController {

    @Autowired
    private ApReadBehaviorService apReadBehaviorService;

    @PostMapping
    public ResponseResult readBehavior(@RequestBody ReadBehaviorDto dto) {
        return apReadBehaviorService.readBehavior(dto);
    }
}

5.3 Service

接口

public interface ApReadBehaviorService {

    /**
     * 保存阅读行为
     * @param dto
     * @return
     */
    public ResponseResult readBehavior(ReadBehaviorDto dto);
}

实现

@Service
@Transactional
@Slf4j
public class ApReadBehaviorServiceImpl implements ApReadBehaviorService {

    @Autowired
    private CacheService cacheService;

    @Override
    public ResponseResult readBehavior(ReadBehaviorDto dto) {
        //1.检查参数
        if (dto == null || dto.getArticleId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2.是否登录
        ApUser user = AppThreadLocalUtil.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //更新阅读次数
        String readBehaviorJson = (String) cacheService.hGet(BehaviorConstants.READ_BEHAVIOR + dto.getArticleId().toString(), user.getId().toString());
        if (StringUtils.isNotBlank(readBehaviorJson)) {
            ReadBehaviorDto readBehaviorDto = JSON.parseObject(readBehaviorJson, ReadBehaviorDto.class);
            dto.setCount((short) (readBehaviorDto.getCount() + dto.getCount()));
        }
        // 保存当前key
        log.info("保存当前key:{} {} {}", dto.getArticleId(), user.getId(), dto);
        cacheService.hPut(BehaviorConstants.READ_BEHAVIOR + dto.getArticleId().toString(), user.getId().toString(), JSON.toJSONString(dto));
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);

    }
}

5.4 测试

请求体

{
    "articleId": 1778978497432260609,
    "count": 10
}

在这里插入图片描述

查看redis

在这里插入图片描述

6 不喜欢

接口地址:/api/v1/un_likes_behavior

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueUnLikesBehaviorDtoUnLikesBehaviorDto
  articleId文章idfalselong
  type0 不喜欢 1 取消不喜欢falseshort

6.1 实体类UnLikesBehaviorDto

在heima-leadnews-model中创建com.heima.model.behavior.dtos.UnLikesBehaviorDto类

@Data
public class UnLikesBehaviorDto {
    // 文章ID
    @IdEncrypt
    Long articleId;

    /**
     * 不喜欢操作方式
     * 0 不喜欢
     * 1 取消不喜欢
     */
    Short type;

}

6.2 Controller

在heima-leadnews-behavior中创建com.heima.behavior.controller.v1.ApUnlikesBehaviorController

@RestController
@RequestMapping("/api/v1/un_likes_behavior")
public class ApUnlikesBehaviorController {

    @Autowired
    private ApUnlikesBehaviorService apUnlikesBehaviorService;

    @PostMapping
    public ResponseResult unLike(@RequestBody UnLikesBehaviorDto dto) {
        return apUnlikesBehaviorService.unLike(dto);
    }
}

6.3 Service

接口

public interface ApUnlikesBehaviorService {

    /**
     * 不喜欢
     * @param dto
     * @return
     */
    public ResponseResult unLike(UnLikesBehaviorDto dto);

}

实现

@Slf4j
@Service
public class ApUnlikesBehaviorServiceImpl implements ApUnlikesBehaviorService {

    @Autowired
    private CacheService cacheService;

    @Override
    public ResponseResult unLike(UnLikesBehaviorDto dto) {

        if (dto.getArticleId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        ApUser user = AppThreadLocalUtil.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        if (dto.getType() == 0) {
            log.info("保存当前key:{} ,{}, {}", dto.getArticleId(), user.getId(), dto);
            cacheService.hPut(BehaviorConstants.UN_LIKE_BEHAVIOR + dto.getArticleId().toString(), user.getId().toString(), JSON.toJSONString(dto));
        } else {
            log.info("删除当前key:{} ,{}, {}", dto.getArticleId(), user.getId(), dto);
            cacheService.hDelete(BehaviorConstants.UN_LIKE_BEHAVIOR + dto.getArticleId().toString(), user.getId().toString());
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}

6.4 测试

请求体

{
    "articleId": 1778978497432260609,
    "type": 0
}

在这里插入图片描述

查看redis

在这里插入图片描述

7 关注与取消关注

接口地址:/api/v1/user/user_follow

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueUserRelationDtoUserRelationDto
  articleId文章idfalselong
  authorId作者idfalseint
  operation0 关注 1 取消falseshort

关注需要在heima-leadnews-user微服务中实现

7.1 实体类UserRelationDto

在heima-leadnews-model中创建com.heima.model.user.dtos.UserRelationDto类

@Data
public class UserRelationDto {

    // 文章作者ID
    @IdEncrypt
    Integer authorId;

    // 文章id
    @IdEncrypt
    Long articleId;
    /**
     * 操作方式
     * 0  关注
     * 1  取消
     */
    Short operation;
}

7.2 Controller

在heima-leadnews-user中创建com.heima.user.controller.v1.UserRelationController类

@RestController
@RequestMapping("/api/v1/user")
public class UserRelationController {

    @Autowired
    private ApUserRelationService apUserRelationService;
  
    @PostMapping("/user_follow")
    public ResponseResult follow(@RequestBody UserRelationDto dto){
        return apUserRelationService.follow(dto);
    }
}

7.3 Service

接口

public interface ApUserRelationService {
    /**
     * 用户关注/取消关注
     * @param dto
     * @return
     */
    public ResponseResult follow(UserRelationDto dto);
}

实现

@Service
public class ApUserRelationServiceImpl implements ApUserRelationService {

    @Autowired
    private CacheService cacheService;


    /**
     * 用户关注/取消关注
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult follow(UserRelationDto dto) {
        //1 参数校验
        if (dto.getOperation() == null || dto.getOperation() < 0 || dto.getOperation() > 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2 判断是否登录
        ApUser user = AppThreadLocalUtil.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer apUserId = user.getId();

        //3 关注 apuser:follow:  apuser:fans:
        Integer followUserId = dto.getAuthorId();
        if (dto.getOperation() == 0) {
            // 将对方写入我的关注中
            cacheService.zAdd(BehaviorConstants.APUSER_FOLLOW_RELATION + apUserId, followUserId.toString(), System.currentTimeMillis());
            // 将我写入对方的粉丝中
            cacheService.zAdd(BehaviorConstants.APUSER_FANS_RELATION+ followUserId, apUserId.toString(), System.currentTimeMillis());

        } else {
            // 取消关注
            cacheService.zRemove(BehaviorConstants.APUSER_FOLLOW_RELATION + apUserId, followUserId.toString());
            cacheService.zRemove(BehaviorConstants.APUSER_FANS_RELATION + followUserId, apUserId.toString());
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);

    }
}

7.4 测试

当前登录的用户id是4

在这里插入图片描述

关注文章的作者id是1102

在这里插入图片描述

请求体:

{
    "articleId": 1778978497432260609,
    "authorId": 1102,
    "operation": 0
}

在这里插入图片描述

查看redis,写入成功

在这里插入图片描述

8 文章收藏

收藏与文章详情数据回显在heima-leadnews-article微服务中实现

接口地址:/api/v1/collection_behavior

请求方式:POST

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueCollectionBehaviorDtoCollectionBehaviorDto
  entryId文章idfalselong
  operation0收藏 1取消收藏falseshort
  publishedTime发布时间falsedate
  type0文章 1动态falseshort

8.0 为文章微服务配置redis

在文章微服务的nacos配置中添加redis配置

redis:
    host: 192.168.204.129
    password: leadnews
    port: 6379

8.1 实体类CollectionBehaviorDto

在heima-leadnews-model中创建com.heima.model.article.dtos.CollectionBehaviorDto类

@Data
public class CollectionBehaviorDto {

    // 文章、动态ID
    @IdEncrypt
    Long entryId;
    /**
     * 收藏内容类型
     * 0文章
     * 1动态
     */
    Short type;

    /**
     * 操作类型
     * 0收藏
     * 1取消收藏
     */
    Short operation;

    Date publishedTime;

}

8.2 Controller

在heima-leadnews-user中创建com.heima.article.controller.v1.ApCollectionController类

@RestController
@RequestMapping("/api/v1/collection_behavior")
public class ApCollectionController {

    @Autowired
    private ApCollectionService apCollectionService;


    @PostMapping
    public ResponseResult collection(@RequestBody CollectionBehaviorDto dto) {
        return apCollectionService.collection(dto);
    }
}

8.3 Service

接口

public interface ApCollectionService {

    /**
     * 收藏
     * @param dto
     * @return
     */
    public ResponseResult collection(CollectionBehaviorDto dto);
}

实现

@Service
@Slf4j
public class ApCollectionServiceImpl implements ApCollectionService {

    @Autowired
    private CacheService cacheService;

    @Override
    public ResponseResult collection(CollectionBehaviorDto dto) {
        //条件判断
        if(dto == null || dto.getEntryId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //判断是否登录
        ApUser user = AppThreadLocalUtil.getUser();
        if(user == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //查询
        String collectionJson = (String) cacheService.hGet(BehaviorConstants.COLLECTION_BEHAVIOR + user.getId(), dto.getEntryId().toString());
        if(StringUtils.isNotBlank(collectionJson) && dto.getOperation() == 0){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"已收藏");
        }

        //收藏
        if(dto.getOperation() == 0){
            log.info("文章收藏,保存key:{},{},{}",dto.getEntryId(),user.getId().toString(), JSON.toJSONString(dto));
            cacheService.hPut(BehaviorConstants.COLLECTION_BEHAVIOR + user.getId(), dto.getEntryId().toString(), JSON.toJSONString(dto));
        }else {
            //取消收藏
            log.info("文章收藏,删除key:{},{},{}",dto.getEntryId(),user.getId().toString(), JSON.toJSONString(dto));
            cacheService.hDelete(BehaviorConstants.COLLECTION_BEHAVIOR + user.getId(), dto.getEntryId().toString());
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}

8.4 测试

请求体

{
    "entryId": 1778978497432260609,
    "operation": 0,
    "publishedTime": 1712976151,
    "type": 0
}

在这里插入图片描述

查看redis

在这里插入图片描述

9 加载文章行为-数据回显

接口地址:/api/v1/article/load_article_behavior

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueArticleInfoDtoArticleInfoDto
  articleId文章idfalselong
  authorId作者idfalseint

9.1 实体类ArticleInfoDto

@Data
public class ArticleInfoDto {
    // 设备ID
    @IdEncrypt
    Integer equipmentId;
    // 文章ID
    @IdEncrypt
    Long articleId;
    // 作者ID
    @IdEncrypt
    Integer authorId;
}

9.2 Controller

在heima-leadnews-model中创建com.heima.article.controller.v1.ArticleInfoController类

@RestController
@RequestMapping("/api/v1/article")
public class ArticleInfoController {

    @Autowired
    private ApArticleService apArticleService;

    @PostMapping("/load_article_behavior")
    public ResponseResult loadArticleBehavior(@RequestBody ArticleInfoDto dto){
        return apArticleService.loadArticleBehavior(dto);
    }
}

9.3 Service

接口

public interface ApArticleService extends IService<ApArticle>{
    /**
     * 加载文章列表
     * @param dto
     * @param type 1 加载更多 2 加载最新
     * @return
     */
    public ResponseResult load(ArticleHomeDto dto, Short type);

    /**
     * 保存文章
     * @param dto
     * @return
     */
    public ResponseResult saveArticle(ArticleDto dto);

    /**
     * 加载文章详情 数据回显
     * @param dto
     * @return
     */
    public ResponseResult loadArticleBehavior(ArticleInfoDto dto);
}

实现,把所有redis中存储的用户行为做成map返回

@Autowired
private CacheService cacheService;

@Override
public ResponseResult loadArticleBehavior(ArticleInfoDto dto) {

    //0.检查参数
    if (dto == null || dto.getArticleId() == null || dto.getAuthorId() == null) {
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }

    //{ "isfollow": true, "islike": true,"isunlike": false,"iscollection": true }
    boolean isfollow = false, islike = false, isunlike = false, iscollection = false;

    ApUser user = AppThreadLocalUtil.getUser();
    if(user != null){
        //喜欢行为
        String likeBehaviorJson = (String) cacheService.hGet(BehaviorConstants.LIKE_BEHAVIOR + dto.getArticleId().toString(), user.getId().toString());
        if(org.apache.commons.lang3.StringUtils.isNotBlank(likeBehaviorJson)){
            islike = true;
        }
        //不喜欢的行为
        String unLikeBehaviorJson = (String) cacheService.hGet(BehaviorConstants.UN_LIKE_BEHAVIOR + dto.getArticleId().toString(), user.getId().toString());
        if(org.apache.commons.lang3.StringUtils.isNotBlank(unLikeBehaviorJson)){
            isunlike = true;
        }
        //是否收藏
        String collctionJson = (String) cacheService.hGet(BehaviorConstants.COLLECTION_BEHAVIOR+user.getId(),dto.getArticleId().toString());
        if(org.apache.commons.lang3.StringUtils.isNotBlank(collctionJson)){
            iscollection = true;
        }

        //是否关注
        Double score = cacheService.zScore(BehaviorConstants.APUSER_FOLLOW_RELATION + user.getId(), dto.getAuthorId().toString());
        System.out.println(score);
        if(score != null){
            isfollow = true;
        }

    }

    Map<String, Object> resultMap = new HashMap<>();
    resultMap.put("isfollow", isfollow);
    resultMap.put("islike", islike);
    resultMap.put("isunlike", isunlike);
    resultMap.put("iscollection", iscollection);

    return ResponseResult.okResult(resultMap);
}

9.4 测试

请求体:

{
    "articleId": 1778978497432260609,
    "authorId": 1102
}

针对当前id为4的用户,对1778978497432260609文章已收藏已点赞已不喜欢(感觉怪怪的,虽然点赞和不喜欢并不冲突),对于1102号作者已关注

在这里插入图片描述

测试成功

  • 12
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AAA码农宝哥.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值