app端文章查看,静态化freemarker,分布式文件系统minIO
1)文章列表加载
1.1)需求分析
文章布局展示
1.2)表结构分析
ap_article 文章基本信息表
ap_article_config 文章配置表
ap_article_content 文章内容表
三张表关系分析
1.3)导入文章数据库
1.3.1)导入数据库
查看当天资料文件夹,在数据库连接工具中执行leadnews_article.sql
1.3.2)导入对应的实体类
ap_article文章表对应实体
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">heima</span>.<span style="color:#000000">model</span>.<span style="color:#000000">article</span>.<span style="color:#000000">pojos</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">IdType</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">TableField</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">TableId</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">TableName</span>;
<span style="color:#770088">import</span> <span style="color:#000000">lombok</span>.<span style="color:#000000">Data</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">io</span>.<span style="color:#000000">Serializable</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">util</span>.<span style="color:#000000">Date</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* <p></span>
<span style="color:#aa5500">* 文章信息表,存储已发布的文章</span>
<span style="color:#aa5500">* </p></span>
<span style="color:#aa5500">*</span>
<span style="color:#aa5500">* @author itheima</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@Data</span>
<span style="color:#555555">@TableName</span>(<span style="color:#aa1111">"ap_article"</span>)
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">ApArticle</span> <span style="color:#770088">implements</span> <span style="color:#000000">Serializable</span> {
<span style="color:#555555">@TableId</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"id"</span>,<span style="color:#000000">type</span> <span style="color:#981a1a">=</span> <span style="color:#000000">IdType</span>.<span style="color:#000000">ID_WORKER</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Long</span> <span style="color:#000000">id</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 标题</span>
<span style="color:#aa5500">*/</span>
<span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">title</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 作者id</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"author_id"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Long</span> <span style="color:#000000">authorId</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 作者名称</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"author_name"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">authorName</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 频道id</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"channel_id"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Integer</span> <span style="color:#000000">channelId</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 频道名称</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"channel_name"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">channelName</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 文章布局 0 无图文章 1 单图文章 2 多图文章</span>
<span style="color:#aa5500">*/</span>
<span style="color:#770088">private</span> <span style="color:#008855">Short</span> <span style="color:#000000">layout</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 文章标记 0 普通文章 1 热点文章 2 置顶文章 3 精品文章 4 大V 文章</span>
<span style="color:#aa5500">*/</span>
<span style="color:#770088">private</span> <span style="color:#008855">Byte</span> <span style="color:#000000">flag</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 文章封面图片 多张逗号分隔</span>
<span style="color:#aa5500">*/</span>
<span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">images</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 标签</span>
<span style="color:#aa5500">*/</span>
<span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">labels</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 点赞数量</span>
<span style="color:#aa5500">*/</span>
<span style="color:#770088">private</span> <span style="color:#008855">Integer</span> <span style="color:#000000">likes</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 收藏数量</span>
<span style="color:#aa5500">*/</span>
<span style="color:#770088">private</span> <span style="color:#008855">Integer</span> <span style="color:#000000">collection</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 评论数量</span>
<span style="color:#aa5500">*/</span>
<span style="color:#770088">private</span> <span style="color:#008855">Integer</span> <span style="color:#000000">comment</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 阅读数量</span>
<span style="color:#aa5500">*/</span>
<span style="color:#770088">private</span> <span style="color:#008855">Integer</span> <span style="color:#000000">views</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 省市</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"province_id"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Integer</span> <span style="color:#000000">provinceId</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 市区</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"city_id"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Integer</span> <span style="color:#000000">cityId</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 区县</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"county_id"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Integer</span> <span style="color:#000000">countyId</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 创建时间</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"created_time"</span>)
<span style="color:#770088">private</span> <span style="color:#000000">Date</span> <span style="color:#000000">createdTime</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 发布时间</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"publish_time"</span>)
<span style="color:#770088">private</span> <span style="color:#000000">Date</span> <span style="color:#000000">publishTime</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 同步状态</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"sync_status"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Boolean</span> <span style="color:#000000">syncStatus</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 来源</span>
<span style="color:#aa5500">*/</span>
<span style="color:#770088">private</span> <span style="color:#008855">Boolean</span> <span style="color:#000000">origin</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 静态页面地址</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"static_url"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">staticUrl</span>;
}</span></span>
ap_article_config文章配置对应实体类
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">heima</span>.<span style="color:#000000">model</span>.<span style="color:#000000">article</span>.<span style="color:#000000">pojos</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">IdType</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">TableField</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">TableId</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">TableName</span>;
<span style="color:#770088">import</span> <span style="color:#000000">lombok</span>.<span style="color:#000000">Data</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">io</span>.<span style="color:#000000">Serializable</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* <p></span>
<span style="color:#aa5500">* APP已发布文章配置表</span>
<span style="color:#aa5500">* </p></span>
<span style="color:#aa5500">*</span>
<span style="color:#aa5500">* @author itheima</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@Data</span>
<span style="color:#555555">@TableName</span>(<span style="color:#aa1111">"ap_article_config"</span>)
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">ApArticleConfig</span> <span style="color:#770088">implements</span> <span style="color:#000000">Serializable</span> {
<span style="color:#555555">@TableId</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"id"</span>,<span style="color:#000000">type</span> <span style="color:#981a1a">=</span> <span style="color:#000000">IdType</span>.<span style="color:#000000">ID_WORKER</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Long</span> <span style="color:#000000">id</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 文章id</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"article_id"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Long</span> <span style="color:#000000">articleId</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 是否可评论</span>
<span style="color:#aa5500">* true: 可以评论 1</span>
<span style="color:#aa5500">* false: 不可评论 0</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"is_comment"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Boolean</span> <span style="color:#000000">isComment</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 是否转发</span>
<span style="color:#aa5500">* true: 可以转发 1</span>
<span style="color:#aa5500">* false: 不可转发 0</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"is_forward"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Boolean</span> <span style="color:#000000">isForward</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 是否下架</span>
<span style="color:#aa5500">* true: 下架 1</span>
<span style="color:#aa5500">* false: 没有下架 0</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"is_down"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Boolean</span> <span style="color:#000000">isDown</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 是否已删除</span>
<span style="color:#aa5500">* true: 删除 1</span>
<span style="color:#aa5500">* false: 没有删除 0</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"is_delete"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Boolean</span> <span style="color:#000000">isDelete</span>;
}</span></span>
ap_article_content 文章内容对应的实体类
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">heima</span>.<span style="color:#000000">model</span>.<span style="color:#000000">article</span>.<span style="color:#000000">pojos</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">IdType</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">TableField</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">TableId</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">TableName</span>;
<span style="color:#770088">import</span> <span style="color:#000000">lombok</span>.<span style="color:#000000">Data</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">io</span>.<span style="color:#000000">Serializable</span>;
<span style="color:#555555">@Data</span>
<span style="color:#555555">@TableName</span>(<span style="color:#aa1111">"ap_article_content"</span>)
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">ApArticleContent</span> <span style="color:#770088">implements</span> <span style="color:#000000">Serializable</span> {
<span style="color:#555555">@TableId</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"id"</span>,<span style="color:#000000">type</span> <span style="color:#981a1a">=</span> <span style="color:#000000">IdType</span>.<span style="color:#000000">ID_WORKER</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Long</span> <span style="color:#000000">id</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 文章id</span>
<span style="color:#aa5500">*/</span>
<span style="color:#555555">@TableField</span>(<span style="color:#aa1111">"article_id"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">Long</span> <span style="color:#000000">articleId</span>;
<span style="color:#aa5500">/**</span>
<span style="color:#aa5500">* 文章内容</span>
<span style="color:#aa5500">*/</span>
<span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">content</span>;
}</span></span>
1.4)实现思路
1,在默认频道展示10条文章信息
2,可以切换频道查看不同种类文章
3,当用户下拉可以加载最新的文章(分页)本页文章列表中发布时间为最大的时间为依据
4,当用户上拉可以加载更多的文章信息(按照发布时间)本页文章列表中发布时间最小的时间为依据
5,如果是当前频道的首页,前端传递默认参数:
-
maxBehotTime:0(毫秒)
-
minBehotTime:20000000000000(毫秒)--->2063年
1.5)接口定义
加载首页 | 加载更多 | 加载最新 | |
---|---|---|---|
接口路径 | /api/v1/article/load | /api/v1/article/loadmore | /api/v1/article/loadnew |
请求方式 | POST | POST | POST |
参数 | ArticleHomeDto | ArticleHomeDto | ArticleHomeDto |
响应结果 | ResponseResult | ResponseResult | ResponseResult |
ArticleHomeDto
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">heima</span>.<span style="color:#000000">model</span>.<span style="color:#000000">article</span>.<span style="color:#000000">dtos</span>;
<span style="color:#770088">import</span> <span style="color:#000000">lombok</span>.<span style="color:#000000">Data</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">util</span>.<span style="color:#000000">Date</span>;
<span style="color:#555555">@Data</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">ArticleHomeDto</span> {
<span style="color:#aa5500">// 最大时间</span>
<span style="color:#000000">Date</span> <span style="color:#000000">maxBehotTime</span>;
<span style="color:#aa5500">// 最小时间</span>
<span style="color:#000000">Date</span> <span style="color:#000000">minBehotTime</span>;
<span style="color:#aa5500">// 分页size</span>
<span style="color:#008855">Integer</span> <span style="color:#000000">size</span>;
<span style="color:#aa5500">// 频道ID</span>
<span style="color:#008855">String</span> <span style="color:#000000">tag</span>;
}</span></span>
1.6)功能实现
1.6.1):导入heima-leadnews-article微服务,资料在当天的文件夹中
注意:需要在heima-leadnews-service的pom文件夹中添加子模块信息,如下:
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#117700"><</span><span style="color:#117700">modules</span><span style="color:#117700">></span>
<span style="color:#117700"><</span><span style="color:#117700">module</span><span style="color:#117700">></span>heima-leadnews-user<span style="color:#117700"></</span><span style="color:#117700">module</span><span style="color:#117700">></span>
<span style="color:#117700"><</span><span style="color:#117700">module</span><span style="color:#117700">></span>heima-leadnews-article<span style="color:#117700"></</span><span style="color:#117700">module</span><span style="color:#117700">></span>
<span style="color:#117700"></</span><span style="color:#117700">modules</span><span style="color:#117700">></span></span></span>
在idea中的maven中更新一下,如果工程还是灰色的,需要在重新添加文章微服务的pom文件,操作步骤如下:
需要在nacos中添加对应的配置
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#221199">spring</span><span style="color:#555555">:</span>
<span style="color:#221199"> datasource</span><span style="color:#555555">:</span>
<span style="color:#221199"> driver-class-name</span><span style="color:#555555">: </span>com.mysql.jdbc.Driver
<span style="color:#221199"> url</span><span style="color:#555555">: </span>jdbc<span style="color:#555555">:</span>mysql<span style="color:#555555">:</span>//localhost<span style="color:#555555">:</span>3306/leadnews_article?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
<span style="color:#221199"> username</span><span style="color:#555555">: </span>root
<span style="color:#221199"> password</span><span style="color:#555555">: </span>root
<span style="color:#aa5500"># 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置</span>
<span style="color:#221199">mybatis-plus</span><span style="color:#555555">:</span>
<span style="color:#221199"> mapper-locations</span><span style="color:#555555">: </span>classpath*<span style="color:#555555">:</span>mapper/*.xml
<span style="color:#aa5500"># 设置别名包扫描路径,通过该属性可以给包中的类注册别名</span>
<span style="color:#221199"> type-aliases-package</span><span style="color:#555555">: </span>com.heima.model.article.pojos</span></span>
1.6.2):定义接口
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">heima</span>.<span style="color:#000000">article</span>.<span style="color:#000000">controller</span>.<span style="color:#000000">v1</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">heima</span>.<span style="color:#000000">model</span>.<span style="color:#000000">article</span>.<span style="color:#000000">dtos</span>.<span style="color:#000000">ArticleHomeDto</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">heima</span>.<span style="color:#000000">model</span>.<span style="color:#000000">common</span>.<span style="color:#000000">dtos</span>.<span style="color:#000000">ResponseResult</span>;
<span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">springframework</span>.<span style="color:#000000">web</span>.<span style="color:#000000">bind</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">PostMapping</span>;
<span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">springframework</span>.<span style="color:#000000">web</span>.<span style="color:#000000">bind</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">RequestBody</span>;
<span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">springframework</span>.<span style="color:#000000">web</span>.<span style="color:#000000">bind</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">RequestMapping</span>;
<span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">springframework</span>.<span style="color:#000000">web</span>.<span style="color:#000000">bind</span>.<span style="color:#000000">annotation</span>.<span style="color:#000000">RestController</span>;
<span style="color:#555555">@RestController</span>
<span style="color:#555555">@RequestMapping</span>(<span style="color:#aa1111">"/api/v1/article"</span>)
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">ArticleHomeController</span> {
<span style="color:#555555">@PostMapping</span>(<span style="color:#aa1111">"/load"</span>)
<span style="color:#770088">public</span> <span style="color:#000000">ResponseResult</span> <span style="color:#000000">load</span>(<span style="color:#555555">@RequestBody</span> <span style="color:#000000">ArticleHomeDto</span> <span style="color:#000000">dto</span>) {
<span style="color:#770088">return</span> <span style="color:#221199">null</span>;
}
<span style="color:#555555">@PostMapping</span>(<span style="color:#aa1111">"/loadmore"</span>)
<span style="color:#770088">public</span> <span style="color:#000000">ResponseResult</span> <span style="color:#000000">loadMore</span>(<span style="color:#555555">@RequestBody</span> <span style="color:#000000">ArticleHomeDto</span> <span style="color:#000000">dto</span>) {
<span style="color:#770088">return</span> <span style="color:#221199">null</span>;
}
<span style="color:#555555">@PostMapping</span>(<span style="color:#aa1111">"/loadnew"</span>)
<span style="color:#770088">public</span> <span style="color:#000000">ResponseResult</span> <span style="color:#000000">loadNew</span>(<span style="color:#555555">@RequestBody</span> <span style="color:#000000">ArticleHomeDto</span> <span style="color:#000000">dto</span>) {
<span style="color:#770088">return</span> <span style="color:#221199">null</span>;
}
}</span></span>
1.6.3):编写mapper文件
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">package</span> <span style="color:#0000ff">com</span>.<span style="color:#000000">heima</span>.<span style="color:#000000">article</span>.<span style="color:#000000">mapper</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">baomidou</span>.<span style="color:#000000">mybatisplus</span>.<span style="color:#000000">core</span>.<span style="color:#000000">mapper</span>.<span style="color:#000000">BaseMapper</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">heima</span>.<span style="color:#000000">model</span>.<span style="color:#000000">article</span>.<span style="color:#000000">dtos</span>.<span style="color:#000000">ArticleHomeDto</span>;
<span style="color:#770088">import</span> <span style="color:#000000">com</span>.<span style="color:#000000">heima</span>.<span style="color:#000000">model</span>.<span style="color:#000000">article</span>.<span style="color:#000000">pojos</span>.<span style="color:#000000">ApArticle</span>;
<span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">apache</span>.<span style="color:#000000">ibatis</span>.<span style="color:#000000">annotations</span>.<span style="color:#000000">Mapper</span>;
<span style="color:#770088">import</span> <span style="color:#000000">org</span>.<span style="color:#000000">apache</span>.<span style="color:#000000">ibatis</span>.<span style="color:#000000">annotations</span>.<span style="color:#000000">Param</span>;
<span style="color:#770088">import</span> <span style="color:#000000">java</span>.<span style="color:#000000">util</span>.<span style="color:#000000">List</span>;
<span style="color:#555555">@Mapper</span>
<span style="color:#770088">public</span> <span style="color:#770088">interface</span> <span style="color:#0000ff">ApArticleMapper</span> <span style="color:#770088">extends</span> <span style="color:#000000">BaseMapper</span><span style="color:#981a1a"><</span><span style="color:#000000">ApArticle</span><span style="color:#981a1a">></span> {
<span style="color:#770088">public</span> <span style="color:#000000">List</span><span style="color:#981a1a"><</span><span style="color:#000000">ApArticle</span><span style="color:#981a1a">></span> <span style="color:#000000">loadArticleList</span>(<span style="color:#555555">@Param</span>(<span style="color:#aa1111">"dto"</span>) <span style="color:#000000">ArticleHomeDto</span> <span style="color:#000000">dto</span>, <span style="color:#555555">@Param</span>(<span style="color:#aa1111">"type"</span>) <span style="color:#008855">Short</span> <span style="color:#000000">type</span>);
}</span></span>
对应的映射文件
在resources中新建mapper/ApArticleMapper.xml 如下配置:
<span style="background-color:#f8f8f8"><span style="color:#333333"><?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></span></span>
1.6.4):编写业务层代码
<span style="background-color:#f8f8f8"><span style="color:#333333">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 com.heima.model.common.dtos.ResponseResult;
import java.io.IOException;
public interface ApArticleService extends IService<ApArticle> {
/**
* 根据参数加载文章列表
* @param loadtype 1为加载更多 2为加载最新
* @param dto
* @return
*/
ResponseResult load(Short loadtype, ArticleHomeDto dto);
}</span></span>
实现类:
<span style="background-color:#f8f8f8"><span style="color:#333333">package com.heima.article.service.impl;
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 com.heima.model.common.dtos.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
@Service
@Transactional
@Slf4j
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements ApArticleService {
// 单页最大加载的数字
private final static short MAX_PAGE_SIZE = 50;
@Autowired
private ApArticleMapper apArticleMapper;
/**
* 根据参数加载文章列表
* @param loadtype 1为加载更多 2为加载最新
* @param dto
* @return
*/
@Override
public ResponseResult load(Short loadtype, ArticleHomeDto dto) {
//1.校验参数
Integer size = dto.getSize();
if(size == null || size == 0){
size = 10;
}
size = Math.min(size,MAX_PAGE_SIZE);
dto.setSize(size);
//类型参数检验
if(!loadtype.equals(ArticleConstants.LOADTYPE_LOAD_MORE)&&!loadtype.equals(ArticleConstants.LOADTYPE_LOAD_NEW)){
loadtype = 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());
//2.查询数据
List<ApArticle> apArticles = apArticleMapper.loadArticleList(dto, loadtype);
//3.结果封装
ResponseResult responseResult = ResponseResult.okResult(apArticles);
return responseResult;
}
}</span></span>
定义常量类
<span style="background-color:#f8f8f8"><span style="color:#333333">package com.heima.common.constants;
public class ArticleConstants {
public static final Short LOADTYPE_LOAD_MORE = 1;
public static final Short LOADTYPE_LOAD_NEW = 2;
public static final String DEFAULT_TAG = "__all__";
}</span></span>
1.6.5):编写控制器代码
<span style="background-color:#f8f8f8"><span style="color:#333333">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.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;
@RestController
@RequestMapping("/api/v1/article")
public class ArticleHomeController {
@Autowired
private ApArticleService apArticleService;
@PostMapping("/load")
public ResponseResult load(@RequestBody ArticleHomeDto dto) {
return apArticleService.load(ArticleConstants.LOADTYPE_LOAD_MORE,dto);
}
@PostMapping("/loadmore")
public ResponseResult loadMore(@RequestBody ArticleHomeDto dto) {
return apArticleService.load(ArticleConstants.LOADTYPE_LOAD_MORE,dto);
}
@PostMapping("/loadnew")
public ResponseResult loadNew(@RequestBody ArticleHomeDto dto) {
return apArticleService.load(ArticleConstants.LOADTYPE_LOAD_NEW,dto);
}
}</span></span>
1.6.6):swagger测试或前后端联调测试
第一:在app网关的微服务的nacos的配置中心添加文章微服务的路由,完整配置如下:
<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]': # 匹配所有请求
allowedOrigins: "*" #跨域处理 允许所有的域
allowedMethods: # 支持的方法
- GET
- POST
- PUT
- DELETE
routes:
# 用户微服务
- id: user
uri: lb://leadnews-user
predicates:
- Path=/user/**
filters:
- StripPrefix= 1
# 文章微服务
- id: article
uri: lb://leadnews-article
predicates:
- Path=/article/**
filters:
- StripPrefix= 1</span></span>
第二:启动nginx,直接使用前端项目测试,启动文章微服务,用户微服务、app网关微服务
2)freemarker
2.1) freemarker 介绍
FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
模板编写为FreeMarker Template Language (FTL)。它是简单的,专用的语言, 不是 像PHP那样成熟的编程语言。 那就意味着要准备数据在真实编程语言中来显示,比如数据库查询和业务运算, 之后模板显示已经准备好的数据。在模板中,你可以专注于如何展现数据, 而在模板之外可以专注于要展示什么数据。
常用的java模板引擎还有哪些?
Jsp、Freemarker、Thymeleaf 、Velocity 等。
1.Jsp 为 Servlet 专用,不能单独进行使用。
2.Thymeleaf 为新技术,功能较为强大,但是执行的效率比较低。
3.Velocity从2010年更新完 2.0 版本后,便没有在更新。Spring Boot 官方在 1.4 版本后对此也不在支持,虽然 Velocity 在 2017 年版本得到迭代,但为时已晚。
2.2) 环境搭建&&快速入门
freemarker作为springmvc一种视图格式,默认情况下SpringMVC支持freemarker视图格式。
需要创建Spring Boot+Freemarker工程用于测试模板。
2.2.1) 创建测试工程
创建一个freemarker-demo 的测试工程专门用于freemarker的功能测试与模板的测试。
pom.xml如下
<span style="background-color:#f8f8f8"><span style="color:#333333"><?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>heima-leadnews-test</artifactId>
<groupId>com.heima</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>freemarker-demo</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- apache 对 java io 的封装工具库 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
</project></span></span>
2.2.2) 配置文件
配置application.yml
<span style="background-color:#f8f8f8"><span style="color:#333333">server:
port: 8881 #服务端口
spring:
application:
name: freemarker-demo #指定服务名
freemarker:
cache: false #关闭模板缓存,方便测试
settings:
template_update_delay: 0 #检查模板更新延迟时间,设置为0表示立即检查,如果时间大于0会有缓存不方便进行模板测试
suffix: .ftl #指定Freemarker模板文件的后缀名</span></span>
2.2.3) 创建模型类
在freemarker的测试工程下创建模型类型用于测试
<span style="background-color:#f8f8f8"><span style="color:#333333">package com.heima.freemarker.entity;
import lombok.Data;
import java.util.Date;
@Data
public class Student {
private String name;//姓名
private int age;//年龄
private Date birthday;//生日
private Float money;//钱包
}</span></span>
2.2.4) 创建模板
在resources下创建templates,此目录为freemarker的默认模板存放目录。
在templates下创建模板文件 01-basic.ftl ,模板中的插值表达式最终会被freemarker替换成具体的数据。
<span style="background-color:#f8f8f8"><span style="color:#333333"><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World!</title>
</head>
<body>
<b>普通文本 String 展示:</b><br><br>
Hello ${name} <br>
<hr>
<b>对象Student中的数据展示:</b><br/>
姓名:${stu.name}<br/>
年龄:${stu.age}
<hr>
</body>
</html></span></span>
2.2.5) 创建controller
创建Controller类,向Map中添加name,最后返回模板文件。
<span style="background-color:#f8f8f8"><span style="color:#333333">package com.xuecheng.test.freemarker.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Controller
public class HelloController {
@GetMapping("/basic")
public String test(Model model) {
//1.纯文本形式的参数
model.addAttribute("name", "freemarker");
//2.实体类相关的参数
Student student = new Student();
student.setName("小明");
student.setAge(18);
model.addAttribute("stu", student);
return "01-basic";
}
}</span></span>
01-basic.ftl,使用插值表达式填充数据
<span style="background-color:#f8f8f8"><span style="color:#333333"><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World!</title>
</head>
<body>
<b>普通文本 String 展示:</b><br><br>
Hello ${name} <br>
<hr>
<b>对象Student中的数据展示:</b><br/>
姓名:${stu.name}<br/>
年龄:${stu.age}
<hr>
</body>
</html></span></span>
2.2.6) 创建启动类
<span style="background-color:#f8f8f8"><span style="color:#333333">package com.heima.freemarker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FreemarkerDemotApplication {
public static void main(String[] args) {
SpringApplication.run(FreemarkerDemotApplication.class,args);
}
}</span></span>
2.2.7) 测试
请求:http://localhost:8881/basic
2.3) freemarker基础
2.3.1) 基础语法种类
1、注释,即<#-- -->,介于其之间的内容会被freemarker忽略
<span style="background-color:#f8f8f8"><span style="color:#333333"><#--我是一个freemarker注释--></span></span>
2、插值(Interpolation):即 ${..}
部分,freemarker会用真实的值代替${..}
<span style="background-color:#f8f8f8"><span style="color:#333333">Hello ${name}</span></span>
3、FTL指令:和HTML标记类似,名字前加#予以区分,Freemarker会解析标签中的表达式或逻辑。
<span style="background-color:#f8f8f8"><span style="color:#333333"><# >FTL指令</#> </span></span>
4、文本,仅文本信息,这些不是freemarker的注释、插值、FTL指令的内容会被freemarker忽略解析,直接输出内容。
<span style="background-color:#f8f8f8"><span style="color:#333333"><#--freemarker中的普通文本-->
我是一个普通的文本</span></span>
2.3.2) 集合指令(List和Map)
1、数据模型:
在HelloController中新增如下方法:
<span style="background-color:#f8f8f8"><span style="color:#333333">@GetMapping("/list")
public String list(Model model){
//------------------------------------
Student stu1 = new Student();
stu1.setName("小强");
stu1.setAge(18);
stu1.setMoney(1000.86f);
stu1.setBirthday(new Date());
//小红对象模型数据
Student stu2 = new Student();
stu2.setName("小红");
stu2.setMoney(200.1f);
stu2.setAge(19);
//将两个对象模型数据存放到List集合中
List<Student> stus = new ArrayList<>();
stus.add(stu1);
stus.add(stu2);
//向model中存放List集合数据
model.addAttribute("stus",stus);
//------------------------------------
//创建Map数据
HashMap<String,Student> stuMap = new HashMap<>();
stuMap.put("stu1",stu1);
stuMap.put("stu2",stu2);
// 3.1 向model中存放Map数据
model.addAttribute("stuMap", stuMap);
return "02-list";
}</span></span>
2、模板:
在templates中新增02-list.ftl
文件
<span style="background-color:#f8f8f8"><span style="color:#333333"><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World!</title>
</head>
<body>
<#-- list 数据的展示 -->
<b>展示list中的stu数据:</b>
<br>
<br>
<table>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>钱包</td>
</tr>
</table>
<hr>
<#-- Map 数据的展示 -->
<b>map数据的展示:</b>
<br/><br/>
<a href="###">方式一:通过map['keyname'].property</a><br/>
输出stu1的学生信息:<br/>
姓名:<br/>
年龄:<br/>
<br/>
<a href="###">方式二:通过map.keyname.property</a><br/>
输出stu2的学生信息:<br/>
姓名:<br/>
年龄:<br/>
<br/>
<a href="###">遍历map中两个学生信息:</a><br/>
<table>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>钱包</td>
</tr>
</table>
<hr>
</body>
</html></span></span>
实例代码:
<span style="background-color:#f8f8f8"><span style="color:#333333"><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World!</title>
</head>
<body>
<#-- list 数据的展示 -->
<b>展示list中的stu数据:</b>
<br>
<br>
<table>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>钱包</td>
</tr>
<#list stus as stu>
<tr>
<td>${stu_index+1}</td>
<td>${stu.name}</td>
<td>${stu.age}</td>
<td>${stu.money}</td>
</tr>
</#list>
</table>
<hr>
<#-- Map 数据的展示 -->
<b>map数据的展示:</b>
<br/><br/>
<a href="###">方式一:通过map['keyname'].property</a><br/>
输出stu1的学生信息:<br/>
姓名:${stuMap['stu1'].name}<br/>
年龄:${stuMap['stu1'].age}<br/>
<br/>
<a href="###">方式二:通过map.keyname.property</a><br/>
输出stu2的学生信息:<br/>
姓名:${stuMap.stu2.name}<br/>
年龄:${stuMap.stu2.age}<br/>
<br/>
<a href="###">遍历map中两个学生信息:</a><br/>
<table>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>钱包</td>
</tr>
<#list stuMap?keys as key >
<tr>
<td>${key_index}</td>
<td>${stuMap[key].name}</td>
<td>${stuMap[key].age}</td>
<td>${stuMap[key].money}</td>
</tr>
</#list>
</table>
<hr>
</body>
</html></span></span>