一.页面介绍
在之前的项目一文章中,提到了功能划分。我们知道了用户有两种情况,管理员和一般用户。也知道了这两种用户可以完成什么功能。而博客页面就是要把这些功能经过后台处理显示在前台。
这个博客页面的规划参照了一些博客,例如CSDN的规划。我们将这个主页上需要的导航进行拆分,确保每个JSP完成不同的任务,可以在不同的页面进行引用。
1.1 公共页面framework.jsp
在这个页面中会显示站点基本信息,和引入侧边栏和博客页脚页面。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="rapid" uri="http://www.rapid-framework.org.cn/rapid" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Cache-Control" content="max-age=72000"/>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<meta name="applicable-device" content="pc,mobile">
<meta name="MobileOptimized" content="width"/>
<meta name="HandheldFriendly" content="true"/>
<link rel="shortcut icon" href="/img/logo.png">
<rapid:block name="description">
<meta name="description" content="${options.optionMetaDescrption}"/>
</rapid:block>
<rapid:block name="keywords">
<meta name="keywords" content="${options.optionMetaKeyword}"/>
</rapid:block>
<rapid:block name="title">
<title>
${options.optionSiteTitle}-${options.optionSiteDescrption}
</title>
</rapid:block>
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/plugin/font-awesome/css/font-awesome.min.css">
<rapid:block name="header-style">
</rapid:block>
</head>
<body>
<div id="page" class="site" style="transform: none;">
<%@ include file="part/header.jsp" %>
<div id="content" class="site-content" style="transform: none;">
<rapid:block name="left"></rapid:block>
<rapid:block name="right">
<%@ include file="part/sidebar-1.jsp" %>
</rapid:block>
</div>
<div class="clear"></div>
<rapid:block name="link"></rapid:block>
<%@ include file="part/footer.jsp" %>
</div>
<script src="/js/jquery.min.js"></script>
<script src="/js/superfish.js"></script>
<script src='/js/sticky.js'></script>
<script src="/js/script.js"></script>
<script src="/plugin/layui/layui.all.js"></script>
<rapid:block name="footer-script"></rapid:block>
</body>
</html>
1.2 侧边栏页面
因为每个页面的侧边栏页面不同,所以有许多侧边栏页面。
sidebar1.jsp:正文右边侧边栏。包含搜索框,显示热评文章(文章在后台是链接形式,可以发送请求,跳转到这个页面),显示所有标签(同文章一样,可以进行点击查看,查看的是这个标签下的所有文章),显示随机文章(也可以点击查看)。
<%--
一般用于正文侧边栏:
包括 搜索,热评文章,所有标签,随机文章
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%--博客主体-右侧侧边栏 start--%>
<div id="sidebar" class="widget-area all-sidebar"
style="position: relative; overflow: visible; box-sizing: border-box; min-height: 1px;">
<%--搜索框--%>
<aside class="widget widget_search">
<div class="searchbar">
<form method="get" id="searchform1" action="/search">
<span> <input type="text" value="" name="keywords" id="s1" placeholder="输入搜索内容" required="">
<button type="submit" id="searchsubmit1">搜索</button>
</span>
</form>
</div>
<div class="clear"></div>
</aside>
<%--搜索框--%>
<%--热评文章 start--%>
<aside class="widget hot_comment" >
<h3 class="widget-title">
<i class="fa fa-bars"></i>热评文章
</h3>
<div id="hot_comment_widget">
<ul>
<c:forEach items="${mostCommentArticleList}" var="m">
<li>
<a href="/article/${m.articleId}" rel="bookmark" title=" (${m.articleCommentCount}条评论)">
${m.articleTitle}
</a>
</li>
</c:forEach>
</ul>
</div>
<div class="clear"></div>
</aside>
<%--热评文章 end--%>
<%--所有标签 start--%>
<aside class="widget">
<h3 class="widget-title">
<i class="fa fa-bars"></i>所有标签
</h3>
<div class="tagcloud">
<c:forEach items="${allTagList}" var="t">
<a href="/tag/${t.tagId}"
class="tag-link-129 tag-link-position-1"
style="font-size: 14px;">
${t.tagName}
</a>
</c:forEach>
<div class="clear"></div>
</div>
<div class="clear"></div>
</aside>
<%--所有标签 end--%>
<%--博客主体-右侧侧边栏-随机文章 start--%>
<aside id="random_post-7" class="widget random_post wow fadeInUp" data-wow-delay="0.3s">
<h3 class="widget-title">
<i class="fa fa-bars"></i>随机文章
</h3>
<div id="random_post_widget">
<ul>
<c:forEach items="${randomArticleList}" var="r">
<li>
<a href="/article/${r.articleId}" rel="bookmark">
${r.articleTitle}
</a>
</li>
</c:forEach>
</ul>
</div>
<div class="clear"></div>
</aside>
<%--博客主体-右侧侧边栏-近期文章 end--%>
</div>
<%--博客主体-右侧侧边栏 end--%>
siderbar2.jsp:首页右边侧边栏。包含显示站点信息(头像,标题,内容,文章数和留言数),显示网站概况(文章总数,留言总数,分类数量,标签数量,浏览总数和最后更新),显示所有标签,显示最新评论(点击跳转到文章下的评论)。
<%--
一般用于首页侧边栏:
包括 关于本站,网站概况,热评文章,所有标签,随机文章 等小工具
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%--博客主体-右侧侧边栏 start--%>
<div id="sidebar" class="widget-area all-sidebar"
style="position: relative; overflow: visible; box-sizing: border-box; min-height: 1px;">
<%--关于本站 start--%>
<aside class="widget about">
<h3 class="widget-title">
<i class="fa fa-bars"></i>关于本站
</h3>
<div id="feed_widget">
<div class="feed-about">
<div class="about-main">
<div class="about-img">
<img src="${options.optionAboutsiteAvatar}"
alt="QR Code">
</div>
<div class="about-name">${options.optionAboutsiteTitle}</div>
<div class="about-the">
${options.optionAboutsiteContent}
</div>
</div>
<div class="clear"></div>
<div class="about-inf">
<span class="about-pn">文章 ${siteBasicStatistics[0]} </span>
<span class="about-cn">留言 ${siteBasicStatistics[1]} </span>
</div>
</div>
</div>
<div class="clear"></div>
</aside>
<%--关于本站 start--%>
<%--网站概况 start--%>
<aside id="php_text-22" class="widget php_text">
<h3 class="widget-title">
<i class="fa fa-bars"></i>网站概况
</h3>
<div class="textwidget widget-text">
<ul class="site-profile">
<li><i class="fa fa-file-o"></i> 文章总数:${siteBasicStatistics[0]} 篇</li>
<li><i class="fa fa-commenting-o"></i> 留言数量:${siteBasicStatistics[1]} 条</li>
<li><i class="fa fa-folder-o"></i> 分类数量:${siteBasicStatistics[2]} 个</li>
<li><i class="fa fa-tags"></i> 标签总数:${siteBasicStatistics[3]} 个</li>
<li><i class="fa fa-link"></i> 链接数量:${siteBasicStatistics[4]} 个</li>
<li><i class="fa fa-eye"></i> 浏览总量:${siteBasicStatistics[5]} 次</li>
<li><i class="fa fa-pencil-square-o"></i> 最后更新:
<span style="color:#2F889A">
<fmt:formatDate value="${lastUpdateArticle.articleUpdateTime}" pattern="yyyy年MM月dd日"/>
</span>
</li>
</ul>
</div>
<div class="clear"></div>
</aside>
<%--网站概况 end--%>
<%--所有标签 start--%>
<aside class="widget">
<h3 class="widget-title">
<i class="fa fa-bars"></i>所有标签
</h3>
<div class="tagcloud">
<c:forEach items="${allTagList}" var="tag">
<a href="/tag/${tag.tagId}"
class="tag-link-129 tag-link-position-1"
style="font-size: 14px;">
${tag.tagName}
</a>
</c:forEach>
<div class="clear"></div>
</div>
<div class="clear"></div>
</aside>
<%--所有标签 end--%>
<%--最新评论 start--%>
<aside id="recent_comments-2" class="widget recent_comments wow fadeInUp" data-wow-delay="0.3s"><h3
class="widget-title"><i class="fa fa-bars"></i>近期评论</h3>
<div id="message" class="message-widget">
<ul>
<c:forEach items="${recentCommentList}" var="r">
<li style="border: none;">
<a href="/article/${r.commentArticleId}/#anchor-comment-${r.commentId}" rel="external nofollow">
<%--<img alt="" src="${r.commentAuthorAvatar}" class="avatar avatar-64 photo" height="64" width="64">--%>
<span class="comment_author">
<strong>${r.commentAuthorName}</strong>
</span>
${r.commentContent}
</a>
</li>
</c:forEach>
</ul>
</div>
<div class="clear"></div>
</aside>
<%--最新评论 end--%>
</div>
<%--博客主体-右侧侧边栏 end--%>
siderbar3.jsp:正文侧边栏。包含搜索框,显示热评文章。
<%--
一般用于正文侧边栏:
包括 搜索,热评文章
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%--博客主体-右侧侧边栏 start--%>
<div id="sidebar" class="widget-area all-sidebar"
style="position: relative; overflow: visible; box-sizing: border-box; min-height: 1px;">
<%--搜索框--%>
<aside class="widget widget_search">
<div class="searchbar">
<form method="get" id="searchform1" action="/search">
<span> <input type="text" value="" name="keywords" id="s1" placeholder="输入搜索内容" required="">
<button type="submit" id="searchsubmit1">搜索</button>
</span>
</form>
</div>
<div class="clear"></div>
</aside>
<%--搜索框--%>
<%--热评文章 start--%>
<aside class="widget hot_comment" >
<h3 class="widget-title">
<i class="fa fa-bars"></i>热评文章
</h3>
<div id="hot_comment_widget">
<ul>
<c:forEach items="${mostCommentArticleList}" var="m">
<li>
<a href="/article/${m.articleId}" rel="bookmark" title=" (${m.articleCommentCount}条评论)">
${m.articleTitle}
</a>
</li>
</c:forEach>
</ul>
</div>
<div class="clear"></div>
</aside>
<%--热评文章 end--%>
</div>
<%--博客主体-右侧侧边栏 end--%>
1.3 顶部导航header.jsp
博客的顶部部分:登录/进入后台(判断Session中有没有User,有的话,显示进入后台,否则显示登录),顶部菜单(还记得之前的管理员后台添加菜单时,就有这个选项),主要菜单,搜索。
<%--
博客顶部部分
包括:顶部菜单,主要菜单(包括搜索按钮),面包屑
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%--导航 start--%>
<header id="masthead" class="site-header">
<%--顶部菜单 start--%>
<nav id="top-header">
<div class="top-nav">
<div class="user-login">
<c:choose>
<c:when test="${sessionScope.user==null}">
<a href="/admin">登录</a>
</c:when>
<c:otherwise>
<a href="/admin">进入后台</a>
</c:otherwise>
</c:choose>
</div>
<div class="menu-topmenu-container">
<ul id="menu-topmenu" class="top-menu">
<c:forEach items="${menuList}" var="m">
<li class="menu-item">
<c:if test="${m.menuLevel==1}">
<a href="${m.menuUrl}" >
<i class="${m.menuIcon}"></i>
<span class="font-text">${m.menuName} </span>
</a>
</c:if>
</li>
</c:forEach>
</ul>
</div>
</div>
</nav><!-- #top-header -->
<%--顶部菜单 end--%>
<%--主要菜单 satrt--%>
<div id="menu-box">
<div id="top-menu">
<span class="nav-search">
<i class="fa fa-search"></i>
</span>
<div class="logo-site"><h1 class="site-title">
<a href="/" title="${options.optionSiteTitle}">${options.optionSiteTitle}</a>
</h1>
<p class="site-description">${options.optionSiteDescrption}</p>
</div><!-- .logo-site -->
<div id="site-nav-wrap">
<div id="sidr-close">
<a href="#sidr-close" class="toggle-sidr-close">×</a>
</div>
<nav id="site-nav" class="main-nav">
<a href="#sidr-main" id="navigation-toggle" class="bars">
<i class="fa fa-bars"></i>
</a>
<div class="menu-pcmenu-container">
<ul id="menu-pcmenu" class="down-menu nav-menu sf-js-enabled sf-arrows">
<li>
<a href="/">
<i class="fa-home fa"></i>
<span class="font-text">首页</span>
</a>
</li>
<c:forEach items="${allCategoryList}" var="category">
<c:if test="${category.categoryPid==0}">
<li>
<a href="/category/${category.categoryId}">
<i class="${category.categoryIcon}"></i>
<span class="font-text">${category.categoryName} </span>
</a>
<ul class="sub-menu">
<c:forEach items="${allCategoryList}" var="cate">
<c:if test="${cate.categoryPid==category.categoryId}">
<li>
<a href="/category/${cate.categoryId}" target="_blank">${cate.categoryName}</a>
</li>
</c:if>
</c:forEach>
</ul>
</li>
</c:if>
</c:forEach>
<%--主要菜单其余部分--%>
<c:forEach items="${menuList}" var="m">
<c:if test="${m.menuLevel == 2}">
<li>
<a href="${m.menuUrl}">
<i class="${m.menuIcon}"></i>
<span class="font-text">${m.menuName} </span>
</a>
</li>
</c:if>
</c:forEach>
</ul>
</div>
</nav>
</div>
<div class="clear"></div>
</div><!-- #top-menu -->
</div><!-- #menu-box -->
<%--主要菜单 satrt--%>
</header><!-- #masthead -->
<%--导航 end start--%>
<%--搜索框 start--%>
<div id="search-main">
<div class="searchbar">
<form method="get" id="searchform" action="/search" accept-charset="UTF-8">
<span>
<input type="text" value="" name="keywords" id="s" placeholder="输入搜索内容"required="">
<button type="submit" id="searchsubmit">搜索</button>
</span>
</form>
</div>
<div class="clear"></div>
</div>
<%--搜索框 end--%>
<rapid:block name="breadcrumb"></rapid:block>
1.4 博客页脚
<%--
博客页脚部分
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%--页脚 start--%>
<footer id="colophon" class="site-footer" role="contentinfo">
<div class="site-info">
<p style="text-align: center;">Copyright © 2020
<a href="/" target="_blank" rel="noopener noreferrer">${options.optionSiteTitle}</a>
All rights reserved.
<a target="_blank" href="/map" >
<span class="font-text">站点地图</span>
</a>
</p>
</div>
<!-- .site-info -->
</footer><!-- .site-footer -->
<%--页脚 end--%>
1.5 分页
<c:if test="${pageInfo.pages > 1}">
<nav class="navigation pagination" role="navigation">
<div class="nav-links">
<c:choose>
<c:when test="${pageInfo.pages <= 3 }">
<c:set var="begin" value="1"/>
<c:set var="end" value="${pageInfo.pages }"/>
</c:when>
<c:otherwise>
<c:set var="begin" value="${pageInfo.pageNum-1 }"/>
<c:set var="end" value="${pageInfo.pageNum + 2}"/>
<c:if test="${begin < 2 }">
<c:set var="begin" value="1"/>
<c:set var="end" value="3"/>
</c:if>
<c:if test="${end > pageInfo.pages }">
<c:set var="begin" value="${pageInfo.pages-2}"/>
<c:set var="end" value="${pageInfo.pages }"/>
</c:if>
</c:otherwise>
</c:choose>
<%--上一页 --%>
<c:choose>
<c:when test="${pageInfo.pageNum eq 1 }">
<%--当前页为第一页,隐藏上一页按钮--%>
</c:when>
<c:otherwise>
<a class="page-numbers" href="${pageUrlPrefix}=${pageInfo.pageNum-1}">
<span class="fa fa-angle-left"></span>
</a>
</c:otherwise>
</c:choose>
<%--显示第一页的页码--%>
<c:if test="${begin >= 2 }">
<a class="page-numbers" href="${pageUrlPrefix}=1">1</a>
</c:if>
<%--显示点点点--%>
<c:if test="${begin > 2 }">
<span class="page-numbers dots">...</span>
</c:if>
<%--打印 页码--%>
<c:forEach begin="${begin }" end="${end }" var="i">
<c:choose>
<c:when test="${i eq pageInfo.pageNum }">
<a class="page-numbers current">${i}</a>
</c:when>
<c:otherwise>
<a class="page-numbers" href="${pageUrlPrefix}=${i}">${i}</a>
</c:otherwise>
</c:choose>
</c:forEach>
<%-- 显示点点点 --%>
<c:if test="${end < pageInfo.pages-1}">
<span class="page-numbers dots">...</span>
</c:if>
<%-- 显示最后一页的数字 --%>
<c:if test="${end < pageInfo.pages }">
<a href="${pageUrlPrefix}=${pageInfo.pages}">${pageInfo.pages}</a>
</c:if>
<%--下一页 --%>
<c:choose>
<c:when test="${pageInfo.pageNum eq pageInfo.pages }">
<%--到了尾页隐藏,下一页按钮--%>
</c:when>
<c:otherwise>
<a class="page-numbers" href="${pageUrlPrefix}=${pageInfo.pageNum+1}">
<span class="fa fa-angle-right"></span>
</a>
</c:otherwise>
</c:choose>
</div>
</nav>
<%--分页 end--%>
</c:if>
二.拦截器
在跳转到博客主页的时候,显示出的页面有什么菜单信息等。这些信息如果是放在响应跳转请求中实现,那么跳转到其他页面的时候,还需要查询这些信息。为了方便起见,我们使用SpringMVC的拦截器进行处理,在处理请求之前,准备资源数据,然后将这些数据当做请求属性放入WebRequest,这样即使进行不断的页面跳转,也会显示信息。
package com.test.ssm.blog.interceptor;
//拦截器
import com.test.ssm.blog.entity.Article;
import com.test.ssm.blog.entity.Category;
import com.test.ssm.blog.entity.Menu;
import com.test.ssm.blog.entity.Options;
import com.test.ssm.blog.enums.ArticleStatus;
import com.test.ssm.blog.enums.LinkStatus;
import com.test.ssm.blog.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
@Component
public class HomeResourceInterceptor implements HandlerInterceptor {
@Autowired
private ArticleService articleService;
@Autowired
private CategoryService categoryService;
@Autowired
private TagService tagService;
@Autowired
private LinkService linkService;
@Autowired
private OptionsService optionsService;
@Autowired
private MenuService menuService;
/**
* 在请求处理之前,该方法主要是用于准备资源数据的,然后可以把他它们当做请求属性放在WebRequest
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
//菜单显示
List<Menu> menuList=menuService.listMenu();
httpServletRequest.setAttribute("menuList",menuList);
//分类
List<Category> categoryList=categoryService.listCategory();
httpServletRequest.setAttribute("allCategoryList",categoryList);
//获得网站概况
List<String> siteBasicStatistics=new ArrayList<>();
siteBasicStatistics.add(articleService.countArticle(ArticleStatus.PUBLISH.getValue())+"");
siteBasicStatistics.add(articleService.countArticleComment()+"");
siteBasicStatistics.add(categoryService.countCategory()+"");
siteBasicStatistics.add(tagService.countTag()+"");
siteBasicStatistics.add(linkService.countLink(LinkStatus.NORMAL.getValue())+"");
siteBasicStatistics.add(articleService.countArticleView()+"");
httpServletRequest.setAttribute("siteBasicStatistics",siteBasicStatistics);
//最后更新的文章
Article lastUpdateArticle=articleService.getLastUpdateArticle();
httpServletRequest.setAttribute("lastUpdateArticle",lastUpdateArticle);
//页脚显示(显示博客基本信息Options)
Options options=optionsService.getOptions();
httpServletRequest.setAttribute("options",options);
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
一定记得这个拦截器要在SpringMVC的配置文件进行配置:
<!--6.拦截器-->
<mvc:interceptors>
<!--只要进行请求,就进行拦截,获取网站基本信息-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.test.ssm.blog.interceptor.HomeResourceInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/admin"/>
<bean class="com.test.ssm.blog.interceptor.SecurityInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
三.文章详细信息显示
3.1 文章详情JSP页面
这个除了显示文章信息和侧边栏之外,最重要的就是显示文章下的评论。当你是在登录下的状态去回复评论的时候,下面就会显示用户信息去回复。如果不是以博主的身份进行评论,则需要输入自己的信息(这个部分的Controller操作会在后面讲到,现在就是说明下页面显示)。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="rapid" uri="http://www.rapid-framework.org.cn/rapid" %>
<rapid:override name="title">
<title>${article.articleTitle}</title>
</rapid:override>
<rapid:override name="header-style">
<rapid:override name="header-style">
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/highlight.css">
<style>
.entry-title {
background: #f8f8f8;
}
</style>
</rapid:override>
</rapid:override>
<rapid:override name="breadcrumb">
<%--面包屑导航 start--%>
<nav class="breadcrumb">
<a class="crumbs" href="/">
<i class="fa fa-home"></i>首页
</a>
<c:choose>
<c:when test="${article.categoryList != null && article.categoryList.size() > 0}">
<c:forEach items="${article.categoryList}" var="c">
<i class="fa fa-angle-right"></i>
<a href="/category/${c.categoryId}">
${c.categoryName}
</a>
</c:forEach>
</c:when>
<c:otherwise>
<i class="fa fa-angle-right"></i>
<a>未分类</a>
</c:otherwise>
</c:choose>
<i class="fa fa-angle-right"></i>
正文
</nav>
<%--面包屑导航 end--%>
</rapid:override>
<rapid:override name="left">
<%--博客主体-左侧文章正文 start--%>
<div id="primary" class="content-area">
<main id="main" class="site-main" role="main">
<article class="post" id="articleDetail" data-id="${article.articleId}">
<header class="entry-header">
<h1 class="entry-title">
${article.articleTitle}
</h1>
</header><!-- .entry-header -->
<div class="entry-content">
<div class="single-content">
${article.articleContent}
</div>
<div class="clear"></div>
<div id="social">
<div class="social-main">
<span class="like">
<a href="javascript:;" data-action="ding" data-id="1" title="点赞"
class="favorite" onclick="increaseLikeCount()">
<i class="fa fa-thumbs-up"></i>赞
<i class="count"
id="count-${article.articleId}">${article.articleLikeCount}</i>
</a>
</span>
<div class="shang-p">
<div class="shang-empty"><span></span></div>
<span class="shang-s">
<a onclick="PaymentUtils.show();" style="cursor:pointer">赏</a>
</span>
</div>
<div class="share-sd">
<span class="share-s" style="margin-top: 25px!important;">
<a href="javascript:void(0)" id="share-s" title="分享">
<i class="fa fa-share-alt"></i>分享
</a>
</span>
<div id="share">
<ul class="bdsharebuttonbox bdshare-button-style1-16" data-bd-bind="1503997585792">
<li><a title="更多" class="bds_more fa fa-plus-square" data-cmd="more"
onclick="return false;" href="#"></a></li>
<li><a title="分享到QQ空间" class="fa fa-qq" data-cmd="qzone" onclick="return false;"
href="#"></a></li>
<li><a title="分享到新浪微博" class="fa fa-weibo" data-cmd="tsina"
onclick="return false;" href="#"></a></li>
<li><a title="分享到腾讯微博" class="fa fa-pinterest-square" data-cmd="tqq"
onclick="return false;" href="#"></a></li>
<li><a title="分享到人人网" class="fa fa-renren" data-cmd="renren"
onclick="return false;" href="#"></a></li>
<li><a title="分享到微信" class="fa fa-weixin" data-cmd="weixin"
onclick="return false;" href="#"></a></li>
</ul>
</div>
</div>
<div class="clear"></div>
</div>
</div>
<footer class="single-footer">
<ul class="single-meta">
<c:if test="${sessionScope.user!=null}">
<li class="edit-link">
<a target="_blank" class="post-edit-link"
href="/admin/article/edit/${article.articleId}">编辑</a>
</li>
</c:if>
<li class="comment">
<a href="/article/${article.articleId}#comments"
rel="external nofollow">
<i class="fa fa-comment-o"></i>
<i class="comment-count">${commentList.size()}</i>
</a>
</li>
<li class="views">
<i class="fa fa-eye"></i> <span
class="articleViewCount">${article.articleViewCount}</span>
views
</li>
<li class="r-hide">
<a href="javascript:pr()" title="侧边栏">
<i class="fa fa-caret-left"></i>
<i class="fa fa-caret-right"></i>
</a>
</li>
</ul>
<ul id="fontsize">
<li>A+</li>
</ul>
<div class="single-cat-tag">
<div class="single-cat">所属分类:
<c:forEach items="${article.categoryList}" var="c">
<a href="/category/${c.categoryId}">
${c.categoryName}
</a>
</c:forEach>
</div>
</div>
</footer><!-- .entry-footer -->
<div class="clear"></div>
</div><!-- .entry-content -->
</article><!-- #post -->
<%--所属标签 start--%>
<div class="single-tag">
<ul class="" data-wow-delay="0.3s">
<c:forEach items="${article.tagList}" var="t">
<li>
<a href="/tag/${t.tagId}" rel="tag"
style="background:#666666">
${t.tagName}
</a>
</li>
</c:forEach>
</ul>
</div>
<%--所属标签 end--%>
<%--版权声明 start--%>
<div class="authorbio wow fadeInUp">
<img alt="${article.user.userNickname}" src="${article.user.userAvatar}"
class="avatar avatar-64 photo" height="64" width="64">
<ul class="postinfo">
<li></li>
<li><strong>版权声明:</strong>本站原创文章,于<fmt:formatDate
value="${article.articleCreateTime}"
pattern="yyyy-MM-dd"/>,由
<strong>
${article.user.userNickname}
</strong>
发表。
</li>
<li class="reprinted"><strong>转载请注明:</strong>
<a href="/article/${article.articleId}"
rel="bookmark"
title="本文固定链接 /article/${article.articleId}">
${article.articleTitle} | ${options.optionSiteTitle}</a>
</li>
</ul>
<div class="clear"></div>
</div>
<%--版权声明 end--%>
<%--相关文章 start--%>
<div id="single-widget">
<div class="wow fadeInUp" data-wow-delay="0.3s">
<aside id="related_post-2" class="widget">
<h3 class="widget-title">
<span class="s-icon"></span>相关文章
</h3>
<div id="related_post_widget">
<ul>
<c:forEach items="${similarArticleList}" var="s">
<li>
<a href="/article/${s.articleId}">${s.articleTitle}</a>
</li>
</c:forEach>
</ul>
</div>
<div class="clear"></div>
</aside>
<%--猜你喜欢 start--%>
<aside id="hot_post-8" class="widget hot_post">
<h3 class="widget-title"><span class="s-icon"></span>猜你喜欢</h3>
<div id="hot_post_widget">
<ul>
<c:forEach items="${mostViewArticleList}" var="m">
<li>
<a href="/article/${m.articleId}">
${m.articleTitle}
</a>
</li>
</c:forEach>
</ul>
</div>
<div class="clear"></div>
</aside>
<%--猜你喜欢 end--%>
</div>
<div class="clear"></div>
</div>
<%--相关文章 end--%>
<%--上一篇下一篇 start--%>
<nav class="nav-single">
<c:choose>
<c:when test="${preArticle!=null}">
<a href="/article/${preArticle.articleId}" rel="next">
<span class="meta-nav">
<span class="post-nav">上一篇
<i class="fa fa-angle-left"></i>
</span>
<br>${preArticle.articleTitle}
</span>
</a>
</c:when>
<c:otherwise>
<span class="meta-nav">
<span class="post-nav">
没有了<br>
</span>已是第一篇文章
</span>
</c:otherwise>
</c:choose>
<c:choose>
<c:when test="${afterArticle!=null}">
<a href="/article/${afterArticle.articleId}" rel="next">
<span class="meta-nav">
<span class="post-nav">下一篇
<i class="fa fa-angle-right"></i>
</span>
<br>${afterArticle.articleTitle}
</span>
</a>
</c:when>
<c:otherwise>
<span class="meta-nav">
<span class="post-nav">
没有了<br>
</span>已是最后文章
</span>
</c:otherwise>
</c:choose>
<div class="clear"></div>
</nav>
<%--上一篇下一篇 end--%>
<%--评论区域 start--%>
<div class="scroll-comments"></div>
<div id="comments" class="comments-area">
<div id="respond" class="comment-respond">
<h3 id="reply-title" class="comment-reply-title"><span id="reply-title-word">发表评论</span>
<a rel="nofollow" id="cancel-comment-reply-link"
href="/article/${article.articleId}#respond"
style="">取消回复</a>
</h3>
<form id="comment_form" method="post">
<c:if test="${sessionScope.user!=null}">
<div class="user_avatar">
<img alt="努力"
src="${sessionScope.user.userAvatar}"
class="avatar avatar-64 photo" height="64" width="64">
登录者:${sessionScope.user.userNickname}
<br> <a href="javascript:void(0)" onclick="logout()">登出</a>
<input type="hidden" name="commentRole" value="1">
<input type="hidden" name="commentAuthorName"
value="${sessionScope.user.getUserNickname()}">
<input type="hidden" name="commentAuthorEmail"
value="${sessionScope.user.getUserEmail()}">
<input type="hidden" name="commentAuthorUrl" value="${sessionScope.user.getUserUrl()}">
</div>
</c:if>
<p class="comment-form-comment">
<textarea id="comment" name="commentContent" rows="4" tabindex="1" required></textarea>
</p>
<div id="comment-author-info">
<input type="hidden" name="commentPid" value="0">
<input type="hidden" name="commentPname" value="">
<c:if test="${sessionScope.user == null}">
<input type="hidden" name="commentRole" value="0">
<p class="comment-form-author">
<label for="author_name">
昵称<span class="required">*</span>
</label>
<input type="text" name="commentAuthorName" id="author_name" class="" value=""
tabindex="2" required>
</p>
<p class="comment-form-email">
<label for="author_email">
邮箱<span class="required">*</span>
</label>
<input type="email" name="commentAuthorEmail" id="author_email" class="" value=""
tabindex="3" required>
</p>
<p class="comment-form-url">
<label for="author_url">网址</label>
<input type="url" name="commentAuthorUrl" id="author_url" class="" value=""
tabindex="4">
</p>
</c:if>
</div>
<div class="clear"></div>
<p class="form-submit">
<input id="submit" name="submit" type="submit" tabindex="5" value="提交评论">
<input type="hidden" name="commentArticleId"
value="${article.articleId}" id="article_id">
<input type="hidden" name="commentPid" id="comment_pid" value="0">
</p>
</form>
</div>
<ol class="comment-list">
<c:set var="floor" value="0"/>
<c:forEach items="${commentList}" var="c">
<c:if test="${c.commentPid == 0}">
<c:set var="floor" value="${floor + 1}"/>
<li class="comments-anchor">
<ul id="anchor-comment-${c.commentId}"></ul>
</li>
<li class="comment">
<div id="div-comment-${c.commentId}" class="comment-body">
<div class="comment-author vcard">
<img class="avatar" src="${c.commentAuthorAvatar}" alt="avatar"
style="display: block;">
<strong>${c.commentAuthorName} </strong>
<c:if test="${c.commentRole == 1}">
<i class="fa fa-black-tie" style="color: #c40000;"></i>
<span class=""
style="margin-top: 2px!important;color: #c40000;font-size: 13px;;"><b>博主</b></span>
</c:if>
<span class="comment-meta commentmetadata">
<span class="ua-info" style="display: inline;">
<br>
<span class="comment-aux">
<span class="reply">
<a rel="nofollow" class="comment-reply-link" href="#respond"
onclick="replyComment()">回复
</a>
</span>
<fmt:formatDate value="${c.commentCreateTime}"
pattern="yyyy年MM月dd日 HH:mm:ss"/>
<c:if test="${sessionScope.user != null}">
<a href="javascript:void(0)"
onclick="deleteComment(${c.commentId})">删除</a>
<a class="comment-edit-link"
href="/admin/comment/edit/${c.commentId}"
target="_blank">编辑</a>
</c:if>
<span class="floor"> ${floor}楼 </span>
</span>
</span>
</span>
<p>
<c:if test="${c.commentPid!=0}">
<span class="at">@ ${c.commentPname}</span>
</c:if>
${c.commentContent}
</p>
</div>
</div>
<ul class="children">
<c:set var="floor2" value="0"/>
<c:forEach items="${commentList}" var="c2">
<c:if test="${c.commentId == c2.commentPid}">
<c:set var="floor2" value="${floor2+1}"/>
<li class="comments-anchor">
<ul id="anchor-comment-${c2.commentId}"></ul>
</li>
<li class="comment">
<div id="div-comment-${c.commentId}" class="comment-body">
<div class="comment-author vcard">
<img class="avatar" src="${c2.commentAuthorAvatar}" alt="avatar"
style="display: block;">
<strong>${c2.commentAuthorName} </strong>
<c:if test="${c2.commentRole==1}">
<i class="fa fa-black-tie" style="color: #c40000;"></i>
<span class=""
style="margin-top: 2px!important;color: #c40000;font-size: 13px;;"><b>博主</b></span>
</c:if>
<span class="comment-meta">
<span class="ua-info" style="display: inline;">
<br>
<span class="comment-aux">
<span class="reply">
<a rel="nofollow" class="comment-reply-link" href="#respond"
onclick="replyComment()">回复
</a>
</span>
<fmt:formatDate value="${c2.commentCreateTime}"
pattern="yyyy年MM月dd日 HH:mm:ss"/>
<c:if test="${sessionScope.user != null}">
<a href="javascript:void(0)"
onclick="deleteComment(${c2.commentId})">删除</a>
<a class="comment-edit-link"
href="/admin/comment/edit/${c2.commentId}"
target="_blank">编辑</a>
</c:if>
<span class="floor"> ${floor2}层 </span>
</span>
</span>
</span>
<p>
<c:if test="${c2.commentPid!=0}">
<c:if test="${c2.commentPid!=0}">
<span class="at">@ ${c2.commentPname}</span>
</c:if>
${c2.commentContent}
</c:if>
</p>
</div>
</div>
</li>
</c:if>
</c:forEach>
</ul>
</li>
</c:if>
</c:forEach>
</ol>
</div>
<%--评论框 end--%>
</main>
<!-- .site-main -->
</div>
<%--博客主体-左侧文章正文end--%>
</rapid:override>
<%--侧边栏 start--%>
<rapid:override name="right">
<%@include file="../Public/part/sidebar-1.jsp" %>
</rapid:override>
<%--侧边栏 end--%>
<rapid:override name="footer-script">
<script src="${pageContext.request.contextPath}/js/jquery.cookie.js"></script>
<script type="text/javascript">
$(document).ready(function () {
if ($('#author_name').val() == '') {
var author = localStorage.getItem("author");
$("#author_name").val(author == 'undefined' ? '' : author);
}
if ($('#author_email').val() == '') {
var email = localStorage.getItem("email");
$("#author_email").val(email == 'undefined' ? '' : email);
}
if ($('#author_url').val() == '') {
var url = localStorage.getItem("url");
$("#author_url").val(url == 'undefined' ? '' : url);
}
});
var articleId = $("#articleDetail").attr("data-id");
increaseViewCount(articleId);
layui.code({
elem: 'pre',//默认值为.layui-code
// skin: 'notepad', //如果要默认风格,不用设定该key。
about: false
});
</script>
</rapid:override>
<%@ include file="../Public/framework.jsp" %>
3.2 ArticleController
3.2.1 文章详情页显示
这个就是基本的查询信息,放入Model中。
@Controller
public class ArticleController {
@Autowired
private ArticleService articleService;
@Autowired
private CommentService commentService;
@Autowired
private UserService userService;
@Autowired
private TagService tagService;
@Autowired
private CategoryService categoryService;
//文章详情页显示
@RequestMapping(value = "article/{articleId}")
public String getArticleDetailPage(@PathVariable("articleId")Integer articleId, Model model){
//文章信息
Article article=articleService.getArticleByStatusAndId(ArticleStatus.PUBLISH.getValue(),articleId);
if(article==null)
{
return "Home/Error/404";
}
//用户信息
User user=userService.getUserById(article.getArticleUserId());
article.setUser(user);
model.addAttribute("article",article);
//评论列表
List<Comment> commentList=commentService.listCommentByArticleId(articleId);
model.addAttribute("commentList",commentList);
//相关文章
List<Integer> categoryIds=articleService.listCategoryIdByArticleId(articleId);
List<Article> similarArticleList=articleService.listArticleByCategoryIds(categoryIds,5);
model.addAttribute("similarArticleList",similarArticleList);
//测你喜欢
List<Article> mostViewArticleList=articleService.listArticleByViewCount(5);
model.addAttribute("mostViewArticleList",mostViewArticleList);
//获取下一篇文章
Article afterArticle=articleService.getAfterArticle(articleId);
model.addAttribute("afterArticle",afterArticle);
//获取上一篇文章
Article preArticle=articleService.getPreArticle(articleId);
model.addAttribute("preArticle",preArticle);
//侧边栏
//标签列表显示
List<Tag> allTagList=tagService.listTag();
model.addAttribute("allTagList",allTagList);
//获得随机文章
List<Article> randomArticleList=articleService.listRandomArticle(8);
model.addAttribute("randomArticleList",randomArticleList);
//获得热评文章
List<Article> mostCommentArticleList=articleService.listArticleByCommentCount(8);
model.addAttribute("mostCommentArticleList",mostCommentArticleList);
return "Home/Page/articleDetail";
}
3.2.2 点赞
JSP页面:
<script type="text/javascript">
...
var articleId = $("#articleDetail").attr("data-id");
increaseViewCount(articleId);
layui.code({
elem: 'pre',//默认值为.layui-code
// skin: 'notepad', //如果要默认风格,不用设定该key。
about: false
});
</script>
Ajax方法是:这个会在浏览器的Cookie中创建一个标识viewId,当从第一次其他页面点入这个文章的时候,Cookie中的viewId便是null,就可以进行下面的ajax请求方法。便可以防止在这个页面刷新后增加浏览量。只要传递过来的文章Id和这个viewId不同,便说明是从其他页面过来的可以进行增加浏览量。
//文章浏览量+1
function increaseViewCount(articleId) {
if ($.cookie("viewId") != articleId || $.cookie("viewId") == null) {
$.ajax({
async: false,
type: "POST",
url: "/article/view/" + articleId,
dataType: 'json',
contentType: 'application/json',
success: function (data) {
$(".articleViewCount").html(data);
$.cookie(
"viewId",
articleId,//需要cookie写入的业务
{
"path": "/", //cookie的默认属性
}
);
},
error: function () {
alert("获取数据出错!");
},
});
}
}
这个就是文章的点赞功能。
//点赞添加
@RequestMapping(value = "/article/like/{id}",method = RequestMethod.POST)
@ResponseBody
public String increaseLikeCount(@PathVariable("id")Integer id)
{
Article article=articleService.getArticleByStatusAndId(ArticleStatus.PUBLISH.getValue(),id);
Integer articleCount=article.getArticleLikeCount()+1;
article.setArticleLikeCount(articleCount);
articleService.updateArticle(article);
return JSON.toJSONString(articleCount);
}
3.3.3 文章访问量增加
JSP页面:
<a href="javascript:;" data-action="ding" data-id="1" title="点赞"
class="favorite" onclick="increaseLikeCount()">
<i class="fa fa-thumbs-up"></i>赞
<i class="count"
id="count-${article.articleId}">${article.articleLikeCount}</i>
</a>
Ajax方法:这个处理方式和增加浏览量的处理方式是一样的。都是想Cookie中放入一个likeId。当第一次点击这个赞的时候,就可以进行请求,同时将文章ID放入likeId中,防止在这个页面无限次点赞。
//点赞+1
function increaseLikeCount() {
if ($.cookie("likeId") != articleId || $.cookie("likeId") == null) {
$.ajax({
async: false,
type: "POST",
url: "/article/like/" + articleId,
dataType: 'json',
contentType: 'application/json',
success: function (data) {
$(".count").html(data);
$.cookie(
"likeId",
articleId,//需要cookie写入的业务
{
"path": "/", //cookie的默认属性
}
);
},
error: function () {
//alert("获取数据出错!");
},
});
}
}
Controller层:
//文章访问数量增加
@RequestMapping(value = "/article/view/{id}", method = {RequestMethod.POST})
@ResponseBody
public String increaseViewCount(@PathVariable("id")Integer id){
Article article = articleService.getArticleByStatusAndId(ArticleStatus.PUBLISH.getValue(), id);
Integer articleCount = article.getArticleViewCount() + 1;
article.setArticleViewCount(articleCount);
System.out.println(articleCount);
articleService.updateArticle(article);
return JSON.toJSONString(articleCount);
}
3.3 页面显示
文章详情页显示:
目前博主是在登录的状态下,评论部分是这样显示的:
未登录的时候:
四.根据分类查询文章列表
在之前的后台页面中,文章列表的表格中会显示分类列表,管理员后台:
一般用户后台:
博客主页的菜单显示:
在点击文章进来后,会显示这个文章所属的分类层次:
可以看到这些页面都有这个分类的显示,可以进行点击,点击后就会跳转到显示这个分类下所有文章的页面。
4.1 分类下文章列表JSP页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="rapid" uri="http://www.rapid-framework.org.cn/rapid" %>
<rapid:override name="description">
<meta name="description" content="${category.categoryName}"/>
</rapid:override>
<rapid:override name="keywords">
<meta name="keywords" content="${category.categoryName}"/>
</rapid:override>
<rapid:override name="title">
<title>${category.categoryName}</title>
</rapid:override>
<%--面包屑导航 start--%>
<rapid:override name="breadcrumb">
<nav class="breadcrumb">
<a class="crumbs" href="/">
<i class="fa fa-home"></i>首页</a>
<i class="fa fa-angle-right"></i>
<c:choose>
<c:when test="${category != null}">
<a href="/category/${category.categoryId}">${category.categoryName}</a>
<i class="fa fa-angle-right"></i> 文章
</c:when>
<c:otherwise>
该分类不存在
</c:otherwise>
</c:choose>
</nav>
</rapid:override>
<%--面包屑导航 end--%>
<rapid:override name="left">
<%--博客主体-左侧正文 start--%>
<div id="primary" class="content-area">
<main id="main" class="site-main">
<c:choose>
<c:when test="${pageInfo != null}">
<c:choose>
<c:when test="${pageInfo.list.size() != 0}">
<%--文章列表-start--%>
<c:forEach items="${pageInfo.list}" var="a">
<article class="post">
<figure class="thumbnail">
<a href="/article/${a.articleId}">
<img width="280" height="210"
src="/img/thumbnail/random/img_${a.articleId%15}.jpg"
class="attachment-content size-content wp-post-image"
alt="${a.articleTitle}">
</a>
<span class="cat">
<a href="/category/${category.categoryId}">${category.categoryName}</a>
</span>
</figure>
<header class="entry-header">
<h2 class="entry-title">
<a href="/article/${a.articleId}" rel="bookmark">
${a.articleTitle}
</a>
</h2>
</header><!-- .entry-header -->
<div class="entry-content">
<div class="archive-content">
${a.articleSummary}...
</div>
<span class="title-l"></span>
<span class="new-icon">
<c:choose>
<c:when test="${a.articleStatus == 2}">
<i class="fa fa-bookmark-o"></i>
</c:when>
<c:otherwise>
<jsp:useBean id="nowDate"
class="java.util.Date"/> <%--当前时间--%>
<c:set var="interval"
value="${nowDate.time - a.articleCreateTime.time}"/><%--时间差毫秒数--%>
<fmt:formatNumber value="${interval/1000/60/60/24}"
pattern="#0"
var="days"/><%--取天数整数--%>
<c:if test="${days <= 7}">NEW</c:if>
</c:otherwise>
</c:choose>
</span>
<span class="entry-meta">
<span class="date">
<fmt:formatDate value="${a.articleCreateTime}"
pattern="yyyy年MM月dd日"/>
</span>
<span class="views">
<i class="fa fa-eye"></i>
${a.articleViewCount} views
</span>
<span class="comment">
<a href="/article/${a.articleId}#comments"
rel="external nofollow">
<i class="fa fa-comment-o"></i>
<c:choose>
<c:when test="${a.articleCommentCount==0}">
发表评论
</c:when>
<c:otherwise>
${a.articleCommentCount}
</c:otherwise>
</c:choose>
</a>
</span>
</span>
<div class="clear"></div>
</div><!-- .entry-content -->
<span class="entry-more">
<a href="/article/${a.articleId}"
rel="bookmark">阅读全文
</a>
</span>
</article>
</c:forEach>
<%--文章列表-end--%>
</c:when>
<c:otherwise>
<section class="no-results not-found">
<div class="post">
<p>该分类目前还没有文章!</p>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</section>
</c:otherwise>
</c:choose>
</c:when>
<c:otherwise>
<section class="no-results not-found">
<div class="post">
<p>该分类不存在</p>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</section>
</c:otherwise>
</c:choose>
</main>
<%@ include file="../Public/part/paging.jsp" %>
</div>
<%-- 博客主体-左侧正文 end--%>
</rapid:override>
<%@ include file="../Public/framework.jsp" %>
4.2 CategoryController
这个就是根据分类ID查找文章列表。
package com.test.ssm.blog.controller.home;
import com.github.pagehelper.PageInfo;
import com.test.ssm.blog.entity.Article;
import com.test.ssm.blog.entity.Category;
import com.test.ssm.blog.entity.Tag;
import com.test.ssm.blog.enums.ArticleStatus;
import com.test.ssm.blog.service.ArticleService;
import com.test.ssm.blog.service.CategoryService;
import com.test.ssm.blog.service.TagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.HashMap;
import java.util.List;
@Controller
public class CategoryController {
@Autowired
private CategoryService categoryService;
@Autowired
private ArticleService articleService;
@Autowired
private TagService tagService;
//根据分类查询文章
@RequestMapping("/category/{cateId}")
public String getArticleListByCategory(@PathVariable("cateId")Integer cateId,
@RequestParam(required = false,defaultValue = "1")Integer pageIndex,
@RequestParam(required = false,defaultValue = "10")Integer pageSize,
Model model){
//获得分类信息
Category category=categoryService.getCategoryById(cateId);
if(category==null){
return "redirect:/400";
}
model.addAttribute("category",category);
//文章列表
HashMap<String,Object> criteria=new HashMap<>(2);
criteria.put("categoryId",cateId);
criteria.put("status", ArticleStatus.PUBLISH.getValue());
PageInfo<Article> articlePageInfo=articleService.pageArticle(pageIndex,pageSize,criteria);
model.addAttribute("pageInfo",articlePageInfo);
//侧边栏
//标签列表显示
List<Tag> allTagList=tagService.listTag();
model.addAttribute("allTagList",allTagList);
//获得随机文章
List<Article> randomArticleList=articleService.listRandomArticle(8);
model.addAttribute("randomArticleList",randomArticleList);
//获得热评文章
List<Article> mostCommentArticleList=articleService.listArticleByCommentCount(8);
model.addAttribute("mostCommentArticleList",mostCommentArticleList);
model.addAttribute("pageUrlPrefix","/category/"+pageIndex+"?pageIndex");
return "Home/Page/articleListByCategory";
}
}
4.3 页面显示
五.根据标签查询文章
在之前的后台管理页面,管理员后台:
一般用户后台:
前台的侧边栏:
点击这个列表中的标签都会跳转到显示这个标签下文章列表的页面。
5.1 标签下的文章列表JSP页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="rapid" uri="http://www.rapid-framework.org.cn/rapid" %>
<rapid:override name="description">
<meta name="description" content="${category.categoryName}"/>
</rapid:override>
<rapid:override name="keywords">
<meta name="keywords" content="${category.categoryName}"/>
</rapid:override>
<rapid:override name="title">
<title>${category.categoryName}</title>
</rapid:override>
<%--面包屑导航 start--%>
<rapid:override name="breadcrumb">
<nav class="breadcrumb">
<a class="crumbs" href="/">
<i class="fa fa-home"></i>首页</a>
<i class="fa fa-angle-right"></i>
<c:choose>
<c:when test="${tag != null}">
<a href="/tag/${tag.tagId}">${tag.tagName}</a>
<i class="fa fa-angle-right"></i> 文章
</c:when>
<c:otherwise>
该标签不存在
</c:otherwise>
</c:choose>
</nav>
</rapid:override>
<%--面包屑导航 end--%>
<rapid:override name="left">
<%--博客主体-左侧正文 start--%>
<div id="primary" class="content-area">
<main id="main" class="site-main">
<c:choose>
<c:when test="${pageInfo.list.size() != 0}">
<%--文章列表-start--%>
<c:forEach items="${pageInfo.list}" var="a">
<article class="post">
<figure class="thumbnail">
<a href="/article/${a.articleId}">
<img width="280" height="210"
src="/img/thumbnail/random/img_${a.articleId%15}.jpg"
class="attachment-content size-content wp-post-image"
alt="${a.articleTitle}">
</a>
<span class="cat">
<a href="/category/${a.categoryList[0].categoryId}">${a.categoryList[0].categoryName}</a>
</span>
</figure>
<header class="entry-header">
<h2 class="entry-title">
<a href="/article/${a.articleId}" rel="bookmark">
${a.articleTitle}
</a>
</h2>
</header><!-- .entry-header -->
<div class="entry-content">
<div class="archive-content">
${a.articleSummary}...
</div>
<span class="title-l"></span>
<span class="new-icon">
<c:choose>
<c:when test="${a.articleStatus == 2}">
<i class="fa fa-bookmark-o"></i>
</c:when>
<c:otherwise>
<jsp:useBean id="nowDate"
class="java.util.Date"/> <%--当前时间--%>
<c:set var="interval"
value="${nowDate.time - a.articleCreateTime.time}"/><%--时间差毫秒数--%>
<fmt:formatNumber value="${interval/1000/60/60/24}"
pattern="#0"
var="days"/><%--取天数整数--%>
<c:if test="${days <= 7}">NEW</c:if>
</c:otherwise>
</c:choose>
</span>
<span class="entry-meta">
<span class="date">
<fmt:formatDate value="${a.articleCreateTime}"
pattern="yyyy年MM月dd日"/>
</span>
<span class="views">
<i class="fa fa-eye"></i>
${a.articleViewCount} views
</span>
<span class="comment">
<a href="/article/${a.articleId}#comments"
rel="external nofollow">
<i class="fa fa-comment-o"></i>
<c:choose>
<c:when test="${a.articleCommentCount==0}">
发表评论
</c:when>
<c:otherwise>
${a.articleCommentCount}
</c:otherwise>
</c:choose>
</a>
</span>
</span>
<div class="clear"></div>
</div><!-- .entry-content -->
<span class="entry-more">
<a href="/article/${a.articleId}"
rel="bookmark">阅读全文
</a>
</span>
</article>
</c:forEach>
<%--文章列表-end--%>
</c:when>
</c:choose>
</main>
<%@ include file="../Public/part/paging.jsp" %>
</div>
<%-- 博客主体-左侧正文 end--%>
</rapid:override>
<%@ include file="../Public/framework.jsp" %>
5.2 TagController
package com.test.ssm.blog.controller.home;
import com.github.pagehelper.PageInfo;
import com.test.ssm.blog.entity.Article;
import com.test.ssm.blog.entity.Tag;
import com.test.ssm.blog.enums.ArticleStatus;
import com.test.ssm.blog.service.ArticleService;
import com.test.ssm.blog.service.TagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.HashMap;
import java.util.List;
@Controller
public class TagController {
@Autowired
private TagService tagService;
@Autowired
private ArticleService articleService;
//根据标签查询文章
@RequestMapping("/tag/{tagId}")
public String getArticleListBytTag(@PathVariable("tagId")Integer tagId,
@RequestParam(required = false,defaultValue = "1")Integer pageIndex,
@RequestParam(required = false,defaultValue = "10")Integer pageSize, Model model){
//该标签信息
Tag tag = tagService.getTagById(tagId);
if (tag == null) {
return "redirect:/404";
}
model.addAttribute("tag", tag);
//文章列表
HashMap<String, Object> criteria = new HashMap<>(2);
criteria.put("tagId", tagId);
criteria.put("status", ArticleStatus.PUBLISH.getValue());
PageInfo<Article> articlePageInfo = articleService.pageArticle(pageIndex, pageSize, criteria);
System.out.println(articlePageInfo.getSize());
model.addAttribute("pageInfo", articlePageInfo);
//侧边栏
//标签列表显示
List<Tag> allTagList = tagService.listTag();
model.addAttribute("allTagList", allTagList);
//获得随机文章
List<Article> randomArticleList = articleService.listRandomArticle(8);
model.addAttribute("randomArticleList", randomArticleList);
//获得热评文章
List<Article> mostCommentArticleList = articleService.listArticleByCommentCount(8);
model.addAttribute("mostCommentArticleList", mostCommentArticleList);
model.addAttribute("pageUrlPrefix", "/tag?pageIndex");
return "Home/Page/articleListByTag";
}
}
5.3 页面显示
在点击上面页面的Spring的标签链接之后,跳转的页面显示为:
六.评论操作
6.1 评论显示JSP
我们在之前的第二节文章详细信息JSP页面的时候,就发现了底下的部分就是评论部分。也就是说评论并没有单独的JSP。我们把这个评论框的JSP拿出来
<%--评论区域 start--%>
<div class="scroll-comments"></div>
<div id="comments" class="comments-area">
<div id="respond" class="comment-respond">
<h3 id="reply-title" class="comment-reply-title"><span id="reply-title-word">发表评论</span>
<a rel="nofollow" id="cancel-comment-reply-link"
href="/article/${article.articleId}#respond"
style="">取消回复</a>
</h3>
<form id="comment_form" method="post">
<c:if test="${sessionScope.user!=null}">
<div class="user_avatar">
<img alt="努力"
src="${sessionScope.user.userAvatar}"
class="avatar avatar-64 photo" height="64" width="64">
登录者:${sessionScope.user.userNickname}
<br> <a href="javascript:void(0)" onclick="logout()">登出</a>
<input type="hidden" name="commentRole" value="1">
<input type="hidden" name="commentAuthorName"
value="${sessionScope.user.getUserNickname()}">
<input type="hidden" name="commentAuthorEmail"
value="${sessionScope.user.getUserEmail()}">
<input type="hidden" name="commentAuthorUrl" value="${sessionScope.user.getUserUrl()}">
</div>
</c:if>
<p class="comment-form-comment">
<textarea id="comment" name="commentContent" rows="4" tabindex="1" required></textarea>
</p>
<div id="comment-author-info">
<input type="hidden" name="commentPid" value="0">
<input type="hidden" name="commentPname" value="">
<c:if test="${sessionScope.user == null}">
<input type="hidden" name="commentRole" value="0">
<p class="comment-form-author">
<label for="author_name">
昵称<span class="required">*</span>
</label>
<input type="text" name="commentAuthorName" id="author_name" class="" value=""
tabindex="2" required>
</p>
<p class="comment-form-email">
<label for="author_email">
邮箱<span class="required">*</span>
</label>
<input type="email" name="commentAuthorEmail" id="author_email" class="" value=""
tabindex="3" required>
</p>
<p class="comment-form-url">
<label for="author_url">网址</label>
<input type="url" name="commentAuthorUrl" id="author_url" class="" value=""
tabindex="4">
</p>
</c:if>
</div>
<div class="clear"></div>
<p class="form-submit">
<input id="submit" name="submit" type="submit" tabindex="5" value="提交评论">
<input type="hidden" name="commentArticleId"
value="${article.articleId}" id="article_id">
<input type="hidden" name="commentPid" id="comment_pid" value="0">
</p>
</form>
</div>
<ol class="comment-list">
<c:set var="floor" value="0"/>
<c:forEach items="${commentList}" var="c">
<c:if test="${c.commentPid == 0}">
<c:set var="floor" value="${floor + 1}"/>
<li class="comments-anchor">
<ul id="anchor-comment-${c.commentId}"></ul>
</li>
<li class="comment">
<div id="div-comment-${c.commentId}" class="comment-body">
<div class="comment-author vcard">
<img class="avatar" src="${c.commentAuthorAvatar}" alt="avatar"
style="display: block;">
<strong>${c.commentAuthorName} </strong>
<c:if test="${c.commentRole == 1}">
<i class="fa fa-black-tie" style="color: #c40000;"></i>
<span class=""
style="margin-top: 2px!important;color: #c40000;font-size: 13px;;"><b>博主</b></span>
</c:if>
<span class="comment-meta commentmetadata">
<span class="ua-info" style="display: inline;">
<br>
<span class="comment-aux">
<span class="reply">
<a rel="nofollow" class="comment-reply-link" href="#respond"
onclick="replyComment()">回复
</a>
</span>
<fmt:formatDate value="${c.commentCreateTime}"
pattern="yyyy年MM月dd日 HH:mm:ss"/>
<c:if test="${sessionScope.user != null}">
<a href="javascript:void(0)"
onclick="deleteComment(${c.commentId})">删除</a>
<a class="comment-edit-link"
href="/admin/comment/edit/${c.commentId}"
target="_blank">编辑</a>
</c:if>
<span class="floor"> ${floor}楼 </span>
</span>
</span>
</span>
<p>
<c:if test="${c.commentPid!=0}">
<span class="at">@ ${c.commentPname}</span>
</c:if>
${c.commentContent}
</p>
</div>
</div>
<ul class="children">
<c:set var="floor2" value="0"/>
<c:forEach items="${commentList}" var="c2">
<c:if test="${c.commentId == c2.commentPid}">
<c:set var="floor2" value="${floor2+1}"/>
<li class="comments-anchor">
<ul id="anchor-comment-${c2.commentId}"></ul>
</li>
<li class="comment">
<div id="div-comment-${c.commentId}" class="comment-body">
<div class="comment-author vcard">
<img class="avatar" src="${c2.commentAuthorAvatar}" alt="avatar"
style="display: block;">
<strong>${c2.commentAuthorName} </strong>
<c:if test="${c2.commentRole==1}">
<i class="fa fa-black-tie" style="color: #c40000;"></i>
<span class=""
style="margin-top: 2px!important;color: #c40000;font-size: 13px;;"><b>博主</b></span>
</c:if>
<span class="comment-meta">
<span class="ua-info" style="display: inline;">
<br>
<span class="comment-aux">
<span class="reply">
<a rel="nofollow" class="comment-reply-link" href="#respond"
onclick="replyComment()">回复
</a>
</span>
<fmt:formatDate value="${c2.commentCreateTime}"
pattern="yyyy年MM月dd日 HH:mm:ss"/>
<c:if test="${sessionScope.user != null}">
<a href="javascript:void(0)"
onclick="deleteComment(${c2.commentId})">删除</a>
<a class="comment-edit-link"
href="/admin/comment/edit/${c2.commentId}"
target="_blank">编辑</a>
</c:if>
<span class="floor"> ${floor2}层 </span>
</span>
</span>
</span>
<p>
<c:if test="${c2.commentPid!=0}">
<c:if test="${c2.commentPid!=0}">
<span class="at">@ ${c2.commentPname}</span>
</c:if>
${c2.commentContent}
</c:if>
</p>
</div>
</div>
</li>
</c:if>
</c:forEach>
</ul>
</li>
</c:if>
</c:forEach>
</ol>
</div>
这个最终显示有两种不同的显示:
一种是在博主登录的情况下,会显示隐藏的信息,例如博主的图像和昵称等。在这个下面会显示评论的列表:
一种是在没有登录的情况下,需要你自己填入基本信息进行评论,如下:
6.1 CommentController
我们在上面的JSP中并没有发现表单的action和请求链接,这是因为在JS中获取了表单信息,使用ajax的形式提交评论。在评论成功后,会将刚才的输入的信息放入到缓存中,设置一个过期时间。
//ajax提交评论信息
$("#comment_form").submit(function () {
$.ajax({
async: false,
type: "POST",
url: '/comment',
contentType: "application/x-www-form-urlencoded; charset=utf-8",
data: $("#comment_form").serialize(),
success: function (data) {
if (data.code == 0) {
layer.msg("评论成功!");
localStorage.setItem('author', $("#author_name").val());
localStorage.setItem('email', $("#author_email").val());
localStorage.setItem('url', $("#author_url").val());
window.setTimeout("window.location.reload()", 2000);
return false;
} else {
layer.msg(data.msg);
}
},
error: function () {
}
})
return false;
})
CommentController层:要注意评论时候的身份
@Controller
@RestController
public class CommentController {
@Autowired
private CommentService commentService;
@Autowired
private ArticleService articleService;
//添加评论
@RequestMapping(value = "/comment",method = RequestMethod.POST)
public JsonResult insertComment(HttpServletRequest servletRequest, Comment comment){
//添加评论
comment.setCommentCreateTime(new Date());
comment.setCommentIp(MyUtils.getIpAddr(servletRequest));
if(servletRequest.getSession().getAttribute("user")!=null){
//如果是在登录的情况下,创建的comment是以博主身份创建的
comment.setCommentRole(Role.ADMIN.getValue());
}else{
comment.setCommentRole(Role.VISITOR.getValue());
}
//根据Email创建头像
comment.setCommentAuthorAvatar(MyUtils.getGravatar(comment.getCommentAuthorEmail()));
//过滤字符:HtmlUtil
comment.setCommentContent(HtmlUtil.escape(comment.getCommentContent()));
comment.setCommentAuthorName(HtmlUtil.escape(comment.getCommentAuthorName()));
comment.setCommentAuthorEmail(HtmlUtil.escape(comment.getCommentAuthorEmail()));
comment.setCommentAuthorUrl(HtmlUtil.escape(comment.getCommentAuthorUrl()));
try{
commentService.insertComment(comment);
Article article=articleService.getArticleByStatusAndId(ArticleStatus.PUBLISH.getValue(),comment.getCommentArticleId());
articleService.updateCommentCount(article.getArticleId());
}catch (Exception e){
e.printStackTrace();
return new JsonResult().fail();
}
return new JsonResult().ok();
}
}
然后我们注意到这个删除和回复只在博主登录后才会有,也就是博主才有资格对评论进行删除和编辑的操作。这个发送的请求就是管理员后台评论的请求。
七.搜索操作
这是主页点击搜索后出现的搜索框:
<%--搜索框--%>
<aside class="widget widget_search">
<div class="searchbar">
<form method="get" id="searchform1" action="/search">
<span> <input type="text" value="" name="keywords" id="s1" placeholder="输入搜索内容" required="">
<button type="submit" id="searchsubmit1">搜索</button>
</span>
</form>
</div>
<div class="clear"></div>
</aside>
这是文章详情页的搜索框:
<%--搜索框--%>
<aside class="widget widget_search">
<div class="searchbar">
<form method="get" id="searchform1" action="/search">
<span> <input type="text" value="" name="keywords" id="s1" placeholder="输入搜索内容" required="">
<button type="submit" id="searchsubmit1">搜索</button>
</span>
</form>
</div>
<div class="clear"></div>
</aside>
7.1 搜索后显示文章列表JSP页面
输入搜索内容,点击搜索后跳转的页面。会显示文章列表。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="rapid" uri="http://www.rapid-framework.org.cn/rapid" %>
<rapid:override name="title">
<title>搜索结果</title>
</rapid:override>
<rapid:override name="breadcrumb">
<%--面包屑导航 start--%>
<nav class="breadcrumb">
<a class="crumbs" href="/">
<i class="fa fa-home"></i>首页</a>
<i class="fa fa-angle-right"></i>
搜索 ${param.keywords} 找到 ${pageInfo.total} 个与之相关的文章
</nav>
<%--面包屑导航 end--%>
</rapid:override>
<rapid:override name="left">
<%--博客主体 start--%>
<section id="content" class="site-content shadow">
<%--博客主体-左侧正文 start--%>
<section id="primary" class="content-area">
<main id="main" class="site-main">
<c:choose>
<c:when test="${pageInfo.list.size() != 0}">
<%--文章列表-start--%>
<c:forEach items="${pageInfo.list}" var="a">
<article class="post">
<figure class="thumbnail">
<a href="/article/${a.articleId}">
<img width="280" height="210"
src="/img/thumbnail/random/img_${a.articleId%15}.jpg"
class="attachment-content size-content wp-post-image"
alt="${a.articleTitle}">
</a>
<span class="cat">
<a href="/category/${a.categoryList[0].categoryId}">${a.categoryList[0].categoryName}</a>
</span>
</figure>
<header class="entry-header">
<h2 class="entry-title">
<a href="/article/${a.articleId}" rel="bookmark">
${a.articleTitle}
</a>
</h2>
</header><!-- .entry-header -->
<div class="entry-content">
<div class="archive-content">
${a.articleSummary}...
</div>
<span class="title-l"></span>
<span class="new-icon">
<c:choose>
<c:when test="${a.articleStatus == 2}">
<i class="fa fa-bookmark-o"></i>
</c:when>
<c:otherwise>
<jsp:useBean id="nowDate"
class="java.util.Date"/> <%--当前时间--%>
<c:set var="interval"
value="${nowDate.time - a.articleCreateTime.time}"/><%--时间差毫秒数--%>
<fmt:formatNumber value="${interval/1000/60/60/24}"
pattern="#0"
var="days"/><%--取天数整数--%>
<c:if test="${days <= 7}">NEW</c:if>
</c:otherwise>
</c:choose>
</span>
<span class="entry-meta">
<span class="date">
<fmt:formatDate value="${a.articleCreateTime}"
pattern="yyyy年MM月dd日"/>
</span>
<span class="views">
<i class="fa fa-eye"></i>
${a.articleViewCount} views
</span>
<span class="comment">
<a href="/article/${a.articleId}#comments"
rel="external nofollow">
<i class="fa fa-comment-o"></i>
<c:choose>
<c:when test="${a.articleCommentCount==0}">
发表评论
</c:when>
<c:otherwise>
${a.articleCommentCount}
</c:otherwise>
</c:choose>
</a>
</span>
</span>
<div class="clear"></div>
</div><!-- .entry-content -->
<span class="entry-more">
<a href="/article/${a.articleId}"
rel="bookmark">阅读全文
</a>
</span>
</article>
</c:forEach>
<%--文章列表-end--%>
</c:when>
</c:choose>
</main>
<%@ include file="../Public/part/paging.jsp" %>
</section>
</section>
</rapid:override>
<%@ include file="../Public/framework.jsp" %>
7.2 Controller
根据传入过来的关键字进行搜索。
//搜索
@RequestMapping("/search")
public String search(@RequestParam("keywords")String keywords,
@RequestParam(required = false,defaultValue = "1")Integer pageIndex,
@RequestParam(required = false,defaultValue = "10")Integer pageSize,
Model model){
//文章列表
HashMap<String,Object> criteria=new HashMap<>(2);
criteria.put("status",ArticleStatus.PUBLISH.getValue());
criteria.put("keywords",keywords);
//根据文章状态和输入的关键字进行搜索
PageInfo<Article> articlePageInfo=articleService.pageArticle(pageIndex,pageSize,criteria);
model.addAttribute("pageInfo",articlePageInfo);
//侧边栏显示
//标签列表显示
List<Tag> allTagList=tagService.listTag();
model.addAttribute("allTagList",allTagList);
//获得随机文章
List<Article> randomArticleList=articleService.listRandomArticle(8);
model.addAttribute("randomArticleList",randomArticleList);
//获得热评文章
List<Article> mostCommentArticleList=articleService.listArticleByCommentCount(8);
model.addAttribute("mostCommentArticleList",mostCommentArticleList);
//最新评论
List<Comment> recentCommentList=commentService.listRecentComment(10);
model.addAttribute("recentCommentList",recentCommentList);
model.addAttribute("pageUrlPrefix","/search?pageIndex");
return "Home/Page/search";
}
7.3 页面显示
查找到相关的文章:
没有与关键字相关的文章:
八.公告显示
博客主页会显示滚动的公告,点击这个公告就会到公告详细页面。
8.1 公告详情JSP页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="rapid" uri="http://www.rapid-framework.org.cn/rapid" %>
<rapid:override name="header-style">
<style>
.entry-title {
background: #f8f8f8;
}
</style>
</rapid:override>
<rapid:override name="breadcrumb">
<%--面包屑导航 start--%>
<nav class="breadcrumb">
<a class="crumbs" href="/">
<i class="fa fa-home"></i>首页
</a>
<i class="fa fa-angle-right"></i>
博客公告
<i class="fa fa-angle-right"></i>
正文
</nav>
<%--面包屑导航 end--%>
</rapid:override>
<rapid:override name="left">
<%--博客主体-左侧文章正文 start--%>
<div id="primary" class="content-area">
<main id="main" class="site-main" role="main">
<article class="post" style="min-height: 500px;">
<header class="entry-header">
<h1 class="entry-title">
${notice.noticeTitle}
</h1>
</header><!-- .entry-header -->
<div class="entry-content">
<div class="single-content">
${notice.noticeContent}
</div>
<br><br>
<footer class="single-footer">
<ul class="single-meta">
<li class="r-hide">
<a href="javascript:pr()" title="侧边栏">
<i class="fa fa-caret-left"></i>
<i class="fa fa-caret-right"></i>
</a>
</li>
</ul>
<ul id="fontsize">
<li>A+</li>
</ul>
<div class="single-cat-tag">
<div class="single-cat">日期:<fmt:formatDate value="${notice.noticeCreateTime}" pattern="yyyy年MM月dd日"/>
</div>
</div>
</footer><!-- .entry-footer -->
<div class="clear"></div>
</div><!-- .entry-content -->
</article><!-- #post -->
</main>
<!-- .site-main -->
</div>
<%--博客主体-左侧文章正文end--%>
</rapid:override>
<%--侧边栏 start--%>
<rapid:override name="right">
<%@include file="../Public/part/sidebar-3.jsp" %>
</rapid:override>
<%--侧边栏 end--%>
<%@ include file="../Public/framework.jsp" %>
8.2 HomeNoticeController
package com.test.ssm.blog.controller.home;
import com.test.ssm.blog.entity.Article;
import com.test.ssm.blog.entity.Notice;
import com.test.ssm.blog.service.ArticleService;
import com.test.ssm.blog.service.NoticeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
public class HomeNoticeController {
@Autowired
private NoticeService noticeService;
@Autowired
private ArticleService articleService;
//公告详情页
@RequestMapping(value = "/notice/{noticeId}")
public String NoticeDetailView(@PathVariable("noticeId")Integer noticeId, Model model){
//公告内容和信息显示
Notice notice=noticeService.getNoticeById(noticeId);
model.addAttribute("notice",notice);
//侧边栏
//热评文章
List<Article> mostCommentArticleList=articleService.listArticleByCommentCount(8);
model.addAttribute("mostCommentArticleList",mostCommentArticleList);
return "Home/Page/noticeDetail";
}
}
8.3 页面显示
九.申请友链
我们可以看到首页文章列表下有一个博客链接,这个就是友情链接。
我们可以在博客前台进行友情链接的申请。
9.1 申请JSP页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="rapid" uri="http://www.rapid-framework.org.cn/rapid" %>
<rapid:override name="header-style">
<style>
.entry-title {
background: #f8f8f8;
}
</style>
<link rel="stylesheet" href="/plugin/layui/css/layui.css">
</rapid:override>
<rapid:override name="breadcrumb">
<%--面包屑导航 start--%>
<nav class="breadcrumb">
<a class="crumbs" href="/">
<i class="fa fa-home"></i>首页
</a>
<i class="fa fa-angle-right"></i>
申请友链
<i class="fa fa-angle-right"></i>
正文
</nav>
<%--面包屑导航 end--%>
</rapid:override>
<rapid:override name="left">
<%--博客主体-左侧文章正文 start--%>
<div id="primary" class="content-area">
<main id="main" class="site-main" role="main">
<article class="post" style="min-height: 500px;">
<header class="entry-header">
<h1 class="entry-title">
申请友链
</h1>
</header><!-- .entry-header -->
<div class="entry-content">
<div class="single-content">
<form class="layui-form layui-form-pane" id="applyLinkForm" method="post">
<div class="layui-form-item">
<label class="layui-form-label">网站名称</label>
<div class="layui-input-block">
<input type="text" name="linkName" placeholder="如:${options.optionSiteTitle}" class="layui-input" required>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">网站地址</label>
<div class="layui-input-block">
<input type="url" name="linkUrl" placeholder="如:" class="layui-input" required>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">网站描述</label>
<div class="layui-input-block">
<input type="text" name="linkDescription" placeholder="如:${options.optionSiteDescrption}" class="layui-input" required>
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">备注</label>
<div class="layui-input-block">
<textarea placeholder="申请原因和联系方式" class="layui-textarea" name="linkOwnerContact" maxlength="100"></textarea>
</div>
</div>
<div class="layui-form-item">
<button class="layui-btn" lay-submit="">提交申请</button>
</div>
</form>
</div>
<br><br>
<footer class="single-footer">
<ul class="single-meta">
<li class="r-hide">
<a href="javascript:pr()" title="侧边栏">
<i class="fa fa-caret-left"></i>
<i class="fa fa-caret-right"></i>
</a>
</li>
</ul>
<ul id="fontsize">
<li>A+</li>
</ul>
</footer><!-- .entry-footer -->
<div class="clear"></div>
</div><!-- .entry-content -->
</article><!-- #post -->
</main>
<!-- .site-main -->
</div>
<%--博客主体-左侧文章正文end--%>
</rapid:override>
<%--侧边栏 start--%>
<rapid:override name="right">
<%@include file="../Public/part/sidebar-3.jsp" %>
</rapid:override>
<%--侧边栏 end--%>
<rapid:override name="footer-script">
<script>
</script>
</rapid:override>
<%@ include file="../Public/framework.jsp" %>
9.2 HomeLinkController
package com.test.ssm.blog.controller.home;
import com.test.ssm.blog.entity.Article;
import com.test.ssm.blog.entity.Link;
import com.test.ssm.blog.enums.LinkStatus;
import com.test.ssm.blog.service.ArticleService;
import com.test.ssm.blog.service.LinkService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Date;
import java.util.List;
@Controller
public class HomeLinkController {
@Autowired
private LinkService linkService;
@Autowired
private ArticleService articleService;
@RequestMapping("/applyLink")
public String applyLinkView(Model model)
{
//侧边栏显示
//显示热评文章
List<Article> mostCommentArticleList=articleService.listArticleByCommentCount(8);
model.addAttribute("mostCommentArticleList",mostCommentArticleList);
return "Home/Page/applyLink";
}
@RequestMapping(value = "/applyLinkSubmit",method = RequestMethod.POST)
@ResponseBody
public void applyLinkSubmit(Link link){
link.setLinkStatus(LinkStatus.HIDDEN.getValue());
link.setLinkCreateTime(new Date());
link.setLinkUpdateTime(new Date());
linkService.insertLink(link);
}
}
9.3 页面显示
十.页面操作
10.1 文章归档
点击,就是显示所有文章列表。
//文章归档页面显示
@RequestMapping(value = "/articleFile")
public String articleFile(Model model){
List<Article> articleList=articleService.listAllNotWithContent();
model.addAttribute("articleList",articleList);
//热评文章
List<Article> mostCommentArticleList=articleService.listArticleByCommentCount(8);
model.addAttribute("mostCommentArticleList",mostCommentArticleList);
return "Home/Page/articleFile";
}
10.2 关于本站
这个显示是在Heade.jsp,显示的是菜单信息
<div class="menu-topmenu-container">
<ul id="menu-topmenu" class="top-menu">
<c:forEach items="${menuList}" var="m">
<li class="menu-item">
<c:if test="${m.menuLevel==1}">
<a href="${m.menuUrl}" >
<i class="${m.menuIcon}"></i>
<span class="font-text">${m.menuName} </span>
</a>
</c:if>
</li>
</c:forEach>
</ul>
</div>
我们可以看到的是这个菜单的链接请求是发送菜单的Url。申请友链和文章归档都是早早添加到Controller中的, 不是自定义的。关于本站相当于自定义页面,所以为了方便其他自定义页面的请求,所以获取的是URL,然后根据这个进行页面查询。
点击关于本站,显示关于本站的基本信息。
页面详情页的Controller:
//页面详情页
@RequestMapping(value = "/{key}")
public String pageDetail(@PathVariable("key")String key, Model model){
Page page=pageService.getPageByKey(1,key);
if(page==null){
return "redirect:/404";
}
model.addAttribute("page",page);
//侧边栏
//热评文章
List<Article> mostCommentArticleList=articleService.listArticleByCommentCount(8);
model.addAttribute("mostCommentArticleList",mostCommentArticleList);
return "Home/Page/page";
}
点击了关于本站,页面显示:
10.3 站点地图
站点地图是一个放网站所有链接的页面。
Controller:
//站点地图显示
@RequestMapping(value = "/map")
public String siteMap(Model model)
{
//文章
List<Article> articleList=articleService.listAllNotWithContent();
model.addAttribute("articleList",articleList);
//分类
List<Category> categoryList=categoryService.listCategory();
model.addAttribute("categoryList",categoryList);
//标签
List<Tag> tagList=tagService.listTag();
model.addAttribute("tagList",tagList);
//侧边栏
//热评
List<Article> mostCommentArticleList=articleService.listArticleByCommentCount(8);
model.addAttribute("mostCommentArticleList",mostCommentArticleList);
return "Home/Page/siteMap";
}
页面显示为: