资讯详情

SSM+JSP教务管理系统全解析:从JavaWeb基础到部署实践

📅 2026/10/2 22:33:28 | 华诺云谱 👁 阅读
SSM+JSP教务管理系统全解析:从JavaWeb基础到部署实践
1. 教务管理系统为什么还在用SSMJSP这套组合最近帮一个学弟把他毕设的javaweb项目从头到尾捋了一遍恰好就是一个基于javaweb和mysql的ssmmaven教务管理系统技术栈是javassmjsplayuiechartsmysql。捋完之后我最大的感受是这套组合虽然看着有点老派但作为课程设计、毕业设计乃至中小型学校内部教务管理场景来说它的价值被严重低估了。网上很多人一上来就劝你上Spring Boot但SSMJSP这套组合在校园里依然撑起了大量系统的后端。先说清楚这套组合各自扮演的角色。SSM指的是SpringSpringMVCMyBatis它们各管一段Spring负责管理Bean的生命周期和依赖注入SpringMVC负责控制层的请求分发和参数绑定MyBatis负责数据持久化层的SQL映射。JSP负责页面渲染Layui负责桌面前端UI组件ECharts负责图表可视化MySQL存数据Maven管依赖和构建。这整套流程跑起来之后你会发现它其实和Spring Boot在业务开发上的思维是一脉相承的只是配置手工了一些、封装少了一些。但恰恰是这份手工感让你更容易理解一个Web请求从浏览器到数据库再到响应页面中间到底发生了什么。对初学者来说这套系统跑通一遍的收获比直接用Spring Boot写几个CRUD接口要大得多。这篇内容适合这几类人看正在做毕业设计、课程设计技术选型需要SSM框架的学生接手了学校或者外包的JSP老项目需要快速上手维护的开发人员以及想补一补JavaWeb基础、搞明白SSM到底怎么协同工作的人。我会把搭建环境、核心模块设计、前后端交互、部署打包这些环节都过一遍把我实际跑这套系统时踩过的坑一并放进去。2. 动手前先把Maven和MySQL环境捋顺这步能省一半时间2.1 Maven到底是干嘛的以及settings.xml必须改的三处很多同学第一次接触Maven光看依赖管理和构建工具这两个词就蒙了。用人话解释Maven相当于你家装修时的建材供应商清单。以前你写JavaWeb项目要用某个jar包得自己去官网下载然后把jar包复制到WEB-INF/lib目录下麻烦不说版本冲突的时候更是欲哭无泪。用了Maven之后你只需要在pom.xml里声明我要用哪个库、什么版本Maven会自动帮你下载并管理依赖编译、测试、打包也全靠它一条命令搞定。我建议在动手写代码之前先把Maven的配置文件settings.xml改三个地方不改的话后面极大概率会卡住本地仓库路径。默认在C盘用户目录下的.m2文件夹时间长了会占好几个G建议改到其他盘。例如localRepositoryD:/maven-repository/localRepository配置阿里云镜像仓库。因为Maven中央仓库在国外下载依赖时经常慢到让人暴躁配置镜像之后速度会快很多mirror idaliyunmaven/id mirrorOfcentral/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror配置JDK编译版本。Maven默认用的编译等级可能跟你本机的不一致最好固定下来避免后面编译报错profile idjdk-1.8/id activation activeByDefaulttrue/activeByDefault jdk1.8/jdk /activation properties maven.compiler.source1.8/maven.compiler.source maven.compiler.target1.8/maven.compiler.target maven.compiler.compilerVersion1.8/maven.compiler.compilerVersion /properties /profile2.2 MySQL 8安装和连接驱动的那些坑数据库方面我遇到过的坑比Maven多。现在的机器上普遍安装的是MySQL 8.x但很多SSM项目的教程和依赖还是按MySQL 5.7写的。如果你装的是MySQL 8连接驱动类要从com.mysql.jdbc.Driver改成com.mysql.cj.jdbc.Driver同时连接URL里建议显式加上时区参数否则启动项目时会直接报SSL连接错误或者时间服务异常。我一般这么写jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/edu_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue jdbc.usernameroot jdbc.password你设置的密码注意allowPublicKeyRetrievaltrue这个参数MySQL 8自带的安全机制会要求在连接时获取公钥不加这个参数有时会报Public Key Retrieval is not allowed的错误。使用Navicat for MySQL工具连接数据库时如果报e0434352这类乱码错误通常就是字符集选错了连接页面的编码选utf8mb4基本都能解决。2.3 IDEA里启动带JSP的Web项目别选错运行方式用IDEA运行这种传统JSP项目很多人不知道怎么启动直接右键main方法就跑了结果发现页面全是404。正确的做法是先配置Tomcat把Artifact选成war包形式再点运行。这里有个关键点IDEA里要选择war exploded方式这是爆炸式部署它会直接把资源文件拷到Tomcat的临时目录里改JSP不用重新打包就能生效开发效率高很多。另外如果你的JSP页面里的静态资源类似layui的css、js文件全部加载不出来先检查访问路径里的项目上下文根路径。在IDEA的Tomcat配置里有个Application context参数如果你填的是/edu那静态资源访问路径就必须写成/edu/layui/css/layui.css这种JSP页面里也要统一加上${pageContext.request.contextPath}前缀。这个细节能挡掉一大半新手求助帖。2.4 建库建表要按业务来不是随便敲几行SQL教务管理系统的数据库表设计以我实现的这个为例核心是这几张表管理员表、学生表、教师表、课程表、选课表、成绩表还有存储学生课表的关联表。各表之间用外键字段关联比如选课表里的studentId关联学生表的主键courseId关联课程表主键。建表时有个经验所有主键统一用自增id不搞复杂的复合主键后面MyBatis分页和关联查询会轻松很多。字符集统一设置成utf8mb4别用utf8否则遇到生僻字和emoji表情会直接乱码。字段名尽量用下划线风格比如student_name、course_credit因为MyBatis的驼峰转换很好用配置一行mapUnderscoreToCamelCasetrue就能把student_name自动映射成studentName。3. 核心功能模块拆解教务系统到底在管什么3.1 功能清单从登录到选课到成绩统计一条链路串起来一个能拿去演示的教务管理系统功能面通常覆盖这几个大块登录认证分角色登录管理员、教师、学生进入不同首页学生管理管理员维护学生信息支持增删改查、按班级和学号搜索课程管理维护课程库设定学分、学时、授课教师选课管理学生在线选课管理员可以做调课和退课操作成绩录入与查询教师录入成绩学生查看成绩管理员做全局查看数据统计用ECharts展示各院系人数分布、课程选课热度、成绩分数段统计这几个模块串起来之后一个日常的教务流程就清晰了管理员建课程、维护学生信息学生登录选课教师登录录入成绩学生在页面上看到成绩和学分。每一条数据从录入到展示背后都是SSM里一次完整的请求-服务-持久化调用。3.2 SSM分层代码结构包名怎么组织才不腻歪我用这套系统时工程包结构是按照标准的三层架构来组织的com.edu.system ├── controller (控制层) ├── service (业务层) ├── dao (数据访问层) ├── entity (实体类) ├── interceptor (拦截器) ├── utils (工具类) └── vo (视图对象)控制层只做参数接收和结果返回不写业务逻辑。业务层处理核心逻辑比如选课时要校验课程容量是否已满、学生是否已经选过这门课数据访问层只做SQL操作。这个职责划分看起来很基础但执行到位之后系统的可维护性直线上升。我之前见过不少项目的Controller里堆了1000多行代码连查询SQL都写在Controller里后面改需求的时候基本是牵一发动全身。3.3 登录到展示成绩的完整请求链路举个例子学生登录之后查看自己成绩。请求会走这样一条链路浏览器发起请求/grade/list携带参数studentIdSpringMVC的前端控制器DispatcherServlet拦截到请求通过HandlerMapping找到对应的GradeControllerGradeController接收参数调用GradeService的listByStudent方法GradeService调用GradeDao查询数据GradeDao的Mapper接口执行XML里的SQL语句返回List数据逐层返回Controller把结果放到Model里在JSP里用JSTL循环展示或者用Layui的表格组件填充前端数据能把这个链路讲清楚面试或者答辩时基本就稳了。SSM之所以被称为SSM就是因为它把每一个环节都显式化你能看到每一层次的存在这也是我建议学生党用这套框架的原因——它能帮你建立完整的Web开发认知模型。3.4 权限拦截为什么必须加而经常被忽略教务管理系统有三个角色如果不加权限控制学生登录后直接访问/teacher/grade/add就能录成绩系统的安全性等于零。我在实现里用SpringMVC的Interceptor做了一个简单的登录拦截和角色校验public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); Object user session.getAttribute(loginUser); if (user null) { response.sendRedirect(/login.jsp); return false; } return true; } }然后在SpringMVC配置文件里注册拦截路径比如拦截所有/manager/**、/teacher/**、/student/**的请求放行/login、静态资源等路径。这块如果不写答辩时老师随便一测就能找出问题。4. JSPLayui做页面这几处细节值得认真对待4.1 Layui在JSP里的引入姿势Layui是一个很经典的国产前端UI框架它的历史比很多同学的学龄还长但在传统JavaWeb项目里的地位依然稳固。它自带表格、表单、弹窗、分页这些后台管理最常用的组件依赖简单引入一个layui.css和一个layui.js就能跑起来不像现在很多前端框架还要搞Node环境、编译打包这在JSP项目的场景里简直是降维打击。在JSP中引入Layui我建议用本地化引入不要去引CDN因为内网演示环境可能没有外网CDN挂了页面直接裸奔。下载好Layui的压缩包之后解压到webapp目录下的static文件夹里然后在JSP的head区域写link relstylesheet href${pageContext.request.contextPath}/static/layui/css/layui.css script src${pageContext.request.contextPath}/static/layui/layui.js/script还有一个细节值得注意JSP页面在第一次加载完如果发现Layui表格或者数据渲染偶尔不刷新很多人会想到加载完后刷新一次。其实那是不必要的问题通常出在项目里同时引了多个版本的jQuery或者layui.use在模块加载完成之前就执行了渲染。正确的做法是在页面底部执行layui.use([table, form, layer], function () { var table layui.table; var form layui.form; // 在这里完成表格渲染和数据填充 });Layui的模块化加载机制和jQuery的document ready不是一个套路把数据初始化放在use的回调里面才是规范写法。4.2 ECharts做统计图表数据怎么从后端取教务管理系统里最有视觉冲击力的是首页的数据统计面板一般会用ECharts画几个图表——各院系人数占比、课程选课人数排行、成绩分布柱状图。如果你是用Layui表格做数据展示ECharts做图表配合起来效果完全够用。ECharts在前端的使用很简单一个是引入echarts.js文件一个是在页面准备一个固定高度的div容器然后初始化图表。但关键问题在于后端数据怎么给到前端。我这里推荐一个实操中比较稳妥的做法后端提供一个返回JSON数据的Controller方法前端在页面加载时用jQuery的ajax去拉取数据再用ECharts的setOption填充图表。比如人员统计后端返回这样的JSON{ code: 0, msg: , data: [ {name: 计算机学院, value: 320}, {name: 外国语学院, value: 180}, {name: 经管学院, value: 260} ] }前端代码类似这样$.ajax({ url: /manager/chartData, type: GET, dataType: json, success: function (res) { var chart echarts.init(document.getElementById(majorPie)); chart.setOption({ tooltip: {trigger: item}, series: [{ name: 学生人数, type: pie, radius: 60%, data: res.data }] }); } });ECharts的setOption支持数据动态更新所以不需要刷新页面。这也是为什么我建议在JSP页面中尽量把图表初始化和数据加载分离这样后端数据一变前端图表跟着变演示的时候效果非常直观。4.3 JSP里EL表达式和JSTL的典型应用JSP页面里避免直接写大量Java脚本片断就是那种% %不然页面会极度混乱统称为面条代码。我现在习惯的做法是Controller把数据放在Model里页面通过EL表达式和JSTL标签输出。举几个典型的例子%-- 输出登录用户的姓名 --% 欢迎${sessionScope.loginUser.realName} %-- 循环输出学生列表 --% c:forEach varstudent items${studentList} tr td${student.studentNo}/td td${student.studentName}/td td${student.className}/td /tr /c:forEach这是我个人的经验——EL表达式加JSTL已经能满足绝大部分展示需求而且页面代码的可读性比Java脚本片断高很多排错也方便。遇到需要格式化日期之类的需求用fmt标签就好。5. MyBatis映射文件里那些低级的错一个比一个能坑人5.1 参数传递别把map写成mapzMyBatis的Mapper接口和XML之间的参数传递是SSM项目里报错频率最高的区域没有之一。常见的错误类型有这些参数类型不匹配接口方法签名是ListStudent selectByClass(String className)XML里写的parameterType是另一个类型启动时或调用时报绑定错误。XML里取不到参数值单参数时用#{paramName}但方法签名里没有用Param(paramName)注解导致参数名找不到。解决办法是统一加 Param 注解。返回类型不匹配查询返回多条数据接口里却写成了单个对象。SQL里用了MySQL关键字没转义比如order、desc、condition这类单词做字段名执行时直接报错。我在这个教务系统里写选课记录插入时就撞见过desc字段导致SQL执行失败的问题。处理方式很简单写SQL时用反引号把字段名包起来INSERT INTO select_course (student_id, course_id, create_time, desc) VALUES (#{studentId}, #{courseId}, #{createTime}, #{desc})当然更好的做法是在设计表结构时直接避开这些关键字但如果接手的老表改不了反引号就是你的救命稻草。5.2 一对多关联查询resultMap该怎么配成绩查询页面通常要展示课程名、学分、任课教师这些跨表信息这涉及MyBatis的关联查询。刚开始学MyBatis的人容易直接在SQL里join然后把结果塞到一个大DTO类里这样是完全可行的但更贴合MyBatis风格的写法是定义ResultMap做自动映射。我的习惯是用一个VO类承接页面需要的字段比如GradeVO里面同时放课程信息和成绩数据SQL直接关联多张表返回VO的List。这样做的好处是代码清晰前端拿数据时不用一层层剥对象。MyBatis的驼峰自动映射配置别忘了加不然你查出来的student_name字段是不认studentName属性的mybatis: configuration: map-underscore-to-camel-case: true5.3 分页查询手写limit还是用PageHelper教务管理系统里学生列表、课程列表都需要分页展示。我建议直接引入PageHelper这个分页插件它做的事情非常简单在你执行的SQL后面自动追加limit语句前提是调用PageHelper.startPage之后紧跟一条查询。PageHelper.startPage(pageNum, pageSize); ListStudent list studentDao.selectStudentList(); PageInfoStudent pageInfo new PageInfo(list);PageInfo里已经封装好了总条数、总页数、当前页等等常用信息前端Layui表格直接对接这些字段就行。有一点要留心PageHelper只对紧接着的下一条查询SQL生效所以startPage之后不能有其它操作介入否则分页效果就乱了。6. 打包部署从IDEA到Tomcat再上线6.1 传统JSP项目怎么打war包Maven命令背下来传统JavaWeb项目的部署产物是war包。Maven里打包命令很简单mvn clean install或者跳过测试尽快打包mvn clean install -DskipTests命令执行完后在target目录下会生成一个war文件。之后把这个war扔到Tomcat的webapps目录下启动Tomcatwar包就会被自动解压部署。这里有个细节部署后的访问路径默认是war包的文件名比如edu-management.war访问URL就是http://localhost:8080/edu-management/login.jsp。如果不想带这个路径可以把war包改名成ROOT.war这样直接通过根路径访问。6.2 Maven里依赖scope配错导致的问题JSP项目里servlet-api和jsp-api这两个依赖scope必须配成provided意思是编译时需要运行时不打包进去因为Tomcat自身已经带了这些类。如果配成默认的compile打出来的war包会把这些jar也塞进去运行时常常版本冲突轻则启动警告重则ClassNotFoundException。这一点很多人踩了坑还不明所以。6.3 Tomcat版本和JDK版本匹配这个坑必须写清楚另一个让人崩溃的坑是IDEA里配置Tomcat时Tomcat版本和JDK版本不匹配。比如Tomcat 10.1要求JDK 11及以上如果你用的是JDK 8就老老实实选Tomcat 9或者Tomcat 8.5。启动时如果报UnsupportedClassVersionError就是版本不匹配了。反之如果你用JDK 11去跑Tomcat 8也会出幺蛾子。这个问题在环境配置的初期就会爆发所以先把Tomcat版本和JDK版本对应关系摆清楚可以省一整个下午的排查时间。7. 项目写完之后我还推荐你做这几件事系统跑通功能演示完答辩过了是不是就完事了我的建议是如果你时间还充裕可以参考这几个方向做进一步优化无论是写在简历里还是作为面试谈资都能加分不少。第一把密码从明文存储改成MD5加盐哈希或者用Spring Security做更完善的认证授权。很多教务系统项目直接明文存密码这是最容易被安全方向面试官抓到的点。第二给核心表加上创建时间和更新时间字段用MyBatis的自动填充功能维护形成一套完整的数据审计链路。第三在数据统计模块增加更多维度的图表比如教师工作量统计、课程通过率趋势图把ECharts的威力发挥出来。第四把项目部署到云服务器上配上数据库远程访问让评委或面试官能在手机浏览器里直接访问你的系统这个演示效果比笔记本电脑里的截图好太多。按照我个人的实际操作体会这套SSM教务管理系统最大的价值不在于功能本身有多复杂而在于它用最直接的方式把JavaWeb开发的全链路串联了起来。你通过它弄清楚了Spring容器是怎么回事、SpringMVC的请求流程长什么样、MyBatis的SQL映射到底做了什么之后再回头看Spring Boot会发现很多概念都是相通的只是配置变少了封装变厚了但底层思维还是那一套。这也是为什么我始终建议走JavaWeb这条路的新人不要急着跳进Spring Boot的舒适区先用SSM做一次完整的项目把地基打扎实后面无论接触什么新框架都能做到心里有数。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