加载中
🤖
AI审核中

博客侧边栏热门文章与最新文章功能实现详解

  Java   22分钟   254浏览   0评论
AI
AI智能摘要
正在分析文章内容

前言

在博客系统中,侧边栏是提升用户体验的重要组件。通过在文章详情页添加热门文章最新文章侧边栏,可以帮助读者快速发现优质内容,增加页面浏览量和用户停留时间。本文将详细介绍如何在 Spring Boot + Thymeleaf 技术栈中实现这一功能。

效果预览

功能需求分析

核心功能

  1. 热门文章:按浏览量排序,展示前5篇最受欢迎的文章
  2. 最新文章:按发布时间排序,展示前3篇最新发布的文章
  3. 响应式设计:PC端显示在左侧,移动端自动隐藏
  4. 性能优化:使用缓存和字段筛选,减少数据库查询开销

视觉设计

  • 热门文章带排名标识(前三名使用特殊颜色区分)
  • 显示文章浏览量
  • 最新文章使用圆点标识
  • 文章标题超长时自动截断并显示省略号

技术实现方案

一、数据库层优化

首先,我们需要一个高效的 SQL 查询来获取侧边栏所需的文章数据。为了避免查询文章内容等大字段,我们只查询必要字段:

<!-- ArticleMapperCustom.xml -->
<select id="findSidebarArticles" resultType="com.zou.blog.model.domain.ArticleCustom">
    SELECT
        id,
        article_title,
        article_url,
        article_views,
        article_newstime,
        article_thumbnail
    FROM mayday_article
    WHERE article_status = #{status}
    AND article_post = #{post}
    ORDER BY article_newstime DESC
</select>

优化要点

  • 只查询必要字段(不包含 article_content 等大字段)
  • 按发布时间倒序排列,便于获取最新文章
  • 通过状态过滤,只查询已发布的文章

二、服务层实现

在 Service 层添加缓存注解,提高查询性能:

@Override
@Cacheable(value = ARTICLES_CACHE_NAME, key = "'sidebarArticles'+#status+#post")
public List<ArticleCustom> findSidebarArticles(int status, String post) {
    return articleMapperCustom.findSidebarArticles(status, post);
}

三、控制器层逻辑

在文章详情页控制器中,获取侧边栏数据并进行排序处理:

@GetMapping(value = {"post/{articleUrl}", "post/{articleUrl}.html"})
public String post(Model model,
                   @PathVariable(value = "articleUrl") String articleUrl,
                   HttpServletRequest request) {
    // ... 其他代码

    // 获取侧边栏文章列表(带缓存,只查询必要字段)
    List<ArticleCustom> sidebarArticles = articleService.findSidebarArticles(
        ArticleStatus.PUBLISH.getStatus(), 
        PostType.POST_TYPE_POST.getValue()
    );

    // 获取热门文章(按浏览量排序,前5篇)
    List<ArticleCustom> sortedHotArticles = sidebarArticles.stream()
        .sorted((a1, a2) -> {
            Long views1 = a1.getArticleViews() != null ? a1.getArticleViews() : 0L;
            Long views2 = a2.getArticleViews() != null ? a2.getArticleViews() : 0L;
            return views2.compareTo(views1); // 降序排列
        })
        .limit(5)
        .collect(Collectors.toList());
    model.addAttribute("hotArticles", sortedHotArticles);

    // 获取最新文章(按创建时间排序,前3篇)
    List<ArticleCustom> sortedLatestArticles = sidebarArticles.stream()
        .limit(3)
        .collect(Collectors.toList());
    model.addAttribute("latestArticles", sortedLatestArticles);

    // ... 其他代码
}

关键逻辑解析

  1. 热门文章排序:使用 Stream API 按 articleViews 降序排列,处理 null 值情况
  2. 最新文章获取:由于 SQL 已经按时间倒序排列,直接取前3条即可
  3. 数据复用:一次查询,两种用途,减少数据库访问次数

四、前端页面实现

HTML 结构(Thymeleaf 模板)

<!-- 页面整体容器 -->
<div class="post-page-wrapper">
    <!-- PC端左侧边栏 -->
    <aside class="post-sidebar-left">
        <div class="sidebar-left-inner">
            <!-- 热门文章区域 -->
            <div class="sidebar-section hot-articles">
                <h3 class="sidebar-title">
                    <i class="fa fa-fire"></i>
                    热门文章
                </h3>
                <ul class="sidebar-list">
                    <li class="sidebar-item" 
                        th:each="hotArticle, iterStat : ${hotArticles}" 
                        th:if="${iterStat.index < 5}">
                        <a th:href="@{'/post/'+${hotArticle.articleUrl}}" class="sidebar-link">
                            <span class="sidebar-rank" 
                                  th:class="'sidebar-rank rank-' + ${iterStat.index + 1}" 
                                  th:text="${iterStat.index + 1}"></span>
                            <span class="sidebar-text" th:text="${hotArticle.articleTitle}"></span>
                        </a>
                        <div class="sidebar-meta">
                            <i class="fa fa-eye"></i>
                            <span th:text="${hotArticle.articleViews != null ? hotArticle.articleViews : 0}"></span>
                        </div>
                    </li>
                </ul>
            </div>

            <!-- 最新文章区域 -->
            <div class="sidebar-section latest-articles">
                <h3 class="sidebar-title">
                    <i class="fa fa-clock-o"></i>
                    最新文章
                </h3>
                <ul class="sidebar-list">
                    <li class="sidebar-item" 
                        th:each="latestArticle, iterStat : ${latestArticles}" 
                        th:if="${iterStat.index < 3}">
                        <a th:href="@{'/post/'+${latestArticle.articleUrl}}" class="sidebar-link">
                            <span class="sidebar-dot"></span>
                            <span class="sidebar-text" th:text="${latestArticle.articleTitle}"></span>
                        </a>
                    </li>
                </ul>
            </div>
        </div>
    </aside>

    <!-- 文章主体区域 -->
    <article class="main-content page-page">
        <!-- 文章内容... -->
    </article>
