Java教程

87-day10-app端文章详情开发(点赞 阅读,转发 等行为相关)

本文主要是介绍87-day10-app端文章详情开发(点赞 阅读,转发 等行为相关),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

第十章 app端用户行为处理

目标

  • 能够理解app端的行为记录
  • 能够完成作者关注行为的功能
  • 能够完成文章点赞行为的功能
  • 能够完成文章阅读行为的功能
  • 能够掌握不喜欢和收藏功能的实现思路
  • 能够完成app文章关系展示功能

1 app-用户操作行为记录

用户行为数据的记录包括了关注、点赞、不喜欢、收藏、阅读等行为

这些行为与当前app端的功能实现没有任何关系,即使没有行为数据,功能也不耽误实现,那为什么要做行为数据的保存呢?

黑马头条项目整个项目开发涉及web展示和大数据分析来给用户推荐文章,如何找出哪些文章是热点文章进行针对性的推荐呢?这个时候需要进行大数据分析的准备工作,埋点。

所谓“埋点”,是数据采集领域(尤其是用户行为数据采集领域)的术语,指的是针对特定用户行为或事件进行捕获、处理和发送的相关技术及其实施过程。比如用户某个icon点击次数、阅读文章的时长,观看视频的时长等等。

黑马头条课程里主要涉及到了关注行为,点赞行为,阅读行为的保存。其他类似于不喜欢、收藏功能可根据这些实现的功能自行实现。

1.1 行为微服务搭建

1.1.1 创建行为微服务

处理行为是一个量比较大的操作,所以专门创建一个微服务来处理行为相关操作,参考别的微服务进行搭建即可

1615343452401

创建api:

1615343479035

行为服务中pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>itheima-leadnews-service</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>itheima-leadnews-service-behaviour</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-behaviour-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-common-db</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>itheima-leadnews-core-controller</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

1.1.2 application.yml

spring:
  profiles:
    active: dev
---
server:
  port: 9006
spring:
  profiles: dev
  application:
    name: leadnews-behaviour
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.211.136:8848
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_behaviour?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.behaviour.pojo
logging:
  level.com: debug

---
server:
  port: 9006
spring:
  profiles: test
  application:
    name: leadnews-behaviour
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.211.136:8848
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_behaviour?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.behaviour.pojo
---
server:
  port: 9006
spring:
  profiles: pro
  application:
    name: leadnews-behaviour
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.211.136:8848
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_behaviour?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.behaviour.pojo

1.1.3 启动类

@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(basePackages = "com.itheima.behaviour.mapper")
public class BehaviourApplication {
    public static void main(String[] args) {
        SpringApplication.run(BehaviourApplication.class,args);
    }
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

1.1.4 使用代码生成器生成

通过代码生成器生成pojo,controller,service ,mapper,和xml

1615343907640

生成之后copy到如下目录:

1615343872390

1615343856549

1.2 关注行为

1.2.1 需求分析

​ 在文章详情中,当用户点击了关注作者按钮,需要记录当前行为到表中,目前只需要存储数据即可,后期会做实时的流式处理,根据这些基础数据做热点文章的计算。

1.2.2 思路分析

(1)ap_follow_behavior APP关注行为表

1586442444126

(2)ap_behavior_entry 行为实体表

行为实体指的是使用的终端设备或者是登录的用户,统称为行为实体

type :0终端设备 1用户

行为实体与APP关注行为表是一对多的关系,关注行为需要知道是谁(设备或用户)关注了该文章信息

1600096344635

1586237260586

关注与取消关注的功能已经实现,当用户点击了关注保存关注行为,取消关注不保存数据。

因为只做保存操作,只需要在【关注业务操作】的时候发送消息给行为微服务 【行为微服务】获取消息进行数据保存即可。

实现步骤:

1 用户微服务中关注操作发送消息,保存用户行为

2 行为微服务接收消息

2.1 获取行为实体

2.2 保存数据

1615367605932

1.2.3 功能实现

1.2.3.1 环境搭建

(1)用户微服务添加依赖

<!-- kafka依赖 begin -->
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka-test</artifactId>
    <scope>test</scope>
</dependency>

(2)在用户微服务中搭建kafka的环境

1615344399705

spring:
  profiles:
    active: dev
---
server:
  port: 9002
spring:
  application:
    name: leadnews-user
  profiles: dev
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_user?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
  kafka:
    # 配置连接到服务端集群的配置项 ip:port,ip:port
    bootstrap-servers: 192.168.211.136:9092
    producer:
      batch-size: 16384
      buffer-memory: 33554432
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      retries: 10
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.user.pojo
logging:
  level.com: debug
---
server:
  port: 9002
spring:
  application:
    name: leadnews-user
  profiles: pro
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_user?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
  kafka:
    # 配置连接到服务端集群的配置项 ip:port,ip:port
    bootstrap-servers: 192.168.211.136:9092
    producer:
      batch-size: 16384
      buffer-memory: 33554432
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      retries: 10
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.user.pojo
---
server:
  port: 9002
spring:
  application:
    name: leadnews-user
  profiles: test
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_user?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
  kafka:
    # 配置连接到服务端集群的配置项 ip:port,ip:port
    bootstrap-servers: 192.168.211.136:9092
    producer:
      batch-size: 16384
      buffer-memory: 33554432
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      retries: 10
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.user.pojo

(3)添加依赖到行为服务

<!-- kafka依赖 begin -->
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka-test</artifactId>
    <scope>test</scope>
</dependency>

1615344551783

(4)修改yaml文件:添加kafka消费者:

1615344636957

spring:
  profiles:
    active: dev
---
server:
  port: 9006
spring:
  profiles: dev
  application:
    name: leadnews-behaviour
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.211.136:8848
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_behaviour?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  kafka:
    # 配置连接到服务端集群的配置项 ip:port,ip:port
    bootstrap-servers: 192.168.211.136:9092
    consumer:
      auto-offset-reset: earliest
      group-id: behaviour-consumer-group
      # 默认值即为字符串
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      # 默认值即为字符串
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.behaviour.pojo
logging:
  level.com: debug

---
server:
  port: 9006
spring:
  profiles: test
  application:
    name: leadnews-behaviour
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.211.136:8848
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_behaviour?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  kafka:
    # 配置连接到服务端集群的配置项 ip:port,ip:port
    bootstrap-servers: 192.168.211.136:9092
    consumer:
      auto-offset-reset: earliest
      group-id: behaviour-consumer-group
      # 默认值即为字符串
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      # 默认值即为字符串
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.behaviour.pojo
---
server:
  port: 9006
spring:
  profiles: pro
  application:
    name: leadnews-behaviour
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.211.136:8848
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.211.136:3306/leadnews_behaviour?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  kafka:
    # 配置连接到服务端集群的配置项 ip:port,ip:port
    bootstrap-servers: 192.168.211.136:9092
    consumer:
      auto-offset-reset: earliest
      group-id: behaviour-consumer-group
      # 默认值即为字符串
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      # 默认值即为字符串
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.itheima.behaviour.pojo
1.2.3.2 生产者实现

发送消息需要准备一个FollowBehaviorDto,进行数据的传递

(1)创建dto

package com.itheima.behaviour.dto;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;

@Data
@Setter
@Getter
public class FollowBehaviorDto {
    //文章id
    Long articleId;
    //被关注者 用户ID
    Integer followId;
    //关注者  用户id
    Integer userId;
    //设备ID
    Integer equipmentId;
}

1615346191178

(2)新建常量,固定当前消息的topic

public static final String FOLLOW_BEHAVIOR_TOPIC="follow.behavior.topic";

1615346229671

(3)用户微服务中添加依赖:

<dependency>
    <groupId>com.itheima</groupId>
    <artifactId>itheima-leadnews-behaviour-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

(4)注入KafkaTemplate 并在实现类中发送消息

      FollowBehaviorDto dto = new FollowBehaviorDto();
            //被关注者 用户的ID
            dto.setFollowId(apAuthor.getUserId());
            //文章
            dto.setArticleId(relationDto.getArticleId());
            //关注者 用户的ID
            dto.setUserId(currentUserId);

            kafkaTemplate.send(BusinessConstants.MqConstants.FOLLOW_BEHAVIOR_TOPIC, JSON.toJSONString(dto));

整体代码如下:

package com.itheima.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.article.feign.ApAuthorFeign;
import com.itheima.article.pojo.ApAuthor;
import com.itheima.behaviour.dto.FollowBehaviorDto;
import com.itheima.common.constants.BusinessConstants;
import com.itheima.common.exception.LeadNewsException;
import com.itheima.common.pojo.Result;
import com.itheima.common.pojo.StatusCode;
import com.itheima.common.util.RequestContextUtil;
import com.itheima.user.dto.UserRelationDto;
import com.itheima.user.mapper.ApUserFanMapper;
import com.itheima.user.mapper.ApUserFollowMapper;
import com.itheima.user.pojo.ApUser;
import com.itheima.user.pojo.ApUserFan;
import com.itheima.user.pojo.ApUserFollow;
import com.itheima.user.service.ApUserFollowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
 * <p>
 * APP用户关注信息表 服务实现类
 * </p>
 *
 * @author ljh
 * @since 2021-11-28
 */
@Service
public class ApUserFollowServiceImpl extends ServiceImpl<ApUserFollowMapper, ApUserFollow> implements ApUserFollowService {

    @Autowired
    private ApUserFollowMapper apUserFollowMapper;

    @Autowired
    private ApUserFanMapper apUserFanMapper;

