5.app端查看文章列表

app端查看文章列表

一、需求分析

image-20221125235753460

二、表结构分析

2.1 ap_article 文章基本信息表

在这里插入图片描述

2.2 ap_article_config 文章配置表

image-20221126000026815

2.3 ap_article_content 文章内容表

image-20221126000130050

2.4表关系

image-20221126000228432

三、功能实现思路分析

1,在默认频道展示10条文章信息

2,可以切换频道查看不同种类文章

3,当用户下拉可以加载最新的文章(分页),本页文章列表中发布时间最大的时间为依据

4,当用户上拉可以加载更多的文章信息(按照发布时间),本页文章列表中发布时间最小的时间为依据

5,如果是当前频道的首页,前端传递默认参数:

  • maxBehotTime:0(毫秒)

  • minBehotTime:20000000000000(毫秒)—>2063年

sql分析

#1.按照发布时间倒序查询十条文章
select * from ap_article order by publish_time desc limit 10;

#2.下面这个aa是给ap-article表起别名
select * from ap_article aa order by aa.publish_time desc limit 10;

#3.按照发布频道倒序查询十条文章
select * from ap_article aa where aa.channel_id = 1 order by aa.publish_time desc limit 10;

#4.查询首页
select * from ap_article aa where aa.channel_id = 1 and aa.publish_time < '2063-04-19 01:00:59'
order by aa.publish_time desc limit 10;

#5.查询更多,例如2020-09-08 10:20:12这个时间是当前页发布时间最早的,那就要查比它还要早的(上滑)
select * from ap_article aa where aa.channel_id = 1 and aa.publish_time < '2020-09-08 10:20:12'
order by aa.publish_time desc LIMIT 10; 

#6.查询最新,例如2020-09-07 22:30:33这个时间是当前页发布时间最晚的,那就要查比它还要晚的(下拉)
select * from ap_article aa where aa.channel_id = 1 and aa.publish_time > '2020-09-07 22:30:33'	
order by aa.publish_time desc limit 10;


select * from ap_article;

#多表查询
select * from ap_article aa left join ap_article_config bb on aa.id = bb.article_id 
where bb.is_down != 1 
  and bb.is_delete != 1
  and aa.channel_id = 1 
  and aa.publish_time < '2063-04-19 01:00:59'
  order by aa.publish_time desc limit 10;

四、搭建文章微服务,代码实现功能

在heima-leadnews-service新建子模块heima-leadnews-article

4.1启动类

package com.heima.article;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;

@SpringBootApplication()//exclude= DataSourceAutoConfiguration.class
@EnableDiscoveryClient
@MapperScan("com.heima.article.mapper")
public class ArticleApplication {

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

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

        return interceptor;
    }
}

4.2 bootstrap.yml配置文件

server:
  port: 51802
spring:
  application:
    name: leadnews-article
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.1.2:8848
      config:
        server-addr: 192.168.1.2:8848
        file-extension: yml

4.3 nacos配置管理中心

dataId要与本地配置的服务名一致

spring:
  redis:
    host: 192.168.1.2
#    password: leadnews 
    port: 6379
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.1.2:3306/leadnews_article?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
    username: root
    password: 1234
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.heima.model.article.pojos

4.4接口定义

image-20221126003630408

4.5 实体类

(1) 文章信息表ap_article,存储已发布的文章
package com.heima.model.article.pojos;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * <p>
 * 文章信息表,存储已发布的文章
 * </p>
 */

@Data
@TableName("ap_article")
public class ApArticle implements Serializable {

    @TableId(value = "id",type = IdType.ID_WORKER)
    private Long id;


    /**
     * 文章标题
     */
    private String title;

    /**
     * 作者id
     */
    @TableField("author_id")
    private Long authorId;

    /**
     * 作者名称
     */
    @TableField("author_name")
    private String authorName;

    /**
     * 频道id
     */
    @TableField("channel_id")
    private Integer channelId;

    /**
     * 频道名称
     */
    @TableField("channel_name")
    private String channelName;

    /**
     * 文章布局  0 无图文章   1 单图文章    2 多图文章
     */
    private Short layout;

    /**
     * 文章标记  0 普通文章   1 热点文章   2 置顶文章   3 精品文章   4 大V 文章
     */
    private Byte flag;

