简介:这是一份基于Spring Boot与SSM框架的大创管理系统毕业论文,定位为计算机专业学生及毕业设计开发者的参考资料,核心解决大学生创新创业项目管理中申报、审核、评审等流程的规范化与信息化问题。论文结构完整,从摘要、研究背景、可行性分析、需求分析到数据库设计、数据流图、详细设计与测试均有展开,并系统描述了学生、指导老师、院系管理员三种角色的功能模块,其中学生项目申报、老师项目审核、管理员项目评审等核心业务均有涉及,可帮助读者快速理解一套B/S架构管理系统的完整开发脉络。压缩包内含1个doc文档,约2.57MB,包含论文正文、目录、系统截图及参考文献,适合作为毕业设计论文模板或同类课题的系统设计参照。已有134人学习下载,适合正在开展大创或类似管理类课题、需要快速把握论文框架与数据库设计思路的读者。
1. 大创管理系统:从项目申报到结项的全流程管理
大创项目管理的痛点,往往不是没人干活,而是流程散在各处:申报书发到微信群,中检材料在邮箱里,结项报告又变成一堆压缩包,老师审核时要逐个下载再手工登记。这套基于 Spring Boot 的大创管理系统,把学生、指导老师、院系管理员三个角色装进同一个浏览器平台,从项目申报、中检、结项到评审方案与专家评审,全都在线完成。对正在做 SSM 或 Spring Boot 毕业设计的同学来说,这份资源的价值在于:它同时包含可运行的工程源码和完整的毕业论文文档,从可行性分析、数据库设计到功能测试都能直接对照。对想给学院大创流程做信息化的人来说,三角色权限划分和评审方案管理也提供了很实在的参考。
2. 技术架构与数据设计:SSM + MySQL 的三层结构
2.1 技术选型:为什么用 Spring Boot 而不直接写 SSM
传统 SSM 项目在搭建时最耗时间的就是 spring-mvc.xml、mybatis-config.xml 加上 web.xml 那一堆配置,数据源、事务、扫描路径写错一个,启动阶段就要反复试错。这套系统的设计思路是:业务上仍按 Spring + SpringMVC + MyBatis 来组织,但用 Spring Boot 做底座,把多数样板配置交给自动配置处理。也就是说,你拿到工程后不需要从零拼配置,改一个 application.yml 就能把数据库、端口、日志全部带起来。
JDK 1.8 是 Spring Boot 项目里很常用的版本,资源里这份工程的依赖也按这个基线来锁。服务层用 Spring 管理 Bean,控制层用 SpringMVC 接收请求,数据访问层用 MyBatis 写 SQL,三层职责清楚。B/S 架构决定了所有功能最终都跑在浏览器里,服务器只需部署一套应用,学生、指导老师、院系管理员按角色登录后看到的是不同菜单,不需要在每台电脑上装客户端。
server: port: 8080 servlet: context-path: / spring: datasource: url: jdbc:mysql://localhost:3306/dachuang?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver servlet: multipart: max-file-size: 20MB max-request-size: 20MB mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.dachuang.entity这段配置里,port 控制 Web 服务端口,datasource 下的四项是 MySQL 连接的关键:连接地址指定了库名 dachuang,characterEncoding=utf8 保证中文参数不乱码,serverTimezone 必须写成当前地区时区,否则新版 JDBC 驱动在连接时会直接抛时区异常。multipart 配置预留了项目申报和优秀项目模块里上传图片、附件的容量,20MB 对结项报告这类文档基本够用,如果后续要传视频材料,可以按需要调大。
有人会问,既然用了 Spring Boot,为什么不干脆用 JPA 或 MyBatis-Plus?这个项目保持原生 MyBatis 加 XML 映射,一方面是因为论文和答辩时需要讲清楚 SQL 与实体映射关系,另一方面是大创项目里很多字段都是文本类型,例如评审方案的创新点、成员素质、预期成果,这些用 XML 写动态 SQL 比注解拼接更直观。Spring Boot 的 starter 已经帮我们自动装配了 SpringMVC、事务管理、日志等基础组件,你只要保证启动类上带 @MapperScan 注解,把 Mapper 接口扫描进去就行。
2.2 三个角色与九大功能模块的对应关系
系统的一个核心逻辑是角色驱动菜单。学生登录后能看到的包括优秀项目、项目信息、评审方案、大创资讯、项目申报管理、项目中检管理、项目结项管理、项目评审管理、专家评审管理。指导老师比学生多了个人中心、优秀项目管理、项目类型管理、项目信息管理这些模块,并在项目申报、中检、结项、评审环节拥有审核入口。院系管理员的菜单覆盖最全,还额外负责评审方案管理和专家评审的统筹分配。
| 功能模块 | 学生 | 指导老师 | 院系管理员 |
|---|---|---|---|
| 大创资讯 | 查看 | 查看 | 管理 |
| 优秀项目 | 查看 | 管理 | 管理 |
| 项目类型 | 查看 | 管理 | 管理 |
| 项目申报 | 提交/查看 | 审核 | 审核/分配 |
| 项目中检 | 提交材料 | 审核 | 审核 |
| 项目结项 | 提交材料 | 审核 | 审核 |
| 评审方案 | 查看 | 管理 | 管理 |
| 专家评审 | 查看结果 | 参与评审 | 分配专家 |
这种设计本质上是一种基于 RBAC 的权限模型。数据库中不直接给用户表加一堆是否管理员字段,而是通过 role 字段区分身份,登录后把角色写入 session,前端菜单按角色渲染,后端在 Controller 或拦截器里再做一次放行判断。院系管理员和指导老师的菜单高度相似,但操作对象不同:管理员管的是全院项目,老师只管自己名下学生申报的项目。因此业务代码中所有列表查询都要带上范围条件,管理员按院系过滤,老师按关联的学生 id 过滤。
从实现上讲,角色和状态往往比按钮级别的权限更好落地。多数学校的信息化系统中,一个项目记录会经历“草稿—已提交—老师通过—管理员通过—中检提交—中检通过—结项提交—结项通过”的状态链。把状态设计成一个 int 字段,0 表示草稿,1 表示已提交,2 表示指导老师已审核,3 表示院系管理员已审核,这样查询进度时一条 SELECT 就能完成,不需要引入复杂的工作流引擎。
2.3 数据库核心表设计:字段、类型与实体关系
从论文中的 E-R 图可以还原出这样几条核心实体:用户、大创资讯、评审方案、项目信息、项目申报、中检记录、结项记录、专家评审结果。实际工程里为了减少关联复杂度,通常会把学生、指导老师、管理员统一放在 user 表里,用 role 字段区分,项目申报表单独存学生和指导老师的 id。
大创资讯表是常见的资讯发布结构,字段包括标题、简介、图片、内容、创建时间。这里重点拆一下评审方案表的字段来源:标题、图片、创新点、前期准备、实施方案、预期成果、经费预算、成员素质、创建时间。这些字段在数据库层几乎都是 varchar 或 longtext,因为评审老师要写的是大段文字,不适合把长度卡死。
CREATE TABLE `review_plan` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `addtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `title` varchar(200) NOT NULL COMMENT '评审方案标题', `picture` varchar(200) DEFAULT NULL COMMENT '封面图', `innovation` longtext COMMENT '创新点', `preparation` longtext COMMENT '前期准备', `implementation` longtext COMMENT '实施方案', `expected_result` longtext COMMENT '预期成果', `budget` decimal(10,2) DEFAULT NULL COMMENT '经费预算', `member_quality` longtext COMMENT '成员素质', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='评审方案';这张表的字段顺序与论文里的实体属性图一致,addtime 用于在列表页按时间倒序排列,title 经常作为查询条件,建议加普通索引。budget 用 decimal 而不是 float,是为了避免在经费统计时出现精度误差,这是金额字段的通用写法。longtext 类型在 MySQL 下最多能存 4GB,用来放创新点、实施方案这类多行文本完全够用。
项目申报表、中检表、结项表建议共用一套 id 和 project_id 关联设计,而不是各自独立建无关联的大宽表。比如 project_info 表保存项目名称、项目类型、负责人、指导老师、所属院系,project_declaration 表保存申报书的详细内容,midcheck 和 completion 表分别保存过程材料。这样一次申报对应一条 project_info,后续中检和结项都通过 project_id 找到这条记录,统计全校在研项目时也只需要 count project_info 表。
3. 核心模块拆解:一个项目从申报到结项的完整链路
3.1 登录认证与拦截器权限控制
登录模块看起来简单,实际上是整个系统的安全边界。常见做法是使用 Spring Boot 拦截器,在 WebMvcConfigurer 里注册一个 HandlerInterceptor,preHandle 方法中从 session 里取用户信息,取不到就重定向到登录页。这里要注意放行路径的配置,登录接口、静态资源图片、CSS、JS 必须排除在拦截范围之外,否则用户连登录页的背景图都加载不出来。
public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object user = request.getSession().getAttribute("loginUser"); if (user == null) { // 未登录统一跳转到登录页 response.sendRedirect(request.getContextPath() + "/login"); return false; } // 登录后把角色放进 request,方便 Controller 里做功能开关 request.setAttribute("role", ((User) user).getRole()); return true; } }加上 WebMvcConfigurer 后,拦截器只对 /admin/、/student/、/teacher/** 这类业务路径生效。这里有一个容易翻车的点:如果你把 /** 全部拦截,Spring Boot 默认的 favicon 请求也会被拦,浏览器会一直转圈,控制台一片空白,排查起来很玄学。我的习惯是把放行列表写成静态资源目录加登录接口,能少踩很多坑。角色判断不要只依赖前端隐藏按钮,后端在保存申报时还要校验当前登录用户的角色,否则用户直接构造 POST 请求就能绕过界面限制。
3.2 项目申报模块:学生提交、指导老师审核
项目申报是整条管理链路的起点。学生打开申报页面,选择项目类型,填写项目名称、成员、指导老师、申报书内容,提交后生成一条 status=1 的数据。此时指导老师登录个人中心,看到待审核列表,点击通过后状态变为 2,进入管理员审核环节。这个推进过程用 Service 层的一个方法就能完成。
@Service public class ProjectDeclarationService { @Autowired private ProjectDeclarationMapper declarationMapper; @Transactional(rollbackFor = Exception.class) public void submitDeclaration(ProjectDeclaration declaration) { // 首次提交:状态置 1,写入提交时间 if (declaration.getId() == null) { declaration.setStatus(1); declaration.setSubmitTime(new Date()); declarationMapper.insert(declaration); } else { // 被退回后再次提交:回到待审核状态 declaration.setStatus(1); declarationMapper.updateById(declaration); } } public void auditDeclaration(Long declarationId, Integer auditResult) { ProjectDeclaration record = declarationMapper.selectById(declarationId); if (auditResult == 2) { // 老师审核通过 record.setStatus(2); record.setAuditOpinion("同意立项"); } else { // 审核不通过,退给学生修改,学生端能看到退回意见 record.setStatus(0); record.setAuditOpinion("请补充实施方案后再提交"); } declarationMapper.updateById(record); } }submitDeclaration 中,id 为空代表第一次申报,id 不为空代表被退回后的重新提交,状态统一回到 1。auditDeclaration 是典型的审核逻辑,结果值用 2 表示通过、0 表示退回,而不是用布尔字段,因为后续管理员还会加一层审核,int 状态可以继续向后扩展。@Transactional 保证写入申报主表和更新状态这两个操作要么同时成功,要么一起回滚,防止出现项目记录写进去了但状态没更新的脏数据。
3.3 项目中检与结项管理:状态流转的实现
申报通过后,项目进入执行期,学生需要在指定时间提交中检材料,包括进度说明、阶段性成果、经费使用情况。这里的核心是状态流转:当前状态为 3(已立项)时允许提交中检;中检通过后变为 4;到结项阶段,学生上传结题报告、成果附件,老师审核后状态变为 5;管理员最终确认后变为 6,项目闭环。
public static final int STATUS_PROJECT_STARTED = 3; public static final int STATUS_MIDCHECK_PASSED = 4; public static final int STATUS_COMPLETION_PASSED = 5; public static final int STATUS_FINAL_APPROVED = 6; public void updateProjectStatus(Long projectId, int currentStatus, int targetStatus) { ProjectInfo project = projectInfoMapper.selectById(projectId); if (project.getStatus() != currentStatus) { throw new IllegalStateException("当前项目状态不允许此操作"); } project.setStatus(targetStatus); projectInfoMapper.updateById(project); }这段代码写得很克制,但恰好把状态机最常见的两个问题避开了。第一个问题是越级操作,比如项目还没中检就直接提交结项,所以方法入参带了 currentStatus 做前置校验,与数据库里的当前状态不一致就抛异常。第二个问题是并发提交,两个页面同时点击提交时,最后一次 update 可能覆盖前面的状态,因此工程落地时我一般会在 project_info 表加 version 字段做乐观锁,update 语句带上 where version = #{oldVersion},而不是只做读后写。
中检表和结项表本质上都是过程表,存的是各个节点上传的附件路径和审核意见,它们不需要复制项目的所有信息,只存 project_id、材料路径、意见、时间即可。列表页显示进度时,通过 join project_info 一次性查出项目标题、负责人、当前状态,比在 Java 里循环查询要快得多,这也是 MyBatis 写多表关联的常见价值点。
3.4 评审方案与专家评审:评分数据的入库逻辑
评审模块是这个系统的特色模块。院系管理员先创建评审方案,确定评审指标,比如创新点、前期准备、实施方案、预期成果、经费预算、成员素质,然后指定专家账号,专家登录后对待评审项目逐项打分。打分数据不是直接更新项目表,而是单独落一张 expert_review 表,保存方案 id、项目 id、专家 id、各项分数和总分。
<insert id="insertExpertReview" parameterType="map"> INSERT INTO expert_review ( plan_id, project_id, expert_id, innovation_score, preparation_score, implementation_score, result_score, total_score, create_time ) VALUES ( #{planId}, #{projectId}, #{expertId}, #{innovationScore}, #{preparationScore}, #{implementationScore}, #{resultScore}, #{innovationScore} + #{preparationScore} + #{implementationScore} + #{resultScore}, NOW() ) </insert>这里用 MySQL 的表达式直接把四项指标相加,避免应用层先算一遍再传值。参数 Map 传值比实体传值更灵活,但可读性差一些,项目里如果指标字段固定不变,我更建议写一个 ExpertReview 实体类,用 @Param 绑定业务含义清晰的参数名。总分计算放在 SQL 层还有一个好处,就是即便应用层漏传了 totalScore,数据库也会自动生成,不会留下 null。
专家评审的结果读出来后,页面展示的通常是统计图表,这个统计逻辑一般放在 Controller 层组装,返回给前端的是一个结构清晰的指标列表。这里要注意,评审结果表是按专家 ID 存的,同一位专家可能既评审项目 A 又评审项目 B,所以列表查询必须先按 project_id 分组,再用 AVG 聚合,否则 join 项目表时会出现行数翻倍的问题。多个项目踩到过这个“关联查询行数翻倍”,解决方案就是 group by project_id 后再 join,不要反过来先 join 再 group。
4. 本地跑通:环境准备、配置与启动
4.1 开发环境与项目目录结构
跑这个项目不需要太新的机器,JDK 1.8、Maven 3.6+、MySQL 5.7 或 8.0,再加一个 IDEA 或 Eclipse 就能启动。代码是标准的 Spring Boot 工程结构,包名一般以项目缩写为根,下面是 config、controller、service、mapper、entity、common 几个包。config 里放 WebMvc 配置和拦截器注册,controller 按学生端、老师端、管理员端分开,mapper 里是接口和 XML 文件。
src/main/java/com/dachuang ├── config # WebMvc 配置、拦截器注册 ├── controller # 学生、指导老师、院系管理员端口 ├── service # 业务层接口与实现 ├── mapper # MyBatis Mapper 接口 ├── entity # 实体类,对应数据库表 └── common # 常量、工具类、统一返回结果resource 目录下放着 application.yml、静态页面资源或 templates、mapper XML 目录。拿到资源后先不要急着启动,第一步是把整个目录导入 IDEA,选择 Maven 项目,等待依赖下载完成。如果网络不稳定导致依赖下载失败,可以去本地 Maven 仓库把 lastUpdated 后缀的文件清理掉再重新导入,这比反复点刷新有用得多。
4.2 MySQL 建库建表与数据初始化
源码包里一般会附带一个 dachuang.sql 或类似名称的数据库脚本,里面包含建库语句、建表语句和初始数据。先用命令行或 Navicat 执行脚本,再确认三张基础表的数据:user 表里应该初始化了学生、指导老师、院系管理员三个账号,review_plan 表可能有一条示例评审方案,大创资讯表有一条可展示的资讯记录。
mysql -uroot -p CREATE DATABASE IF NOT EXISTS dachuang DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE dachuang; SOURCE dachuang.sql;这里强烈建议手动指定 utf8mb4,尤其是 MySQL 8.0 环境。很多跑不起来的问题都出在数据库默认字符集是 latin1,导致后续中文乱码的排查非常痛苦。执行完脚本后,用 SHOW TABLES 看一眼表数量,再用 SELECT * FROM user; 验证账号数据是否存在,确认无误后再去改配置文件。
4.3 application.yml 配置与启动步骤
数据库脚本导入成功后,唯一必须改的就是 application.yml 里的连接信息。把 password 改成你本机 MySQL 的密码,如果你本机 MySQL 端口不是 3306,url 里的端口也要一起改。如果导入的库名不是 dachuang,记得同步修改 url 中的库名。改完后直接运行启动类,控制台出现 Tomcat started on port 8080 就说明启动成功。
mvn clean package -DskipTests java -jar target/dachuang-system-1.0.0.jar也可以直接用 IDEA 运行主类,开发阶段这种方式调试更顺手。启动成功后浏览器访问 http://localhost:8080/login,能打开登录页说明基础环境没有问题。登录页可以先用数据库里初始化的管理员账号试一遍,确认三条角色的菜单渲染都正常。如果页面样式缺失,多半是静态资源路径问题,后面避坑章节会专门讲。
4.4 页面路径与功能验证清单
系统登录后,建议按下面这张清单把主要链路走一遍,而不是随机点点点。走通一次完整流程,基本就能断定代码有没有被改坏。
| 验证步骤 | 操作路径 | 预期结果 |
|---|---|---|
| 学生注册登录 | 注册页面 | 注册后可以正常登录并进入学生端 |
| 项目申报 | 学生端菜单 | 提交后状态变为待审核 |
| 老师审核 | 指导老师端菜单 | 审核后状态推进到下一环节 |
| 管理员分配评审 | 院系管理员菜单 | 评审方案可以关联指定专家 |
| 专家打分 | 评审账号登录 | 打分保存后总分正确 |
验证过程中,重点看两个目前项目里容易出问题的地方:一是学生提交项目后,指导老师列表里能否立刻看到;二是专家评审打分后,院系管理员的统计页是否能汇总出平均分。这两条链路分别对应申报审核和评审入库,是系统最核心的业务闭环。
5. 避坑指南:启动报错、权限失效与数据库时区的 5 个常见问题
5.1 启动直接报错:端口被占用
现象:控制台打印 Port 8080 was already in use,应用启动后立刻退出。
原因:上一次运行未完全关闭,或者本地其他服务占了 8080 端口。
解决:先找到占用进程,杀掉后再启动。Linux 或 macOS 下用 lsof -i:8080 查看占用进程,Windows 下用 netstat -ano | findstr 8080 拿到 PID,然后 taskkill /PID 对应编号 /F。如果不想杀进程,也可以直接把 application.yml 里的 server.port 改成 8090,改动一处即可,不影响其他功能。
5.2 数据库连接失败:时区与驱动版本不匹配
现象:启动时报 Communications link failure 或 The server time zone value is unrecognized。
原因:新版 MySQL Connector/J 要求明确指定时区,旧版本驱动则不需要;如果驱动版本和 MySQL 版本差距太大,还会出现认证插件不兼容的问题。
解决:在 datasource.url 后追加 serverTimezone=Asia/Shanghai,并确保 driver-class-name 是 com.mysql.cj.jdbc.Driver。注意 Asia 和 Shanghai 之间不要拼错,拼错会直接报 unrecognized。如果项目用的还是 5.x 老驱动,建议升级到 8.x,因为新版驱动对 MySQL 8.0 的 caching_sha2_password 认证支持更好。
5.3 登录后页面跳转异常:拦截器放行路径配置错了
现象:登录成功后跳转主页,却一眨眼被弹回登录页;或者静态 CSS、JS 全部 404。
原因:拦截器把登录接口和静态资源也拦了,preHandle 里拿不到 session 中的 loginUser,于是强制重定向。
解决:检查 WebMvcConfigurer 里 addInterceptors 注册的路径,登录接口、注册接口、/static/、/js/、/css/、/images/都要 addPathPatterns 放行。判断拦截器是否生效,可以在 preHandle 里临时加一行日志,打印请求 URI,启动后一次就能看清哪个路径被误拦截。
5.4 中文乱码:三次传递出现编码不一致
现象:页面显示正常,但提交到数据库的中文变成问号,或者从数据库读出来乱码。
原因:页面编码、连接参数、数据库字符集三者没统一。常见组合是页面用了 UTF-8,连接 URL 少了 characterEncoding=utf8,数据库表却是 latin1。
解决:页面统一 UTF-8,连接 URL 加上 useUnicode=true&characterEncoding=utf8,建表时用 utf8mb4。项目里导出的 SQL 文件如果是旧的,建议执行前先检查表定义,把 CHARSET=latin1 改成 utf8mb4 再导入。修改后重启服务、重新提交一次数据,不要只在数据库端做转换,那治标不治本。
5.5 图片上传后无法显示:静态资源映射缺失
现象:项目申报时上传的图片保存成功,但在页面里 img 标签访问时返回 404。
原因:Spring Boot 默认只映射 classpath 下的静态目录,你上传到磁盘绝对路径的图片不在默认映射范围内。
解决:写一个 WebMvcConfigurer 的配置类,把本地磁盘目录映射到 /upload/** 访问路径。常见做法是 addResourceHandlers,设置 file:D:/dachuang/upload/ 这样的物理路径。注意路径末尾要加分隔符,否则映射会失效。这种问题只靠前台不好查,打开浏览器开发者工具看图片请求的响应状态码,404 基本就是映射没配。
6. 二次开发改造:从新增字段到扩展评审流程
6.1 新增“项目经费”字段的完整流程
如果想把经费预算从评审方案表挪到项目申报表,改造的最小闭环是:先在 project_declaration 表加字段 ALTER TABLE project_declaration ADD COLUMN budget decimal(10,2) DEFAULT NULL;,再在实体类里加上对应的 BigDecimal 属性,然后在 Mapper 的 XML 里新增一条 update 语句,最后把前端表单里的输入框 name 属性改成和实体字段一致。这条链路看着简单,但漏掉任何一环都会出问题:漏了 XML 字段,更新时静默失败;漏了前端 name,提交后拿不到值。
6.2 把单次评审改成多轮评审
目前评审方案是一次打分定结果,如果想改成初赛、复赛两轮,不需要改库,直接在 expert_review 表加一个 round 字段,默认 1。查询时 where plan_id = ? and round = 2 就能区分轮次。统计平均分时也要按 round 分组,否则初赛复赛分数会混在一起。这个改动的好处是不动主表结构,只加一个带默认值的字段,对已有数据零影响。
从那以后我每次接手这类 Spring Boot 管理项目,都会强制走一遍“先看表设计,再看状态流,最后写页面对接”的顺序,而不是拿到代码就跑。先花十分钟弄清楚每个状态数字代表什么、哪张表和哪张表是主外键关系,后面改功能、修 BUG 都会顺利很多。希望帮到你。
本文还有配套的精品资源,点击获取