    @Autowired
    private ApAuthorFeign apAuthorFeign;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Override
    public void follow(UserRelationDto relationDto) throws LeadNewsException {

        //判断当前用户是否是匿名用户

        if (RequestContextUtil.isAnonymous()) {
            throw new LeadNewsException(StatusCode.NEED_LOGIN.code(), StatusCode.NEED_LOGIN.message());
        }


        Integer currentUserId = RequestContextUtil.getUserId();

        //先根据页面传递过来的作者的ID 获取到作者的信息(user_id:作者对应的app_user_id,name,id)

        ApAuthor apAuthor = apAuthorFeign.findById(relationDto.getAuthorId()).getData();
        if (apAuthor == null) {
            throw new LeadNewsException("错误");
        }
        if (relationDto.getOperation() == 1) {
            //如果是关注 就添加关注记录

            // 需要先查询 是否有记录 有记录不能添加记录
            QueryWrapper<ApUserFollow> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_id", currentUserId);
            queryWrapper.eq("follow_id", apAuthor.getUserId());
            ApUserFollow apUserFollow1 = apUserFollowMapper.selectOne(queryWrapper);
            if (apUserFollow1 != null) {
                throw new LeadNewsException("已经关注过了");
            }

            // 张三 关注了 李四
            ApUserFollow apUserFollow = new ApUserFollow();
            //张三
            apUserFollow.setUserId(currentUserId);

            //李四
            apUserFollow.setFollowId(apAuthor.getUserId());
            apUserFollow.setFollowName(apAuthor.getName());
            apUserFollow.setLevel(1);//普通的关注
            apUserFollow.setIsNotice(1);
            apUserFollow.setCreatedTime(LocalDateTime.now());
            apUserFollowMapper.insert(apUserFollow);


            //添加粉丝记录
            ApUserFan apUserFan = new ApUserFan();
            //张三

            apUserFan.setFansId(currentUserId);
            apUserFan.setFansName(RequestContextUtil.getRequestUserTokenInfo().getName());

            //李四
            apUserFan.setUserId(apAuthor.getUserId());
            apUserFan.setLevel(1);
            apUserFan.setIsDisplay(0);
            apUserFan.setIsShieldLetter(0);
            apUserFan.setIsShieldComment(0);
            apUserFan.setCreatedTime(LocalDateTime.now());

            apUserFanMapper.insert(apUserFan);

            //发送消息 消息本身:包含 文章的ID  当前的用户的ID(这个是只有用户才能关注,设备是不允许关注的),作者对应的app_user的ID

            //todo
            FollowBehaviorDto dto = new FollowBehaviorDto();
            //被关注者 用户的ID
            dto.setFollowId(apAuthor.getUserId());
            //文章
            dto.setArticleId(relationDto.getArticleId());
            //关注者 用户的ID
            dto.setUserId(currentUserId);

            kafkaTemplate.send(BusinessConstants.MqConstants.FOLLOW_BEHAVIOR_TOPIC, JSON.toJSONString(dto));

        } else {
            //取消关注 删除记录
            //删除 取消关注
            apUserFollowMapper.deleteFollow(currentUserId, apAuthor.getUserId());
            //删除 粉丝记录
            apUserFanMapper.deleteFan(apAuthor.getUserId(), currentUserId);
        }
    }
}

1.2.3.3 消费者实现

步骤:

(1)在行为微服务中实现查询行为实体业务

(2)在行为微服务中实现保存关注行为数据

(3)在行为微服务中创建监听类监听消息 实现业务

(1)在行为微服务中实现查询行为实体业务

1615346531972

@Service
public class ApBehaviorEntryServiceImpl extends ServiceImpl<ApBehaviorEntryMapper, ApBehaviorEntry> implements ApBehaviorEntryService {


    @Override
    public ApBehaviorEntry findByUserIdOrEquipmentId(Integer userId, Integer type) {
        QueryWrapper<ApBehaviorEntry> queryWrapper = new QueryWrapper<ApBehaviorEntry>();
        queryWrapper.eq("entry_id",userId);
        queryWrapper.eq("type",type);//标识用户
        ApBehaviorEntry entry = getOne(queryWrapper);
        return entry;
    }
}

(2)在行为微服务中实现保存关注行为数据

1623684550510

    public static final Integer TYPE_USER = 1;//用户

    public static final Integer TYPE_E = 0;//设备
@Service
public class ApFollowBehaviorServiceImpl extends ServiceImpl<ApFollowBehaviorMapper, ApFollowBehavior> implements ApFollowBehaviorService {

    @Autowired
    private ApBehaviorEntryService apBehaviorEntryService;

    @Override
    public void saveFollowBehavior(FollowBehaviorDto dto) {
        //1.查询行为实体
      ApBehaviorEntry apBehaviorEntry = apBehaviorEntryService.findByUserIdOrEquipmentId(userId, SystemConstants.TYPE_USER);
        if (entry != null) {
            //2.判断 如果行为实体为空 则不做处理
            //3.如果 行为实体有值 则保存关注行为数据
            ApFollowBehavior alb = new ApFollowBehavior();
            //设置实体ID
            alb.setEntryId(entry.getId());
            //设置创建时间
            alb.setCreatedTime(LocalDateTime.now());
            //设置文章的ID
            alb.setArticleId(dto.getArticleId());
            //设置被关注者 用户的ID
            alb.setFollowId(dto.getFollowId());
            save(alb);
        }
    }
}

1615346576710

(3)在行为微服务中创建监听类监听消息 实现业务

@Component
public class FollowBehaviorListener {

    @Autowired
    private ApFollowBehaviorService apFollowBehaviorService;

    //监听消息
    @KafkaListener(topics = BusinessConstants.MqConstants.FOLLOW_BEHAVIOR_TOPIC)
    public void receiverMessage(ConsumerRecord<?,?> record){
        if(record!=null){
            FollowBehaviorDto dto = JSON.parseObject(record.value().toString(), FollowBehaviorDto.class);
            //保存关注行为数据
            apFollowBehaviorService.saveFollowBehavior(dto);
        }
    }
}

(4) 测试

先登录

1615368097836

再关注:

1615368131754

查看:

1615368146847

1.3 点赞行为

1.3.1 需求分析

1586443337731

当前登录的用户点击了”赞“,就要保存当前行为数据

1.3.2 思路分析

1615346692348

当前用户点赞以后保存数据,取消点赞则不删除数据

保存也是根据当前行为实体和文章id进行保存

1.3.3 功能实现

(1)创建dto 用于接收页面传递的参数进行保存点赞行为

@Data
@Setter
@Getter
public class LikesBehaviourDto {
    // 设备ID
    Integer equipmentId;

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

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

1617248752958

(2)controller

@PostMapping("/like")
public Result like(@RequestBody LikesBehaviourDto likesBehaviourDto) throws Exception{
    apLikesBehaviorService.like(likesBehaviourDto);
    return Result.ok();
}

1617248800406

(3)业务层

@Service
public class ApLikesBehaviorServiceImpl extends ServiceImpl<ApLikesBehaviorMapper, ApLikesBehavior> implements ApLikesBehaviorService {