</div>

CSS 样式实现

/* ==================== PC端侧边栏样式(左侧固定) ==================== */

/* 页面整体容器 */
.post-page-wrapper {
    display: flex;
    gap: 30px;
    max-width: 1400px;
    margin: 0 auto;
    padding: 0 20px;
    position: relative;
}

/* 左侧边栏基础样式 - 默认隐藏 */
.post-sidebar-left {
    display: none;
}

/* PC端显示左侧边栏 */
@media (min-width: 1024px) {
    .post-sidebar-left {
        display: block;
        width: 260px;
        flex-shrink: 0;
        position: relative;
    }

    /* 左侧边栏内部容器 - 固定定位 */
    .sidebar-left-inner {
        position: sticky;
        top: 100px;
        max-height: calc(100vh - 120px);
        overflow-y: auto;
    }
}

/* 侧边栏区域样式 */
.sidebar-section {
    background: #fff;
    border-radius: 12px;
    padding: 20px;
    margin-bottom: 20px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
    border: 1px solid #f0f0f0;
}

.sidebar-title {
    font-size: 16px;
    font-weight: 600;
    color: #333;
    margin: 0 0 16px 0;
    padding-bottom: 12px;
    border-bottom: 2px solid #f5f5f5;
    display: flex;
    align-items: center;
    gap: 8px;
}

/* 排名样式 */
.sidebar-rank {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 600;
    color: #666;
    background: #f5f5f5;
    flex-shrink: 0;
}

.sidebar-rank.rank-1 {
    background: linear-gradient(135deg, #ff6b6b, #ee5a5a);
    color: #fff;
}

.sidebar-rank.rank-2 {
    background: linear-gradient(135deg, #ffa502, #ff9500);
    color: #fff;
}

.sidebar-rank.rank-3 {
    background: linear-gradient(135deg, #2ed573, #26d063);
    color: #fff;
}

/* 文章标题文本 */
.sidebar-text {
    flex: 1;
    font-size: 14px;
    line-height: 1.5;
    color: #333;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

/* 最新文章圆点 */
.sidebar-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #eb5055;
    flex-shrink: 0;
    margin-top: 8px;
}

关键技术点解析

1. 粘性定位(Sticky Positioning)

.sidebar-left-inner {
    position: sticky;
    top: 100px;
    max-height: calc(100vh - 120px);
    overflow-y: auto;
}

使用 position: sticky 实现侧边栏随页面滚动而固定,提升用户体验。top: 100px 确保侧边栏不会被顶部导航栏遮挡。

2. Stream API 排序

List<ArticleCustom> sortedHotArticles = sidebarArticles.stream()
    .sorted((a1, a2) -> {
        Long views1 = a1.getArticleViews() != null ? a1.getArticleViews() : 0L;
        Long views2 = a2.getArticleViews() != null ? a2.getArticleViews() : 0L;
        return views2.compareTo(views1);
    })
    .limit(5)
    .collect(Collectors.toList());

使用 Java 8 Stream API 进行内存排序,避免多次数据库查询。同时处理 null 值,防止空指针异常。

3. 响应式设计

@media (min-width: 1024px) {
    .post-sidebar-left {
        display: block;
    }
}

@media (max-width: 767px) {
    .post-page-wrapper {
        padding: 0;
        width: 100%;
    }
}

通过媒体查询实现响应式布局:

  • PC端(≥1024px):显示侧边栏
  • 平板端(768px-1023px):隐藏侧边栏
  • 移动端(<767px):调整布局宽度

4. 缓存优化

@Cacheable(value = ARTICLES_CACHE_NAME, key = "'sidebarArticles'+#status+#post")
public List<ArticleCustom> findSidebarArticles(int status, String post) {
    return articleMapperCustom.findSidebarArticles(status, post);
}

使用 Spring Cache 注解,将侧边栏文章列表缓存起来,减少数据库查询次数,提高页面加载速度。

效果展示

PC端效果

  • 左侧显示热门文章和最新文章两个区块
  • 热门文章前三名带有渐变色排名标识
  • 文章标题超长时自动截断显示省略号
  • 侧边栏随页面滚动保持可见

移动端效果

  • 侧边栏自动隐藏,专注于文章内容阅读
  • 页面宽度自适应,无水平滚动条

总结

通过本文的介绍,我们实现了一个功能完善、性能优良的博客侧边栏系统。主要技术亮点包括:

  1. 数据库优化:只查询必要字段,减少数据传输
  2. 缓存机制:使用 Spring Cache 提高查询性能
  3. Stream API:内存排序,减少数据库访问
  4. 响应式设计:适配各种屏幕尺寸
  5. 粘性定位:提升用户体验

这个实现方案不仅满足了功能需求,还兼顾了性能和用户体验,可以作为类似功能的参考实现。

如果你觉得文章对你有帮助,那就请作者喝杯咖啡吧☕
微信
支付宝
  0 条评论
AI助手
召田最帅boy的小助手
🤖
我是召田最帅boy的小助手
我已经阅读了这篇文章,可以帮您:
理解文章内容 · 解答细节问题 · 分析核心观点