博客地址:ONESTARの客棧
源碼領取方式一:
- 掃一掃文末二維碼,關注公衆號【編程日刊】,後臺回覆【博客】,即可領取源碼
源碼領取方式二:
以jpa爲持久層源碼地址:https://github.com/oneStarLR/myblog-jpa
以mybatis爲持久層源碼地址:https://github.com/oneStarLR/myblog-mybaits
歡迎給star以鼓勵(^_−)☆
本文將根據首頁顯示來進行講述,首頁有搜索、最新博客推薦顯示、文章列表顯示、博客信息統計等功能,將從這幾個方面進行講述,主要是後端的開發,前端只會給出部分代碼,不會進行講解。
一、首頁顯示
分析
問:首頁顯示需要考慮到哪些問題?
答:根據前端頁面功能來看,兩個最基本的查詢,一個是查詢最新文章列表,一個是查詢最新推薦文章;還有就是搜搜索功能,根據關鍵字搜索博客;另外,就是統計博客信息,有博客總數、訪問總數、評論總數、留言總數。
問:那各個功能需要怎樣設計呢?
答: 這裏根據每個功能來進行分析
- 查詢最新文章列表:定義一個FirstPageBlog首頁實體類來查詢首頁文章列表信息,並定義getAllFirstPageBlog接口來關聯SQL實現查詢功能
- 查詢最新推薦文章:定義一個RecommendBlog實體類來查詢推薦文章列表信息,並定義getRecommendedBlog接口來關聯SQL實現查詢
- 搜索博客:由於搜索博客顯示的還是博客列表信息,所以還是通過FirstPageBlog實體類來顯示查詢信息,並定義getSearchBlog接口來關聯SQL實現查詢功能
- 統計博客信息:統計博客信息分別定義了getBlogTotal、getBlogViewTotal、getBlogCommentTotal、getBlogMessageTotal接口來關聯SQL實現博客總數、訪問總數、評論總數、留言總數的統計
1. 定義實體類
根據上面的分析,這裏需要定義兩個查詢實體類,分別是:最新博客列表實體類(FirstPageBlog)、最新推薦實體類(RecommendBlog)
最新博客列表實體類
由於首頁最新博客列表除了需要顯示博客信息外,還需要顯示分類、作者等信息,所以還需要定義分類名稱和用戶名、用戶頭像屬性。在queryvo包下創建FirstPageBlog實體類,代碼如下(省去get、set、toString方法):
package com.star.queryvo;
import java.util.Date;
/**
* @Description: 首頁博客信息實體類
* @Date: Created in 9:39 2020/6/19
* @Author: ONESTAR
* @QQ羣: 530311074
* @URL: https://onestar.newstar.net.cn/
*/
public class FirstPageBlog {
//博客信息
private Long id;
private String title;
private String firstPicture;
private Integer views;
private Integer commentCount;
private Date updateTime;
private String description;
//分類名稱
private String typeName;
//用戶名
private String nickname;
//用戶頭像
private String avatar;
}
最新推薦實體類
最新推薦只要顯示博客標題、首圖信息,但要注意這裏要體現出是否推薦到推薦欄來,所以還要有個boolean類型的變量recommend,如下(省去get、set、toString方法):
package com.star.queryvo;
/**
* @Description: 推薦博客數據實體類
* @Date: Created in 9:47 2020/6/19
* @Author: ONESTAR
* @QQ羣: 530311074
* @URL: https://onestar.newstar.net.cn/
*/
public class RecommendBlog {
private Long id;
private String title;
private String firstPicture;
private boolean recommend;
}
2. 持久層接口
由於都是和博客相關的接口,這裏就都寫在BlogDao類中,mapper和業務層也是一樣。根據上面的分析,這裏需要定義以下接口,在BlogDao接口中添加如下:
//查詢首頁最新博客列表信息
List<FirstPageBlog> getFirstPageBlog();
//查詢首頁最新推薦信息
List<RecommendBlog> getAllRecommendBlog();
//搜索博客列表
List<FirstPageBlog> getSearchBlog(String query);
//統計博客總數
Integer getBlogTotal();
//統計訪問總數
Integer getBlogViewTotal();
//統計評論總數
Integer getBlogCommentTotal();
//統計留言總數
Integer getBlogMessageTotal();
3. mapper
mapper是和持久層接口相對應的,在BlogDao.xml中添加如下SQL:
<!--查詢首頁最新博客列表信息-->
<resultMap id="firstPageBlog" type="com.star.queryvo.FirstPageBlog">
<id property="id" column="id"/>
<result property="title" column="title"/>
<result property="firstPicture" column="first_picture"/>
<result property="views" column="views"/>
<result property="commentCount" column="comment_count"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="description" column="description"/>
<result property="typeName" column="name"/>
<result property="nickname" column="nickname"/>
<result property="avatar" column="avatar"/>
</resultMap>
<select id="getFirstPageBlog" resultMap="firstPageBlog">
select b.id,b.title,b.first_picture, b.views, b.comment_count,b.create_time,b.update_time,b.description,
t.name ,
u.nickname, u.avatar
from myblog.t_blog b, myblog.t_type t,myblog.t_user u
where b.type_id = t.id and u.id = b.user_id order by b.create_time desc
</select>
<!--查詢推薦文章-->
<select id="getAllRecommendBlog" resultType="com.star.queryvo.RecommendBlog">
select * from myblog.t_blog where t_blog.recommend = true order by t_blog.create_time desc limit 4;
</select>
<!--搜索文章-->
<select id="getSearchBlog" resultMap="firstPageBlog">
<bind name="pattern" value="'%' + query + '%'" />
select b.id,b.title,b.first_picture, b.views,b.comment_count,b.update_time,b.description,
t.name ,
u.nickname, u.avatar
from myblog.t_blog b, myblog.t_type t,myblog.t_user u
where b.type_id = t.id and u.id = b.user_id and (b.title like #{pattern} or b.content like #{pattern})
order by b.update_time desc
</select>
<!--統計博客信息-->
<select id="getBlogTotal" resultType="Integer">
select count(*) from myblog.t_blog
</select>
<select id="getBlogViewTotal" resultType="Integer">
select coalesce (sum(views),0) from myblog.t_blog
</select>
<select id="getBlogCommentTotal" resultType="Integer">
select count(*) from myblog.t_comment
</select>
<select id="getBlogMessageTotal" resultType="Integer">
select count(*) from myblog.t_message
</select>
講解:
查詢首頁最新博客列表信息和查詢推薦文章都是前面提到過的知識點,搜索文章也在博客管理裏面有講解過,用的是模糊查詢,這裏說一統計訪問總數的SQL,在上一版的代碼中,用的是:select sum(views) from myblog.t_blog,這裏用的是:select coalesce (sum(views),0) from myblog.t_blog,在上一版中,當sum求和返回爲null時,是會報空指針異常的,這裏用coalesce (sum(views),0),打當sum求和爲null時賦值爲0,就能解決這個問題
4. 業務層
業務層接口
在BlogService接口中定義以下接口
//查詢首頁最新博客列表信息
List<FirstPageBlog> getAllFirstPageBlog();
//查詢首頁最新推薦信息
List<RecommendBlog> getRecommendedBlog();
//搜索博客列表
List<FirstPageBlog> getSearchBlog(String query);
//統計博客總數
Integer getBlogTotal();
//統計訪問總數
Integer getBlogViewTotal();
//統計評論總數
Integer getBlogCommentTotal();
//統計留言總數
Integer getBlogMessageTotal();
接口實現類
在BlogServiceImpl接口實現類中添加:
//查詢首頁最新博客列表信息
@Override
public List<FirstPageBlog> getAllFirstPageBlog() {
return blogDao.getFirstPageBlog();
}
//查詢首頁最新推薦信息
@Override
public List<RecommendBlog> getRecommendedBlog() {
List<RecommendBlog> allRecommendBlog = blogDao.getAllRecommendBlog();
return allRecommendBlog;
}
//搜索博客列表
@Override
public List<FirstPageBlog> getSearchBlog(String query) {
return blogDao.getSearchBlog(query);
}
//統計博客總數
@Override
public Integer getBlogTotal() {
return blogDao.getBlogTotal();
}
//統計訪問總數
@Override
public Integer getBlogViewTotal() {
return blogDao.getBlogViewTotal();
}
//統計評論總數
@Override
public Integer getBlogCommentTotal() {
return blogDao.getBlogCommentTotal();
}
//統計留言總數
@Override
public Integer getBlogMessageTotal() {
return blogDao.getBlogMessageTotal();
}
5. 控制器
在controller包下創建IndexController類,根據前面的功能分析,編寫如下代碼:
package com.star.controller;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.star.queryvo.FirstPageBlog;
import com.star.queryvo.RecommendBlog;
import com.star.service.BlogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import java.util.List;
/**
* @Description: 首頁控制器
* @Date: Created in 21:01 2020/5/20
* @Author: ONESTAR
* @QQ羣: 530311074
* @URL: https://onestar.newstar.net.cn/
*/
@Controller
public class IndexController {
@Autowired
private BlogService blogService;
//分頁查詢博客列表
@GetMapping("/")
public String index(Model model, @RequestParam(defaultValue = "1",value = "pageNum") Integer pageNum, RedirectAttributes attributes){
PageHelper.startPage(pageNum,10);
List<FirstPageBlog> allFirstPageBlog = blogService.getAllFirstPageBlog();
List<RecommendBlog> recommendedBlog = blogService.getRecommendedBlog();
PageInfo<FirstPageBlog> pageInfo = new PageInfo<>(allFirstPageBlog);
System.out.println("pageInfo:" +pageInfo);
model.addAttribute("pageInfo",pageInfo);
model.addAttribute("recommendedBlogs", recommendedBlog);
return "index";
}
//搜索博客
@PostMapping("/search")
public String search(Model model,
@RequestParam(defaultValue = "1", value = "pageNum") Integer pageNum,
@RequestParam String query) {
PageHelper.startPage(pageNum, 1000);
List<FirstPageBlog> searchBlog = blogService.getSearchBlog(query);
PageInfo<FirstPageBlog> pageInfo = new PageInfo<>(searchBlog);
model.addAttribute("pageInfo", pageInfo);
model.addAttribute("query", query);
return "search";
}
//博客信息統計
@GetMapping("/footer/blogmessage")
public String blogMessage(Model model){
int blogTotal = blogService.getBlogTotal();
int blogViewTotal = blogService.getBlogViewTotal();
int blogCommentTotal = blogService.getBlogCommentTotal();
int blogMessageTotal = blogService.getBlogMessageTotal();
model.addAttribute("blogTotal",blogTotal);
model.addAttribute("blogViewTotal",blogViewTotal);
model.addAttribute("blogCommentTotal",blogCommentTotal);
model.addAttribute("blogMessageTotal",blogMessageTotal);
return "index :: blogMessage";
}
}
6. 前後端交互
- 最新推薦:
<div class="m-margin-tb-tiny four wide column" th:each="blog : ${recommendedBlogs}">
<a href="#" class="class_outer" th:href="@{/blog/{id}(id=${blog.id})}" target="_blank">
<img src="../static/images/backimg1.jpg" th:src="@{${blog.firstPicture}}" alt="" class="ui rounded image">
<span class="class_cover" >
<h4 class="m-font-size-blog-text m-margin-tb-tiny" th:text="${blog.title}">大聖,此去欲何?</h4>
</span>
</a>
</div>
- 文章列表
<div class="ui padded segment m-padded-tb-large m-opacity" th:each="blog : ${pageInfo.list}">
<div class="ui large aligned mobile reversed stackable grid">
<!--博文信息-->
<div class="eleven wide column ">
<h3 class="ui header" ><a href="#" th:href="@{/blog/{id}(id=${blog.id})}" target="_blank" class="m-black m-title-font" th:text="${blog.title}">大聖,此去欲何?</a></h3>
<p class="m-text m-margin-top-max" th:text="|${blog.description}......|">戴上金箍,沒法愛你;放下金箍,沒法保護你。我知道上天不會給我第二次機會,曾經我們說好的永遠,原來也僅僅只有,十二畫,而已。“大聖,此去欲何?”“踏南天,碎凌霄。”“若一去不回……”“便一去不回” 其實很多時候,我們都是有機會的,最後真正放棄的,是我們自己。......</p>
<div class="ui m-margin-top-max grid">
<div class="eleven wide column">
<div class="ui mini horizontal link list">
<div class="item">
<img src="../static/images/me.jpg" th:src="@{${blog.avatar}}" alt="" class="ui avatar image">
<div class="content"><a href="#" th:href="@{/about}" target="_blank" class="header" th:text="${blog.nickname}" >oneStar</a></div>
</div>
<div class="item">
<i class="calendar icon"></i><span th:text="${#dates.format(blog.createTime,'yyyy-MM-dd')}">2020-01-01</span>
</div>
<div class="item">
<i class="eye icon"></i> <span th:text="${blog.views}">2222</span>
</div>
<div class="item">
<i class="comment outline icon"></i> <span th:text="${blog.commentCount}">2222</span>
</div>
</div>
</div>
<div class="right aligned five wide column">
<a href="#" target="_blank" class="ui teal basic label m-padded-tiny m-text-thin" th:text="${blog.typeName}">好文</a>
</div>
</div>
</div>
<!--博文圖片-->
<div class="five wide column">
<a href="#" th:href="@{/blog/{id}(id=${blog.id})}" target="_blank">
<img src="../static/images/backimg1.jpg" th:src="@{${blog.firstPicture}}" alt="" class="ui rounded image">
</a>
</div>
</div>
</div>
- 分頁顯示文章列
<div class="ui bottom attached segment m-opacity stackable grid">
<div class="three wide column" align="center">
<a class="item" th:href="@{/(pageNum=${pageInfo.hasPreviousPage}?${pageInfo.prePage}:1)}" th:unless="${pageInfo.isFirstPage}">上一頁</a>
</div>
<div class="ten wide column" align="center">
<p> <span th:text="${pageInfo.pageNum}"></span> / <span th:text="${pageInfo.pages}"></span> </p>
</div>
<div class="three wide column" align="center">
<a class="item" th:href="@{/(pageNum=${pageInfo.hasNextPage}?${pageInfo.nextPage}:${pageInfo.pages})}" th:unless="${pageInfo.isLastPage}">下一頁</a>
</div>
</div>
- 搜索博客
<form name="search" action="#" th:action="@{/search}" method="post" target="_blank">
<div class="ui icon transparent input m-margin-tb-tiny" style="color: white">
<input style="color: white" type="text" name="query" placeholder="Search...." th:value="${query}">
<i onclick="document.forms['search'].submit()" class="search link icon"></i>
</div>
</form>
- 統計博客信息
HTML:
<div id="blog-message">
<div class="ui inverted link list" style="align-content: center;margin-top: 10px" th:fragment="blogMessage">
<div class="m-text-thin" style="text-align: left;margin-left: 75px;">
文章總數: <h2 class="ui orange header m-inline-block m-margin-top-null" style="font-size:medium;" th:text="${blogTotal}"> 14 </h2> 篇
</div>
<div class="m-text-thin" style="text-align: left;margin-left: 75px">
訪問總數: <h2 class="ui orange header m-inline-block m-margin-top-null" style="font-size:medium;" th:text="${blogViewTotal}"> 14 </h2> 次
</div>
<div class="m-text-thin" style="text-align: left;margin-left: 75px">
評論總數: <h2 class="ui orange header m-inline-block m-margin-top-null" style="font-size:medium;" th:text="${blogCommentTotal}"> 14 </h2> 條
</div>
<div class="m-text-thin" style="text-align: left;margin-left: 75px">
留言總數: <h2 class="ui orange header m-inline-block m-margin-top-null" style="font-size:medium;" th:text="${blogMessageTotal}"> 14 </h2> 條
</div>
</div>
</div>
JS:
$('#blog-message').load(/*[[@{/footer/blogmessage}]]*/"/footer/blogmessage");
7. 運行訪問
運行項目,訪問 http://localhost:8080/, 在後臺添加測試文章後能在前端頁面查看,並且在底部欄可以查看本站的信息
至此,SpringBoot搭建個人博客的博客首頁顯示開發完成,下一篇將講述博客詳情頁面顯示
【點關注,不迷路,歡迎持續關注本站】