从概要设计说明书看社团宣传管理平台的JSP架构与二次开发
简介:面向高校软件工程课程设计与毕业设计的《社团宣传管理平台项目概要设计说明书》docx文档,由程赵旭、王成龙等五人团队于2020年5月至7月完成。文档围绕平台整体架构与核心功能展开,既包含编写目的、项目背景,也细化了操作流程、数据增加/修改/删除流程、总体结构与数据结构等章节,并针对管理员、社长、社员三类角色进行功能分配,同时给出外部接口设计,可帮助读者快速掌握Web平台概要设计的标准写法。资源为单个docx文件,压缩包整体仅511KB,内容精炼、目录完整,便于学习、复用与二次修改。目前已有80人学习下载,适合需要参考社团管理类系统设计文档或开展同类课程项目的读者,也适用于撰写课程设计报告、划分功能模块以及规划数据库结构的实用范本。
1. 一份概要设计说明书能干什么:先看清社团宣传管理平台的骨架
拿到一个 2020 年做完的社团宣传管理平台源码包,我最先读的不是代码,而是这份《概要设计说明书》。原因很简单:JSP 页面又散又乱,Servlet 跳转靠字符串,真正能告诉你“角色边界在哪、每条数据流怎么走”的,只有设计文档。这个项目是一个典型的 Web 课程设计工程:前台展示加后台管理,划分出管理员、社长、社员三类角色,技术栈锁死在 Sql Server 2008 + Tomcat + JDBC 上。如果你正打算把一个老项目跑起来,或者准备拿类似系统做答辩、二次开发,这份文档能让你少走很多弯路——尤其是“数据删除先弹 confirm 再跳转”这类细节,代码里看不出来,文档里写得很清楚。
2. 技术选型与总体结构:JSP + JDBC + Sql Server 的架构取舍
2.1 运行环境与技术栈:这份文档锁定了什么
文档在“任务概述”里写得很直白:系统建立在 WEB 平台上,使用 Sql Server 2008 作为后台数据库,能处理社团申请、社团活动等信息的统计和查询。这不是一个追求新技术的项目,而是一个典型的教学型管理系统——它的价值不在技术前沿,而在模块划分是否清楚、数据流是否完整。
技术栈可以整理成一张环境清单:
| 组成 | 选型 | 说明 |
|---|---|---|
| 后端语言 | Java(JSP + Servlet) | 页面与逻辑混写,是那个阶段课设项目的普遍形态 |
| 数据库 | Sql Server 2008 | 运行环境章节点名指定,需安装对应 JDBC 驱动 |
| Web 服务器 | Tomcat | 文档称“tomcat 本地服务器”,开发调试就在本机跑 |
| 内部接口 | JDBC | 5.2 节明确写了“与 sql-server 数据库通过 jdbc 接口连接” |
| 前端 | JSP + JavaScript | 表单校验用脚本完成,弹窗提示是主要交互方式 |
这类项目对软件/插件选型的依赖很低,核心就三样:JDBC 驱动包、JSP 标准标签库、一个能跑 Tomcat 的 JDK。连构建工具都可以不用,直接把源码扔进 Eclipse 的 Dynamic Web Project 里就能跑。对于想理解“老项目长什么样”的开发者来说,这套组合反而比 Spring Boot 更好拆——没有自动配置的黑匣子,每一层依赖都摆在明面上。
有一点值得注意:文档强调平台需要“效率高、理解性强、可维护性高、可靠性强”,但运行环境表格原文是空的。真要把项目跑起来,还得自己补环境参数——这个我在第 5 章会展开讲。
2.2 总体结构:前台展示与后台管理的双层布局
从文档 3.1.1 的操作流程能看出系统有两个入口。前台是社团网站展示界面,右侧功能栏有用户登录框,面向的是社员和社长身份;管理员身份则需要点击导航栏的“后台”超链接,进入另一个后台登录界面。这个设计在当时的课设项目里算是有想法的:前台做展示和查询,后台做管理,两类用户走不同的入口,避免权限混用。
入口与角色的对应关系是这样的:
| 入口 | 面向身份 | 主要动作 |
|---|---|---|
| 前台展示界面 | 社员、社长 | 登录、查询社团信息、浏览活动、相册查询 |
| 后台登录界面 | 超级管理员 | 账号密码比对,通过后进入后台管理 |
| 后台管理界面 | 管理员 | 用户管理、活动审核、新闻制度管理、系统管理 |
这种分层的好处是:社员的日常操作不需要进后台,减少了误操作的可能;管理员的权限集中在后台,审计的时候只看一块地方就行。缺陷也很明显——权限判断完全靠 JSP 页面级跳转控制,没有统一的拦截器,后面改权限就要一个页面一个页面翻。
2.3 功能分配矩阵:三类角色各管什么
文档 3.3 节把功能按角色拆成了三块,这是整份设计书里最有价值的部分。管理员是超级用户,负责系统用户管理、注册会员管理、社长注册管理、社团信息查询、社团活动管理、社团活动审核、新闻和制度管理、日程表信息管理、社团相册管理、系统管理,一共 10 项。社长管的是具体社团事务:个人资料、社团信息、相册、成员、日志、日程表、活动、聚餐,8 项。社员最少,主要是查询和个人操作:个人资料、我的社团查询、相册查询、信息查询、聚餐查询、日志查询与管理、收藏管理。
把三块放到一起看,权限边界很清楚:审核权在管理员,事务管理权在社长,社员只有查询和个人管理权。活动审核单独被拎出来给管理员,说明业务上非常在意“社团发什么活动要有人把关”,这在高校场景下是合理的。日程表管理和社团聚餐管理这两个模块是这套系统区别于一般新闻站的地方,二次开发时如果要做差异化,这两块是最值得保留的功能。
3. 核心模块拆解:三角色权限与四条数据流程的完整链路
3.1 登录校验链路:DAO 层比对与双入口跳转
文档 3.1.1 讲登录写得很具体:密码经 DAO 层与数据库中信息对比,之后判断跳转还是弹 Alert 警告框。翻译成代码,就是一个典型的登录 Servlet + DAO 查询:
// MemberDAO.java 登录校验(课设项目里的常见写法) public Member login(String account, String password, String roleType) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = DBUtil.getConnection(); String sql = "SELECT * FROM t_member WHERE login_account = ? AND login_password = ? AND user_type = ?"; ps = conn.prepareStatement(sql); ps.setString(1, account); ps.setString(2, password); ps.setString(3, roleType); rs = ps.executeQuery(); if (rs.next()) { Member m = new Member(); m.setId(rs.getInt("id")); m.setUserName(rs.getString("user_name")); m.setUserType(rs.getString("user_type")); return m; } return null; } catch (SQLException e) { e.printStackTrace(); return null; } finally { DBUtil.close(conn, ps, rs); } }三个参数对应前端登录框的三样输入:login_account 是账号,login_password 是密码,user_type 是身份单选——社员还是社长走前台登录,管理员走后台登录页时传入的是“超级管理员”。注意 SQL 里用的全是问号占位符,这是 PreparedStatement 的基本要求,目的是防 SQL 注入。老课设代码里直接拼字符串的很多,这份文档既然点名了 DAO 层,说明写的时候是有意识的。
登录成功后的跳转由调用方决定:查询结果不为空,跳转到对应角色的后台主页;为空则弹 Alert 警告框,提示“密码与账户不匹配”。有两处细节需要自己补:密码在这里是明文比对,如果真要部署,至少要做 MD5 加盐;user_type 的比对放在 DAO 层,意味着数据库里必须有一个字段专门存身份,这个在第 4 章表结构里会看到。
3.2 数据增加流程:系统自动编号与表单校验
文档对新增流程的描述是:每个信息都配有一个编号,编号字段不可人为编写,系统自动给出;其他信息由用户填写,格式和正确性由系统判断,通过校验才保存,不合法输入直接报错。
前端 JSP 表单加 JavaScript 校验,是这个流程的标准落地方式:
<form action="addActivityServlet" method="post" onsubmit="return validateForm();"> <input type="text" name="actName" placeholder="活动名称" required /> <input type="date" name="actTime" required /> <input type="text" name="actPlace" placeholder="活动地点" required /> <textarea name="actContent" rows="4" placeholder="活动内容" required></textarea> <button type="submit">提交</button> </form> <script> function validateForm() { var name = document.getElementsByName("actName")[0].value.trim(); if (name.length === 0) { alert("活动名称不能为空"); return false; } return true; } </script>“编号字段不可人为编写”是靠数据库自增完成的,表单里压根不放编号输入框。新增活动时,提交动作把 actName、actTime、actPlace、actContent 四个字段发给 Servlet,Servlet 再调 DAO 执行 INSERT,主键 activityid 由数据库自动生成,页面上不需要也不允许用户传。这样做的好处是避免并发时主键冲突,坏处是用户看不到即将写入的编号——所以新增成功后一般会跳回列表页,让用户通过列表看到系统分配的编号。
表单校验分两层:前端 JS 管交互体验,比如必填项为空就提示;后端 Servlet 还要再校验一遍,防止绕过浏览器直接 POST。文档原文没提后端二次校验,但在这个场景下是必须补的,否则格式校验形同虚设。
3.3 数据修改流程:JSP 回显与格式校验
修改流程的描述是:从后台界面选中要修改的社员信息,点击“修改”超链接进另一个 JSP 页面,修改后的格式要和后台代码规定一致,不一致就提示重新修改。这段描述里有意思的是“后台代码规定格式”这几个字——说明校验规则是写死在服务端的,前端只是配合。
编辑页的经典写法是先查后填,把数据从数据库查出来塞进表单:
<!-- editMember.jsp 修改页面 --> <% // 数据由 EditMemberServlet 提前查好并塞进 request Member member = (Member) request.getAttribute("member"); %> <form action="updateMemberServlet" method="post"> <input type="hidden" name="id" value="<%= member.getId() %>" /> <label>姓名</label> <input type="text" name="userName" value="<%= member.getUserName() %>" /> <label>身份</label> <select name="userType"> <option value="社员" <%= "社员".equals(member.getUserType()) ? "selected" : "" %>>社员</option> <option value="社长" <%= "社长".equals(member.getUserType()) ? "selected" : "" %>>社长</option> </select> <button type="submit">保存</button> </form>这条链路由四步组成:列表页携带 id 跳转到编辑页 → EditMemberServlet 按 id 把记录查出来 setAttribute → JSP 用脚本表达式回显到控件 → 用户改完提交到 updateMemberServlet。隐藏域里的 id 是整条链路的信物,它保证更新语句的 WHERE 条件能命中正确的记录,所以一定不能丢,也不能让用户改。格式校验在服务端做,比如用户名字段最长 20 个字符、身份字段只能是“社员/社长/超级管理员”三选一,不满足就返回到编辑页并提示错误。
这里有个常见问题:如果更新后不回显错误信息,用户会以为保存成功了,实际数据没变。文档里说的“提示管理员重新修改”,落地方式一般是在编辑页顶部放一个错误提示条,把校验失败的原因原样展示出来。
3.4 数据删除流程:confirm 确认框的前后端联动
删除流程文档描述得很细:点击操作模块的“删除”超链接,弹出 confirm 确定取消框,显示“是否真的要删除”,点击确定后删除相关信息并更新数据库。这个交互在 JSP 项目里的标准写法是:
<a href="deleteMemberServlet?id=5" onclick="return confirm('是否真的要删除');">删除</a>onclick 的返回值是关键:return confirm(...) 返回 true 时浏览器继续执行 href 跳转,返回 false 则中断跳转。很多人写着写着就把 return 漏了,写成 οnclick="confirm('是否真的要删除')",结果无论点确定还是取消,href 都会照常跳转——这是最容易翻车的地方。
服务端接到 deleteMemberServlet?id=5 后,执行的是物理删除,也就是真正的 DELETE FROM t_member WHERE id = 5。文档明确写了“更新数据库”,说明设计上就是要删干净。物理删除的副作用是:如果这条数据关联了活动、日志或收藏,关联表里的外键会变成孤儿数据。所以现在做系统,我一般会把物理删除改成逻辑删除,加一个 del_flag 字段把数据隐藏起来,而不是直接删行——这个改造点在最后一章细说。
4. 数据结构设计:从关系模型到 Sql Server 物理表的落地
4.1 逻辑结构:关系模型的取舍与实体关系
文档 5.1 节的表述有点绕,“以数学概率为基础,存取路径对社团管理人员透明”说的其实是关系模型的特性。Sql Server 2008 本身就是标准关系型数据库,所以系统用的是关系模型无疑。它的优点是表达简单、增删改查都和表结构一一对应;代价是复杂查询要写多表 JOIN,性能依赖 SQL 优化,数据量大时要牺牲一部分响应速度。对社团宣传这个场景——几百个社团、几千个成员、每天几十条活动信息——完全够用。
原文给出了核心实体:学生(社员)、管理员、登录账号、登录密码、社团类型、社长、建立时间,以及申请、管理、更新三种联系。把这些整理成实体关系表:
| 实体 | 关键属性 | 与其他实体的关系 |
|---|---|---|
| 社员/学生 | 登录账号、登录密码、用户类型、个人资料 | 申请加入社团(N 对 1) |
| 超级管理员 | 登录账号、登录密码、admin 身份 | 管理系统所有数据 |
| 社长 | 登录账号、登录密码、所在社团 | 管理本社团事务 |
| 社团 | 社团类型、建立时间、社长、简介 | 被社员申请,被社长管理 |
| 社团活动 | 活动名称、时间、地点、内容、审核状态 | 由管理员审核,由社长发起 |
用户类型(user_type)在逻辑设计里承担了角色识别功能,这也是为什么登录 SQL 里要带 user_type 条件。文档没有强调的一点是:社长本身也是社员,他的身份应该有两条记录,一条作为成员的基础身份,一条作为社长的管理身份。这个设计问题留到二次开发时会成为改造点。
4.2 物理结构:五张核心表与字段规划
原文 5.2 节用一句话列出了五张表,这是整份设计文档里唯一能直接落到建表语句的信息。表名和主键如下:
| 表名 | 主键字段名 | 业务含义 |
|---|---|---|
| 社团申请信息 | applysid | 学生申请入社的申请记录 |
| 网站新闻 | articleid | 社团新闻和制度公告 |
| 留言信息 | bbsid | 前台留言板 |
| 社团信息 | cinfoid | 每个社团的基本档案 |
| 活动信息 | activityid | 社团发布的活动 |
字段内容文档没有给全,但按这类系统的惯例,每张表的字段是可以推导出来的。社团信息表一般会有社团名称、社团类型、社长、建立时间、简介;活动信息表会有活动名称、时间、地点、内容、发布人、审核状态;网站新闻表会有标题、正文、发布时间、发布人。需要特别注意的是“审核状态”字段,文档在功能分配里明确写了管理员有“社团活动审核”权限,所以活动信息表里至少要有一个字段记录待审/通过/驳回三种状态。
这份文档有一点做得很好:它在引言里就要求“编写严谨的数据字典”,但正文其实没有给出完整的数据字典。所以拿着这份说明书做二次开发,第一件事不是写代码,而是把每个表的字段名、类型、约束补齐——这份文档的价值在于告诉你有哪些表,剩下的要靠自己填。
4.3 建表 SQL 与关键约束:Sql Server 落地示例
以活动信息表为例,建表语句可以这么写:
-- 活动信息表(Sql Server 2008 兼容写法) CREATE TABLE t_activity ( activityid INT IDENTITY(1,1) PRIMARY KEY, act_name NVARCHAR(50) NOT NULL, act_time DATETIME NOT NULL, act_place NVARCHAR(100) NOT NULL, act_content NVARCHAR(500) NULL, audit_status INT DEFAULT 0, -- 0 待审核,1 通过,2 驳回 publisher NVARCHAR(20) NOT NULL ); -- 社团信息表 CREATE TABLE t_cinfo ( cinfoid INT IDENTITY(1,1) PRIMARY KEY, cinfo_name NVARCHAR(50) NOT NULL, cinfo_type NVARCHAR(20) NOT NULL, president NVARCHAR(20) NOT NULL, establish_time DATETIME DEFAULT GETDATE(), description NVARCHAR(500) NULL );IDENTITY(1,1) 就是文档里说的“系统自动给出编号”——从 1 开始,每次加 1,由数据库保证唯一,应用层不需要也不能干预。NVARCHAR 是 Sql Server 里存中文的推荐类型,VARCHAR 在中文场景下容易出乱码。GETDATE() 是 Sql Server 取当前时间的内置函数,和 MySQL 的 NOW() 不一样,跨数据库移植时要改。audit_status 默认值为 0,表示新插入的活动默认待审核,这也印证了文档里“活动审核权在管理员”的功能设计。
表与表之间的关联在文档里没有展开,但按逻辑可以推断:申请信息表的外键指向社团信息表,活动表可以通过发布者字段关联回社长账号。没有外键约束也不奇怪,课设项目为了省事经常只建表不建外键,代价就是删除数据时容易产生脏数据——这正好呼应了上一章说的物理删除隐患。
5. 接口、运行环境与常见问题排查:把文档读薄再跑起来
5.1 外部接口:用户界面规范与软硬件环境解读
文档的接口设计分三块:用户界面按 Windows 应用软件规范设计,风格简约,用对话框交互;软件接口是 Tomcat 本地服务器,支持 Windows 2000 以上系统;硬件接口写的是 Intel 或其他系列微型计算机,内存 16G 以上,硬盘 512G 以上。
前两条能理解,第三条明显有问题。一个社团宣传网站,Tomcat 加 Sql Server 的双进程部署,2 核 4G 的服务器跑几百个社团绰绰有余,16G 内存是开发机的配置,不是服务器的。这属于把开发环境要求误抄到了部署环境里,读文档时要有判断力,不能照着准备机器。实际的推荐环境是:
| 用途 | 配置 | 说明 |
|---|---|---|
| 开发机 | 8G 内存,Windows 10,Eclipse/IDEA | 跑 Tomcat、Sql Server 开发实例 |
| 部署服务器 | 2 核 4G,Windows Server 或 Linux | Tomcat 8 + Sql Server 2008 R2 |
| 客户端 | 任意能开浏览器的设备 | 文档强调“在任何地点使用,正常连网的计算机” |
界面设计用对话框交互,对应到实现里就是 alert 弹窗和 confirm 确认框,简单直接,但对用户体验一般。二次开发如果想提升质感,可以把 alert 换成页面内嵌提示,但那就是后话了。
5.2 内部接口:JDBC 连接 Sql Server 的写法
内部接口全文只有一句话,“与 sql-server 数据库通过 jdbc 接口进行连接”。听起来轻描淡写,实际跑起来卡住的人最多。JDBC 连接 Sql Server 2008 的常用工具类长这样:
// DBUtil.java —— JDBC 连接 Sql Server 2008 public class DBUtil { private static final String DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; private static final String URL = "jdbc:sqlserver://localhost:1433;DatabaseName=club"; private static final String USER = "sa"; private static final String PWD = "your_password"; static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PWD); } }URL 的格式是 Sql Server 专用的:jdbc:sqlserver:// 开头,localhost 是主机地址,1433 是默认端口,DatabaseName=club 指定要连接的库名。USER 和 PWD 要替换成实际的登录账号——开发时可以用 sa,部署前建议建一个独立账号,只授予 club 库的读写权限,避免数据库被拖库时权限爆炸。驱动类 com.microsoft.sqlserver.jdbc.SQLServerDriver 来自 sqljdbc4.jar,这个 jar 必须放到 WEB-INF/lib 目录下,否则运行时会报 ClassNotFoundException,这是 JDBC 连接最典型的坑。
另一个容易忽略的点:Sql Server 2008 默认可能只开 Windows 身份验证,JDBC 用的 SQL Server 身份验证需要到 SSMS 里手动启用“混合模式”,并给 sa 或新建账号设置密码。这个不配好,代码写对了也连不上。
5.3 Tomcat 部署与数据库初始化:把项目真正跑起来
文档对部署只字未提,这里按课设项目的标准流程补齐。第一步,在 Sql Server 里创建 club 数据库,执行第 4 章的建表脚本。第二步,插入默认管理员账号,否则后台登录入口是死的:
INSERT INTO t_member(login_account, login_password, user_type, user_name) VALUES ('admin', 'admin123', '超级管理员', '系统管理员');第三步,把源码导入 IDE,配置 Web 项目,Artifact 命名为 club,部署到本地 Tomcat。启动后访问 http://localhost:8080/club/,先从前台登录框走社员登录,再从导航栏的“后台”链接走管理员登录,两条入口通畅、能完成一次增删改查,就算跑通了。
这里提醒一句:admin/admin123 是搭建时自己初始化的示例账号,文档原文并没有给出任何预设账号。如果你下载的源码包里带着数据库脚本,优先看脚本里有没有现成的账号,不要直接用上面这条 SQL 里的值,避免和已有数据冲突。
5.4 常见问题排查:读概要设计时最容易踩的五个坑
坑一:照着硬件接口买服务器,白白多花预算。现象是文档写“内存 16G 以上,硬盘 512G 以上”,照着买了高配机器。原因在于 16G/512G 是典型开发机配置,被误抄成了部署要求。解决方法是按实际并发评估,社团宣传平台 2 核 4G 起步足够,带宽和备份策略比单机配置更值得投入。
坑二:JDBC 连数据库报 Login failed for user。现象是驱动、URL、账号密码都对,一执行查询就报登录失败。原因是 Sql Server 默认只开了 Windows 身份验证,JDBC 走的是 SQL Server 身份验证,两边没对上。解决方法是打开 SSMS,服务器属性 → 安全性,启用“SQL Server 和 Windows 身份验证模式”,再为当前账号设置密码。
坑三:删除确认框不弹,点了直接删。现象是点击删除超链接没有任何提示,数据就没了。原因是 onclick 事件里少了 return,confirm 的结果没有返回给浏览器。解决方法是把删除链接写成<a href="deleteServlet?id=5" onclick="return confirm('是否真的要删除');">删除</a>,确认取消框弹不弹就看这一个 return。
坑四:前台登录框能登录,但跳错了页面。现象是社员账号登录后进了后台管理界面。原因是登录 SQL 没有把 user_type 作为查询条件,DAO 只校验了账号密码,没校验身份。解决方法是在登录方法里带上身份参数,让三个角色各自只能进各自的入口。
坑五:修改表单提交后中文乱码。现象是页面显示正常,提交到数据库后全是问号。原因是 Tomcat 8 之前默认按 ISO-8859-1 解码 POST 请求,中文字节被拆坏。解决方法是在 Servlet 入口加一行request.setCharacterEncoding("UTF-8"),并保证 JSP 页面本身是 UTF-8 编码。
6. 二次开发改造思路:给旧系统做一次分层手术
拿到这份设计书和配套源码,最值得做的不是加功能,而是先解决结构问题。第一步是分层:把 JSP 里的 Java 脚本抽干净,Servlet 只负责接收参数和转发,业务规则放进 Service 层,数据库访问留在 DAO 层。第二步是权限收口:加一个 Filter 拦截/back/*路径,判断 session 里的 userType 是不是“超级管理员”,不是就直接重定向到登录页——这一步能堵住原来页面级跳转的权限漏洞。第三步是改造删除逻辑,把物理删除换成逻辑删除,保留数据痕迹:
-- 逻辑删除改造:给核心表加删除标记 ALTER TABLE t_activity ADD del_flag INT NOT NULL DEFAULT 0; -- 原来直接 DELETE,现在只更新标记 UPDATE t_activity SET del_flag = 1 WHERE activityid = ?; -- 查询列表时统一带上过滤条件 SELECT * FROM t_activity WHERE del_flag = 0;改造完怎么验证?把第 3 章的四条流程重新走一遍:登录双入口是否正常、新增活动提交后列表是否出现、修改后回显是否正确、删除后记录是否从前端消失且数据库里 del_flag 已置 1。这四条跑通了,重构就没有伤到业务。
从这次拆解里我养成一个习惯:拿到任何旧项目,先画数据字典和权限矩阵,再动代码。这份概要设计说明书的意义也在这里——它的价值不在于写得有多完备,而在于给了你一张地图,地图上的坑我替你踩过了。完整说明书连同需求文档一起在资源包里,下载后按第 5 章的清单逐项核对,能节省你自己摸索的时间。希望帮到你。
本文还有配套的精品资源,点击获取