尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

从2004年ASP图书管理系统看三层架构与状态驱动设计

从2004年ASP图书管理系统看三层架构与状态驱动设计 简介《基于Web的图书管理系统的设计与开发》是一篇以图书借阅与系统维护为核心的本科毕业论文面向计算机相关专业学生、毕业设计撰写者及Web开发初学者。文档基于B/S架构选用ASP、VBscript与SQL Server 2000作为主要开发工具系统讲解了从开发工具选型、需求分析、功能模块划分、数据库设计到具体功能代码实现的完整流程。内容重点包括借书还书处理、遗失书籍与读者证挂失等异常处理、数据备份与恢复、管理员口令维护、借阅统计报表生成并给出了界面风格设计建议与系统运行情况分析可直接借鉴其数据库表结构、模块划分思路和排错经验。资源包内共有1个doc文档大小仅1.11MB方便下载后对照学习。该论文格式规范、目录完整适合当作课程设计或毕业论文的写作模板。目前资源已有91人学习值得需要开发或设计图书管理系统的读者参考。1. 基于Web的图书管理系统一份2004年的论文为何还值得拆解接手过一个还在跑 ASP 的老项目的人大概都经历过这种场面代码里全是!-- #include filedata_conn.inc --数据库连接串直接写在页面上连翻页都要靠 VBScript 手写。但你不得不承认这类系统能活十几年靠的并不是技术新而是业务模型清晰。这份 2004 年的毕业论文《基于Web的图书管理系统的设计与开发》就是典型代表——它面向大中型企业图书馆用 FrontPage 做前台、ASP 写业务、SQL Server 2000 存数据把借书、还书、挂失、备份、报表整条链路完整跑通。放在今天看虽然技术栈过时但里面的三层式 Web 结构、状态标志位设计、异常处理分支仍然能直接迁移到现代 web 项目里。无论你是要做图书管理系统课程设计还是维护遗留系统拆解这份资源都能少踩很多坑。2. 三层式 Web 结构选型FrontPage、ASP、IIS 与 SQL Server 20002.1 前台工具选型FrontPage 为什么比 Dreamweaver 更合适2004 年前后做网页主流编辑工具无非记事本、FrontPage、Dreamweaver。论文里明确否掉了记事本——手写 HTML 对开发人员的熟练度要求太高而且工作繁琐。剩下的 FrontPage 和 Dreamweaver 都是所见即所得但作者选了 FrontPage。理由是 FrontPage 在网页编辑上更专业、稳定、可修改性强而 Dreamweaver 尽管功能更多、支持 DHTML 和 CSS 标准甚至“傻瓜式”到不需要懂 HTML但对一个需要频繁调业务逻辑的团队来说功能的堆砌反而容易掩盖问题。这个选择放到今天看其实反映了项目定位图书借阅管理系统是给管理员每天用的工具型系统不是展示型官网。界面要的是简洁、稳定、能快速切换功能而不是花哨的动画效果。所以工具选型不是“哪个强选哪个”而是“哪个最贴合项目场景”。对比维度FrontPageDreamweaver记事本上手难度中低高HTML 可见性好较弱原始站点管理有有无适合场景功能型 Web 项目展示型网站代码控与 IIS/ASP 集成原生友好一般手动配置从表格能看出FrontPage 和 IIS 同为微软系配合起来天然顺畅这在当时是很实在的考量。2.2 ASP IIS 组成的三层式 Web 结构的价值论文中提到了一个关键架构三层式 Web 结构即浏览器、IISASP、后端数据库。IIS 作为 Web 服务器承载 ASP 脚本执行ASP 通过 ActiveX Server 组件与数据库交互最终结果以 HTML 返回浏览器。这种结构最大的好处是前端不需要安装任何业务组件所有逻辑集中在服务器端。原文列出了这种结构的几个收益减少构建和维护成本、加快联机过程、应用软件集中在服务器端开发管理前端可用任何浏览器后端可存取任何数据库。这与现在前后端分离、接口化的思路本质相同——只是当时没有 REST API而是用 ASP 页面直接输出动态 HTML。理解这一点再看那些高并发的现代 Web 应用你会发现核心架构思想并没有变变的只是中间层的实现方式。2.3 数据库选型为什么企业项目不能随便用 Access论文对比了 Oracle、SQL Server 2000、Access 三个选项。Oracle 适合超大型数据库对本系统来说操作过于复杂数据量也到不了那个级别。Access 对付小项目没问题但公司其他系统都在用 SQL Server而且随着企业规模扩大图书量和读者信息量只会增加Access 很可能撑不住。所以最终选了 SQL Server 2000理由很朴素操作直观、上手容易、安全性强、处理数据量大放在现在的语境下就是“数据库要跟着业务走不能只图方便”。2.4 ADO 连接 SQL Server五步法及参数说明ASP 操作数据库的标准手段是 ADOActiveX Data Objects。论文把连接过程拆成了五步我从维护老项目的经验看这套流程至今仍是理解 ASP 数据库操作的核心创建数据源 DSN或者直接写连接字符串创建 Connection 对象打开连接通过 RecordSet 或 Execute 执行 SQL关闭对象并释放资源。下面是典型的 ASP 连接代码% 使用 ODBC 驱动连接 SQL Server Dim conn Set conn Server.CreateObject(ADODB.Connection) conn.ConnectionString DRIVER{SQL Server};SERVER127.0.0.1;UIDsa;PWD123456;DATABASElibrary conn.Open Dim rs, sqlstr sqlstr SELECT * FROM book_input WHERE book_state0 Set rs Server.CreateObject(ADODB.RecordSet) rs.Open sqlstr, conn, 3, 3 遍历结果集 Do While Not rs.EOF Response.Write rs(book_name) br rs.MoveNext Loop rs.Close Set rs Nothing conn.Close Set conn Nothing %这段代码的逻辑很经典先创建ADODB.Connection再设置连接字符串其中SERVER是数据库实例名UID和PWD是登录账号密码DATABASE指向系统所在的 Library 库。随后创建ADODB.RecordSet用rs.Open sqlstr, conn, 3, 3执行查询第二个参数 3 代表动态游标第三个参数 3 代表乐观锁定两者组合后才能对结果集进行灵活的增删改。最后一定要关闭对象否则占用的服务器连接资源不会自动释放时间一长生出大量死连接。这段代码里的Do While ... Loop就是典型的数据行遍历方式整个思路与现在用 JDBC 或 ADO.NET 操作数据库没有本质差别。3. 需求分析与数据库设计图书借阅系统的四张核心表3.1 需求分析工作人员与管理员的权限边界论文对需求分析做得很扎实把用户分成两类图书馆工作人员和图书馆管理人员。工作人员需要完成图书信息的增删改查、读者信息维护、借书还书操作、借阅信息统计、逾期和遗失等异常处理以及所有查询统计表单的打印。管理人员除了这些还要能做系统维护、数据备份恢复、用户权限控制。这个划分很关键因为在编码之前你就能确定哪些功能需要权限校验。例如普通工作人员不应该有备份数据库的权限更不应该能修改其他管理员的密码。需求分析阶段就把权限边界画清楚后面的功能模块才不至于缠在一起。这也是论文中“权限控制”能独立成块的原因。3.2 功能模块划分借阅、异常、维护、报表如何解耦论文把系统划成了几个独立功能模块借书/还书处理、异常处理、系统维护、报表打印。模块之间通过数据库共享状态而不是页面互相跳转调用。这样设计的好处很明显借书时只需要修改book_input表的isloan字段还书时反过来挂失时更新readerinformation表的reader_state。每个模块只管自己的逻辑不关心其他模块的内部实现。这种“模块化 状态驱动”的思路在今天仍然是最稳妥的工程实践。哪怕你用 Java 写后台用 Vue 写前台也一样要遵守这个原则业务模块之间不能直接调用彼此的内部函数而是通过数据状态进行通信。论文中提到的“框架式界面”也是为了提高操作效率——管理员不必在前台后台间来回切换所有功能集中在左侧导航右侧内容区随时刷新。3.3 数据库设计bookmenu、book_input、readerinformation、login 表结构论文设计了四张核心表分别是图书类目表bookmenu、图书基本信息表book_input、读者基本信息表readerinformation、系统用户表login。这四张表构成了整个系统的数据骨架。下面是各表的关键字段图书类目信息表 bookmenu字段名类型说明book_typevarchar(50)图书类别代码book_kindvarchar(50)图书类别名称book_memovarchar(50)类别备注图书基本信息表 book_input字段名类型说明ISBNvarchar(50)图书索引号book_novarchar(50)图书编号唯一book_namevarchar(50)图书名称publishingvarchar(50)出版社book_authorvarchar(50)编著者book_pricefloat单价book_kindvarchar(50)类别名称sale_datevarchar(20)出版日期book_statevarchar(10)0-正常 1-逾期未还 2-已遗失isloanvarchar(10)0-未借出 1-已借出loanervarchar(50)借阅者loandatevarchar(20)借阅日期读者基本信息表 readerinformation字段名类型说明reader_novarchar(50)读者证号reader_namevarchar(50)读者姓名reader_sexvarchar(2)性别reader_idvarchar(50)工号reader_placevarchar(50)所在部门reader_zhichengvarchar(50)职称reader_stateint0-正常 1-有过期未还 2-证已挂失lost_datevarchar(20)挂失日期系统用户信息表 login字段名类型说明Usernamevarchar(245)管理员名称Userpasswordvarchar(245)密码Userclassint1-一般管理 2-最高管理从这些表的设计能看出系统把业务状态直接放在主数据表里没有引入额外的流水表。比如book_input表里直接用loaner字段记录当前借阅者loandate记录借出时间。这样做的优点是查询快缺点是历史信息丢失。实际项目中如果要做借阅历史分析通常会在借还操作时往独立流水表写一条记录。但你也要明白2004 年的企业图书室最关心的就是“当前谁借着这本书”而不是“这本书过去一年被借过几次”。所以这个设计是符合当时场景的。3.4 状态标志位设计图书状态与读者状态如何驱动业务流程系统中大量使用状态标志位。图书有book_state和isloan两个维度一个是物理状态正常、逾期、遗失一个是借阅状态借出、未借出。读者有reader_state区分正常、有过期未还、已挂失。这种“多字段组合状态”的设计虽然简单但很有效。举例来说借书时先查读者状态如果reader_state1说明这个读者有逾期未还的书系统直接拒绝借书如果reader_state2说明读者证已挂失也不能借。同时还要查该书状态如果book_state1表示这本书已经逾期未还不能外借。通过两三个整型字段就把最复杂的业务规则表达清楚了。维护这类系统时最忌讳的就是把状态字段的数值含义写死在代码里而没有任何注释。建议在开发初期就维护一张状态码对照表放到项目文档里不然过半年连自己都会忘。4. 借书还书与异常处理的代码实现细节4.1 借书流程权限校验、读者校验与借阅数量上限借书是系统的核心功能论文给出了完整的算法流程核心可归纳为四步先验证登录权限再根据读者证号查读者信息然后检查读者状态和借阅数量最后写入借阅记录并更新图书状态。这里我给出一个简化版的 ASP 逻辑实现用来展示状态判断和字段更新的顺序% 借书主流程 borrowbook.asp If Session(username) Then Response.Redirect login.asp End If reader_no Request.Form(reader_no) book_no Request.Form(book_no) 查询读者信息 Set rsReader Server.CreateObject(ADODB.RecordSet) rsReader.Open SELECT * FROM readerinformation WHERE reader_no reader_no , conn, 3, 3 If rsReader.EOF Then Response.Write 读者证不存在 Response.End End If reader_state rsReader(reader_state) borrowed_count rsReader(borrowed_count) 假设存在此字段记录已借数量 If reader_state 2 Then Response.Write 读者证已挂失不能借书 Response.End End If If reader_state 1 Or borrowed_count 3 Then Response.Write 您有逾期未还书籍或借阅数量已达上限 Response.End End If 查询图书状态 Set rsBook Server.CreateObject(ADODB.RecordSet) rsBook.Open SELECT * FROM book_input WHERE book_no book_no , conn, 3, 3 If rsBook.EOF Then Response.Write 图书编号不存在 Response.End End If If rsBook(isloan) 1 Or rsBook(book_state) 0 Then Response.Write 图书不可借出 Response.End End If 更新图书状态 conn.Execute UPDATE book_input SET isloan1, loaner reader_no , loandate Date() WHERE book_no book_no rsReader.Close rsBook.Close Set rsReader Nothing Set rsBook Nothing %这段代码的逻辑很清晰第一层是会话校验防止未登录用户直接调用页面第二层是读者校验排除挂失用户和超量用户第三层是图书校验排除已借出和异常状态的书籍最后才执行更新。注意这里用Date()函数写入当前日期在 SQL Server 里对应的就是GETDATE()如果通过参数化查询写类型匹配会更稳。论文里提到的借阅上限设为 3这个值在现实场景中应当根据企业规模调整但状态判断的思路是通用的。4.2 还书流程状态更新与逾期判断还书相对于借书要简单主要做三件事判断是否逾期、更新图书状态为未借出、清除借阅者信息。逾期判断需要比对loandate与当前日期相差的天数论文中提到了“超过限定借书时间的天数”但没有给出具体的计算方式。常见做法是写一条查询语句比较DATEDIFF的值-- 还书时检查是否逾期loan_days_limit 为允许的最大借阅天数 SELECT book_no, loaner, DATEDIFF(DAY, loandate, GETDATE()) AS borrowed_days, CASE WHEN DATEDIFF(DAY, loandate, GETDATE()) 30 THEN 1 ELSE 0 END AS is_overdue FROM book_input WHERE book_no A001 AND isloan 1这条 SQL 的核心是利用DATEDIFF计算实际借阅天数然后与业务规则里的 30 天比较。is_overdue字段直接给出是否逾期标记。如果逾期还书时还要将book_state置为 1并在异常处理模块中记录。这里有个容易踩的坑loandate在表里是varchar类型如果写入格式不统一比如2004-05-10和2004/5/10混存DATEDIFF会直接报错。所以设计数据库时日期字段最好用datetime或smalldatetime而不该用字符串。4.3 遗失书籍与读者证挂失异常流的实现异常处理是图书管理系统最重要的模块因为它是正常流程的补充处理不好会产生数据不一致。遗失书籍的处理逻辑分两步先把book_input表的book_state置为 2已遗失再更新读者信息同时记录赔偿信息。读者证挂失类似把readerinformation表的reader_state置为 2并记录lost_date。以下是典型的挂失更新操作-- 读者证挂失 UPDATE readerinformation SET reader_state 2, lost_date GETDATE() WHERE reader_no R0001; -- 遗失书籍标记图书状态同时将读者状态置为 1有过期未还 UPDATE book_input SET book_state 2 WHERE book_no A001; UPDATE readerinformation SET reader_state 1 WHERE reader_no R0001;注意遗失书籍和逾期未还虽然都影响读者状态但处理方式不同。逾期未还是“可等待归还”的遗失则意味着这本书可能永远回不来。所以遗失操作里除了改状态一般还会生成一条赔偿记录。论文中没有细说赔偿计算的公式但通常按图书原价或倍率计算。这里的关键在于两个表的状态更新要放在同一事务里否则可能出现图书已标记遗失但读者状态没改的中间态。4.4 系统维护数据备份恢复与管理员口令维护系统维护模块包括数据库备份与恢复、管理员登录、注册、删除、密码修改和权限修改。论文中明确最高权限管理员才能进行备份操作。在 SQL Server 2000 时代备份通常直接用BACKUP DATABASE命令-- 备份数据库到指定路径 BACKUP DATABASE library TO DISK D:\backup\library_20040510.bak WITH FORMAT, NAME N图书馆备份; -- 恢复数据库 RESTORE DATABASE library FROM DISK D:\backup\library_20040510.bak WITH REPLACE;这里WITH FORMAT会覆盖旧备份文件WITH REPLACE允许覆盖现有数据库。实际操作中备份文件最好带到服务器以外的存储位置避免同一台机器磁盘损坏导致数据全丢。论文里还提到管理员口令维护常见做法是登录后修改密码也就是执行UPDATE login SET Userpassword新密码 WHERE Username当前用户。但这里有个安全点密码不能明文存储。2004 年的系统可能直接存字符串现在的做法至少要用 MD5 加盐或 SHA-256 哈希否则数据库一旦泄露所有管理员账号就暴露了。5. 报表打印与运行验证从论文到可复现的检查清单5.1 水晶报表在 Web 系统中的集成思路论文中提到水晶报表技术但没有贴出具体代码。以当时的场景水晶报表可以通过 ASP 的CrystalReportViewer控件嵌入页面也可以导出为 PDF 或 Excel。常见做法是根据查询条件生成报表对象绑定数据源后交由控件渲染。报表类型数据来源关键 SQL图书借阅统计book_input readerinformationSELECT book_name, loaner, loandate FROM book_input WHERE isloan1逾期未还统计book_inputSELECT * FROM book_input WHERE DATEDIFF(DAY, loandate, GETDATE()) 30遗失书籍清单book_inputSELECT * FROM book_input WHERE book_state2读者借阅排行book_inputSELECT loaner, COUNT(*) FROM book_input GROUP BY loaner集成水晶报表时有一个容易踩的坑报表服务器需要与 Web 服务器同域或配置身份信任否则 IIS 调用报表服务时会权限不足。我当时维护老系统时就遇到过页面正常但报表控件一直报“数据库登录失败”的问题最后发现是报表里的数据源连接串使用了本地账号而 Web 服务器用匿名身份访问报表服务导致数据库认证失败。解决办法是在报表数据源中配置 SQL Server 的 sa 账号或专用只读账号并确保 Windows 身份验证的权限路径完整。5.2 系统运行情况验证借书、还书、挂失、备份的测试要点论文最后用一章描述了系统运行情况对应到今天的术语就是功能测试。这部分虽然没有自动化测试用例但可以作为手工验收清单。当时论文的验证场景包括借书/还书、遗失处理、挂失处理、登录界面、管理员信息修改、数据库备份恢复。我从这些场景里提炼出几个关键检查点借书时输入合法读者证号和合法图书编号确认页面能成功更新isloan和loaner字段借书时故意使用已挂失的读者证确认系统提示“读者证已挂失”并中断操作还书时确认系统能正确清除loaner和loandate并将isloan置为 0挂失后重新尝试借书必须在重新补办读者证后恢复状态才能借出备份数据库后删除一条记录再执行恢复观察记录是否能完整还原修改管理员密码后重新登录旧密码必须失效。这组检查点几乎覆盖了系统的所有核心链路。对于现在的 Web 项目你完全可以把这套场景改写成接口测试用例用 Postman 或 pytest 跑回归。重点在于验证的不只是“成功路径”更要覆盖“异常路径”比如读者挂失后仍借书、图书已经遗失却想还书、备份文件路径不存在等。5.3 一个具体技巧用状态标志位追踪图书生命周期最后分享一个从这套系统里延伸出来的技巧就是利用book_state和isloan的组合生成图书生命周期追踪视图。原始系统里这两组字段分开记录但实际使用中你往往想知道一本书从入馆到遗失的完整轨迹。例如book_state0且isloan1表示图书已借出且正常book_state1且isloan1表示该书已逾期正在读者手上book_state2表示已遗失、不可再借。你可以用一条 SQL 把所有状态聚合成一个生命周期阶段SELECT book_no, book_name, CASE WHEN book_state0 AND isloan0 THEN 在馆 WHEN book_state0 AND isloan1 THEN 借出 WHEN book_state1 AND isloan1 THEN 逾期未还 WHEN book_state2 THEN 遗失 ELSE 异常状态 END AS life_cycle, loaner, loandate FROM book_input ORDER BY life_cycle;这种写法把分散的状态字段映射成可读的业务状态比在代码里逐个判断if要清晰得多。你可以在报表中直接引用这条 SQL也可以把CASE WHEN放到存储过程里做成视图。维护老系统时我最常用这个技巧排查数据问题能快速找出哪些书处于“借出但状态异常”的中间态避免人工挨条比对。本文还有配套的精品资源点击获取
返回列表