在《【ASP】连接Access数据库的登陆系统》(点击打开链接)中介绍了数据库增删改查的应用,完成了一个登录系统,只是代码非常凌乱,非常不容易维护。下面用一种MVC分层结构的思想,去优化ASP登录系统的写作,就算让你用这种已经日落山河的脚本语言去写作也要写好一点。
首先如下图,基于Access数据库Database.mdb中的一张user_info表,如下图:
完成如下图一个包括登录、注册、修改密码的用户账号系统:
这个系统的目录结构如下图,页面比较多,不过各司其职,分工明确:
一、M层
1、数据库操作类db.asp在《【ASP】利用数据库操作类优化数据库表的增删改查》(点击打开链接)中已经介绍过了,不过这次对其部分代码进行修改。在这个用户系统写作过程,发现利用构造函数与析构函数来操作Access数据库很不稳定,容易出现关闭、打开连接的互斥出错。因此直接分成两个方法,在每次getbySQL与setbySQL都自行开自行关,避免数据库连接的处理问题。
<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<%
'禁止缓存'
Response.CacheControl="no-cache"
Response.Expires=-1
Response.Charset="UTF-8" '配合第一行设定网页编码'
'数据库操作类'
Class DB
Private CONN '数据库连接'
Private RS '数据库查询结果集'
Private Sub Open_db_connect() '类的构造过程,进行数据库连接、初始化数据库查询结果集的操作'
Set CONN=server.createobject("ADODB.connection")
if CONN.state<>1 then '判断现在数据库是否正在连接,才打开一次数据库,避免过多的数据库连接'
CONN.open "DBQ="&server.MapPath("/my_asp/Database.mdb")&";password=root;DRIVER={Microsoft Access Driver (*.mdb)}"
end if
Set RS=server.CreateObject("adodb.recordset")
End Sub
Public Function getbySQL(sql) '根据sql语句,对数据库有返回结果查询'
Open_db_connect()
RS.open sql,CONN,1,3
if not (RS.bof or RS.eof) then '如果查询结果非空,就将所有查询结果压到数组里面'
MyArray=RS.GetRows
getbySQL=MyArray '返回这个记载查询结果的数组给前台'
end if
Close_db_connect()
End Function
Public Sub setbySQL(sql) '根据sql语句,对数据库进行无返回结果的操作'
Open_db_connect()
CONN.execute sql
Close_db_connect()
End Sub
Private Sub Close_db_connect() '类的析构函数,主要是关闭数据库连接'
if CONN.state=1 then '判断现在数据库是否打开,是,才关闭'
CONN.close
set Con=nothing
end if
End Sub
End Class
%>
2、接着是user.asp,用户操作的集合,一系列建立在表user_info之上的方法,因为这些过程(方法)会在登录处理、注册处理、修改密码处理中多次用到,所以就抽象出来了。这样可以避免在C层直接操作数据库了。
<!-- #include file="db.asp" -->
<%
Set db_control=New DB '初始化用户操作类'
Function has_this_user(username) '是否存在该用户的判断'
MyArray=db_control.getbySQL("select * from user_info where username='"&username&"'")
has_this_user=isarray(MyArray)
End Function
Function get_password(username) '根据用户名取得密码'
MyArray=db_control.getbySQL("select password from user_info where username='"&username&"'")
get_password=MyArray(0,0)
End Function
Sub insert_user(username,password) '插入用户'
db_control.setbySQL("insert into user_info(username,password) values('"&username&"','"&password&"')")
End Sub
Sub update_user(username,password) '修改用户密码'
db_control.setbySQL("update user_info set password='"&password&"' where username='"&username&"'")
End Sub
%>
二、V层
先写V层,一是V层简单,二是C层是连接M层与V层的桥梁,配合两者才好解释。
1、index.html,没什么好说的,就是3个表单,注意表单处理的两个问题《【HTML】表单form中一单回车就提交的text、一点击就提交的button》(点击打开链接),《【JavaScript】在前台验证表单,必须使用οnsubmit="return xx()"的形式》(点击打开链接),在你写作的过程中,如果你发现的Onsubmit函数不管用,很可能你的OnSubmit函数中途出现语法错误。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>用户系统</title>
</head>
<body>
<h1>登录</h1>
<form action="login.asp" method="post">
用户名:<input type="text" name="username"/><br />
密码:<input type="password" name="password"/><br />
<input type="submit" value="提交"/><br />
</form>
<h1>注册</h1>
<form action="register.asp" method="post" οnsubmit="return register_check()">
用户名:<input type="text" id="register_username" name="username"/><br />
密码:<input type="password" id="register_password1" name="password"/><br />
请再次输入密码:<input type="password" id="register_password2"/><br />
<input type="submit" value="提交"/><br />
</form>
<h1>修改密码</h1>
<form action="update.asp" method="post" οnsubmit="return update_check()">
用户名:<input type="text" id="update_username" name="username"/><br />
旧密码:<input type="password" id="update_password" name="old_password"/><br />
新密码:<input type="password" id="update_password1" name="new_password"/><br />
请再次输入密码:<input type="password" id="update_password2"/><br />
<input type="submit" value="提交"/><br />
</form>
</body>
<script src="check_form.js"></script>
</html>
2、注意到,所有在前台的表单验证的js函数都藏在check_form.js里面,而且这个check_form.js引用一定在放在body节点的结束作为脚本,意为当body中所有节点被加载完成才进行验证,不然,你把这个节点放在头部,里面的验证函数很可能找不到节点的,这个判断很简单,就是取节点,判断是否为空,两次输入的密码是否一致。
function check_equal(password1,password2){//判断密码是否相等
if(password1==password2){
return true;
}
else{
return false;
}
}
function register_check(){//注册表单的判断
var username=document.getElementById("register_username").value;
var password1=document.getElementById("register_password1").value;
var password2=document.getElementById("register_password2").value;
if(username.length>0&&password1.length>0&&password2.length>0){
if(check_equal(password1,password2)){
return true;
}
else{
alert("两次输入的密码不一致!");
}
}
else{
alert("用户名、密码任意一项为空!");
}
return false;
}
function update_check(){//修改密码表单的判断
var username=document.getElementById("update_username").value;
var password=document.getElementById("update_password").value;
var password1=document.getElementById("update_password1").value;
var password2=document.getElementById("update_password2").value;
if(username.length>0&&password.length>0&&password1.length>0&&password2.length>0){
if(check_equal(password1,password2)){
return true;
}
else{
alert("两次输入的密码不一致!");
}
}
else{
alert("用户名、密码任意一项为空!");
}
return false;
}
三、C层
最后C层,其实C层的处理有了M层中user.asp的基础,获取V层中index.html表单传递过来的值,根据相关的判断,进行一番处理,打印一段弹出并跳转的JS和用户交互就行了。打印的JS脚本用asp中的&不停连接字符串地。根据判断进行构造。
这里还要注意一点,亲测,要对response.write打印出的javascript,先加上一个charset="utf-8",进行强行的编码控制,否则会在不明情况产生乱码,毕竟asp,也就是vbscript这门语言确实古老。
1、首先是登录处理login.asp的代码:
<!-- #include file="user.asp" -->
<%
username=Request.Form("username")
password=Request.Form("password")
info="<script charset='utf-8'>"
if has_this_user(username) then
if password=get_password(username) then
info=info&"alert('登录成功!');"
else
info=info&"alert('密码错误!');"
end if
else
info=info&"alert('查无此人!');"
end if
info=info&"window.location.href='index.html'"
info=info&"</script>"
response.Write info
%>
2、之后是注册处理的register.asp的代码:
<!-- #include file="user.asp" -->
<%
username=Request.Form("username")
password=Request.Form("password")
info="<script charset='utf-8'>"
if has_this_user(username) then
info=info&"alert('已有该用户,请换个用户名注册!');"
else
call insert_user(username,password)
info=info&"alert('注册成功!');"
end if
info=info&"window.location.href='index.html'"
info=info&"</script>"
response.Write info
%>
3、最后是修改密码处理update.asp的代码:
<!-- #include file="user.asp" -->
<%
username=Request.Form("username")
old_password=Request.Form("old_password")
new_password=Request.Form("new_password")
info="<script charset='utf-8'>"
if has_this_user(username) then
if old_password=get_password(username) then
call update_user(username,new_password)
info=info&"alert('修改成功!');"
else
info=info&"alert('密码错误!');"
end if
else
info=info&"alert('查无此人!');"
end if
info=info&"window.location.href='index.html'"
info=info&"</script>"
response.Write info
%>
都是先引用user.asp文件,然后不停地调用里面的过程与函数,来完成一些列的判断,这样就不用在这个C层写这么多东西。
通过这样的ASP分层,可以让代码变得更加地清晰,同时,容易维护与修改。
不会让脚本语言等夹杂在一切,写完一次就毫无可读性,修改起来要找半天。