    @Autowired
    private ApBehaviorEntryService apBehaviorEntryService;
    @Override
    public void like(LikesBehaviourDto likesBehaviourDto) throws Exception {

        //1.检查 参数值
        if(likesBehaviourDto == null
                || likesBehaviourDto.getArticleId() == null
                || likesBehaviourDto.getType() > 2
                || likesBehaviourDto.getType() < 0
                || likesBehaviourDto.getOperation() < 0
                || likesBehaviourDto.getOperation() > 1){
            throw new LeadNewsException("错误的参数");
        }
       //2.先获取当前用户的ID 如果是0 标识匿名用户 如果不是0 就是真实的用户

        Integer currentUserId = RequestContextUtil.getUserId();
        ApBehaviorEntry entry = null;
        if (RequestContextUtil.isAnonymous()) {
            entry = apBehaviorEntryService.findByUserIdOrEquipmentId(likesBehaviourDto.getEquipmentId()
                    , SystemConstants.TYPE_E);
        } else {
            entry = apBehaviorEntryService.findByUserIdOrEquipmentId(currentUserId
                    , SystemConstants.TYPE_USER);
        }
        if (entry == null) {
            throw new LeadNewsException("用户实体不存在");
        }
        //2.添加数据到表中(添加 也有可能是更新)

        if(likesBehaviourDto.getOperation()==1) {
            //点赞
            //查询是否存在点赞记录 如果有 则不用点赞
            //select * from xxx where entry_id=? and article_id=?


            QueryWrapper<ApLikesBehavior> queryWrapper =new QueryWrapper<ApLikesBehavior>();
            queryWrapper.eq("entry_id",entry.getId());
            queryWrapper.eq("article_id",likesBehaviourDto.getArticleId());
            ApLikesBehavior apLikesBehavior = apLikesBehaviorMapper.selectOne(queryWrapper);
            if(apLikesBehavior!=null){//说明有记录(有可能是取消点赞的)

                if(apLikesBehavior.getOperation()==0){
                    apLikesBehavior.setOperation(1);//
                    apLikesBehaviorMapper.updateById(apLikesBehavior);
                }

                return;
            }

            ApLikesBehavior entity = new ApLikesBehavior();
            entity.setOperation(likesBehaviourDto.getOperation());
            entity.setArticleId(likesBehaviourDto.getArticleId());
            entity.setEntryId(entry.getId());//根据用户ID 或者设备ID 从 实体表中获取实体对象 再获取到主键 设置到这里
            entity.setCreatedTime(LocalDateTime.now());
            entity.setType(0);
            apLikesBehaviorMapper.insert(entity);
        }else{
            //取消点赞

            //更新  update xxx set operation=0 where entry_id=? and article_id=? and operation=1
            QueryWrapper<ApLikesBehavior> queryWrapper =new QueryWrapper<ApLikesBehavior>();
            queryWrapper.eq("entry_id",entry.getId());
            queryWrapper.eq("article_id",likesBehaviourDto.getArticleId());
            queryWrapper.eq("operation",1);
            ApLikesBehavior apLikesBehavior = apLikesBehaviorMapper.selectOne(queryWrapper);
            if(apLikesBehavior!=null){
                apLikesBehavior.setOperation(0);
                apLikesBehaviorMapper.updateById(apLikesBehavior);
            }

        }
    }
}

添加异常构造函数:

1617248834988

(4)在app网关中配置行为微服务的路由

spring:
  profiles:
    active: dev
---
server:
  port: 6003
spring:
  application:
    name: leadnews-app-gateway
  profiles: dev
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有请求
            allowedOrigins: "*" #跨域处理 允许所有的域
            allowedHeaders: "*"
            allowedMethods: # 支持的方法
              - GET
              - POST
              - PUT
              - DELETE
      routes:
        # 文章微服务
        - id: article
          uri: lb://leadnews-article
          predicates:
            - Path=/article/**
          filters:
            - StripPrefix= 1
        # app用户微服务
        - id: user
          uri: lb://leadnews-user
          predicates:
            - Path=/user/**
          filters:
            - StripPrefix= 1
        - id: behaviour
          uri: lb://leadnews-behaviour
          predicates:
            - Path=/behaviour/**
          filters:
            - StripPrefix= 1
---
server:
  port: 6003
spring:
  application:
    name: leadnews-app-gateway
  profiles: test
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有请求
            allowedOrigins: "*" #跨域处理 允许所有的域
            allowedHeaders: "*"
            allowedMethods: # 支持的方法
              - GET
              - POST
              - PUT
              - DELETE
      routes:
        # 文章微服务
        - id: article
          uri: lb://leadnews-article
          predicates:
            - Path=/article/**
          filters:
            - StripPrefix= 1
        # app用户微服务
        - id: user
          uri: lb://leadnews-user
          predicates:
            - Path=/user/**
          filters:
            - StripPrefix= 1
        - id: behaviour
          uri: lb://leadnews-behaviour
          predicates:
            - Path=/behaviour/**
          filters:
            - StripPrefix= 1
---
server:
  port: 6003
spring:
  application:
    name: leadnews-app-gateway
  profiles: pro
  cloud:
    nacos:
      server-addr: 192.168.211.136:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有请求
            allowedOrigins: "*" #跨域处理 允许所有的域
            allowedHeaders: "*"
            allowedMethods: # 支持的方法
              - GET
              - POST
              - PUT
              - DELETE
      routes:
        # 文章微服务
        - id: article
          uri: lb://leadnews-article
          predicates:
            - Path=/article/**
          filters:
            - StripPrefix= 1
        # app用户微服务
        - id: user
          uri: lb://leadnews-user
          predicates:
            - Path=/user/**
          filters:
            - StripPrefix= 1
        - id: behaviour
          uri: lb://leadnews-behaviour
          predicates:
            - Path=/behaviour/**
          filters:
            - StripPrefix= 1

1615354500748

(5)由于点赞 主键没有自增,我们使用雪花算法来生成主键

添加如下代码:

1617255644281

修改如下配置:

1617255668111

(6)测试

启动项目:

1615368753632

先app登录:

1615368785322

点赞:

1615368806883

1615368817364

校验成功:

1615368836832

1.4 阅读行为

1.4.1 需求分析

当用户查看了某一篇文章,需要记录当前用户查看的次数,阅读时长,阅读文章的比例,加载的时长(非必要)

这些数据保存到一个表中。当用户查看了一篇文章的详情,点击返回重新加入文章列表发送请求,记录当前用户阅读此文章的行为。

1.4.2 思路分析

ap_read_behavior APP阅读行为表

1586444602628

当点击一篇文章之后,查看了之后,点击返回重新回到文章列表的时候,由前端发送请求给到后台即可。至于次数,时长由前端来进行计算即可。

1.4.3 功能实现

(1)创建dto来接收请求数据

@Data
public class ReadBehaviorDto {
    // 设备ID
    Integer equipmentId;

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

    /**
     * 阅读次数
     */
    Integer count;

