SSM智慧校园管理系统实战:从框架整合到毕设答辩全攻略
2026/9/8 0:31:17 网站建设 项目流程

每年到了毕业设计季,Java Web方向被问到最多的题目之一,就是“基于SSM的智慧校园管理系统”。这个题目我太熟了——从自己当年做毕设开始,到后来帮学弟学妹改代码、给培训班学生讲框架整合,前前后后经手的同类型项目不下几十套。市面上标着35494这种编号的源码包更是满天飞,一份源码挂到不同平台换个封面又是一套新项目。

但说句实在话,真正能把这套系统讲明白、能应对答辩追问、能在源码基础上做出自己东西的人,比例并不高。原因也很简单:SSM这个组合虽然经典,但整合过程涉及Spring、Spring MVC、MyBatis三个框架的协同,配置又多又碎,任何一个环节没对上,项目就起不来。等你三天三夜把环境跑通,论文和答辩又成了新一轮头秃。

所以这篇文章我就拿“SSM智慧校园管理系统”这个题目当例子,从选题思路、数据库设计、框架整合到核心模块实现、常见坑排查,完整拆一遍。不管你是正在写这篇毕设,还是买了源码想要读懂改造,这篇文章都值得你花十分钟看完。

1. 为什么SSM智慧校园管理系统每年都是毕设“人气王”

1.1 业务场景站得住脚,需求边界清晰

先说实话,毕设选题最怕什么?最怕题目听起来高大上,结果一动手发现需求模糊、边界不清,糊了两个星期还不知道第一步该建什么表。智慧校园管理系统就完全不存在这个问题。

校园管理本身是一个非常成熟、非常具象的业务场景。你要处理的实体就是学生、教师、课程、成绩、宿舍、公告这些学校里明摆着的东西。每个实体的属性是什么、彼此之间什么关系,哪怕不写需求文档,任何一个上过大学的人都能帮你列出一二三四。这就意味着你根本不需要花大量时间去做需求调研,可以直接把精力放在代码实现和系统设计上。

更关键的是,这个场景天然适合展示“管理信息系统”的价值。一个学校可能有几千名学生、几百门课程、若干栋宿舍楼,人工管理会出现信息不同步、查询效率低、数据易出错等问题,而系统化管理刚好能一一化解。答辩的时候老师问到“你这个系统解决了什么问题”,你随便举几个场景就能答得很充实。

1.2 SSM技术栈的价值与选型思考

SSM指的是Spring、Spring MVC、MyBatis这三个框架的组合。在Spring Boot已经大行其道的今天,为什么还要用SSM做项目?这里面有实际原因,也有教学层面的考量。

从实际原因看,很多高校的Java课程体系里,SSM仍然是必修内容。教材、实验课、期末项目都以SSM为主,学生对这个组合的熟悉度天然更高。答辩时老师也普遍熟悉SSM,源码拿出来能讲清楚的地方更多,不会像某些冷门框架那样一问一个不吱声。

从技术学习的角度看,SSM其实比Spring Boot更能体现框架整合的原理。Spring Boot的自动配置确实方便,但“方便”的背后是把很多细节藏起来了。而SSM要求你手动去配数据源、配事务、配MyBatis的SqlSessionFactory,每一条配置你都要自己写出来,这反而逼着你把Spring的IoC和AOP原理、MyBatis的映射机制真正搞懂。所以很多老师是故意让学生用SSM做毕设的,为的就是看你能不能把J2EE这条完整链路走通。

当然,如果你们学校明确允许用Spring Boot,那你也可以把SSM快速跑通之后,在论文里写一段“基于SSM的设计思想,可平滑迁移到Spring Boot”,这样既蹭了SSM的经典,又显得你视野开阔。但核心交付物一定还是SSM,别给自己找额外麻烦。

1.3 功能模块拆解:做多少模块最合适

很多同学一上来就想把系统做大:在线课程、图书借阅、一卡通消费、人脸识别门禁……恨不得把整个数字化校园都塞进去。这个想法很危险。毕设是有时间极限的,模块越多,每个模块的完成度就越低,出了问题排查起来也越困难。

