标签:name app day10 点赞 Integer leadnews com id itheima
第十章 app端用户行为处理
目标
- 能够理解app端的行为记录
- 能够完成作者关注行为的功能
- 能够完成文章点赞行为的功能
- 能够完成文章阅读行为的功能
- 能够掌握不喜欢和收藏功能的实现思路
- 能够完成app文章关系展示功能
1 app-用户操作行为记录
用户行为数据的记录包括了关注、点赞、不喜欢、收藏、阅读等行为
这些行为与当前app端的功能实现没有任何关系,即使没有行为数据,功能也不耽误实现,那为什么要做行为数据的保存呢?
黑马头条项目整个项目开发涉及web展示和大数据分析来给用户推荐文章,如何找出哪些文章是热点文章进行针对性的推荐呢?这个时候需要进行大数据分析的准备工作,埋点。
所谓“埋点”,是数据采集领域(尤其是用户行为数据采集领域)的术语,指的是针对特定用户行为或事件进行捕获、处理和发送的相关技术及其实施过程。比如用户某个icon点击次数、阅读文章的时长,观看视频的时长等等。
黑马头条课程里主要涉及到了关注行为,点赞行为,阅读行为的保存。其他类似于不喜欢、收藏功能可根据这些实现的功能自行实现。
1.1 行为微服务搭建
1.1.1 创建行为微服务
处理行为是一个量比较大的操作,所以专门创建一个微服务来处理行为相关操作,参考别的微服务进行搭建即可
创建api:
行为服务中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
生成之后copy到如下目录:
1.2 关注行为
1.2.1 需求分析
在文章详情中,当用户点击了关注作者按钮,需要记录当前行为到表中,目前只需要存储数据即可,后期会做实时的流式处理,根据这些基础数据做热点文章的计算。
1.2.2 思路分析
(1)ap_follow_behavior APP关注行为表
(2)ap_behavior_entry 行为实体表
行为实体指的是使用的终端设备或者是登录的用户,统称为行为实体。
type :0终端设备 1用户
行为实体与APP关注行为表是一对多的关系,关注行为需要知道是谁(设备或用户)关注了该文章信息
关注与取消关注的功能已经实现,当用户点击了关注保存关注行为,取消关注不保存数据。
因为只做保存操作,只需要在【关注业务操作】的时候发送消息给行为微服务 【行为微服务】获取消息进行数据保存即可。
实现步骤:
1 用户微服务中关注操作发送消息,保存用户行为
2 行为微服务接收消息
2.1 获取行为实体
2.2 保存数据
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的环境
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>
(4)修改yaml文件:添加kafka消费者:
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;
}
(2)新建常量,固定当前消息的topic
public static final String FOLLOW_BEHAVIOR_TOPIC="follow.behavior.topic";
(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)在行为微服务中实现查询行为实体业务
@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)在行为微服务中实现保存关注行为数据
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);
}
}
}
(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) 测试
先登录
再关注:
查看:
1.3 点赞行为
1.3.1 需求分析
当前登录的用户点击了”赞“,就要保存当前行为数据
1.3.2 思路分析
当前用户点赞以后保存数据,取消点赞则不删除数据
保存也是根据当前行为实体和文章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;
}
(2)controller
@PostMapping("/like")
public Result like(@RequestBody LikesBehaviourDto likesBehaviourDto) throws Exception{
apLikesBehaviorService.like(likesBehaviourDto);
return Result.ok();
}
(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);
}
}
}
}
添加异常构造函数:
(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
(5)由于点赞 主键没有自增,我们使用雪花算法来生成主键
添加如下代码:
修改如下配置:
(6)测试
启动项目:
先app登录:
点赞:
校验成功:
1.4 阅读行为
1.4.1 需求分析
当用户查看了某一篇文章,需要记录当前用户查看的次数,阅读时长,阅读文章的比例,加载的时长(非必要)
这些数据保存到一个表中。当用户查看了一篇文章的详情,点击返回重新加入文章列表发送请求,记录当前用户阅读此文章的行为。
1.4.2 思路分析
ap_read_behavior APP阅读行为表
当点击一篇文章之后,查看了之后,点击返回重新回到文章列表的时候,由前端发送请求给到后台即可。至于次数,时长由前端来进行计算即可。
1.4.3 功能实现
(1)创建dto来接收请求数据
@Data
public class ReadBehaviorDto {
// 设备ID
Integer equipmentId;
// 文章、动态、评论等ID
Long articleId;
/**
* 阅读次数
*/
Integer count;
/**
* 阅读时长(S)
*/
Integer readDuration;
/**
* 阅读百分比 不带小数
*/
Integer percentage;
/**
* 加载时间
*/
Integer loadDuration;
}
(2) controller
@PostMapping("/read")
public Result read(@RequestBody ReadBehaviorDto readBehaviorDto) throws Exception{
apReadBehaviorService.readBehavior(readBehaviorDto);
return Result.ok();
}
(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);
}
}
}
同样设置主键采用雪花算法实现:
(4)测试
当用户查看了一篇文章的详情,点击返回重新加入文章列表发送请求,记录当前用户阅读此文章的行为.该行为通过POSTMAN来进行测试。
先登录:
阅读行为保存:
{
"articleId":1368752420570234881,
"count":1,
"readDuration":1,
"percentage":99,
"loadDuration":1,
"operation":1
}
点击三次之后:
1.5 不喜欢行为和收藏行为(作业)
1.5.1不喜欢实现思路
为什么会有不喜欢?
一旦用户点击了不喜欢,不再给当前用户推荐这一类型的文章信息
1.定义DTO 用于接收请求传递过来的参数
2.编写controller service 在service 中首先需要获取当前用户是否为 用户 或者设备。判断是否有行为实体,如果有则进行保存,保存的时候先校验是否已经存在,如果存在,则为更新即可
3.设置POJO主键生成策略为 雪花算法生成。
ap_unlikes_behavior APP不喜欢行为表
dto:
@Data
public class UnLikesBehaviorDto {
Integer equipmentId;
Long articleId;
/**
* 不喜欢操作方式
* 0 不喜欢
* 1 取消不喜欢
*/
Integer type;
}
1.5.2 收藏功能实现思路
收藏表在文章库中,为什么不设计在行为库?
因为app端用户可以个人中心找到自己收藏的文章列表,这样设计更方便。便于关联表查询,如果是夸库,则不能关联表查询。
1.定义DTO 用于接收请求传递过来的参数
2.编写controller service 在service 中首先需要获取当前用户是否为 用户 或者设备。判断是否有行为实体,如果有则进行保存,保存的时候先校验是否已经存在,如果存在,则为更新即可
3.设置POJO主键生成策略为 雪花算法生成。
ap_collection APP收藏信息表
对象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 实现思路
1 用户查看文章详情,展示文章信息(功能已实现),同时需要展示当前文章的行为(点赞,收藏等)
2 根据用户id(已登录)或设备id(未登录)去查询当前实体id
3 通过实体id和前端传递过来的文章id去查询收藏表、点赞表、不喜欢表;其中点赞和不喜欢需要远程调用behavior微服务获取数据。
4 在文章详情展示是否关注此作者,需要通过当前用户和作者关系表进行查询,有数据则关注,无数据则没有关注
返回的格式如下:
{"isfollow":true,"islike":true,"isunlike":false,"iscollection":true}
通过图来说明思路如下:
简单总结下就是 点击查询文章详情时,再发送一个请求 通过文章微服务获取其他相关的譬如:收藏,关注,点赞,等数据 判断是否关注,点赞 ,收藏之后返回一个JSON给前端 前端根据JSON的值进行展示即可
2.2.2 表关系说明
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;
}
(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);
}
(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支持:
2.3.3 实现查询行为实体
(1)创建feign
@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:
/**
* 根据设备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)在文章微服务中调用:
@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接口:
@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;
}
(3)文章微服务中调用:
@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
@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接口
@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)文章微服务调用
@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接口
@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);
}
(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);
}
}
//略...
2.3.7 查询是否收藏
查询是否收藏 由于 收藏表在文章微服务直接调用即可
//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;
}
标签:name,app,day10,点赞,Integer,leadnews,com,id,itheima 来源: https://www.cnblogs.com/ofanimon/p/16188475.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。