打开原教程视频
注:本人是编程小白,这个是我第一个尝试的项目,编写该系列博客是为了记录第一次做项目的经历,其中肯定会有不少不成熟的操作甚至错误之处,如果可以,希望大神指出,谢谢大家。
异步请求方式登录的实现
先解释一下同步和异步的概念
同步请求:客户端发出数据后,等服务器发回响应以后才发下一个数据包的通讯方式。即客户端发送请求后不能进行任何操作,直到收到服务器的响应。并且收到响应数据后,页面会进行整体刷新,出现闪烁的效果
异步请求:客户端发出数据后,不需要等待服务器响应也可以进行其它操作,如继续发送数据。同时进行异步请求的客户端接受到响应数据只会刷新局部页面,不会产生闪烁的情况。
异步请求前端代码的编写:
function dologin() {
//异步请求
var floginacct=$("#floginacct");
var fuserpswd=$("#fuserpswd");
var ftype=$("#ftype");
if ($.trim(floginacct.val())==""){//判断账号文本框是否为空或无意义的空格串
alert("账号不能为空!");
floginacct.val("");//清空账号文本框的内容
floginacct.focus();//光标回到账号文本框上
return false;
}
if ($.trim(fuserpswd.val())==""){//判断密码文本框是否为空或无意义的空格串
alert("密码不能为空!");
fuserpswd.val("");//清空账号文本框的内容
fuserpswd.focus();//光标回到账号文本框上
return false;
}
$.ajax({
type : "post",
url : "dispatcherController/doLogin.do",//指定url路径
data :{
//向后台发送数据
"loginacct" : floginacct.val(),
"userpswd" : fuserpswd.val(),
"type" : ftype.val()
},
beforeSend : function () {//登录前的操作
return true;
},
success : function (result) {//登录成功的操作
if(result.success){
alert("登录成功!");
//跳转到前台/后台页面
}else {//登录失败的操作
alert("登录失败!");
}
},
error : function (result) {//出现异常的操作
alert(result.message);
}
});
观察上面的代码,我们可以获知后台需要返回一个result的实体类对象,该实体类应该要有success和message属性,所以在common的module中的util包下编写一个AjaxResult的实体类。
package com.bin.crowdfunding.util;
public class AjaxResult {
private boolean success;
private String message;
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
最后的步骤就是重新编写DispatcherController里面的doLogin方法了,
代码如下:
/**
* @ResponseBody 结合Jackson组件,将返回结果转换为字符串.将JSON串以流的形式返回给客户端.
* 即{"success":false,"message":"登录失败!"}或
* {"success":true}
* @param user
* @param session
* @return
*/
@RequestMapping(value = "/doLogin")
public @ResponseBody Object doLogin(User user, HttpSession session) {
AjaxResult result=new AjaxResult();
try {
String digest = MD5Util.digest(user.getUserpswd());
user.setUserpswd(digest);
User userLogin = userService.queryUserLogin(user);
session.setAttribute(Const.LOGIN_USER, userLogin);//将用户信息传递到前端显示
result.setSuccess(true);
} catch (Exception e) {
result.setMessage("登录出现异常,请联系管理员");
e.printStackTrace();
result.setSuccess(false);
}
return result;
}
那么接下来我们测试一下;
可以看到各个功能正常执行,而且页面也只是进行局部刷新(异步请求),而不是整体刷新(同步请求)。
使用MD5对登录密码进行加密
MD5加密算法有以下特点:
1、压缩性:任意长度的数据,算出的MD5值的长度都是固定的。(32位长度的字符串)
2、容易计算:从原数据计算出MD5值很容易。(不可逆算法)
3、抗修改性:对源数据进行任何的修改,那怕只修改一个字节,所得MD5值都有很大的区别。
4、强抗碰撞:已知源数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
我们先准备用来计算MD5值的工具类,在common的module下的util包下建立MD5Util的实体类,将下面的代码粘贴过去。
package com.bin.crowdfunding.util;
import java.security.MessageDigest;
/**
MD5算法 哈希算法
MD5算法具有以下特点:
1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
2、容易计算:从原数据计算出MD5值很容易。
3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
*/
public class MD5Util {
public static String digest16(String inStr) {
return digest(inStr, 16);
}
public static String digest(String inStr) {
return digest(inStr, 32);
}
private static String digest(String inStr, int rang) {
MessageDigest md5 = null;
if ( StringUtil.isEmpty(inStr) ) {
return "";
}
try {
md5 = MessageDigest.getInstance("MD5"); //取得算法
} catch (Exception e) {
e.printStackTrace();
return "";
}
char[] charArray = inStr.toCharArray();
byte[] byteArray = new byte[charArray.length];
for (int i = 0; i < charArray.length; i++) {
byteArray[i] = (byte) charArray[i];
}
byte[] md5Bytes = md5.digest(byteArray); //加密
StringBuilder hexValue = new StringBuilder();
for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16)
hexValue.append("0");
hexValue.append(Integer.toHexString(val));
}
if ( rang == 32 ) {
return hexValue.toString();
} else {
return hexValue.toString().substring(8, 24);//转换为32位字符串
}
}
public static void main(String args[]) {
String s = new String("123");
System.out.println(digest(s));
}
}
代码中还需要一个StringUtil实体类来判断空字符串,我们继续在util包下创建StringUtil类
public class StringUtil {
public static boolean isEmpty(String s) {
return s == null || "".equals(s); // s == null | s.equals(""); //位与,逻辑与区别,非空字符串放置在前面,避免空指针
}
public static boolean isNotEmpty(String s) {
return !isEmpty(s);
}
}
这里我们先使用工具类下的main方法计算123的MD5值,并将其替换到数据库的测试数据中。
然后在查询数据之前我们将接受到的密码进行MD5加密计算,同时输出加密后的密文和查询出来的密码是否一致。
String digest = MD5Util.digest(user.getUserpswd());
user.setUserpswd(digest);
System.out.println(user.getLoginacct());
System.out.println(user.getUserpswd());
System.out.println(userLogin.getLoginacct());
System.out.println(userLogin.getUserpswd());
重新启动服务器进行测试。
可以看到两个数据一致,功能添加成功。
添加登录后的后台界面
这时我们需要在webapp/jsp下新建一个main.jsp,并在资料中找到main.html,将其内容复制到main.jsp中。
<%--
Created by IntelliJ IDEA.
User: 黄彬
Date: 2020/5/27
Time: 22:46
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
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 lang="zh-CN">
<head>
<base href="<%=basePath%>"/>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="css/font-awesome.min.css">
<link rel="stylesheet" href="css/main.css">
<style>
.tree li {
list-style-type: none;
cursor:pointer;
}
.tree-closed {
height : 40px;
}
.tree-expanded {
height : auto;
}
</style>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<div><a class="navbar-brand" style="font-size:32px;" href="#">众筹平台 - 控制面板</a></div>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li style="padding-top:8px;">
<div class="btn-group">
<button type="button" class="btn btn-default btn-success dropdown-toggle" data-toggle="dropdown">
<i class="glyphicon glyphicon-user"></i> ${sessionScope.user.username} <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#"><i class="glyphicon glyphicon-cog"></i> 个人设置</a></li>
<li><a href="#"><i class="glyphicon glyphicon-comment"></i> 消息</a></li>
<li class="divider"></li>
<li><a href="dispatcherController/logout.do"><i class="glyphicon glyphicon-off"></i> 退出系统</a></li>
</ul>
</div>
</li>
<li style="margin-left:10px;padding-top:8px;">
<button type="button" class="btn btn-default btn-danger">
<span class="glyphicon glyphicon-question-sign"></span> 帮助
</button>
</li>
</ul>
<form class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="查询">
</form>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<div class="tree">
<ul style="padding-left:0px;" class="list-group">
<li class="list-group-item tree-closed" >
<a href="main.html"><i class="glyphicon glyphicon-dashboard"></i> 控制面板</a>
</li>
<li class="list-group-item tree-closed">
<span><i class="glyphicon glyphicon glyphicon-tasks"></i> 权限管理 <span class="badge" style="float:right">3</span></span>
<ul style="margin-top:10px;display:none;">
<li style="height:30px;">
<a href="user.html"><i class="glyphicon glyphicon-user"></i> 用户维护</a>
</li>
<li style="height:30px;">
<a href="role.html"><i class="glyphicon glyphicon-king"></i> 角色维护</a>
</li>
<li style="height:30px;">
<a href="permission.html"><i class="glyphicon glyphicon-lock"></i> 许可维护</a>
</li>
</ul>
</li>
<li class="list-group-item tree-closed">
<span><i class="glyphicon glyphicon-ok"></i> 业务审核 <span class="badge" style="float:right">3</span></span>
<ul style="margin-top:10px;display:none;">
<li style="height:30px;">
<a href="auth_cert.html"><i class="glyphicon glyphicon-check"></i> 实名认证审核</a>
</li>
<li style="height:30px;">
<a href="auth_adv.html"><i class="glyphicon glyphicon-check"></i> 广告审核</a>
</li>
<li style="height:30px;">
<a href="auth_project.html"><i class="glyphicon glyphicon-check"></i> 项目审核</a>
</li>
</ul>
</li>
<li class="list-group-item tree-closed">
<span><i class="glyphicon glyphicon-th-large"></i> 业务管理 <span class="badge" style="float:right">7</span></span>
<ul style="margin-top:10px;display:none;">
<li style="height:30px;">
<a href="cert.html"><i class="glyphicon glyphicon-picture"></i> 资质维护</a>
</li>
<li style="height:30px;">
<a href="type.html"><i class="glyphicon glyphicon-equalizer"></i> 分类管理</a>
</li>
<li style="height:30px;">
<a href="process.html"><i class="glyphicon glyphicon-random"></i> 流程管理</a>
</li>
<li style="height:30px;">
<a href="advertisement.html"><i class="glyphicon glyphicon-hdd"></i> 广告管理</a>
</li>
<li style="height:30px;">
<a href="message.html"><i class="glyphicon glyphicon-comment"></i> 消息模板</a>
</li>
<li style="height:30px;">
<a href="project_type.html"><i class="glyphicon glyphicon-list"></i> 项目分类</a>
</li>
<li style="height:30px;">
<a href="tag.html"><i class="glyphicon glyphicon-tags"></i> 项目标签</a>
</li>
</ul>
</li>
<li class="list-group-item tree-closed" >
<a href="param.html"><i class="glyphicon glyphicon-list-alt"></i> 参数管理</a>
</li>
</ul>
</div>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1 class="page-header">控制面板</h1>
<div class="row placeholders">
<div class="col-xs-6 col-sm-3 placeholder">
<img data-src="holder.js/200x200/auto/sky" class="img-responsive" alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img data-src="holder.js/200x200/auto/vine" class="img-responsive" alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img data-src="holder.js/200x200/auto/sky" class="img-responsive" alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img data-src="holder.js/200x200/auto/vine" class="img-responsive" alt="Generic placeholder thumbnail">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
</div>
</div>
</div>
</div>
<script src="jquery/jquery-2.1.1.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
<script src="script/docs.min.js"></script>
<script type="text/javascript">
$(function () {
$(".list-group-item").click(function(){
if ( $(this).find("ul") ) {
$(this).toggleClass("tree-closed");
if ( $(this).hasClass("tree-closed") ) {
$("ul", this).hide("fast");
} else {
$("ul", this).show("fast");
}
}
});
});
</script>
</body>
</html>
在DispatcherController编写跳转方法
@RequestMapping(value = "/main")
public String main(){
return "main";
}
在login.jsp中找到登录成操作的代码块,添加跳转路径。
success : function (result) {//登录成功的操作
if(result.success){
alert("登录成功!");
//跳转到前台/后台页面
window.location.href="dispatcherController/main.htm";
重启服务器进行测试。
跳转成功
注销功能的实现
我们在main.jsp中找到退出登录的链接,修改其跳转路径。
<li><a href="dispatcherController/logout.do"><i class="glyphicon glyphicon-off"></i> 退出系统</a></li>
DispatcherController类中注销操作方法logout:
@RequestMapping(value = "/logout")
public String logout(HttpSession session){
session.invalidate();//销毁session对象
return "redirect:/dispatcherController/index.htm";
}
重新测试,点击退出系统。
页面成功跳转到未登录状态的主界面。
今天的任务完成。
谢谢阅读。