目录
后台登录功能
登录页面:用户名和密码
通过用户名密码来判断用户登录成功还是失败:
登录成功:跳转到新增博客页面
登录失败:错误信息提示,在登录页面
前端页面
login.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="renderer" content="webkit">
<title>后台 - 登录</title>
<link href="<%=basePath%>css/bootstrap.min.css" rel="stylesheet">
<link href="<%=basePath%>font-awesome/css/font-awesome.css" rel="stylesheet">
<link href="<%=basePath%>css/animate.css" rel="stylesheet">
<link href="<%=basePath%>css/style.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="<%=basePath%>js/flavr/flavr/css/animate.css" />
<link rel="stylesheet" type="text/css" href="<%=basePath%>js/flavr/flavr/css/flavr.css" />
<link href="<%=basePath%>css/plugins/toastr/toastr.min.css" rel="stylesheet">
<script type="text/javascript">
// 登录
function login(){
var loginId = $("#loginId").val();
var password = $("#password").val();
if(isEmpty(loginId)){
toastr.error("账户不能为空");
return false;
}
if(isEmpty(password)){
toastr.error("密码不能为空");
return false;
}
$.ajax({
url : "checklogin",
data: $("#form").serialize(),
method : "post",
dataType : "json",
success : function(data) {
if (data.resultCode == 'success') {
window.location.href = "/article/add";
}else{
toastr.error(data.errorInfo);
return false;
}
}
})
}
</script>
<style>
.loginscreen.middle-box{padding-top:260px;}
</style>
</head>
<body class="gray-bg">
<div class="middle-box text-center loginscreen animated fadeInDown">
<div>
<div>
<h1 class="logo-img"></h1>
</div>
<%--通过form表单将登录用户名/密码提交后台--%>
<form id="form" class="m-t" role="form" >
<div class="form-group"><h2 >博客系统登录后台</h2></div>
<div class="form-group">
<input type="text" name="name" id="loginId" class="form-control" placeholder="用户名">
</div>
<div class="form-group">
<input type="password" name="passwd" id="password" class="form-control" placeholder="密码">
</div>
<button type="button" class="btn btn-primary block full-width m-b" onclick="login()">登 录</button>
</form>
</div>
</div>
<script src="<%=basePath%>js/jquery-2.1.1.min.js" ></script>
<script src="<%=basePath%>js/bootstrap.min.js" ></script>
<script type="text/javascript" src="<%=basePath%>js/flavr/flavr/js/flavr.min.js"></script>
<script type="text/javascript" src="<%=basePath%>js/flavr/base.js"></script>
<script src="<%=basePath%>js/validation.js"></script>
<script src="<%=basePath%>js/plugins/toastr/toastr.min.js"></script>
</body>
</html>
前端页面通过form表单收集用户名以及密码,点击登录按钮后,调转至js中的login()方法进行处理。
在填写信息时,规定用户名和密码不能为空,当返回的状态码为success时,说明输入的用户和密码匹配成功,此时跳转至新增界面,否则的话就弹窗显示用户名和密码输入错误,这里的弹窗使用的是JQuery的toastr弹窗插件。
function login(){
var loginId = $("#loginId").val();
var password = $("#password").val();
if(isEmpty(loginId)){
toastr.error("账户不能为空");
return false;
}
if(isEmpty(password)){
toastr.error("密码不能为空");
return false;
}
$.ajax({
url : "checklogin",
data: $("#form").serialize(),
method : "post",
dataType : "json",
success : function(data) {
if (data.resultCode == 'success') {
window.location.href = "../article/add";
}else{
toastr.error(data.errorInfo);
return false;
}
}
})
}
效果如下:
输入为空:
用户名或密码错误:
后端开发
在UserMapper中定义获取用户名以及密码的方法。
public interface UserMapper {
public User getUserById(Integer id);
public User getUserByNameAndPwd(@Param("name") String name, @Param("pwd") String pwd);
}
Service层进行实现登录检查操作。
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User getUserById(Integer id){
if(id < 0)
return new User();
return userMapper.getUserById(id);
}
public boolean checkLogin(String name, String pwd){
if(userMapper.getUserByNameAndPwd(name, pwd) != null){
return true;
}
return false;
}
}
在UserMapper.xml中通过SQL查找t_manager中的用户名以及密码.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tulun.dao.UserMapper">
<resultMap id="UserMap" type="com.tulun.model.User">
<result property="id" column="id"></result>
<result property="name" column="userName"></result>
<result property="passwd" column="password"></result>
</resultMap>
<select id="getUserById" parameterType="int" resultMap="UserMap">
select * from t_manager where id=#{id}
</select>
<select id="getUserByNameAndPwd" resultMap="UserMap">
select * from t_manager where userName=#{name} and password=#{pwd}
</select>
</mapper>
在Controller层中实现登录操作的url映射,以及登录检查操作,当从数据库能够查询到与输入匹配的用户名以及密码,就返回一个成功的Result对象,否则就返回一个失败对象。
package com.tulun.controller;
import com.tulun.config.Config;
import com.tulun.model.Result;
import com.tulun.model.User;
import com.tulun.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
/**
* Description :
* Created by Resumebb
* Date :2021/4/22
*/
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/login")
public String login(){
return "user/login";
}
@RequestMapping("/checklogin")
@ResponseBody
public Result checkLogin(User user, HttpSession session){
System.out.println("user = " + user);
boolean checkLogin = userService.checkLogin(user.getName(), user.getPasswd());
Result result = new Result("fail", "用户名或密码错误");
if (checkLogin) {
result = new Result("success","成功");
//登录成功记录登录的缓存信息
session.setAttribute(Config.LoginKey, user);
}
return result;
}
}
当前端的js接收到返回的Result对象后进行判断,如果Result的状态码为success就跳转至新增页面,说明登录成功,如果接收到的是fail,那么就还是在login页面。
<script type="text/javascript">
// 登录
function login(){
var loginId = $("#loginId").val();
var password = $("#password").val();
if(isEmpty(loginId)){
toastr.error("账户不能为空");
return false;
}
if(isEmpty(password)){
toastr.error("密码不能为空");
return false;
}
$.ajax({
url : "checklogin",
data: $("#form").serialize(),
method : "post",
dataType : "json",
success : function(data) {
if (data.resultCode == 'success') {
window.location.href = "../article/add";
}else{
toastr.error(data.errorInfo);
return false;
}
}
})
}
</script>
登录成功:
前端界面设计
前面设计了博客的新增功能,数据库存储功能,以及登录验证功能,接下来需要在前端界面将存储到数据库中的博文信息进行展示,浏览,分类查询等,如下。
详情首页
页面左边栏为栏目类别,可以通过点击对文章进行分类查询显示,页面仅显示所选类别的文章。
页面中间为文章预览,显示包过文章的类别,标题,作者,发布时间,标签,阅读量等多种信息,通过点击文章标题可以进入到博文详情页面。
文章右边显示了当前的热门标签,根据数量进行排序显示。
index.jsp如下;
<%--<%@ page language="java" import="java.util.*, java.net.URLEncoder, com.tulun.blog.model.*" pageEncoding="UTF-8"%>--%>
<%--<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>--%>
<%--<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> --%>
<%--<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>--%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fm" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<link rel="stylesheet" id="main-css" href="<%=basePath%>css/demo/style.css" type="text/css" media="all">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=11,IE=10,IE=9,IE=8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<meta name="baidu-site-verification" content="emEdenaBVA">
<meta http-equiv="Cache-Control" content="no-siteapp">
<title>博客系统</title>
</head>
<body id="contain" class="home blog ui-c3">
<section class="container">
<header class="header">
<div class="logo_right"><span class="glyphicon glyphicon-search degfy_search"></span></div>
<div class="logo_left"></div>
<h1 class="logo"><a href="">博客系统</a></h1>
<ul class="nav">
<li class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home menu-item-61">
<a href="">
<span class="glyphicon glyphicon-home"></span>首页
</a>
</li>
<%--类别--%>
<c:forEach items="${categoryList}" var="category">
<li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-61">
<a href="<%=basePath%>loadPage/${category.id}"></span>${category.categoryName}
</a></li>
</c:forEach>
</ul>
<div class="widget_head"></div>
</header>
<div class="content-wrap">
<div class="content" id="content">
<h3 class="title"><strong>最新发布</strong></h3>
<input type="hidden" id="categoryId" value="-1"/>
</div>
</div>
<aside class="sidebar">
<div class="widget widget_tags">
<h3 class="title"><strong>热门标签</strong></h3>
<ul class="widget_tags_inner">
<c:forEach items="${tagList}" var="tag">
<li><a title="" href="javascript:;" >${tag.tagName}</a></li>
</c:forEach>
</ul>
</div>
</aside>
</section>
<%--从本项目的指定路径获取js文件--%>
<script type="text/javascript" src="<%=basePath%>js/jquery-2.1.1.min.js"></script>
<%--自定义js--%>
<script type="text/javascript" src="<%=basePath%>js/article/article_list.js"></script>
</body>
</html>
js脚本
该js主要实现了通过ajax实现url拼接,然后加载不同的文章详情页。
$(function(){
loadNextPage(99);
$(window).scroll(function(){
checkload();
});
//建立加载判断函数
function checkload(){
totalheight = parseFloat($(window).height()) + parseFloat($(window).scrollTop());
if ($(document).height() <= totalheight) {
if($("#lastId").val() != 'undefined' && $("#lastId").val() != null && $("#lastId").val() != ''){
loadNextPage($("#lastId").val());
}
}
}
//创建ajax加载函数,并设置变量C,用于输入调用的页面频道,请根据实际情况判断使用,非必要。
function loadNextPage(lastId){
$.ajax({
url : '../loadPage1/'+$("#categoryId").val(),
type : "get",
success : function(data) {
if($.trim(data) != ''){
$("#lastId").remove();
$("#content").append(data);
$('img').lazyload();
}
}
});
}
});
function goTag(tagName){
window.location.href = "http://coriger.com/tag/"+encodeURI(encodeURI(tagName))
}
function getRootPath() {
//获取当前网址,如: http://localhost:8080/GameFngine/share/meun.jsp
var curWwwPath = window.document.location.href;
//获取主机地址之后的目录,如: GameFngine/meun.jsp
var pathName = window.document.location.pathname;
var pos = curWwwPath.indexOf(pathName);
//获取主机地址,如: http://localhost:8080
var localhostPaht = curWwwPath.substring(0, pos);
//获取带"/"的项目名,如:/GameFngine
var projectName = pathName.substring(0,
pathName.substr(1).indexOf('/') + 1);
return (localhostPaht + projectName + "/");
}
SSM整体设计
Dao层
新增两个接口,用于获取文章的标签以及类别信息。
public interface ArticleTagMapper {
public List<Tag> getTagByArticleId(Integer articleId);
}
public Category getCategoryById(Integer id);
Service层
@Service
public class CategoryService {
@Autowired
private CategoryMapper categoryMapper;
public List<Category> selectAllCategory(){
return categoryMapper.getAllCategory();
}
public Category getCategoryById(Integer id){
return categoryMapper.getCategoryById(id);
}
}
Mapper.xml
根据之前数据库的设计,t_article_tag表中存储了文章id以及标签id,通过联合查询获取到标签表中的信息。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tulun.dao.ArticleTagMapper">
<select id="getTagByArticleId" resultType="com.tulun.model.Tag">
select tt.* from t_article_tag ta, t_tag tt where ta.tagId =tt.id and ta.articleId = #{articleId}
</select>
</mapper>
Controller
控制层中一是实现详情主页面的url映射,而是实现点击不同的类别,加载相应的子博文详情页面。
package com.tulun.controller;
import com.tulun.model.Article;
import com.tulun.model.Category;
import com.tulun.model.Tag;
import com.tulun.service.ArticleService;
import com.tulun.service.CategoryService;
import com.tulun.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 java.util.List;
/**
* Description :
* Created by Resumebb
* Date :2021/5/2
*/
@Controller
public class HomeController {
@Autowired
private CategoryService categoryService;
@Autowired
private TagService tagService;
@Autowired
private ArticleService articleService;
@RequestMapping("/index")
public String index(Model model){
List<Category> categories = categoryService.selectAllCategory();
List<Tag> tags = tagService.selectAllTag();
model.addAttribute("categoryList", categories);
model.addAttribute("tagList", tags);
return "/home/index";
}
@RequestMapping("/loadPageAll")
public String loadAll(Model model){
List<Article> allArticle = articleService.getAllArticle();
model.addAttribute("articleList", allArticle);
return "/home/articlepager";
}
//按照类别进行加载
@RequestMapping("/loadPage/{id}")
public String loadPage(Model model, @PathVariable("id") Integer id) {
//通过类别id来加载类别信息
Category category = categoryService.getCategoryById(id);
//当前类别信息
model.addAttribute("ca", category);
List <Category> categories = categoryService.selectAllCategory();
List <Tag> tags = tagService.selectAllTag();
model.addAttribute("categoryList", categories);
model.addAttribute("tagList",tags);
return "/home/articlepager1";
}
//加载指定类别的内容
@RequestMapping("/loadPage1/{id}")
public String loadPage1(Model model, @PathVariable("id") Integer id) {
List <Article> articles = articleService.getAllArticleByCategoryId(id);
model.addAttribute("articleList", articles);
return "/home/articlepager";
}
}
子博文界面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fm" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><head>
<link rel="stylesheet" id="main-css" href="<%=basePath%>css/demo/style.css" type="text/css" media="all" />
<meta http-equiv="X-UA-Compatible" content="IE=11,IE=10,IE=9,IE=8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0" />
<meta name="baidu-site-verification" content="emEdenaBVA" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<title>${ca.categoryName} - 博客系统</title>
</head>
<body id="contain" class="home blog ui-c3">
<section class="container">
<header class="header">
<div class="logo_right"><span class="glyphicon glyphicon-search degfy_search"></span></div>
<div class="logo_left"></div>
<h1 class="logo"><a href="">博客系统</a></h1>
<ul class="nav">
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-61">
<a href="<%=basePath %>">
<span class="glyphicon glyphicon-home"></span>首页
</a>
</li>
<c:forEach items="${categoryList}" var="category">
<li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-61
<c:if test="${ca.id == category.id}">
current_page_item
</c:if>
">
<a href="<%=basePath%>loadPage/${category.id}">${category.categoryName}
</a></li>
</c:forEach>
</ul> <div class="widget_head">
</div>
</header>
<div class="content-wrap">
<div class="content" id="content">
<h3 class="title"><strong>${ca.categoryName}</strong></h3>
<input type="hidden" id="categoryId" value="${ca.id}"/>
</div>
</div>
<aside class="sidebar">
<div class="widget widget_tags">
<h3 class="title"><strong>热门标签</strong></h3>
<ul class="widget_tags_inner">
<c:forEach items="${tagList}" var="tag">
<li><a title="">${tag.tagName}</a></li>
</c:forEach>
</ul>
</div>
</div>
</aside>
</section>
<div id="back_hidden"></div>
<script type="text/javascript" src="<%=basePath%>js/jquery-2.1.1.min.js"></script>
<%--自定义的路径--%>
<script type="text/javascript" src="<%=basePath%>js/category/article_list.js"></script>
</body>
</html>
部署至服务器