我给你的建议是控制在6到8个核心模块之间,覆盖三类角色即可。

  • 管理员端:用户管理、院系/班级管理、课程管理、公告管理、数据统计
  • 教师端:课程查看、学生选课名单、成绩录入与修改
  • 学生端:个人信息维护、选课/退课、成绩查询、公告查看

这个模块划分的好处在于:每类角色都有独立的操作视图,但底层数据是打通的,体现出系统的一体性。比如管理员维护好的课程数据,教师能在自己的界面看到,学生能据此选课,选完课教师才能录成绩,录完成绩学生才能查分——整个业务闭环非常流畅,答辩时顺着这条链路讲一遍,逻辑清清楚楚。

模块数量宁少勿多,但每个模块要做到“读、增、删、改、查”齐全,有条件再加一个统计图标,整体完整度就很高了。

2. 系统设计与数据库建模的核心细节

2.1 权限模型:三类角色的登录设计

智慧校园系统的用户可以分为管理员、教师、学生三类。业务上他们各看各的界面、各干各的活,但存储上如果给每一类角色单独建一张用户表,那登录验证就得写三遍,后期的扩展和维护都很难受。

更合理的做法是采用经典的RBAC模型,也就是“用户-角色-权限”的分层设计。在毕设这个量级,不一定要做到权限表、角色菜单表的全量配置,但至少要保证“用户表 + 用户类型字段”的结构。也就是说,一张统一的用户表存登录账号和密码,用role字段区分类型,再按角色分别关联到学生表或教师表获取业务信息。

这样登录时只需要查一次用户表,拿到role之后走对应的业务逻辑即可。认证通过后把用户信息放进session,后续请求通过拦截器判断角色是否允许访问某个URL。

密码存储这块,虽然很多老教程还在用MD5加密,但更稳妥的做法是MD5加盐或BCrypt。如果项目已经用了MD5也没关系,答辩时能说清楚“为什么加盐”“盐存在哪里”就行。不要用明文密码,这是基本的职业素养问题。

2.2 核心数据表结构设计

数据库设计是整个系统的地基,表建不好后面全是坑。我把最核心的几张表结构理出来,你可以直接参考着建。

用户表是最基础的表,凡是能登录系统的都进这张表。我一般这样设计:

字段名类型说明
idint / bigint主键自增
usernamevarchar(32)登录用户名,唯一
passwordvarchar(64)加密后的密码
rolevarchar(20)admin / teacher / student
statustinyint是否启用
create_timedatetime创建时间

学生表用来存学生的业务信息,与用户表通过user_id关联:

字段名类型说明
idint主键
user_idint关联用户表
student_novarchar(20)学号,唯一
namevarchar(20)姓名
gendervarchar(4)性别
class_namevarchar(50)班级
majorvarchar(50)专业
phonevarchar(11)联系方式
dormitoryvarchar(50)宿舍信息

课程表和选课表是系统里关系最复杂的部分。课程表存基础的课程信息,选课表作为关联表,同时承担存储成绩的功能。也就是说成绩字段不单独建表,而是放在选课记录里,一门课一个学生对应一条选课记录,成绩字段可空,教师录完分之后才有值。

这种设计在答辩时非常加分,因为你能准确说出“选课表是课程表和学生表之间的桥梁表”,说明你是真正理解多对多关系如何处理的人。

2.3 表关系与字段设计的三个实用原则

第一个原则是能用逻辑外键就不用物理外键。很多教材里强调要建外键约束,但在实际开发中,尤其是MyBatis这种半自动框架的项目里,物理外键会严重影响插入和删除的效率,维护起来也麻烦。更常见的做法是在Java代码层面维护关联关系,数据库表之间靠逻辑上的字段对应即可。答辩问起来就说“为了性能和灵活性,采用逻辑外键设计”,这个理由站得住脚。

