SSM框架实战-搭建自己的个人博客3-登录实现及前端界面设计

目录


后台登录功能

前端页面

 后端开发

前端界面设计

详情首页

js脚本

SSM整体设计

Dao层

 Service层

Mapper.xml

Controller

子博文界面

部署至服务器


后台登录功能

登录页面:用户名和密码

通过用户名密码来判断用户登录成功还是失败:

登录成功:跳转到新增博客页面

登录失败:错误信息提示,在登录页面

前端页面

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>

部署至服务器

 

 

 

 

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值