Skip to content

mvc三层构架在asp中的应用

2010年2月13日

前段时间读了不少关于MVC的文章,试着在ASP中应用了一下,发现对于小程序,代码量会大幅度增加,但是逻辑清晰,数据封装很合理,以前需要仔细规划的代码复用竟然成了理所当然的事情。

所谓MVC,即Model(模型),View(视图),Control(控制)三层架构。各部分各司其职,Model即底层构架,包含与数据库连接的部分,View即UI展示部分,与用户直接打交道,Control即控制层,负责接收View的请求并做适当预处理后交由Model处理,然后接收Model返回值并做格式化处理返回View层。简单地说,Model直接与系统底层如数据库等打交道,而不管数据出去后如何用,View只负责请求和展示数据,而不管详细流程,Control分别与View和Model打交道,并负责数据的验证、格式化等工作。

写了一个获取用户资料的ASP中应用:

先写Model层,定义数据库地址,打开连接数据库,获取记录。

在写Model层之前定义了两个类:Cls_Config整站设置,包括数据库地址;Cls_DatabaseModel,负责打开关闭数据库连接。

Cls_ConfigModel.asp代码如下:

asp
<%
Class Cls_ConfigModel
	Private i_datapath,i_sitename,i_sitedomain,i_mastermail
	Private Sub Class_Initialize()
		i_datapath="data\testtdata.mdb"
		i_sitename="testsite"
		i_sitedomain="www.test.cn"
		i_mastermail="master@test.cn"
	End Sub
	Public property get DataPath
		DataPath=server.MapPath(i_datapath)
	End property
	Public property get SiteName
		SiteName=i_sitename
	End property
	Public property get SiteDomain
		SiteDomain=i_sitedomain
	End property
	Public property get MasterMail
		MasterMail=i_mastermail
	End property
End Class
%>
<%
Class Cls_ConfigModel
	Private i_datapath,i_sitename,i_sitedomain,i_mastermail
	Private Sub Class_Initialize()
		i_datapath="data\testtdata.mdb"
		i_sitename="testsite"
		i_sitedomain="www.test.cn"
		i_mastermail="master@test.cn"
	End Sub
	Public property get DataPath
		DataPath=server.MapPath(i_datapath)
	End property
	Public property get SiteName
		SiteName=i_sitename
	End property
	Public property get SiteDomain
		SiteDomain=i_sitedomain
	End property
	Public property get MasterMail
		MasterMail=i_mastermail
	End property
End Class
%>

Cls_DatabaseModel.asp代码如下:

asp
<!--#include file="cls_configmodel.asp" -->
<!--#include file="../public/cls_cache.asp" -->
<%
Class Cls_DatabaseModel
	Private i_config,i_cache,i_datapath
	Private i_conn
	Private Sub Class_Initialize()
		set i_cache = new Cls_Cache
		if i_cache.GetCache("Config","DataPath") = "" then
			set i_config = new Cls_ConfigModel
			i_datapath = i_config.DataPath
			Call i_cache.SetCache("Config","DataPath",i_datapath)
		else
			i_datapath = i_cache.GetCache("Config","DataPath")
		end if
		set i_cache = nothing
	End Sub
	Private Sub Class_Terminate()
		set i_config=nothing
	End Sub
	Public property get Conn
		set Conn=i_conn
	End property
	Public Function OpenConn()
		set i_conn=server.createobject("adodb.connection")
		i_conn.open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="& i_datapath &";User ID=admin;Password=;Jet OLEDB:Database Password="
	End Function
	Public Function CloseConn()
		set i_conn=nothing
	End Function
End Class
%>
<!--#include file="cls_configmodel.asp" -->
<!--#include file="../public/cls_cache.asp" -->
<%
Class Cls_DatabaseModel
	Private i_config,i_cache,i_datapath
	Private i_conn
	Private Sub Class_Initialize()
		set i_cache = new Cls_Cache
		if i_cache.GetCache("Config","DataPath") = "" then
			set i_config = new Cls_ConfigModel
			i_datapath = i_config.DataPath
			Call i_cache.SetCache("Config","DataPath",i_datapath)
		else
			i_datapath = i_cache.GetCache("Config","DataPath")
		end if
		set i_cache = nothing
	End Sub
	Private Sub Class_Terminate()
		set i_config=nothing
	End Sub
	Public property get Conn
		set Conn=i_conn
	End property
	Public Function OpenConn()
		set i_conn=server.createobject("adodb.connection")
		i_conn.open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="& i_datapath &";User ID=admin;Password=;Jet OLEDB:Database Password="
	End Function
	Public Function CloseConn()
		set i_conn=nothing
	End Function
End Class
%>

其中Cls_Cache是一个缓存类,这里缓存了数据库地址。

用户Model层Cls_UserModel.asp代码如下:

asp
<!--#include file="cls_databasemodel.asp" -->
<%
Class Cls_UserModel
	Private i_database,i_sql,i_rs
	Public UserInfo()
	Private Sub Class_Initialize()
		set i_database=new Cls_DatabaseModel
	End Sub
	Private Sub Class_Terminate()
		set i_database=nothing
	End Sub
	Public Function GetUserInfo(KeyType,Key)
		select case KeyType
		case "uid"
			i_sql="select * from [MYT_User] where UserId=" & Key
		case "uname"
			i_sql="select * from [MYT_User] where UserName=&#39;" & Key & "&#39;"
		end select
		i_database.OpenConn()
		set i_rs = i_database.Conn.execute(i_sql)
		if not i_rs.eof then
			ReDim UserInfo(i_rs.fields.count)
			for i=0 to i_rs.fields.count-1
				UserInfo(i)=i_rs(i)
			next
		else
			ReDim UserInfo(2)
			UserInfo(0)=0
			UserInfo(1)="guest"
		End if
		i_rs.close
		set i_rs=nothing
		i_database.CloseConn()
	End Function
End Class
%>
<!--#include file="cls_databasemodel.asp" -->
<%
Class Cls_UserModel
	Private i_database,i_sql,i_rs
	Public UserInfo()
	Private Sub Class_Initialize()
		set i_database=new Cls_DatabaseModel
	End Sub
	Private Sub Class_Terminate()
		set i_database=nothing
	End Sub
	Public Function GetUserInfo(KeyType,Key)
		select case KeyType
		case "uid"
			i_sql="select * from [MYT_User] where UserId=" & Key
		case "uname"
			i_sql="select * from [MYT_User] where UserName=&#39;" & Key & "&#39;"
		end select
		i_database.OpenConn()
		set i_rs = i_database.Conn.execute(i_sql)
		if not i_rs.eof then
			ReDim UserInfo(i_rs.fields.count)
			for i=0 to i_rs.fields.count-1
				UserInfo(i)=i_rs(i)
			next
		else
			ReDim UserInfo(2)
			UserInfo(0)=0
			UserInfo(1)="guest"
		End if
		i_rs.close
		set i_rs=nothing
		i_database.CloseConn()
	End Function
End Class
%>

Model层构造SQL语句并查询,然后将记录集存入UserInfo数组,供Control层调用。

Control层Cls_User.asp代码如下:

asp
<!--#include file="../model/cls_usermodel.asp" -->
<%
Class Cls_User
	Private i_uid,i_uname,i_user
	Private Sub Class_Initialize()
		set i_user = new Cls_UserModel
	End Sub
	Private Sub Class_Terminate()
		set i_user=nothing
	End Sub
	Public property get Uid
		Uid=i_uid
	End property
	Public property get UName
		Uname=i_uname
	End property
	Public property let Uid(Userid)
		i_uid=Userid
		Call i_user.GetUserInfo("uid",Userid)
		FillInfo()
	End property
	Public property let UName(UserName)
		i_uname=UserName
		Call i_user.GetUserInfo("uname",UserName)
		FillInfo()
	End property
	Private Function FillInfo()
		i_uid=i_user.UserInfo(0)
		i_uname=i_user.UserInfo(1)
	End Function
End Class
%>
<!--#include file="../model/cls_usermodel.asp" -->
<%
Class Cls_User
	Private i_uid,i_uname,i_user
	Private Sub Class_Initialize()
		set i_user = new Cls_UserModel
	End Sub
	Private Sub Class_Terminate()
		set i_user=nothing
	End Sub
	Public property get Uid
		Uid=i_uid
	End property
	Public property get UName
		Uname=i_uname
	End property
	Public property let Uid(Userid)
		i_uid=Userid
		Call i_user.GetUserInfo("uid",Userid)
		FillInfo()
	End property
	Public property let UName(UserName)
		i_uname=UserName
		Call i_user.GetUserInfo("uname",UserName)
		FillInfo()
	End property
	Private Function FillInfo()
		i_uid=i_user.UserInfo(0)
		i_uname=i_user.UserInfo(1)
	End Function
End Class
%>

Cls_User类中只定义了两个属性:i_uid,i,uname。当View层给i_uid或者i_uname赋值的时候调用Model层查询用户信息,然后用Fillinfo函数填写属性供View层调用。

View层UserInfo.asp代码如下:

asp
<!--#include file="control/cls_user.asp" -->
<!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=gb2312" />
<title>显示用户信息</title>
</head>
<body>
<%
set User=new Cls_User
for iii=1 to 100
	User.Uid=2
	response.write User.Uid
	response.write User.UName
next
set User=nothing
%>
</body>
</html>
<!--#include file="control/cls_user.asp" -->
<!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=gb2312" />
<title>显示用户信息</title>
</head>
<body>
<%
set User=new Cls_User
for iii=1 to 100
	User.Uid=2
	response.write User.Uid
	response.write User.UName
next
set User=nothing
%>
</body>
</html>

这样调用逻辑就非常清晰了。

试着加了一个循环(注释掉的代码),查询100个用户大约要3秒左右,看来频繁连接数据库开销确实很大。

另外,循环的时候变量不能用i,不然只能显示第一个用户信息,不知何故。

三层构架的大致思想基本算是掌握了,缓存应用还不够自如,模板类的实现还没开始。任重道远。

PS:今天大年三十,祝所有人幸福安康!