第二个原则是删除操作优先用逻辑删除。很多毕设系统是直接DELETE物理删数据,但真实业务系统里,学生误删了要恢复、管理员要看历史记录,物理删除都做不到。建议每张业务表都加一个deleted字段,默认0,删除时改成1,查询时统一过滤deleted=0。这个细节虽然小,但能体现你的工程意识。

第三个原则是时间字段统一用datetime类型,不要图省事用varchar存字符串。很多人为了导入方便把时间存成“2024-05-01 10:30:00”这种文本,结果后面要按时间排序、统计月度数据的时候才发现字符串排序不是按时间顺序来的,苦不堪言。datetime类型配合Java的LocalDateTime,整体处理更优雅。

3. SSM框架整合实操:从零搭一套能跑的环境

3.1 开发环境与版本组合

SSM项目虽然配置繁琐,但版本选对了能少踩一半的坑。我强烈推荐以下组合,这套组合我实测过无数次,稳定性和兼容性都很好:

  • JDK 1.8:虽然JDK 17已经出来很久了,但SSM项目在JDK 8下运行最稳定,而且网上资料最多
  • Maven 3.6.3:负责依赖管理和项目构建
  • Tomcat 8.5:对应Servlet 3.1规范,兼容性很好
  • MySQL 5.7或8.0:两者都可以,注意8.0需要配置时区参数
  • IDEA:开发工具,社区版也能用
  • Spring 5.3.x:别用太老的4.x版本了,跟现代JDK的兼容性不好

如果对你手里拿到的源码不确定版本,最简单的方式是直接看pom.xml里的依赖版本号。如果pom里写的是老版本依赖,比如Spring 4.3,你也别急着升级,版本升级牵连的配置改动比较大,先保证项目能跑,再考虑技术更新。

3.2 三大配置文件逐项拆解

SSM整合的难点和重点全在配置文件里。我把关键配置抽出来逐一讲解。

首先是你最核心的web.xml。这个文件配置了Spring的启动监听器和Spring MVC的前端控制器。有一个非常经典的坑:很多人配了ContextLoaderListener,但忘了让它加载Spring的配置文件;或者配了DispatcherServlet,但它的init-param路径写错,导致Spring容器启动时报找不到Bean。

<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>

注意这里DispatcherServlet映射的是/,意味着所有请求都会经过Spring MVC处理。这也是为什么后面必须配置静态资源放行的原因,否则CSS、JS、图片全部404。

然后是spring-mvc.xml。这里要开启注解驱动、配置组件扫描和视图解析器:

<context:component-scan base-package="com.example.controller" /> <mvc:annotation-driven /> <mvc:resources location="/static/" mapping="/static/**" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean>

视图解析器这块如果你用的是JSP,prefix指向WEB-INF下的jsp目录,这样页面不会被直接URL访问到,安全性好。如果你用的是Thymeleaf,配置方式会不同,但结构逻辑一致。

最后是spring-mybatis.xml,这里配置数据源、SqlSessionFactory和MyBatis的Mapper扫描。这是SSM整合里最容易出错的一环。关键是mapperLocations要指向你的XML文件路径,别写错了:

