本文介绍了28.博客系统项目开发之文章详情页制作求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。
对技术面试,学习经验等有一些体会,在此分享。
Spring Boot 博客系统项目开发之文章详情页制作
本项目的开源仓库地址为:https://github.com/ZHENFENG13/My-Blog
除 My-Blog 项目外,我也在维护另外一个开源项目,仓库地址为:https://github.com/newbee-ltd/newbee-mall
感兴趣的朋友可以去关注一下。
文章总览
在前面几个实验中我们一直有提到文章详情页,因为训练营课程安排顺序的缘故,博客详情页被安排在了后面一些,详情页还没有制作完成所以有些 a 标签中的跳转链接地址无法填上,这个实验就来该开发文章详情页的相关功能了,我会从页面设计和排版讲起,之后是功能实现和页面优化。
知识点
- 详情页页面设计
- 详情查询功能实现及页面渲染
- markdown 格式转换
- 页面优化
环境
- JDK 1.8 或者更高版本
- Spring Boot 2.1.0-RELEASE
- Maven 3+
详情功能实现
页面设计
大家也常常浏览各个博客网站,应该能够看出来其实文章详情最重要的就是文章内容的展示,以及文章其他相关字段的展示,比如标签、浏览量之类的信息也会在文章详情页进行展示,接下来我们看一下我们这个博客系统最终的文章详情页展现效果来确认该页面的布局设计,如下图所示:
顶部导航栏和底部页脚区域是所有页面都有的页面元素,属于公共区域,这里就不再赘述,截图中也只是文章详情的功能展示区域,重点关注一下图中标注的四个地方,如上图所示,分别标注了四个区域,从上至下依次为:
- 文章的分类信息展示区域:主要用于放置分类名称和分类图标字段;
- 文章标题区域:放置文章标题,字体相较于其他部分会大很多;
- 文章的基础信息区域:放置文章的标签、时间、浏览量等字段;
- 文章详情区域:文章内容的展示区域,以上三个区域通常是固定的,而文章详情区域则会因为文章内容的多少动态的变化,内容多则占用的版面就多,反之就会少一些。
页面中还会有文章的评论列表区域和文章评论的输入区域,在本次实验中暂时就不介绍了,后面会单独用一个章节来开发博客的评论模块。
当然,以上版面设计的分析只是对于我的博客模板来说是这样的,社区中还有许多其他的博客系统项目,由于前端的设计和实现非常灵活且多变,这些博客系统可能又是另外一些页面样式和页面布局,比如我们的博客系统就有三个页面模板,不同的模板就会有不同的样式。
数据格式定义
通过上面的图片我们也能够看出文章详情页需要的字段,包括文章标题、文章标签、文章分类、文章内容等等字段,基本上文章表中的字段都用到了,返回数据的格式很清晰,编码如下:
package com.site.blog.my.core.controller.vo; import java.io.Serializable; import java.util.Date; import java.util.List; public class BlogDetailVO implements Serializable { private Long blogId; private String blogTitle; private Integer blogCategoryId; private Integer commentCount; private String blogCategoryIcon; private String blogCategoryName; private String blogCoverImage; private Long blogViews; private List<String> blogTags; private String blogContent; private Byte enableComment; private Date createTime; }
详情页跳转
详情页通常是通过点击博客列表页中的单个卡片中的链接跳转而来的,首页中以及搜素页面中会有这些跳转链接,详情页的路径我们定义为 /blog/{blogId},首先我们来修改首页模板代码及搜索页模板代码,添加 a 标签中的详情页跳转路径,修改如下:
- index.html 博客列表
<a th:href="@{'/blog/' + ${blog.blogId}}"> <img th:src="@{${blog.blogCoverImage}}" alt="" /> <h3><th:block th:text="${blog.blogTitle}"></th:block></h3> </a>
- index .html 点击最多
<li> <a th:href="@{'/blog/' + ${hotBlog.blogId}}"> <th:block th:text="${hotBlog.blogTitle}"></th:block> </a> </li>
- index .html 最新发布
<li> <a th:href="@{'/blog/' + ${newBlog.blogId}}"> <th:block th:text="${newBlog.blogTitle}"></th:block> </a> </li>
- list.html 博客列表
<a th:href="@{'/blog/' + ${blog.blogId}}"> <img th:src="@{${blog.blogCoverImage}}" alt="" /> <h3><th:block th:text="${blog.blogTitle}"></th:block></h3> </a>
链接添加后,在点击后就会跳转到详情页面,接下来是详情页的功能实现讲解。
数据查询实现
首先,是数据查询的功能实现,上述详情页面中的字段可以通过直接查询 tb_blog 文章表和 tb_blog_category 分类表来获取,传参时只需要传入文章的主键 id 即可,实现逻辑如下。
定义 service 方法,业务层代码如下(注:完整代码位于 com.site.blog.my.core.service.impl.BlogServiceImpl.java):
/** * 文章详情获取 * * @param blogId * @return */ public BlogDetailVO getBlogDetail(Long blogId) { Blog blog = blogMapper.selectByPrimaryKey(blogId); //不为空且状态为已发布 BlogDetailVO blogDetailVO = getBlogDetailVO(blog); if (blogDetailVO != null) { return blogDetailVO; } return null; } /** * 方法抽取 * * @param blog * @return */ private BlogDetailVO getBlogDetailVO(Blog blog) { //判空以及发布状态是否为已发布 if (blog != null && blog.getBlogStatus() == 1) { //增加浏览量 blog.setBlogViews(blog.getBlogViews() + 1); blogMapper.updateByPrimaryKey(blog); BlogDetailVO blogDetailVO = new BlogDetailVO(); BeanUtils.copyProperties(blog, blogDetailVO); //md格式转换 blogDetailVO.setBlogContent(MarkDownUtil.mdToHtml(blogDetailVO.getBlogContent())); BlogCategory blogCategory = categoryMapper.selectByPrimaryKey(blog.getBlogCategoryId()); if (blogCategory == null) { blogCategory = new BlogCategory(); blogCategory.setCategoryId(0); blogCategory.setCategoryName("默认分类"); blogCategory.setCategoryIcon("/admin/dist/img/category/00.png"); } //分类信息 blogDetailVO.setBlogCategoryIcon(blogCategory.getCategoryIcon()); if (!StringUtils.isEmpty(blog.getBlogTags())) { //标签设置 List<String> tags = Arrays.asList(blog.getBlogTags().split(",")); blogDetailVO.setBlogTags(tags); } return blogDetailVO; } return null; }
我们定义了 getBlogDetail()
方法并传入 blogId 参数,该方法的执行逻辑为:
- 根据 blogId 直接查询 tb_blog 表中的记录
- 判断查出的结果是否为空以及文章状态是否为发布状态,不是发布状态返回 null 值
- 每次请求文章详情接口都会执行浏览量加一的操作,直接修改 tb_blog 表中的 blog_view 字段
- 将 markdown 格式的 content 内容字段转换为带有 html 标签的页面,因为在后台管理系统中操作时使用的是 Editor.md 编辑器,存储到数据库中的字段也是 markdown 格式的字段,在页面中显示的话需要进行转换
- 设置分类信息字段
- 设置标签字段
- 返回结果
markdown 格式转换
在详情页的页面设计中我给出了文章详情页的最终展示效果图,通过 f12 打开浏览器控制台,我们来看一下页面的 html 源码,查看结果如下:
通过控制台的页面源码我们可以看出,此时页面上展示的文章内容已经不是 markdown 格式的,而是符合 html 标签语法的代码片段了,但是数据库里的内容确实是 markdown 格式的文档,我们打开数据库来确认一下该字段的值,内容如下:
数据库中存储的内容与页面上显示的内容并不同,也就是说在文章详情请求的过程中,肯定有一个步骤对这个字段进行了转换处理,这一步骤在前文中也已经提到了,接下来我来介绍一下如何将 markdown 格式的 content 内容字段转换为带有 html 标签的页面。
想要达到这个目的,我们需要借助第三方工具类,本系统中我们选择的 markdown 解析器是 CommonMark 解析器,首先需要将相关依赖引入到 pom.xml 文件中,依赖文件增加如下设置:
“`xml
Spring Boot 博客系统项目开发之文章详情页制作
本项目的开源仓库地址为:https://github.com/ZHENFENG13/My-Blog
除 My-Blog 项目外,我也在维护另外一个开源项目,仓库地址为:https://github.com/newbee-ltd/newbee-mall
感兴趣的朋友可以去关注一下。
文章总览
在前面几个实验中我们一直有提到文章详情页,因为训练营课程安排顺序的缘故,博客详情页被安排在了后面一些,详情页还没有制作完成所以有些 a 标签中的跳转链接地址无法填上,这个实验就来该开发文章详情页的相关功能了,我会从页面设计和排版讲起,之后是功能实现和页面优化。
知识点
- 详情页页面设计
- 详情查询功能实现及页面渲染
- markdown 格式转换
- 页面优化
环境
- JDK 1.8 或者更高版本
- Spring Boot 2.1.0-RELEASE
- Maven 3+
详情功能实现
页面设计
大家也常常浏览各个博客网站,应该能够看出来其实文章详情最重要的就是文章内容的展示,以及文章其他相关字段的展示,比如标签、浏览量之类的信息也会在文章详情页进行展示,接下来我们看一下我们这个博客系统最终的文章详情页展现效果来确认该页面的布局设计,如下图所示:
顶部导航栏和底部页脚区域是所有页面都有的页面元素,属于公共区域,这里就不再赘述,截图中也只是文章详情的功能展示区域,重点关注一下图中标注的四个地方,如上图所示,分别标注了四个区域,从上至下依次为:
- 文章的分类信息展示区域:主要用于放置分类名称和分类图标字段;
- 文章标题区域:放置文章标题,字体相较于其他部分会大很多;
- 文章的基础信息区域:放置文章的标签、时间、浏览量等字段;
- 文章详情区域:文章内容的展示区域,以上三个区域通常是固定的,而文章详情区域则会因为文章内容的多少动态的变化,内容多则占用的版面就多,反之就会少一些。
页面中还会有文章的评论列表区域和文章评论的输入区域,在本次实验中暂时就不介绍了,后面会单独用一个章节来开发博客的评论模块。
当然,以上版面设计的分析只是对于我的博客模板来说是这样的,社区中还有许多其他的博客系统项目,由于前端的设计和实现非常灵活且多变,这些博客系统可能又是另外一些页面样式和页面布局,比如我们的博客系统就有三个页面模板,不同的模板就会有不同的样式。
数据格式定义
通过上面的图片我们也能够看出文章详情页需要的字段,包括文章标题、文章标签、文章分类、文章内容等等字段,基本上文章表中的字段都用到了,返回数据的格式很清晰,编码如下:
package com.site.blog.my.core.controller.vo; import java.io.Serializable; import java.util.Date; import java.util.List; public class BlogDetailVO implements Serializable { private Long blogId; private String blogTitle; private Integer blogCategoryId; private Integer commentCount; private String blogCategoryIcon; private String blogCategoryName; private String blogCoverImage; private Long blogViews; private List<String> blogTags; private String blogContent; private Byte enableComment; private Date createTime; }
详情页跳转
详情页通常是通过点击博客列表页中的单个卡片中的链接跳转而来的,首页中以及搜素页面中会有这些跳转链接,详情页的路径我们定义为 /blog/{blogId},首先我们来修改首页模板代码及搜索页模板代码,添加 a 标签中的详情页跳转路径,修改如下:
- index.html 博客列表
<a th:href="@{'/blog/' + ${blog.blogId}}"> <img th:src="@{${blog.blogCoverImage}}" alt="" /> <h3><th:block th:text="${blog.blogTitle}"></th:block></h3> </a>
- index .html 点击最多
<li> <a th:href="@{'/blog/' + ${hotBlog.blogId}}"> <th:block th:text="${hotBlog.blogTitle}"></th:block> </a> </li>
- index .html 最新发布
<li> <a th:href="@{'/blog/' + ${newBlog.blogId}}"> <th:block th:text="${newBlog.blogTitle}"></th:block> </a> </li>
- list.html 博客列表
<a th:href="@{'/blog/' + ${blog.blogId}}"> <img th:src="@{${blog.blogCoverImage}}" alt="" /> <h3><th:block th:text="${blog.blogTitle}"></th:block></h3> </a>
链接添加后,在点击后就会跳转到详情页面,接下来是详情页的功能实现讲解。
数据查询实现
首先,是数据查询的功能实现,上述详情页面中的字段可以通过直接查询 tb_blog 文章表和 tb_blog_category 分类表来获取,传参时只需要传入文章的主键 id 即可,实现逻辑如下。
定义 service 方法,业务层代码如下(注:完整代码位于 com.site.blog.my.core.service.impl.BlogServiceImpl.java):
/** * 文章详情获取 * * @param blogId * @return */ public BlogDetailVO getBlogDetail(Long blogId) { Blog blog = blogMapper.selectByPrimaryKey(blogId); //不为空且状态为已发布 BlogDetailVO blogDetailVO = getBlogDetailVO(blog); if (blogDetailVO != null) { return blogDetailVO; } return null; } /** * 方法抽取 * * @param blog * @return */ private BlogDetailVO getBlogDetailVO(Blog blog) { //判空以及发布状态是否为已发布 if (blog != null && blog.getBlogStatus() == 1) { //增加浏览量 blog.setBlogViews(blog.getBlogViews() + 1); blogMapper.updateByPrimaryKey(blog); BlogDetailVO blogDetailVO = new BlogDetailVO(); BeanUtils.copyProperties(blog, blogDetailVO); //md格式转换 blogDetailVO.setBlogContent(MarkDownUtil.mdToHtml(blogDetailVO.getBlogContent())); BlogCategory blogCategory = categoryMapper.selectByPrimaryKey(blog.getBlogCategoryId()); if (blogCategory == null) { blogCategory = new BlogCategory(); blogCategory.setCategoryId(0); blogCategory.setCategoryName("默认分类"); blogCategory.setCategoryIcon("/admin/dist/img/category/00.png"); } //分类信息 blogDetailVO.setBlogCategoryIcon(blogCategory.getCategoryIcon()); if (!StringUtils.isEmpty(blog.getBlogTags())) { //标签设置 List<String> tags = Arrays.asList(blog.getBlogTags().split(",")); blogDetailVO.setBlogTags(tags); } return blogDetailVO; } return null; }
我们定义了 getBlogDetail()
方法并传入 blogId 参数,该方法的执行逻辑为:
- 根据 blogId 直接查询 tb_blog 表中的记录
- 判断查出的结果是否为空以及文章状态是否为发布状态,不是发布状态返回 null 值
- 每次请求文章详情接口都会执行浏览量加一的操作,直接修改 tb_blog 表中的 blog_view 字段
- 将 markdown 格式的 content 内容字段转换为带有 html 标签的页面,因为在后台管理系统中操作时使用的是 Editor.md 编辑器,存储到数据库中的字段也是 markdown 格式的字段,在页面中显示的话需要进行转换
- 设置分类信息字段
- 设置标签字段
- 返回结果
markdown 格式转换
在详情页的页面设计中我给出了文章详情页的最终展示效果图,通过 f12 打开浏览器控制台,我们来看一下页面的 html 源码,查看结果如下:
通过控制台的页面源码我们可以看出,此时页面上展示的文章内容已经不是 markdown 格式的,而是符合 html 标签语法的代码片段了,但是数据库里的内容确实是 markdown 格式的文档,我们打开数据库来确认一下该字段的值,内容如下:
数据库中存储的内容与页面上显示的内容并不同,也就是说在文章详情请求的过程中,肯定有一个步骤对这个字段进行了转换处理,这一步骤在前文中也已经提到了,接下来我来介绍一下如何将 markdown 格式的 content 内容字段转换为带有 html 标签的页面。
想要达到这个目的,我们需要借助第三方工具类,本系统中我们选择的 markdown 解析器是 CommonMark 解析器,首先需要将相关依赖引入到 pom.xml 文件中,依赖文件增加如下设置:
“`xml
Spring Boot 博客系统项目开发之文章详情页制作
本项目的开源仓库地址为:https://github.com/ZHENFENG13/My-Blog
除 My-Blog 项目外,我也在维护另外一个开源项目,仓库地址为:https://github.com/newbee-ltd/newbee-mall
感兴趣的朋友可以去关注一下。
文章总览
在前面几个实验中我们一直有提到文章详情页,因为训练营课程安排顺序的缘故,博客详情页被安排在了后面一些,详情页还没有制作完成所以有些 a 标签中的跳转链接地址无法填上,这个实验就来该开发文章详情页的相关功能了,我会从页面设计和排版讲起,之后是功能实现和页面优化。
知识点
- 详情页页面设计
- 详情查询功能实现及页面渲染
- markdown 格式转换
- 页面优化
环境
- JDK 1.8 或者更高版本
- Spring Boot 2.1.0-RELEASE
- Maven 3+
详情功能实现
页面设计
大家也常常浏览各个博客网站,应该能够看出来其实文章详情最重要的就是文章内容的展示,以及文章其他相关字段的展示,比如标签、浏览量之类的信息也会在文章详情页进行展示,接下来我们看一下我们这个博客系统最终的文章详情页展现效果来确认该页面的布局设计,如下图所示:
顶部导航栏和底部页脚区域是所有页面都有的页面元素,属于公共区域,这里就不再赘述,截图中也只是文章详情的功能展示区域,重点关注一下图中标注的四个地方,如上图所示,分别标注了四个区域,从上至下依次为:
- 文章的分类信息展示区域:主要用于放置分类名称和分类图标字段;
- 文章标题区域:放置文章标题,字体相较于其他部分会大很多;
- 文章的基础信息区域:放置文章的标签、时间、浏览量等字段;
- 文章详情区域:文章内容的展示区域,以上三个区域通常是固定的,而文章详情区域则会因为文章内容的多少动态的变化,内容多则占用的版面就多,反之就会少一些。
页面中还会有文章的评论列表区域和文章评论的输入区域,在本次实验中暂时就不介绍了,后面会单独用一个章节来开发博客的评论模块。
当然,以上版面设计的分析只是对于我的博客模板来说是这样的,社区中还有许多其他的博客系统项目,由于前端的设计和实现非常灵活且多变,这些博客系统可能又是另外一些页面样式和页面布局,比如我们的博客系统就有三个页面模板,不同的模板就会有不同的样式。
数据格式定义
通过上面的图片我们也能够看出文章详情页需要的字段,包括文章标题、文章标签、文章分类、文章内容等等字段,基本上文章表中的字段都用到了,返回数据的格式很清晰,编码如下:
package com.site.blog.my.core.controller.vo; import java.io.Serializable; import java.util.Date; import java.util.List; public class BlogDetailVO implements Serializable { private Long blogId; private String blogTitle; private Integer blogCategoryId; private Integer commentCount; private String blogCategoryIcon; private String blogCategoryName; private String blogCoverImage; private Long blogViews; private List<String> blogTags; private String blogContent; private Byte enableComment; private Date createTime; }
详情页跳转
详情页通常是通过点击博客列表页中的单个卡片中的链接跳转而来的,首页中以及搜素页面中会有这些跳转链接,详情页的路径我们定义为 /blog/{blogId},首先我们来修改首页模板代码及搜索页模板代码,添加 a 标签中的详情页跳转路径,修改如下:
- index.html 博客列表
<a th:href="@{'/blog/' + ${blog.blogId}}"> <img th:src="@{${blog.blogCoverImage}}" alt="" /> <h3><th:block th:text="${blog.blogTitle}"></th:block></h3> </a>
- index .html 点击最多
<li> <a th:href="@{'/blog/' + ${hotBlog.blogId}}"> <th:block th:text="${hotBlog.blogTitle}"></th:block> </a> </li>
- index .html 最新发布
<li> <a th:href="@{'/blog/' + ${newBlog.blogId}}"> <th:block th:text="${newBlog.blogTitle}"></th:block> </a> </li>
- list.html 博客列表
<a th:href="@{'/blog/' + ${blog.blogId}}"> <img th:src="@{${blog.blogCoverImage}}" alt="" /> <h3><th:block th:text="${blog.blogTitle}"></th:block></h3> </a>
链接添加后,在点击后就会跳转到详情页面,接下来是详情页的功能实现讲解。
数据查询实现
首先,是数据查询的功能实现,上述详情页面中的字段可以通过直接查询 tb_blog 文章表和 tb_blog_category 分类表来获取,传参时只需要传入文章的主键 id 即可,实现逻辑如下。
定义 service 方法,业务层代码如下(注:完整代码位于 com.site.blog.my.core.service.impl.BlogServiceImpl.java):
/** * 文章详情获取 * * @param blogId * @return */ public BlogDetailVO getBlogDetail(Long blogId) { Blog blog = blogMapper.selectByPrimaryKey(blogId); //不为空且状态为已发布 BlogDetailVO blogDetailVO = getBlogDetailVO(blog); if (blogDetailVO != null) { return blogDetailVO; } return null; } /** * 方法抽取 * * @param blog * @return */ private BlogDetailVO getBlogDetailVO(Blog blog) { //判空以及发布状态是否为已发布 if (blog != null && blog.getBlogStatus() == 1) { //增加浏览量 blog.setBlogViews(blog.getBlogViews() + 1); blogMapper.updateByPrimaryKey(blog); BlogDetailVO blogDetailVO = new BlogDetailVO(); BeanUtils.copyProperties(blog, blogDetailVO); //md格式转换 blogDetailVO.setBlogContent(MarkDownUtil.mdToHtml(blogDetailVO.getBlogContent())); BlogCategory blogCategory = categoryMapper.selectByPrimaryKey(blog.getBlogCategoryId()); if (blogCategory == null) { blogCategory = new BlogCategory(); blogCategory.setCategoryId(0); blogCategory.setCategoryName("默认分类"); blogCategory.setCategoryIcon("/admin/dist/img/category/00.png"); } //分类信息 blogDetailVO.setBlogCategoryIcon(blogCategory.getCategoryIcon()); if (!StringUtils.isEmpty(blog.getBlogTags())) { //标签设置 List<String> tags = Arrays.asList(blog.getBlogTags().split(",")); blogDetailVO.setBlogTags(tags); } return blogDetailVO; } return null; }
我们定义了 getBlogDetail()
方法并传入 blogId 参数,该方法的执行逻辑为:
- 根据 blogId 直接查询 tb_blog 表中的记录
- 判断查出的结果是否为空以及文章状态是否为发布状态,不是发布状态返回 null 值
- 每次请求文章详情接口都会执行浏览量加一的操作,直接修改 tb_blog 表中的 blog_view 字段
- 将 markdown 格式的 content 内容字段转换为带有 html 标签的页面,因为在后台管理系统中操作时使用的是 Editor.md 编辑器,存储到数据库中的字段也是 markdown 格式的字段,在页面中显示的话需要进行转换
- 设置分类信息字段
- 设置标签字段
- 返回结果
markdown 格式转换
在详情页的页面设计中我给出了文章详情页的最终展示效果图,通过 f12 打开浏览器控制台,我们来看一下页面的 html 源码,查看结果如下:
通过控制台的页面源码我们可以看出,此时页面上展示的文章内容已经不是 markdown 格式的,而是符合 html 标签语法的代码片段了,但是数据库里的内容确实是 markdown 格式的文档,我们打开数据库来确认一下该字段的值,内容如下:
数据库中存储的内容与页面上显示的内容并不同,也就是说在文章详情请求的过程中,肯定有一个步骤对这个字段进行了转换处理,这一步骤在前文中也已经提到了,接下来我来介绍一下如何将 markdown 格式的 content 内容字段转换为带有 html 标签的页面。
想要达到这个目的,我们需要借助第三方工具类,本系统中我们选择的 markdown 解析器是 CommonMark 解析器,首先需要将相关依赖引入到 pom.xml 文件中,依赖文件增加如下设置:
“`xml
部分转自互联网,侵权删除联系
最新评论