简介
博客一般都会有一个时间线,本篇介绍时间线接口的实现
代码实现
1、开发时间线功能之前,我们先将数据库中的文章时间打乱,这样的话按照年份汇总会显得比较均匀
package pers.qianyucc.qblog.service;
import cn.hutool.core.util.*;
import lombok.extern.slf4j.*;
import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.context.*;
import org.springframework.test.context.junit4.*;
import pers.qianyucc.qblog.*;
import pers.qianyucc.qblog.dao.*;
import pers.qianyucc.qblog.model.entity.*;
import java.time.*;
import java.util.*;
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {BlogApplication.class})
public class ArticleServiceTest {
@Autowired
private ArticleMapper articleMapper;
@Test
public void solveTime() {
List<ArticlePO> articles = articleMapper.selectList(null);
for (int i = 0; i < articles.size(); i++) {
ArticlePO po = articles.get(i);
LocalDateTime dateTime = LocalDateTime.now().plusYears(RandomUtil.randomInt(-5, 5));
long epochMilli = dateTime.toInstant(ZoneOffset.UTC).toEpochMilli();
po.setGmtCreate(epochMilli);
po.setGmtUpdate(epochMilli);
articleMapper.updateById(po);
}
}
}
说明:
- 先查出所有数据,将创建时间和更新时间上下浮动5年,再写回数据库
2、创建视图层类
package pers.qianyucc.qblog.model.vo;
import lombok.*;
import java.util.*;
@Data
@Builder
public class TimelineVO {
private String year;
private List<Item> items;
@Data
@Builder
public static class Item {
private String id;
private String gmtCreate;
private String title;
}
}
说明:
- 时间线可以按照月份汇总,也可以按照年份汇总,这里按照年份汇总
- 因为要实现点击时间线的标题跳转到对应文章的功能,所以这里连同文章 id 一并返回给前端
3、在 ArticleService 中实现时间线逻辑
public List<TimelineVO> timeline() {
ArrayList<TimelineVO> res = new ArrayList<>();
QueryWrapper<ArticlePO> wrapper = new QueryWrapper<>();
wrapper.select("id", "title", "gmt_create");
List<Map<String, Object>> maps = articleMapper.selectMaps(wrapper);
maps.stream().map(m -> TimelineVO.Item.builder()
.id((String) m.get("id"))
.gmtCreate(BlogUtils.formatDate((Long) m.get("gmt_create")))
.title((String) m.get("title"))
.build())
.collect(Collectors.groupingBy(item -> {
String[] arr = item.getGmtCreate().split("-");
String year = arr[0];
return year;
})).forEach((k, v) -> res.add(TimelineVO.builder().year(k).items(v).build()));
res.sort(Comparator.comparing(TimelineVO::getYear).reversed());
// log.info("timeline list : {}", JSONUtil.toJsonStr(res));
return res;
}
说明:上面代码主要可分为以下几个步骤
- 将查询到的 Map 转换为 Item(TimelineVO 的内部类) 对象
- 从 item 对象的 gmtCreate 属性中获取年份,根据年份分组
- 遍历每个分组,创建 TimelineVO 对象,加入集合
4、在 ArticleController 中新建接口
@GetMapping("/timeline")
@ApiOperation("获取文章时间线")
public Results<List<TimelineVO>> getTimeline() {
List<TimelineVO> timeline = articleService.timeline();
return Results.ok(timeline);
}
5、使用 knife4j 测试
参考代码:https://gitee.com/qianyucc/QBlog2/tree/v-8.0