    /**
     * 文章封面图片 多张逗号分隔
     */
    private String images;

    /**
     * 标签
     */
    private String labels;

    /**
     * 点赞数量
     */
    private Integer likes;

    /**
     * 收藏数量
     */
    private Integer collection;

    /**
     * 评论数量
     */
    private Integer comment;

    /**
     * 阅读数量
     */
    private Integer views;

    /**
     * 省市
     */
    @TableField("province_id")
    private Integer provinceId;

    /**
     * 市区
     */
    @TableField("city_id")
    private Integer cityId;

    /**
     * 区县
     */
    @TableField("county_id")
    private Integer countyId;

    /**
     * 创建时间
     */
    @TableField("created_time")
    private Date createdTime;

    /**
     * 发布时间
     */
    @TableField("publish_time")
    private Date publishTime;

    /**
     * 同步状态
     */
    @TableField("sync_status")
    private Boolean syncStatus;

    /**
     * 来源
     */
    private Boolean origin;

    /**
     * 静态页面地址
     */
    @TableField("static_url")
    private String staticUrl;
}

(2) ap_article_config,APP已发布文章配置表
package com.heima.model.article.pojos;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

/**
 * <p>
 * APP已发布文章配置表
 * </p>
 *
 * @author itheima
 */

@Data
@TableName("ap_article_config")
public class ApArticleConfig implements Serializable {

    @TableId(value = "id",type = IdType.ID_WORKER)
    private Long id;

    /**
     * 文章id
     */
    @TableField("article_id")
    private Long articleId;

    /**
     * 是否可评论
     * true: 可以评论   1
     * false: 不可评论  0
     */
    @TableField("is_comment")
    private Boolean isComment;

    /**
     * 是否可以转发
     * true: 可以转发   1
     * false: 不可转发  0
     */
    @TableField("is_forward")
    private Boolean isForward;

    /**
     * 是否下架
     * true: 下架   1
     * false: 没有下架  0
     */
    @TableField("is_down")
    private Boolean isDown;

    /**
     * 是否已删除
     * true: 删除   1
     * false: 没有删除  0
     */
    @TableField("is_delete")
    private Boolean isDelete;
}

(3) 文章内容
package com.heima.model.article.pojos;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

@Data
@TableName("ap_article_content")
public class ApArticleContent implements Serializable {

    @TableId(value = "id",type = IdType.ID_WORKER)
    private Long id;

    /**
     * 文章id
     */
    @TableField("article_id")
    private Long articleId;

    /**
     * 文章内容
     */
    private String content;
}

4.6 Mapper

package com.heima.article.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.pojos.ApArticle;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface ApArticleMapper extends BaseMapper<ApArticle> {

    /**
     *
     * @param dto
     * @param type 1代表加载更多,2加载最新
     * @return
     */
     List<ApArticle> loadArticleList(@Param("dto") ArticleHomeDto dto, @Param("type") Short type);

}

4.7 对应的映射文件

在resources中新建com/heima/article/mapper/ApArticleMapper.xml 如下配置:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.heima.article.mapper.ApArticleMapper">

    <resultMap id="resultMap" type="com.heima.model.article.pojos.ApArticle">
        <id column="id" property="id"/>
        <result column="title" property="title"/>
        <result column="author_id" property="authorId"/>
        <result column="author_name" property="authorName"/>
        <result column="channel_id" property="channelId"/>
        <result column="channel_name" property="channelName"/>
        <result column="layout" property="layout"/>
        <result column="flag" property="flag"/>
        <result column="images" property="images"/>
        <result column="labels" property="labels"/>
        <result column="likes" property="likes"/>
        <result column="collection" property="collection"/>
        <result column="comment" property="comment"/>
        <result column="views" property="views"/>
        <result column="province_id" property="provinceId"/>
        <result column="city_id" property="cityId"/>
        <result column="county_id" property="countyId"/>
        <result column="created_time" property="createdTime"/>
        <result column="publish_time" property="publishTime"/>
        <result column="sync_status" property="syncStatus"/>
        <result column="static_url" property="staticUrl"/>
    </resultMap>

    <select id="loadArticleList" resultMap="resultMap">
        SELECT
        aa.*
        FROM
        `ap_article` aa
        LEFT JOIN ap_article_config aac ON aa.id = aac.article_id
        <where>
            and aac.is_delete != 1
            and aac.is_down != 1
            <!-- loadmore -->
            <if test="type != null and type == 1">
                and aa.publish_time <![CDATA[<]]> #{dto.minBehotTime}
            </if>
            <if test="type != null and type == 2">
                and aa.publish_time <![CDATA[>]]> #{dto.maxBehotTime}
            </if>
            <if test="dto.tag != '__all__'">
                and aa.channel_id = #{dto.tag}
            </if>
        </where>
        order by aa.publish_time desc
        limit #{dto.size}
    </select>