<context:property-placeholder location="classpath:jdbc.properties" /> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:mybatis-config.xml" /> <property name="mapperLocations" value="classpath:mapper/*.xml" /> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.example.mapper" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean>

3.3 分页、事务、拦截器这些“标配”怎么配

分页用PageHelper最省心。在spring-mybatis.xml里加一个PageHelper插件,配置一下方言就行:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> ... <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <value> helperDialect=mysql reasonable=true </value> </property> </bean> </array> </property> </bean>

实际使用的时候,在Service层查询前调用PageHelper.startPage(pageNum, pageSize),紧接着的第一次查询就会自动分页,然后用PageInfo包一层,分页信息全有了。这个工具的用法属于写一次就能记住的类型,非常方便。

事务方面建议统一使用Spring的注解式事务。在spring-mybatis.xml里加上一行<tx:annotation-driven transaction-manager="transactionManager" />,然后配置好DataSourceTransactionManager,之后在Service实现类或方法上标@Transactional即可。注意事务要放在Service层,不要放在Controller层,原因很简单:Controller是跟页面交互的,Service才是真正处理业务逻辑的地方,事务的边界应该在业务逻辑的边界上。

拦截器用来做登录认证和权限控制,配置在spring-mvc.xml里:

<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**" /> <mvc:exclude-mapping path="/login" /> <mvc:exclude-mapping path="/doLogin" /> <mvc:exclude-mapping path="/static/**" /> <bean class="com.example.interceptor.LoginInterceptor" /> </mvc:interceptor> </mvc:interceptors>

这个配置意味着除了登录请求和静态资源,其他所有请求都会先经过LoginInterceptor去判断session里有没有用户信息。

4. 核心功能模块的实现拆解

4.1 登录认证与权限拦截的实现

登录逻辑本身不难:接收用户名和密码,查询用户表,比对密码,成功后写session,跳转到对应角色的首页。真正需要花心思的是密码比对和权限控制。

密码比对我建议用MD5加盐的方式。盐可以取用户名,也可以用固定的内部字符串。简单实现就是在注册或创建用户时,把密码和目标盐拼起来再做MD5:

public static String md5WithSalt(String password, String salt) { String base = password + salt; return DigestUtils.md5Hex(base); }

登录时数据库字典里存的已经是加密后的结果,直接把输入的密码用同样的方式加密再比较即可。千万不要在代码里写字符串拼接SQL去查密码,那是最初级的注入漏洞。

权限拦截是在LoginInterceptor的preHandle方法里完成的。从session里拿当前用户角色,再判断当前请求路径是否包含该角色的专属前缀,比如/admin/**只允许管理员访问,/teacher/**只允许教师访问,/student/**只允许学生访问。如果角色不匹配,跳转到403页面或者提示无权限。这个设计最好写成可配置的,后面想增加角色时会省事很多。

4.2 学生信息管理:一套标准CRUD背后的代码

学生信息管理是整个系统最典型的功能模块,掌握了它,其他模块的CRUD照葫芦画瓢就行。Controller层接收页面请求,Service层处理业务逻辑,Mapper层跟数据库打交道。以查询学生列表为例,整个链路的代码是这样的。

Controller层:

@RequestMapping("/list") public String list(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize, String keyword, Model model) { PageInfo<StudentVO> pageInfo = studentService.findStudents(pageNum, pageSize, keyword); model.addAttribute("pageInfo", pageInfo); model.addAttribute("keyword", keyword); return "admin/student-list"; }

Service层:

public PageInfo<StudentVO> findStudents(Integer pageNum, Integer pageSize, String keyword) { PageHelper.startPage(pageNum, pageSize); List<StudentVO> list = studentMapper.selectStudentList(keyword); return new PageInfo<>(list); }

Mapper层就是一个接口加一个XML文件,数据库查询用动态SQL处理,关键词为空时查全部,不为空时按学号模糊查询:

<select id="selectStudentList" resultType="com.example.entity.vo.StudentVO"> SELECT s.*, u.username, u.create_time AS accountCreateTime FROM student s LEFT JOIN sys_user u ON s.user_id = u.id <where> <if test="keyword != null and keyword != ''"> AND (s.student_no LIKE CONCAT('%', #{keyword}, '%') OR s.name LIKE CONCAT('%', #{keyword}, '%')) </if> AND s.deleted = 0 </where> ORDER BY s.id DESC </select>

新增和修改的逻辑也很常规,唯一要注意的是新增学生时,不能只往学生表里插数据,还必须同时在用户表里创建一个对应的登录账号。这涉及跨表操作,必须放在同一个事务里。这种细节答辩时很加分,因为你体现了“系统设计要考虑数据完整性”的意识。

4.3 成绩统计图表怎么从数据库到前端

很多毕设系统做了成绩查询功能,但成绩统计图不是必须有,有了的话整个系统的档次会直接提升一个级别。实现思路也不复杂:后端按班级或课程分组,统计各分数段人数,返回给前端,前端用图库渲染。

后端统计的逻辑可以写一条SQL分组查询,比如按分数段统计:

SELECT SUM(CASE WHEN score >= 90 THEN 1 ELSE 0 END) AS excellent, SUM(CASE WHEN score >= 80 AND score < 90 THEN 1 ELSE 0 END) AS good, SUM(CASE WHEN score >= 60 AND score < 80 THEN 1 ELSE 0 END) AS pass, SUM(CASE WHEN score < 60 THEN 1 ELSE 0 END) AS fail FROM student_course WHERE course_id = #{courseId}

前端用ECharts画饼图或柱状图,通过Ajax获取后端接口返回的统计数据,配置一个option再setOption就能出图。我在实际项目里推荐用CND方式引入ECharts,避免自己下载文件放静态目录出错。

这里有一个很容易踩的坑:SSM项目里Controller返回JSON数据,要保证返回的数据格式是合法的JSON字符串。最稳妥的方式是在方法上加@ResponseBody,并配置好Jackson或Fastjson的消息转换器。如果返回的是Map或自定义对象,Jackson会自动转成JSON,但如果返回的是带有日期类型的字段,可能会出现序列化异常,需要加@JsonFormat注解处理。

5. 常见坑与调试实录

5.1 框架整合期最容易翻车的几个点

我自己带人做项目的时候,发现大家90%的时间都耗在项目启动阶段的报错上,真正写业务逻辑反而没那么多问题。这里整理几个出现频率最高的错误,看完能省你好几天时间。

第一个是Spring容器没扫描到Service或Mapper,启动时报NoSuchBeanDefinitionException。这个错误的本质是<context:component-scan>的base-package写错了,或者没有覆盖到Service所在的包。检查方法很简单:打开项目结构,确认包名拼写完全一致,包括大小写。

第二个是MyBatis的BindingException,提示Invalid bound statement (not found)。这个说的是Mapper接口和Mapper XML文件没有正确绑定。排查顺序:看XML文件是否在mapperLocations指定的目录下,看XML里的namespace是否和接口全限定名一致,看每个select/insert标签的id是否和接口方法名一致。这三个地方任何一个对不上,都会报这个错误。

第三个是Tomcat一启动就报ClassNotFoundException或NoClassDefFoundError。这个通常是依赖没有完整导入,或者Maven依赖下载不完整。解决办法是右键项目Maven选项里执行clean,然后选择Reimport,再重启Tomcat。如果还不行,去本地Maven仓库把对应依赖文件夹删掉,重新下载。

5.2 中文乱码与JSON日期格式

中文乱码说大不大,说小不小,处理起来却总让人头大。SSM项目乱码通常出现在三个地方:请求参数乱码、JSON响应乱码、数据库存储乱码。

请求参数乱码最直接的解决办法是在web.xml里配置编码过滤器,让请求和响应都统一使用UTF-8:

<filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

数据库乱码的排查方向是连接URL和表结构。MySQL连接URL里要带上characterEncoding=utf8参数,表的字符集要设置成utf8mb4,否则存emoji类型的数据会报错。注意utf8mb4是utf8的超集,推荐直接用utf8mb4。

JSON日期格式在SSM里是个老问题。默认情况下Jackson序列化Date类型,会输出一串毫秒数,你明明存的是“2024-05-01”,前端接口返回的却是“1714525200000”。解决方法是在日期字段上加注解:

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime;

或者全局配置ObjectMapper。不建议在数据库里用varchar存日期来规避这个问题,那样只是把麻烦从后端转移到了后续统计查询上。

5.3 Maven依赖版本适配清单

SSM项目里,依赖版本不用心控,真的会一个兼容性问题折腾人。我把实测稳定的一份核心依赖清单放在下面,拿走就能用。

  • Spring 5.3.x
  • MyBatis 3.5.x
  • mybatis-spring 2.0.x
  • MySQL Connector 8.0.x
  • Druid 1.2.x
  • Jackson 2.12.x
  • PageHelper 5.3.x
  • javax.servlet-api 4.0.x(provided作用域)
  • JSTL 1.2

特别提醒两个组合:Spring 5.x对应JDK 8+,MyBatis 3.5.x对应JDK 8+,你要是JDK版本低了,运行时容易出UnsupportedClassVersionError;另外MySQL 8.0的连接驱动,URL里必须加serverTimezone=Asia/Shanghai,否则连接数据库直接报错。

依赖下载慢的问题,建议在Maven的settings.xml里配置阿里云镜像。这个属于基础操作,但能极大提升幸福感,你也不想每次clean之后等十几分钟下载依赖吧?

6. 拿到“赠源码”后别急着交,先做这几步

6.1 先跑通,再读代码

我知道很多人买源码就是为了省事,但“省事”不等于“拿到手直接交”。直接交源码的同学,大概率会在答辩时被老师一个问题问崩:“请说一下你这个系统的登录是如何实现的?”你如果支支吾吾答不上来,老师基本上可以断定这代码不是你写的,论文写得再漂亮也没用。

正确姿势是先按我前面说的步骤,把源码跑起来。跑起来之后不要急着改功能,先从数据库脚本开始看,理清表结构,再按“Controller → Service → Mapper → XML”这条链路,挑一两个核心功能完整读一遍,弄明白一个用户从登录到操作业务再到数据落库的完整路径。

读代码的时候用IDEA的全局搜索功能,找到关键词比如“login”“selectByUsername”,顺藤摸瓜,比从头到尾一个文件一个文件看效率高得多。

6.2 二次开发的四个方向

当你把源码读通之后,建议做一点二次开发,让这个项目看起来“是我的作品”而不是“我买的作品”。二次开发的方向很多,我推荐几个性价比高且容易实现的。

第一个方向是新增一个模块。比如原系统没有课程评价功能,你可以在课程管理模块上扩展一个“课程评价”,学生选完课可以给课程打分并填写评语。这个模块涉及一张新表、一套增删改查,跟现有模块的关联也不复杂,属于工作量适中、答辩有亮点的改造。

第二个方向是优化前端样式。很多源码的前端界面还停留在几年前的风格,内容虽然没问题,但一眼看过去就很老旧。你可以把管理员首页改成左右布局,左侧菜单用基于Layui或Bootstrap的样式重做,这种改造只要CSS水平过关,效果立竿见影。

第三个方向是增加信息导入导出功能。用POI把学生信息模板下载、批量导入、列表导出Excel做出来。这功能在毕设里非常加分,因为它是真实校园管理中非常高频的需求,而且技术上有一定门槛,是很好的亮点。

第四个方向是集成第三方能力。比如接入百度地图API展示校园地图、接入钉钉通知、用WebSocket实现站内消息实时提醒。这些功能有一个就够,作为论文里的“项目亮点”章节重点写。

6.3 打包部署与答辩准备

最后说说部署。SSM项目部署不放Spring Boot,因为它是传统打包方式。在IntelliJ IDEA里Package执行mvn clean package,把war包生成到target目录下,然后复制到Tomcat的webapps目录,启动Tomcat,访问路径一般是http://localhost:8080/项目名/

这里有一个很容易忽略的地方:如果你的项目名是打包自动生成的war包名,可能跟你源码里配置的上下文路径不一致,导致静态资源路径全部404。解决方案是修改war包的名称,或者直接把它改成ROOT.war,这样访问路径就是http://localhost:8080/,简洁又不容易出错。

答辩准备这块,把核心流程走一遍,截图留档。老师常问的问题就那么几个:SSM框架的整合原理、项目分成哪几层、某个模块的实现思路、数据库关系如何处理、系统存在哪些不足。前四个我前面都讲了,第五个不要回“没缺点”,回答“目前系统在并发处理上还比较简单,后续可以考虑引入Redis做缓存、增加消息队列处理选课高峰”,这种回答显得你有思考深度,又不会给自己挖坑。

这个项目后续也确实可以往微服务方向延展,把登录认证抽成一个独立服务,课程、成绩、宿舍各模块单独部署,配合Spring Cloud Alibaba那套组件,整个架构就又上了一个台阶。不过这些是后话,先把眼前的毕设做扎实、把源码吃透,比什么都重要。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询