楔子
在写这篇博客时,虽然对七层的理解还处于一知半解阶段,但是不管怎样,七层登陆代码总算是出来了。之前接触过三层登录,尽管三层对系统进行了解耦,但是当我们改动B层或者D层时,U层必须进行相应的改动,才能确保程序的顺利运行。为了解决这个问题,前人们在三层基础上发展了七层:在U层和B层之间添加了一个外观层,通过这个外观层对U层和B层进行解耦,解决三层状态下B层发生改动U必须做相应改动的弊端;同理,在B层和D层之间添加了接口层,对B层和D层进行解耦;最后添加工厂,为数据库的更换提供方便。
代码
U层
解读
和用户进行交互,接手用户的数据随后将数据经外观层传递给B层进行业务逻辑处理。
代码
<span style="font-family:KaiTi_GB2312;font-size:24px;">'/**************************
'*文 件 名: frmLogin
'*命名空间: UI
'*内 容:
'*功 能:
'*文件关系:
'*作 者: 刘超
'*小 组: 刘超
'*生成日期: 2016/07/25 11:27
'*版 本 号: V1.0
'*修改日志:
'*版权说明: 版权所有,盗版不究
'***************************/
#Region "Add Reference 添加引用"
Imports Entity
Imports Facade
#End Region
Public Class frmLogin
'Private Sub btnLogin_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles btnLogin.KeyDown
' If e.KeyCode = "13" Then
' Call btnLogin_Click()
' End If
'End Sub
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
'进行输入框的判断
If txtUser.Text = "" Then
MsgBox("请输入用户名", 0, "温馨提示")
txtUser.Focus()
Exit Sub
End If
If IsNumeric(txtUser.Text) = False Then
MsgBox("用户名请输入纯数字", 0, "温馨提示")
txtUser.Text = ""
txtPassword.Text = ""
txtUser.Focus()
Exit Sub
End If
If txtPassword.Text = "" Then
MsgBox("密码不能为空", 0, "温馨提示")
txtPassword.Focus()
Exit Sub
End If
If IsNumeric(txtPassword.Text) = False Then
MsgBox("请输入纯数字的密码", 0, "温馨提示")
txtPassword.Text = ""
txtPassword.Focus()
Exit Sub
End If
Try
'实例化所需要的各层的类
Dim Facade As New Facade.LoginFacade
Dim fac As New Facade.LoginFacade
Dim UserInfo As New Entity.LoginUserInfo
Dim table As DataTable
'Dim flag As Boolean
UserInfo.UserName = txtUser.Text.Trim
Entity.EntryInfo.UserName = txtUser.Text.Trim '将登陆用户名赋给全局变量UserName
Entity.EntryInfo.OldPassword = txtPassword.Text.Trim '将登录密码赋给全局变量OldPassword
UserInfo.Password = txtPassword.Text
'将U层的信息传入外观层,然后再将外观层传入B层进行判断
table = Facade.CheckUser(UserInfo)
If table.Rows.Count() = 0 Then '判断用户是否存在
MsgBox("该用户不存在,请重新输入", 0, "温馨提示")
txtUser.Text = ""
txtPassword.Text = ""
txtUser.Select()
txtUser.Focus()
Else
Dim strPassword As Boolean
strPassword = Facade.CheckPassword(UserInfo)
If strPassword = False Then
MsgBox("密码错误,请重新输入", 0, "温馨提示")
txtPassword.Text = ""
txtPassword.Focus()
Else
MsgBox("登录成功")
End If '第二层If,判断用户密码是否正确
End If '第一层If,判断用户是否存在
Catch ex As Exception
MsgBox("用户不存在或密码不正确", 0, "提示")
txtPassword.Text = ""
txtUser.Text = ""
txtUser.Select()
txtUser.Focus()
End Try
End Sub
Private Sub btnQuit_Click(sender As Object, e As EventArgs) Handles btnQuit.Click
Me.Close()
End Sub
Private Sub btnLogin_Click()
Throw New NotImplementedException
End Sub
End Class
</span>
App.Settings
<span style="font-family:KaiTi_GB2312;font-size:24px;"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<connectionStrings>
<add name ="conneString" connectionString ="Server=JokerLiu\SQLEXPRESS;Database=CRCSR;User ID=sa;Password=1" />
</connectionStrings>
<appSettings >
<add key ="DBString" value="SQL server" />
</appSettings>
</configuration></span>
Facade
解读
接触U层和B层之间的耦合,接收U层的数据+调用B层的方法=对用户的登录信息进行验证。PS;外观层视粒度大小酌情增删。
代码
<span style="font-family:KaiTi_GB2312;font-size:24px;">'/**************************
'*文 件 名: LoginFacade
'*命名空间: Facade
'*内 容:
'*功 能:
'*文件关系:
'*作 者: 刘超
'*小 组: 刘超
'*生成日期: 2016/07/25 11:06
'*版 本 号: V1.0
'*修改日志:
'*版权说明: 版权所有,盗版不究
'***************************/
#Region "Add Reference 添加引用"
Imports BLL
Imports Entity
#End Region
Public Class LoginFacade
#Region "判断用户是否存在"
''' <summary>
''' 判断用户是否存在
''' </summary>
''' <param name="UserInfo"></param>
''' <returns>
'''
''' </returns>
''' <remarks></remarks>
Public Function CheckUser(ByVal UserInfo As Entity.LoginUserInfo) As DataTable
Dim IsUserExists As New BLL.LoginBLL
Dim table As New DataTable
table = IsUserExists.CheckUser(UserInfo)
Return table
End Function
#End Region
#Region "判断用户密码是否正确"
Public Function CheckPassword(ByVal UserInfo As Entity.LoginUserInfo) As Boolean
Dim IsPasswordExists As New BLL.LoginBLL
Dim flag As Boolean
flag = IsPasswordExists.CheckPassword(UserInfo)
If flag = True Then
Return True
Else
Return False
End If
End Function
#End Region
End Class
</span>
BLL
解读
通过调用工厂中的方法实现相应接口的创建。
代码
<span style="font-family:KaiTi_GB2312;font-size:24px;">'/**************************
'*文 件 名: LoginBLL
'*命名空间: BLL
'*内 容:
'*功 能:
'*文件关系:
'*作 者: 刘超
'*小 组: 刘超
'*生成日期: 2016/07/25 10:18
'*版 本 号: V1.0
'*修改日志:
'*版权说明: 版权所有,盗版不究
'***************************/
#Region "Add Reference 添加引用"
Imports IDAL
Imports Entity
Imports Factory
#End Region
Public Class LoginBLL
#Region "Check if the user exits 检查用户是否存在"
'检查用户是否存在
Public Function CheckUser(ByVal UserInfo As Entity.LoginUserInfo) As DataTable
Dim Factory As New Factory.LoginFactory
Dim IUser As IDAL.LoginIUserInfo
'调用创建用户的工厂方法
IUser = Factory.CreateIUser() '调用工厂的CreateIUser方法创建IUser接口实例
Dim table As New DataTable
table = IUser.selectUser(UserInfo)
Return table
End Function
#End Region
#Region "Check the password is correct 检查密码是否正确 "
Public Function CheckPassword(ByVal UserInfo As Entity.LoginUserInfo) As Boolean
Dim Factory As New Factory.LoginFactory
Dim IUser As IDAL.LoginIUserInfo
IUser = Factory.CreateIUser
Dim table As New DataTable
Dim flag As Boolean
table = IUser.selectUser(UserInfo)
If table.Rows(0).Item(1) = UserInfo.Password Then
flag = False 'true
Else
flag = True 'false 0
End If
Return flag
End Function
#End Region
End Class
</span>
Factory
解读
提供接口的创建服务。
代码
<span style="font-family:KaiTi_GB2312;font-size:24px;">'/**************************
'*文 件 名: LoginFactory
'*命名空间: Factory
'*内 容:
'*功 能:
'*文件关系:
'*作 者: 刘超
'*小 组: 刘超
'*生成日期: 2016/07/25 11:27
'*版 本 号: V1.0
'*修改日志:
'*版权说明: 版权所有,盗版不究
'***************************/
#Region "Add Reference 添加引用"
Imports IDAL
Imports System.Data
Imports System.Reflection '反射
Imports System.Configuration '配置文件
#End Region
Public Class LoginFactory
Private Shared ReadOnly AssemblyName As String = "DAL" '数据库程序集名称,命名空间DAL
Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DB")
Public Function CreateIUser() As LoginIUserInfo
Dim classname As String = "DAL" + "." + strDB + "LoginDAL" '需要实例化的D层的名称
Dim IUser As LoginIUserInfo
'CType 函数将返回表达式显示的转换为指定的数据类型、对象、结构、类或者接口后的结果
IUser = CType(Assembly.Load(AssemblyName).CreateInstance(classname), LoginIUserInfo) '返回LoginIUserInfo
Return IUser
End Function
End Class
</span>
DAL
解读
用于实例化接口
代码
<span style="font-family:KaiTi_GB2312;font-size:24px;">'/**************************
'*文 件 名: LoginDAL
'*命名空间: DAL
'*内 容:
'*功 能:
'*文件关系:
'*作 者: 刘超
'*小 组: 刘超
'*生成日期: 2016/07/24 11:38
'*版 本 号: V1.0
'*修改日志:
'*版权说明: 版权所有,盗版不究
'***************************/
#Region "Add Reference 添加引用"
Imports Entity
Imports DB
Imports IDAL
Imports System.Data.SqlClient
#End Region
Public Class LoginDAL : Implements IDAL.LoginIUserInfo
'实现接口中的方法
Private sqlHelper As New DB.SqlHelper
'判断用户是否存在
Public Function selectUser(UserInfo As LoginUserInfo) As DataTable Implements LoginIUserInfo.selectUser
Dim sql As String '中间变量,用于存储从数据库中查询到的 信息
Dim table As DataTable
'声明并实例化参数组
Dim sqlParams As SqlParameter() = {New SqlParameter("@UserName", UserInfo.UserName), New SqlParameter("@Password", UserInfo.Password)}
sql = "select * from T_User where userID=@UserName and password=@Password"
'调用sqlHelper类中的ExecSELECT方法来执行查询并获取返回值
table = sqlHelper.ExecSelect(sql, CommandType.Text, sqlParams)
Return table
End Function
End Class
</span>
IDAL
解读
对外提供接口
代码
<span style="font-family:KaiTi_GB2312;font-size:24px;">'/**************************
'*文 件 名: LoginIUserInfo
'*命名空间: IDAL
'*内 容:
'*功 能:
'*文件关系:
'*作 者: 刘超
'*小 组: 刘超
'*生成日期: 2016/07/24 11:38
'*版 本 号: V1.0
'*修改日志:
'*版权说明: 版权所有,盗版不究
'***************************/
Imports Entity
Public Interface LoginIUserInfo
'判断用户是否存在
Function selectUser(ByVal UserInfo As Entity.LoginUserInfo) As DataTable
End Interface
</span>
DB(SqlHelper)
解读
用于抽象与数据库进行交互的那部分代码,包括连接数据库和对数据库的执行操作。
代码
SqlHelper
<span style="font-family:KaiTi_GB2312;font-size:24px;">'/**************************
'*文 件 名: SQLHelper
'*命名空间: DB
'*内 容: 暂未知
'*功 能: 暂未知
'*文件关系:
'*作 者: 刘超
'*小 组: 刘超
'*生成日期: 2016/07/23 20:45
'*版 本 号: V1.0
'*修改日志:
'*版权说明: 版权所有,盗版不究
'***************************/
#Region "引用"
Imports System.Data.SqlClient
Imports System.Configuration
Imports System.Data
#End Region
Public Class SqlHelper
Dim DBConnectStr As New DALUtil
Dim DBConnection As New SqlConnection(DBConnectStr.connectString)
'建立数据库连接
Dim cmd As New SqlCommand '实例化一个Command对象,执行对数据的操作
'设置连接 这是什么意思?
'定义命令
Public Function ExecAddDelUpadate(ByVal cmdText As String, ByVal cmdType As CommandType, ByVal sqlParams As SqlParameter()) As Integer
'将传入的值分别赋给cmd的属性的值
Call CloseConn(DBConnection)
Call CloseCmd(cmd)
cmd.Parameters.AddRange(sqlParams) '传入参数
cmd.CommandType = cmdType '设置一个值,解释cmdText 人为指定CommandType的类型,砍掉系统对命令类型的识别过程,从而优化性能
cmd.Connection = DBConnection '设置连接,全局变量
cmd.CommandText = cmdText '设置查询语句
'Try
DBConnection.Open() '打开连接
Return cmd.ExecuteNonQuery() '执行增删改操作
cmd.Parameters.Clear() '清除参数
'Catch ex As Exception
' Return 0
'Finally
'End Try
Call CloseConn(DBConnection)
Call CloseCmd(cmd)
End Function
Public Function ExecAddDelUpdate(ByVal cmdText As String, ByVal cmdType As CommandType) As Integer
'给将要执行的cmd命令赋值
cmd.CommandText = cmdText '对数据库的执行语句
cmd.CommandType = cmdType '设置Sql语句如何解释
cmd.Connection = DBConnection '设置连接
'执行操作
Try
DBConnection.Open()
Return cmd.ExecuteNonQuery()
Catch ex As Exception
Return 0
Finally
Call CloseConn(DBConnection)
Call CloseCmd(cmd)
End Try
End Function
Public Function ExecSelect(ByVal cmdText As String, ByVal cmdType As CommandType, ByVal sqlParams As SqlParameter()) As DataTable
'执行带参的查询操作
Dim adapter As SqlDataAdapter
Dim dt As New DataTable
Dim ds As New DataSet
cmd.CommandText = cmdText
cmd.CommandType = cmdType
cmd.Connection = DBConnection
cmd.Parameters.AddRange(sqlParams)
adapter = New SqlDataAdapter(cmd)
'Try
adapter.Fill(ds)
dt = ds.Tables(0)
cmd.Parameters.Clear()
'Catch ex As Exception
' Throw New Exception("查询失败!")
'Finally
Call CloseConn(DBConnection)
Call CloseCmd(cmd)
'End Try
Return dt
End Function
Public Function ExecSelect(ByVal cmdText As String, ByVal cmdType As CommandType) As DataTable
'Execute query with no paramters 执行无参查询
Dim adapter As SqlDataAdapter
Dim ds As New DataSet
cmd.CommandType = cmdType
cmd.CommandText = cmdText
cmd.Connection = DBConnection
adapter = New SqlDataAdapter(cmd)
Try
adapter.Fill(ds)
Return ds.Tables(0)
Catch ex As Exception
Return Nothing
Finally
Call CloseConn(DBConnection)
Call CloseCmd(cmd)
End Try
End Function
#Region "CloseConn 关闭连接"
Public Sub CloseConn(ByVal conn As SqlConnection)
If (conn.State <> ConnectionState.Closed) Then '如果连接没有关闭
conn.Close() '关闭连接
conn = Nothing '不指向原对象
End If
End Sub
#End Region
#Region "CloseCmd销毁命令"
Public Sub CloseCmd(ByVal cmd As SqlCommand)
If Not IsNothing(cmd) Then '若命令没有被销毁
cmd.Dispose() '销毁命令
cmd = Nothing '不指向原命令
End If
End Sub
#End Region
End Class
</span>
DALUtil
<span style="font-family:KaiTi_GB2312;font-size:24px;">'/**************************
'*文 件 名: DALUtil
'*命名空间: DB
'*内 容: 暂不知
'*功 能: 暂不知
'*文件关系:
'*作 者: 刘超
'*小 组: 刘超
'*生成日期: 2016/07/23 20:33
'*版 本 号: V1.0
'*修改日志:
'*版权说明: 版权所有,盗版不究
'***************************/
Public Class DALUtil
Private ReadOnly db As String = System.Configuration.ConfigurationManager.AppSettings("DBString") '数据库
Private ReadOnly ConnectStr As String = System.Configuration.ConfigurationManager.ConnectionStrings("ConneString").ConnectionString
'sql数据库连接字符串
Public connectString As String = ConnectStr
End Class
</span>
PS
开始时候是参看其他同学的代码进行的学习,后来发现DALUntil可以直接写进去SqlHelper中。
收获
下面是七层登录的代码地图,里面对各层之间的关系描述的非常清晰,很好的帮助了我对七层登陆进行理解。
但是对下面这条代码线还是不太理解,希望大神多多指点一二。
感谢您的宝贵时间,祝生活愉快,谢谢~~
—joker