</mapper>

4.7 Service

package com.heima.article.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.pojos.ApArticle;

import java.util.List;

public interface ApArticleService extends IService<ApArticle> {

    //加载文章列表
    List<ApArticle> load(Short type, ArticleHomeDto dto);
}

4.8 ServiceImpl

package com.heima.article.service.serviceimpl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.ApArticleService;
import com.heima.common.constants.ArticleConstants;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.pojos.ApArticle;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

@Service
@Transactional
@Slf4j
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements ApArticleService {

    @Autowired
    private ApArticleMapper apArticleMapper;

    private static final short MAX_PAGE_SIZE = 50;


    /**
     *
     * @param type 1加载更多,加载最新
     * @param dto
     * @return
     */
    public List<ApArticle> load(Short type, ArticleHomeDto dto) {

        //参数校验

        //1.校验分页条数
        Integer size = dto.getSize();
        if(size == null || size == 0){
            dto.setSize(10);
        }
        Math.min(size, MAX_PAGE_SIZE);

        //2.type
        if(!type.equals(ArticleConstants.LOADTYPE_LOAD_MORE) || type.equals(ArticleConstants.LOADTYPE_LOAD_NEW)){
            type= ArticleConstants.LOADTYPE_LOAD_MORE;
        }

        //频道
        if(StringUtils.isEmpty(dto.getTag())){
            dto.setTag(ArticleConstants.DEFAULT_TAG);
        }
        //时间
        if(dto.getMaxBehotTime() == null){
            dto.setMaxBehotTime(new Date());
        }
        if(dto.getMinBehotTime() == null){
            dto.setMinBehotTime(new Date());
        }


        List<ApArticle> apArticles = apArticleMapper.loadArticleList(dto, type);
        return apArticles;
    }
}

4.9 Controller

package com.heima.article.controller.v1;

import com.heima.article.service.ApArticleService;
import com.heima.common.constants.ArticleConstants;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.common.dtos.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/api/v1/article")
public class ApArticleController {
    @Autowired
    private ApArticleService apArticleService;

    /**
     * 加载首页
     * 请求路径:"api/v1/article/load"
     * 请求方式:post
     * 请求参数: ArticleHomeDto
     * 响应数据:List<Aparticle>
     *
     */
    @PostMapping("/load")
    public ResponseResult load(@RequestBody ArticleHomeDto dto){
        List<ApArticle> apArticles = apArticleService.load(ArticleConstants.LOADTYPE_LOAD_MORE,dto);

        return ResponseResult.okResult(apArticles);
    }


    /**
     *加载更多
     *请求路径:"api/v1/article/loadmore"
     *请求方式:post
     *请求参数: ArticleHomeDto
     *响应数据:List<Aparticle>
     */
    @PostMapping("/loadmore")
    public ResponseResult loadmore(@RequestBody ArticleHomeDto dto){
        List<ApArticle> apArticles = apArticleService.load(ArticleConstants.LOADTYPE_LOAD_MORE,dto);

        return ResponseResult.okResult(apArticles);
    }

    /**
     *加载最新
     *请求路径:"api/v1/article/loadnew"
     *请求方式:post
     *请求参数: ArticleHomeDto
     *响应数据:List<Aparticle>
     */
    @PostMapping("/loadnew")
    public ResponseResult loadnew(@RequestBody ArticleHomeDto dto){
        List<ApArticle> apArticles = apArticleService.load(ArticleConstants.LOADTYPE_LOAD_NEW,dto);

        return ResponseResult.okResult(apArticles);
    }
}

五、配置文章微服务gateway网关断言规则

      routes:
        # 文章微服务
        - id: article
          uri: lb://leadnews-article
          predicates:
            - Path=/article/**
          filters:
            - StripPrefix= 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

糖分你俩颗~~~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值