    /**
     * 阅读时长(S)
     */
    Integer readDuration;

    /**
     * 阅读百分比 不带小数
     */
    Integer percentage;

    /**
     * 加载时间
     */
    Integer loadDuration;

}

1615355674478

(2) controller

@PostMapping("/read")
public Result read(@RequestBody ReadBehaviorDto readBehaviorDto) throws Exception{
    apReadBehaviorService.readBehavior(readBehaviorDto);
    return Result.ok();
}

1615355709983

(3) 业务层

@Service
public class ApReadBehaviorServiceImpl extends ServiceImpl<ApReadBehaviorMapper, ApReadBehavior> implements ApReadBehaviorService {

    @Autowired
    private ApBehaviorEntryService apBehaviorEntryService;

    @Override
    public void readBehavior(ReadBehaviorDto readBehaviorDto) throws Exception {
        //1.参数校验
        if(readBehaviorDto == null || readBehaviorDto.getArticleId() == null){
            throw new LeadNewsException("文章不存在");
        }
       Integer currentUserId = RequestContextUtil.getUserId();
        ApBehaviorEntry entry = null;
        if (RequestContextUtil.isAnonymous()) {
            entry = apBehaviorEntryService.findByUserIdOrEquipmentId(readBehaviorDto.getEquipmentId()
                    , SystemConstants.TYPE_E);
        } else {
            entry = apBehaviorEntryService.findByUserIdOrEquipmentId(currentUserId
                    , SystemConstants.TYPE_USER);
        }
        if (entry == null) {
            throw new LeadNewsException("用户实体不存在");
        }

        //3.保存或更新阅读的行为
        QueryWrapper<ApReadBehavior> queryWrapper = new QueryWrapper<ApReadBehavior>();
        queryWrapper.eq("entry_id",apBehaviorEntry.getId());
        queryWrapper.eq("article_id",readBehaviorDto.getArticleId());

        ApReadBehavior apReadBehavior = getOne(queryWrapper);
        if(apReadBehavior == null){
            apReadBehavior = new ApReadBehavior();
            apReadBehavior.setCount(readBehaviorDto.getCount());
            apReadBehavior.setArticleId(readBehaviorDto.getArticleId());
            apReadBehavior.setPercentage(readBehaviorDto.getPercentage());
            apReadBehavior.setEntryId(entry.getId());
            apReadBehavior.setLoadDuration(readBehaviorDto.getLoadDuration());
            apReadBehavior.setReadDuration(readBehaviorDto.getReadDuration());
            apReadBehavior.setCreatedTime(LocalDateTime.now());
            save(apReadBehavior);
        }else{
            apReadBehavior.setUpdatedTime(LocalDateTime.now());
            apReadBehavior.setCount((apReadBehavior.getCount()+1));
            updateById(apReadBehavior);
        }
    }
}

同样设置主键采用雪花算法实现:

1617255917385

(4)测试

当用户查看了一篇文章的详情,点击返回重新加入文章列表发送请求,记录当前用户阅读此文章的行为.该行为通过POSTMAN来进行测试。

先登录:

1615369201057

阅读行为保存:

1615369224439

{
    "articleId":1368752420570234881,
    "count":1,
    "readDuration":1,
    "percentage":99,
    "loadDuration":1,
    "operation":1

}

点击三次之后:

1615369287142

1.5 不喜欢行为和收藏行为(作业)

1.5.1不喜欢实现思路

为什么会有不喜欢?

一旦用户点击了不喜欢,不再给当前用户推荐这一类型的文章信息

1.定义DTO 用于接收请求传递过来的参数 
2.编写controller service 在service 中首先需要获取当前用户是否为 用户 或者设备。判断是否有行为实体,如果有则进行保存,保存的时候先校验是否已经存在,如果存在,则为更新即可
3.设置POJO主键生成策略为 雪花算法生成。

ap_unlikes_behavior APP不喜欢行为表

1586445655890

dto:

@Data
public class UnLikesBehaviorDto {
 
    Integer equipmentId;

    Long articleId;

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

}

1.5.2 收藏功能实现思路

收藏表在文章库中,为什么不设计在行为库?

因为app端用户可以个人中心找到自己收藏的文章列表,这样设计更方便。便于关联表查询,如果是夸库,则不能关联表查询。

1617257048701

1615356426045

1.定义DTO 用于接收请求传递过来的参数
2.编写controller service 在service 中首先需要获取当前用户是否为 用户 或者设备。判断是否有行为实体,如果有则进行保存,保存的时候先校验是否已经存在,如果存在,则为更新即可
3.设置POJO主键生成策略为 雪花算法生成。

ap_collection APP收藏信息表

1586446252365

对象dto

@Data
public class CollectionBehaviorDto {
    // 设备ID
  
