归档页
关于我
1. 归档页
1.1 需求分析
博客归档页如上所示,它实现的也是对于博客的统计归档,不过是根据时间的先后进行。对于具体某一年来说,同样是按照时间先后进行排列。首先需要获取到博客的总数,在顶部的segment中显示;然后根据年份进行查询数据库,获取对应年份的博客列表,其中列表按照时间降序排列;对于具体的某一篇博客,需要显示的信息有标题、更新时间和标签。
由于年份和对应的博客列表实际上是一种键值对形式,因此可以使用Map进行保存。
1.2 前端处理
归档页面的前端设计如下所示:
<div class="m-container-small m-padded-tb-big" style="height: 800px!important;">
<div class="ui container">
<div class="ui top attached padded segment">
<div class="ui middle aligned two column grid">
<div class="column">
<h3 class="ui teal header">归档</h3>
</div>
<div class="right aligned column">
共 <h2 class="ui orange header m-inline-block m-text-thin" th:text="${blogCount}"> 1 </h2> 篇博客
</div>
</div>
</div>
<!--获取年份和对应的博客列表,依次遍历取出-->
<th:block th:each="item : ${archiveMap}">
<!--key就是年份-->
<h3 class="ui center aligned header" th:text="${item.key}">2017</h3>
<div class="ui fluid vertical menu">
<!--value是博客列表,需要遍历一次取出每一篇-->
<a href="#" th:href="@{/blog/{id}(id=${blog.id})}" target="_blank" class="item" th:each="blog : ${item.value}">
<span>
<i class="mini teal circle icon"></i>
<!--博客标题-->
<span th:text="${blog.title}">关于刻意练习的清单</span>
<!--博客更新时间-->
<div class="ui teal basic left pointing label m-padded-mini " th:text="${#dates.format(blog.updateTime,'MMMdd')}">9月03</div>
</span>
<!--博客标签-->
<div class="ui orange basic left pointing label m-padded-mini " th:text="${blog.flag}">原创</div>
</a>
</div>
</th:block>
</div>
</div>
1.3 后端处理
根据前端的设计可知,程序后端需要往前端传递一个两部分信息:
- 博客的总量
- 以键值对形式保存的博客列表信息
因此,表现层对应的处理方法就需要获取到这两部分信息,方法定义如下:
@Controller
public class ArchiveShowController {
@Autowired
private BlogService blogService;
@GetMapping("/archives")
public String archives(Model model) {
model.addAttribute("archiveMap", blogService.archiveBlog());
model.addAttribute("blogCount", blogService.countBlog());
return "archives";
}
}
首先,调用countBlog()
获取到博客的总量,业务层中方法定义如下:
public interface BlogService {
Long countBlog();
}
@Service
public class BlogServiceImpl implements BlogService {
@Autowired
private BlogRepository blogRepository;
@Override
public Long countBlog() {
return blogRepository.count();
}
}
接着还需要获取以键值对形式保存的博客列表,调用的是archiveBlog()
,方法的定义如下:
public interface BlogService {
Map<String,List<Blog>> archiveBlog();
}
@Service
public class BlogServiceImpl implements BlogService {
@Autowired
private BlogRepository blogRepository;
@Override
public Map<String, List<Blog>> archiveBlog() {
List<String> years = blogRepository.findGroupYear();
Map<String, List<Blog>> map = new HashMap<>();
for (String year : years) {
map.put(year, blogRepository.findByYear(year));
}
return map;
}
}
其中,先调用持久层中的findGroupYear()
获取到年份列表:
public interface BlogRepository extends JpaRepository<Blog, Long> , JpaSpecificationExecutor<Blog> {
// 归档管理
@Query("select function('date_format',b.updateTime,'%Y') as year from Blog b group by function('date_format',b.updateTime,'%Y') order by year desc ")
List<String> findGroupYear();
}
由于Jpa中无法自动构建相应的方法,因此需要我们使用@Query注解自定义查询,查询结果根据年份分组,每一组中又根据更新时间降序排列。获取到年份列表后,遍历列表获取到具体的年份,再调用持久层中的findByYear()
来查询结果:
public interface BlogRepository extends JpaRepository<Blog, Long> , JpaSpecificationExecutor<Blog> {
@Query("select b from Blog b where function('date_format',b.updateTime,'%Y') = ?1")
List<Blog> findByYear(String year);
}
获取到博客列表后,将其和对应的年份组成键值对的数据保存到Map中,最后在表现层中传给前端使用即可。
2. 关于我
2.1 需求分析
这里关于我页面的实现先简单的做成了一种静态的形式,通过在前端中直接添加值来进行显示。更好的方式是应该从数据库中取值,然后在前端显示,后续继续改进。
2.2 前后端处理
既然它是一种静态的显示,因此只需要在前端填入相关的内容即可:
<div class="m-container m-padded-tb-big">
<div class="ui container">
<div class="ui stackable grid">
<div class="eleven wide column">
<div class="ui segment">
<img src="../static/images/kobe.jpg" th:src="@{/images/kobe.jpg}" alt="" class="ui rounded image">
</div>
</div>
<div class="five wide column">
<div class="ui top attached segment">
<div class="ui header">关于我</div>
</div>
<div class="ui attached segment">
<p class="m-text">Forlogen,一个独立开发者,折腾在 0 和 1 世界的大叔;一个终身学习者,誓将学习无限循环. 希望结识可以共同成长的小伙伴.</p>
<p class="m-text">热爱编程,喜欢折腾,正在探索高效学习编程技术的方法...</p>
</div>
<div class="ui attached segment">
<div class="ui orange basic left pointing label">编程</div>
<div class="ui orange basic left pointing label">写作</div>
<div class="ui orange basic left pointing label">思考</div>
<div class="ui orange basic left pointing label">运动</div>
</div>
<div class="ui attached segment">
<div class="ui teal basic left pointing label m-margin-tb-tiny">Java</div>
<div class="ui teal basic left pointing label m-margin-tb-tiny">JavaScript</div>
<div class="ui teal basic left pointing label m-margin-tb-tiny">Node</div>
<div class="ui teal basic left pointing label m-margin-tb-tiny">React</div>
<div class="ui teal basic left pointing label m-margin-tb-tiny">RN</div>
<div class="ui teal basic left pointing label m-margin-tb-tiny">MYSQL</div>
<div class="ui teal basic left pointing label m-margin-tb-tiny">...</div>
</div>
</div>
</div>
</div>
</div>
后端也不需要查询数据库,只需要一个处理页面跳转的方法即可。
@Controller
public class AboutShowController {
@GetMapping("/about")
public String about(){
return "about";
}
}
后端也不需要查询数据库,只需要一个处理页面跳转的方法即可。