    Integer equipmentId;
    // 文章、动态ID
 
    Long entryId;
    /**
     * 收藏内容类型
     * 0文章
     * 1动态
     */
     Integer type;

    /**
     * 操作类型
     * 0收藏
     * 1取消收藏
     */
    Integer operation;
	/**
	  发布时间 冗余字段 接收页面文章的发布时间值
	*/
    LocalDateTime publishedTime;

}

2 app文章关系展示功能

2.1 app文章关系-需求分析

主要是用来展示文章的关系,app端用户必须登录,判断当前用户是否已经关注该文章的作者、是否收藏了此文章、是否点赞了文章、是否不喜欢该文章等

例:如果当前用户点赞了该文章,点赞按钮进行高亮,其他功能类似。

2.2 app文章关系-思路分析

2.2.1 实现思路

1586265034267

1 用户查看文章详情,展示文章信息(功能已实现),同时需要展示当前文章的行为(点赞,收藏等)

2 根据用户id(已登录)或设备id(未登录)去查询当前实体id

3 通过实体id和前端传递过来的文章id去查询收藏表、点赞表、不喜欢表;其中点赞和不喜欢需要远程调用behavior微服务获取数据。

4 在文章详情展示是否关注此作者,需要通过当前用户和作者关系表进行查询,有数据则关注,无数据则没有关注

返回的格式如下:

{"isfollow":true,"islike":true,"isunlike":false,"iscollection":true}

通过图来说明思路如下:

1615369663071

简单总结下就是 点击查询文章详情时,再发送一个请求 通过文章微服务获取其他相关的譬如:收藏,关注,点赞,等数据 判断是否关注,点赞 ,收藏之后返回一个JSON给前端 前端根据JSON的值进行展示即可

2.2.2 表关系说明

1599668118109

2.3 功能实现

2.3.1 思路分析

页面请求 过来后台controller 接收 调用service service内部业务逻辑如下

//1.定义变量
//2.通过feign调用查询 行为实体
//3.查询是否关注  查询是否喜欢  查询是否收藏  查询是否点赞
//3.1 通过feign调用查询 是否喜欢
//3.2 通过feign调用查询 是否点赞
//3.3 通过feign调用查询 是否关注
//3.4 查询是否收藏
//4.获取之后组合map 返回即可,返回的数据格式如下:
{"isfollow":true,"islike":true,"isunlike":false,"iscollection":true}

2.3.2 文章微服务

(1) com.itheima.article.dto下创建dto

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

1615527209338

(2)创建controller

@PostMapping("/load/article/behavior")
public Result<Map<String,Object>> loadArticleBehaviour(@RequestBody ArticleBehaviourDtoQuery articleBehaviourDtoQuery){
    Map<String,Object> resultMap = apArticleService.loadArticleBehaviour(articleBehaviourDtoQuery);
    return Result.ok(resultMap);
}

1615527298430

(3)业务实现类

@Override
public Map<String, Object> loadArticleBehaviour(ArticleBehaviourDtoQuery articleBehaviourDtoQuery) {
    //1.定义变量
    //是否喜欢 默认是false
    boolean isunlike=false;
    //是否点赞 默认是false
    boolean islike = false;
    //是否收藏
    boolean isCollection = false;
    //是否关注
    boolean isFollow = false;
    Map<String,Object> resultMap = new HashMap<String,Object>();
    //{"isfollow":true,"islike":true,"isunlike":false,"iscollection":true}
    resultMap.put("isfollow",isFollow);
    resultMap.put("islike",islike);
    resultMap.put("isunlike",isunlike);
    resultMap.put("iscollection",isCollection);
    //2.通过feign调用查询 行为实体        
    //3.查询是否关注  查询是否喜欢  查询是否收藏 查询是否点赞
    //3.1 通过feign调用查询 是否喜欢       
    //3.2 通过feign调用查询 是否点赞       
    //3.3 通过feign调用查询 是否关注
    //3.3.1 首先根据表结构获取相关的思路(根据页面传递的作者的ID 获取到作者表信息 获取到对应的appuser的ID)

    //3.3.2 再根据该appuserId 和当前的用户的appUserId 从关注表中获取到信息 如果不为空即可

    //3.4 查询是否收藏

    //4.获取之后组合map 返回即可

    return resultMap;
}

启动类中开启feignclient支持:

1615528224504

2.3.3 实现查询行为实体

(1)创建feign

1615527502259

@FeignClient(name="leadnews-behaviour",path = "/apBehaviorEntry",contextId ="apBehaviorEntry" )
public interface ApBehaviorEntryFeign extends CoreFeign<ApBehaviorEntry> {
    @GetMapping("/entryOne")
    public ApBehaviorEntry findByUserIdOrEquipmentId(
            @RequestParam(name="userId",required = true) Integer userId,
            @RequestParam(name="type",required = true)Integer type);
}

(2)在文章微服务中添加依赖:

<dependency>
    <groupId>com.itheima</groupId>
    <artifactId>itheima-leadnews-behaviour-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

(3)在行为微服务中实现feign

controller:

1615527638972

/**
     * 根据设备ID 或者用户的ID 获取实体对象
     * @param userId
     * @param type
     * @return
     */
 @GetMapping("/entryOne")
    public ApBehaviorEntry findByUserIdOrEquipmentId(
            @RequestParam(name="userId",required = true) Integer userId,
            @RequestParam(name="type",required = true)Integer type){
        return apBehaviorEntryService.findByUserIdOrEquipmentId(userId,type);
    }

(4)在文章微服务中调用:

1635668665066

@Autowired
private ApBehaviorEntryFeign apBehaviorEntryFeign;

//略。。。。。


 Integer userId = RequestContextUtil.getUserId();//张三
        ApBehaviorEntry entry=null;
        if(RequestContextUtil.isAnonymous()){
            entry = apBehaviorEntryFeign.findByUserIdOrEquipmentId(articleBehaviourDtoQuery.getEquipmentId(), SystemConstants.TYPE_E);
        }else{
            entry = apBehaviorEntryFeign.findByUserIdOrEquipmentId(userId, SystemConstants.TYPE_USER);
        }
        if(entry==null){
            return resultMap;
        }

//略......

2.3.4 查询是否喜欢

(1)创建feign接口:

1615527894952

@FeignClient(name="leadnews-behaviour",path = "/apUnlikesBehavior",contextId = "apUnlikesBehavior")
public interface ApUnlikesBehaviorFeign extends CoreFeign<ApUnlikesBehavior> {
    /**
     * 根据文章的ID 和entryId获取数据
     * @param articleId
     * @param entryId
     * @return
     */
    @GetMapping("/getUnlikesBehavior")
    public ApUnlikesBehavior getUnlikesBehavior(@RequestParam(name="articleId") Long articleId,@RequestParam(name="entryId")Integer entryId);
}

(2)行为微服务实现feign接口

@GetMapping("/getUnlikesBehavior")
public ApUnlikesBehavior getUnlikesBehavior(@RequestParam(name="articleId") Long articleId, @RequestParam(name="entryId")Integer entryId){
    QueryWrapper<ApUnlikesBehavior> querywraper = new QueryWrapper<ApUnlikesBehavior>();
    querywraper.eq("entry_id",entryId);
    querywraper.eq("article_id",articleId);
    ApUnlikesBehavior apUnlikesBehavior = apUnlikesBehaviorService.getOne(querywraper);
    return apUnlikesBehavior;
}

1615527974611

(3)文章微服务中调用:

1615528037125

@Autowired
private ApUnlikesBehaviorFeign apUnlikesBehaviorFeign;


//略......
//3.查询是否关注  查询是否喜欢  查询是否收藏 查询是否点赞
//3.1 通过feign调用查询 是否喜欢
ApUnlikesBehavior unlikesBehavior = apUnlikesBehaviorFeign.getUnlikesBehavior(articleBehaviourDtoQuery.getArticleId(), entry.getId());
if (unlikesBehavior!=null && "1".equals(unlikesBehavior.getType().toString())) {
    isunlike=true;
    resultMap.put("isunlike",isunlike);
}
//略......

2.3.5 查询是否点赞

(1)创建feign

1615528125645

@FeignClient(name="leadnews-behaviour",path = "/apLikesBehavior",contextId = "apLikesBehavior")
public interface ApLikesBehaviorFeign extends CoreFeign<ApLikesBehavior> {

    /**
     * 根据文章的ID 和 entryId获取 是否点赞
     * @param articleId
     * @param entryId
     * @return
     */
    @GetMapping("/getLikesBehavior")
    public ApLikesBehavior getLikesBehavior(@RequestParam(name="articleId") Long articleId, @RequestParam(name="entryId")Integer entryId);

}

(2)行为微服务实现feign接口

1615528175454

@GetMapping("/getLikesBehavior")
public ApLikesBehavior getLikesBehavior(@RequestParam(name="articleId") Long articleId, @RequestParam(name="entryId")Integer entryId){
    QueryWrapper<ApLikesBehavior> queryWrapper = new QueryWrapper<ApLikesBehavior>();
    queryWrapper.eq("article_id",articleId);
    queryWrapper.eq("entry_id",entryId);
    return apLikesBehaviorService.getOne(queryWrapper);
}

(3)文章微服务调用

1617256605446

 @Autowired
private ApLikesBehaviorFeign apLikesBehaviorFeign;


//略......
ApLikesBehavior likesBehavior = apLikesBehaviorFeign.getLikesBehavior(articleBehaviourDtoQuery.getArticleId(), appEntry.getId());
//1标识点赞
if(likesBehavior!=null && ("1").equals(likesBehavior.getOperation().toString())){
    islike=true;//点赞了
    resultMap.put("islike",islike);
}
//略....

2.3.6 查询是否关注

这个需要注意:

关注表是在user微服务中,并且 表中的关注者 和被关注者 对应的存储都是appUser中的ID ,使用时需要用到当前的作者信息。
思路:
先根据作者ID 查询作者信息 在根据作者信息中的userId   和当前的用户的ID 通过feign调用获取到关注表信息。判断即可。

(1)在user-api中创建feign接口

1615528492149

 @FeignClient(name="leadnews-user",path = "/apUserFollow",contextId = "apUserFollow")
public interface ApUserFollowFeign extends CoreFeign<ApUserFollow> {
    //获取关注信息记录 某一个关注者 和被关注者的ID 获取信息
    @GetMapping("/getApUserFollow")
    ApUserFollow getApUserFollow(@RequestParam(name="followId")Integer followId,@RequestParam(name="userId")Integer userId);
}

(2)在用户微服务中实现接口:

 @GetMapping("/getApUserFollow")
    ApUserFollow getApUserFollow(@RequestParam(name="followId")Integer followId,@RequestParam(name="userId")Integer userId){

        QueryWrapper<ApUserFollow> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("follow_id",followId);
        queryWrapper.eq("user_id",userId);
        return apUserFollowService.getOne(queryWrapper);
    }

1615528555584

(3)在文章微服务中添加依赖:

<dependency>
    <groupId>com.itheima</groupId>
    <artifactId>itheima-leadnews-user-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

(4)调用:

 @Autowired
    private ApAuthorMapper apAuthorMapper;

    @Autowired
    private ApUserFollowFeign apUserFollowFeign;

//略....
ApAuthor apAuthor = apAuthorMapper.selectById(articleBehaviourDtoQuery.getAuthorId());
if(apAuthor!=null){
    Integer followId = apAuthor.getUserId();
    
    ApUserFollow apUserFollow = apUserFollowFeign.getApUserFollow(followId, userId);
    //3.3.2 再根据该appuserId 和当前的用户的appUserId 从关注表中获取到信息 如果不为空即可
    if(apUserFollow!=null){
        isFollow=true;
        resultMap.put("isfollow",isFollow);
    }
}
//略...

1615528654389

2.3.7 查询是否收藏

查询是否收藏 由于 收藏表在文章微服务直接调用即可

1617199355565

//3.4 查询是否收藏
QueryWrapper<ApCollection> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("entry_id", appEntry.getId());
queryWrapper.eq("article_id", articleBehaviourDtoQuery.getArticleId());
queryWrapper.eq("type", 0);
ApCollection apCollection = apCollectionMapper.selectOne(queryWrapper);
if (apCollection != null) {
    isCollection = true;
    resultMap.put("iscollection", isCollection);
}

2.4 文章微服务中获取行为的整体代码如下

@Autowired
    private ApBehaviorEntryFeign apBehaviorEntryFeign;
    @Autowired
    private ApUnlikesBehaviorFeign apUnlikesBehaviorFeign;
    @Autowired
    private ApLikesBehaviorFeign apLikesBehaviorFeign;
    @Autowired
    private ApUserFollowFeign apUserFollowFeign;

    @Autowired
    private ApAuthorMapper apAuthorMapper;

    @Autowired
    private ApCollectionMapper apCollectionMapper;


    @Override
    public Map<String, Object> loadArticleBehaviour(ArticleBehaviourDtoQuery articleBehaviourDtoQuery) {
        //1.定义变量
        //是否喜欢 默认是false
        boolean isunlike = false;
        //是否点赞 默认是false
        boolean islike = false;
        //是否收藏
        boolean isCollection = false;
        //是否关注
        boolean isFollow = false;
        Map<String, Object> resultMap = new HashMap<String, Object>();
        //{"isfollow":true,"islike":true,"isunlike":false,"iscollection":true}
        resultMap.put("isfollow", isFollow);
        resultMap.put("islike", islike);
        resultMap.put("isunlike", isunlike);
        resultMap.put("iscollection", isCollection);
        //2.通过feign调用查询 行为实体

        Integer userId = RequestContextUtil.getUserId();//张三
        ApBehaviorEntry entry=null;
        if(RequestContextUtil.isAnonymous()){
            entry = apBehaviorEntryFeign.findByUserIdOrEquipmentId(articleBehaviourDtoQuery.getEquipmentId(), SystemConstants.TYPE_E);
        }else{
            entry = apBehaviorEntryFeign.findByUserIdOrEquipmentId(userId, SystemConstants.TYPE_USER);
        }
        if(entry==null){
            return resultMap;
        }


        //3.查询是否关注  查询是否喜欢  查询是否收藏 查询是否点赞
        //3.1 通过feign调用查询 是否喜欢
        ApUnlikesBehavior unlikesBehavior = apUnlikesBehaviorFeign.getUnlikesBehavior(articleBehaviourDtoQuery.getArticleId(), entry.getId());
        if (unlikesBehavior!=null && "1".equals(unlikesBehavior.getType().toString())) {
            isunlike=true;
            resultMap.put("isunlike",isunlike);
        }
        //3.2 通过feign调用查询 是否点赞

        ApLikesBehavior likesBehavior = apLikesBehaviorFeign.getLikesBehavior(articleBehaviourDtoQuery.getArticleId(), entry.getId());
        //1标识点赞
        if(likesBehavior!=null && ("1").equals(likesBehavior.getOperation().toString())){
            islike=true;//点赞了
            resultMap.put("islike",islike);
        }

        //3.3 通过feign调用查询 是否关注

        ApAuthor apAuthor = apAuthorMapper.selectById(articleBehaviourDtoQuery.getAuthorId());

        if(apAuthor!=null){
            //作者对应的ap_user_id的值
            Integer followId = apAuthor.getUserId();
            ApUserFollow apUserFollow = apUserFollowFeign.getApUserFollow(followId, userId);
            //3.3.2 再根据该appuserId 和当前的用户的appUserId 从关注表中获取到信息 如果不为空即可
            if(apUserFollow!=null){
                isFollow=true;
                resultMap.put("isfollow",isFollow);
            }
        }
        //3.3.1 首先根据表结构获取相关的思路(根据页面传递的作者的ID 获取到作者表信息 获取到对应的appuser的ID)

        //3.3.2 再根据该appuserId 和当前的用户的appUserId 从关注表中获取到信息 如果不为空即可

        //3.4 查询是否收藏

        //3.4 查询是否收藏
        QueryWrapper<ApCollection> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("entry_id", entry.getId());
        queryWrapper.eq("article_id", articleBehaviourDtoQuery.getArticleId());
        queryWrapper.eq("type", 0);
        ApCollection apCollection = apCollectionMapper.selectOne(queryWrapper);
        if (apCollection != null) {
            isCollection = true;
            resultMap.put("iscollection", isCollection);
        }

        //4.获取之后组合map 返回即可

        return resultMap;
    }
这篇关于87-day10-app端文章详情开发(点赞 阅读,转发 等行为相关)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!