2026届的同学们,这会儿你们大概已经进入毕设选题的阶段了。实验室设备管理系统,这个题目在Java类毕设里面算是个常青树——不复杂,但五脏俱全,该有的框架、表设计、业务逻辑、前端交互全都覆盖得了。而且实验室设备管理这个场景本身就是高校里的真实需求,答辩的时候有理有据,评委不会觉得你是在编一个没用的系统。另一个现实的好处是SSM这套技术栈虽然老,但它恰恰是Java Web课程里学得最多的一套东西,正好把三年学的串起来,面试的时候还能拿出来讲讲自己对框架的理解。这篇文章我会把这个项目的完整思路、数据库设计、核心代码和论文写法一次性捋清楚,重点讲每个关键选择背后的为什么,而不是让你直接抄一段代码就交差。
1. 项目定位与整体设计思路
1.1 实验室设备管理到底在解决什么问题
很多同学上来就写增删改查,做完发现跟课设没区别,答辩的时候讲不出东西。问题出在你没搞清楚这个系统真正的业务痛点。实验室设备管理要解决的核心问题有三个:设备去向不明、借用流程不规范、维护记录缺失。
设备去向不明很好理解,实验室那么多仪器,谁借走了、什么时候还的、现在在哪个实验室,靠Excel或者本子记根本管不住。借用流程不规范就更常见了,学生想用设备直接找老师口头说一声就拿走了,中间没有任何审批和记录,出了问题说不清楚。维护记录缺失则是说设备坏了、什么时候修的、花了多少钱,这些信息如果不沉淀下来,后面做采购预算和设备报废评估的时候完全没有依据。
所以你在设计和写论文的时候,一定要把这几个业务痛点讲清楚,然后让系统的每一个模块都对应解决其中一个痛点。这不是套话,而是你理解这个项目的起点。
1.2 为什么是SSM而不是Spring Boot
很多学生会问我,现在外面公司都用Spring Boot了,为什么毕设还要求用SSM?其实这里有个理解上的偏差。SSM并不是被淘汰了,它是Spring Boot的底层基础。Spring Boot的自动配置、starter机制,本质上还是在管理Spring和SpringMVC的Bean,MyBatis的用法在Spring Boot里也基本没变。你如果SSM能写明白,转Spring Boot就是一两周的事。反过来,如果一上来就只会用Spring Boot,对底层的Bean装配、事务配置、拦截器机制全都不清楚,面试被追问两句就露馅了。
另外从毕设的角度来说,SSM的配置是显式的、写出来的,这其实是个优势。你可以在论文里放核心配置文件截图,逐行讲DataSource怎么配、SqlSessionFactory怎么建、事务管理器怎么切,这些内容非常充实,比Spring Boot那种“配置文件里加个依赖就好了”有东西可写。答辩的时候老师问“你这个事务是怎么控制的”,你可以很自信地说出声明式事务的配置方式和传播行为,这就是SSM训练出来的基本功。
所以选SSM做毕设不是退而求其次,反而是一个打好功底的好机会。建议你专心把SSM吃透,等做完这个项目再去看Spring Boot会发现容易很多。
1.3 系统功能模块全景
实验室设备管理系统,按角色分通常有三类用户:管理员、教师、学生。三类角色对应三种完全不同的操作权限,这是这个系统和多用户权限管理的核心逻辑。
管理员负责全局管理,包括设备信息的增删改查、设备分类维护、用户管理、借用审批、报修处理、数据统计这些。教师比管理员少一些系统级的操作,主要是在自己的实验室范围内管理设备、审批学生的借用申请。学生则是最前端的用户,可以浏览设备清单、查看设备状态,提交借用申请,发起报修。
所以核心功能模块可以拆成六个:设备信息管理、设备分类管理、借用管理、归还管理、报修管理、统计报表。如果还想加点亮点功能,可以考虑加入消息通知(借用审批通过后通知申请人)、操作日志(记录每个关键操作)或者二维码标签(用二维码标识设备,手机扫码查看设备详情和借用状态)。这些附加功能不用都做,挑一个做好就行,论文里也可以作为系统特色来写。
很多同学功能清单列得很大,结果每个模块都只做了个增删改查,这种“大而全”在毕设答辩里反而是减分的。更好的策略是核心功能做得深——比如借用审批流程做完整,状态流转清晰,别人一眼能看到业务闭环;而普通的数据维护界面做标准就行。深度永远比广度重要。
2. 数据库设计与核心表结构
2.1 核心数据表总览
SSM项目的核心在数据库设计,这一块也是论文里的大头。我建议先画ER图再建表,这样逻辑清楚,后面写代码的时候不会频繁改动表结构。实验室设备管理系统我通常建议设计六张核心表:用户表、设备分类表、设备表、借用记录表、报修记录表、操作日志表。下面把每张表的关键字段列出来。
| 表名 | 用途 | 关键字段 |
|---|---|---|
| user | 系统用户 | id, username, password, real_name, role, department, phone |
| equipment_category | 设备分类 | id, name, description |
| equipment | 设备信息 | id, category_id, name, model, location, status, purchase_date, price, supplier |
| borrow_record | 借用/归还记录 | id, equipment_id, user_id, borrow_time, expected_return_time, actual_return_time, status, auditor_id, audit_time, audit_remark |
| repair_record | 报修记录 | id, equipment_id, reporter_id, report_time, description, handler, repair_time, cost, status |
| operation_log | 操作日志 | id, user_id, operation, target_type, target_id, create_time |
这个表结构不算复杂,但足够支撑一个完整的项目。需要注意的是status字段的取值要在设计阶段就约定好,比如设备状态:0表示在库、1表示已借出、2表示维修中、3表示报废;借用记录状态:0表示待审核、1表示已通过、2表示已拒绝、3表示使用中、4表示已归还、5表示已逾期。这些字典值最好在数据库设计文档里写清楚,对后面的编码和论文都是有价值的。
2.2 设备表与分类表的设计细节
设备表是系统的核心表,这里有几个容易踩坑的地方。首先是设备分类,设备分类如果不单独建一张表,而是直接在每个设备记录里存一个分类名称字符串,后面改分类名的时候会非常痛苦,你得把所有关联设备的分类名一起改。所以分类必须独立成表,设备表里只存category_id,通过外键关联。这是数据库设计里最基本的范式规则,但很多同学的课设就是栽在这里。
其次是价格字段,设备的采购价格要保留两位小数,所以数据类型建议用DECIMAL(10, 2)而不是FLOAT或者DOUBLE。浮点数在计算的时候会有精度丢失的问题,你存个9999.99,查出来变成9999.989999999,虽然看着差不多,但做统计报表求和的时候误差会暴露出来。这个知识点你在论文里写一句“为了避免浮点精度问题采用DECIMAL类型”,会显得很专业。
设备状态字段要跟下面说的借用记录联动。设备借出后,equipment表里的status要同步改成1已借出;归还后要改回0在库;报修状态下改成2维修中。这种状态一致性的维护要在Service层做好事务控制,后面会详细说。
2.3 借用单与审批流表设计
借用记录表是整个系统业务逻辑最复杂的部分,也是你论文里可以重点展开的内容。这张表记录了从学生提交申请开始,到管理员审批,再到借出、归还的完整生命周期。
这里需要注意,审批字段(auditor_id、audit_time、audit_remark)和申请字段(user_id、borrow_time、expected_return_time)放在同一张表里是合理的。有的同学一看到审批就想着要拆成两张表,申请一张表审批一张表,这个对于这个项目没有必要。借用记录的status字段本身就区分了待审核、已通过、已拒绝这些状态,管理员只需要对status为待审核的记录执行审核操作就可以了,不需要单独再做一张审批表。这个设计原则叫“状态机模型”,一条记录用状态字段标记当前所处阶段,简单又高效。
还有一个细节是expected_return_time(预计归还时间),这个字段是计算逾期的基础。管理员在审批的时候,可以在这个时间之后把状态标记为已逾期,然后生成一条逾期提醒记录。如果因为设备被逾期未还导致他人无法借用,这个字段就派上了大用场,你可以在BorrowRecordMapper里写一个查询“当前时间超过expected_return_time且状态为已借出”的SQL,这就是一个非常实用的统计功能。
2.4 报修与维护记录表
报修记录表的核心逻辑是设备状态的变更。学生或者教师发现设备故障后提交报修,系统把equipment表里对应设备的status改为维修中,然后报修记录的状态从待处理变为处理中,维修完成后填上维修人员和费用,再把设备状态改回在库。
这里还有个容易忽略的点——报修记录表里最好加上cost(维修费用)字段。表面上看这个字段不参与核心业务,但它支撑了后续的统计报表功能:可以按学期统计维修总费用、按设备统计维修次数,这些数据在实验室的采购决策里是有实际参考价值的。所以每次做系统设计的时候,多想想这个表的数据会在哪里被用到,这样设计出来的表才经得起追问。
如果你在论文里写数据库设计,推荐用PowerDesigner或者draw.io画ER图,表结构用WORD的三线表列出,每个字段备注写清含义和取值。这一章内容不需要太花哨,但一定要完整、准确,评委老师经常翻这一部分。
3. 后端核心实现与关键代码
3.1 SSM三层架构的包结构和配置
SSM的标准分包方式是com.xxx.entity(实体类)、com.xxx.mapper(MyBatis的Mapper接口)、com.xxx.service(业务接口)、com.xxx.service.impl(业务实现)、com.xxx.controller(控制器)、com.xxx.config(配置)外加resources下的mapper映射文件目录。分包清楚了,代码自然就不乱,这也是论文中“系统总体架构”这一节的内容。
核心配置文件有三个,applicationContext.xml、spring-mvc.xml和mybatis-config.xml。但实际很多项目会合并,比如把MyBatis的配置直接放在applicationContext.xml里。我习惯这样做:数据源和MyBatis配置放在applicationContext.xml,spring-mvc.xml只做注解驱动和视图解析器的配置。下面给出关键的配置片段。
<!-- 数据源配置 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/lab_equipment?useUnicode=true&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!-- SqlSessionFactory配置 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="classpath:mapper/*.xml"/> <property name="typeAliasesPackage" value="com.example.entity"/> </bean> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 注解驱动事务 --> <tx:annotation-driven transaction-manager="transactionManager"/>数据库连接池我用的是Druid,因为它的监控功能很强,而且对SQL性能有统计。如果你对这块不熟,用C3P0或者直接Spring自带的DriverManagerDataSource也行,但答辩的时候用Druid会更好讲,因为它有监控面板,你可以在演示的时候打开监控页,展示当前连接数、执行过的SQL,这也是一个加分点。
3.2 设备借用的完整业务闭环
设备借用是系统的核心业务流程,也是最容易出Bug的地方,我建议这个部分的代码一定要自己敲一遍,不要直接复制粘贴。完整的借用流程包含四个步骤:学生提交申请、管理员审核通过、借出设备、归还设备。
提交申请的逻辑比较简单,创建一个BorrowRecord记录,状态为0待审核,同时校验一下设备当前是否处于在库状态,如果不在库则直接提示“该设备当前不可借”。
@Override @Transactional public boolean applyBorrow(Integer equipmentId, Integer userId, Date expectReturnTime) { Equipment equipment = equipmentMapper.selectById(equipmentId); if (equipment == null || equipment.getStatus() != 0) { throw new BusinessException("设备当前不可借用"); } BorrowRecord record = new BorrowRecord(); record.setEquipmentId(equipmentId); record.setUserId(userId); record.setBorrowTime(new Date()); record.setExpectedReturnTime(expectReturnTime); record.setStatus(0); return borrowRecordMapper.insert(record) > 0; }这里我加了@Transactional注解,为什么?因为这里的操作虽然当前只插入了一条记录,但你在真实业务里很可能还要同时更新设备状态为“待借用”,甚至记录操作日志。只要有多个写操作,就必须在同一个事务里执行,要么全部成功,要么全部回滚,不能出现“记录插上了但设备状态没改”这种脏数据。这个用生活类比就是网上转账,你转出去的钱必须保证对方收到,中间任何一步失败,两边都不能有变化。
审核通过的操作如下,这是整个流程最重要的一步:
@Override @Transactional public boolean auditBorrow(Integer recordId, Integer auditorId, boolean approved, String auditRemark) { BorrowRecord record = borrowRecordMapper.selectById(recordId); if (record == null || record.getStatus() != 0) { throw new BusinessException("记录不存在或已处理"); } if (approved) { // 更新借用记录状态为已通过 record.setStatus(1); record.setAuditorId(auditorId); record.setAuditTime(new Date()); record.setAuditRemark(auditRemark); // 设备状态改为已借出 equipmentMapper.updateStatus(record.getEquipmentId(), 1); } else { // 更新状态为已拒绝 record.setStatus(2); record.setAuditorId(auditorId); record.setAuditTime(new Date()); record.setAuditRemark(auditRemark); } borrowRecordMapper.update(record); return true; }注意审核不通过的时候设备状态不需要改变,因为设备本来就没有被借走。归还的时候,不仅要更新借用记录的状态为已归还,还要把设备状态改回0在库。另外还要检查一下归还时间是否晚于预计归还时间,如果是,就是逾期归还,可以记录状态为5逾期并在页面上标红提示。这个逻辑不难,但你能做出来,说明你理解了业务规则。
3.3 统计报表的SQL写法
统计报表是毕设里最容易做出亮点、但很多同学不知道从哪里下手的功能。我建议做三个统计:设备总数和各类状态数量、本月借用次数排行、维修费用汇总。
设备数量统计比较简单:
SELECT SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) AS inStock, SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS borrowed, SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) AS repairing, COUNT(*) AS total FROM equipment设备借用次数排行榜,联表查询一下借用记录和设备表,按借用次数降序排列:
SELECT e.name AS equipment_name, COUNT(b.id) AS borrow_count FROM equipment e LEFT JOIN borrow_record b ON e.id = b.equipment_id AND b.status IN (1, 3, 4, 5) GROUP BY e.id, e.name ORDER BY borrow_count DESC LIMIT 10维修费用按月份汇总,方便做柱状图:
SELECT DATE_FORMAT(report_time, '%Y-%m') AS month, SUM(cost) AS total_cost, COUNT(*) AS repair_count FROM repair_record WHERE status = 2 GROUP BY DATE_FORMAT(report_time, '%Y-%m') ORDER BY month DESC这些统计SQL在MyBatis的XML文件里写,返回的映射可以放到一个专门的StatisticsMapper中。前端展示推荐用ECharts,它是一个纯JS的图表库,引入非常简单,做柱状图、饼图都是几行代码的事,图表出来之后整个系统的视觉效果和层次感会提升一大截。在论文里,你也可以放几张统计页面的截图,说“本系统使用ECharts实现了设备状态的实时可视化”,这比一堆文字描述有说服力得多。
4. 前端页面设计与SSM对接
4.1 传统JSP方案:最稳的选择
前端方案我首先推荐用JSP加JSTL加Bootstrap。理由很简单,如果你没有单独的前端课程基础,JSP是你最可能已经接触过的技术,跟SSM无缝配套,不需要考虑跨域问题,部署也简单,扔进Tomcat就能跑。
用JSP做页面的时候,需要注意把Java代码从JSP页面里清干净。JSP页面里不应该出现<%%>里面写一大段Java逻辑的情况,这会造成前后端耦合、代码可读性差。用JSTL标签配合EL表达式,比如遍历设备列表:
<c:forEach items="${equipmentList}" var="eq"> <tr> <td>${eq.id}</td> <td>${eq.name}</td> <td>${eq.model}</td> <td> <c:if test="${eq.status == 0}">在库</c:if> <c:if test="${eq.status == 1}">已借出</c:if> <c:if test="${eq.status == 2}">维修中</c:if> </td> <td> <a href="${pageContext.request.contextPath}/equipment/edit?id=${eq.id}" class="btn btn-sm btn-primary">编辑</a> <a href="${pageContext.request.contextPath}/equipment/delete?id=${eq.id}" class="btn btn-sm btn-danger" onclick="return confirm('确认删除?')">删除</a> </td> </tr> </c:forEach>Controller返回视图的时候,通过Model把数据传过去:
@Controller @RequestMapping("/equipment") public class EquipmentController { @Resource private EquipmentService equipmentService; @RequestMapping("/list") public String list(Model model) { List<Equipment> equipmentList = equipmentService.listAll(); model.addAttribute("equipmentList", equipmentList); return "equipment/list"; } }这套方案最不容易出错,也是大量毕设的默认选项。缺点就是页面美观度和交互体验一般,但你把Bootstrap用熟练,加一些自定义CSS,整体效果完全够用。
4.2 Vue3加SSM的前后端分离方案
如果基础好一点,想在毕设里展示前后端分离能力,用Vue3加Axios加Element Plus也是一条非常顺畅的路子。而且最近的热词里“vue3连接ssm框架”被搜得很多,说明不少同学都在尝试这条路。但这里我要提醒一下,前后端分离方案会引入跨域问题、接口文档规范和额外的构建步骤,复杂度比JSP高一个量级,如果你时间不充裕,建议不要勉强。
前后端分离的核心是前端静态页面通过Axios调用后端的JSON接口,而后端接口用@ResponseBody(或者@RestController)返回JSON数据。前端Vue3代码大致长这样:
import axios from 'axios' const api = axios.create({ baseURL: 'http://localhost:8080/api', timeout: 10000 }) // 获取设备列表 export function getEquipmentList(params) { return api.get('/equipment/list', { params }) } // 借用设备 export function applyBorrow(data) { return api.post('/borrow/apply', data) }关键点是后端必须开启CORS跨域支持,不然前端在8081端口访问8080端口的数据会被浏览器拦截。在SpringMVC里最简单的方式是用@CrossOrigin注解加到Controller或者对应的方法上:
@RestController @RequestMapping("/api/equipment") @CrossOrigin(origins = "*") public class EquipmentApiController { // ... }或者通过WebMvcConfigurer配置全局CORS映射。这个点踩坑的人特别多,你提前解决了,答辩的时候一句“通过CORS配置解决了跨域访问问题”就能体现实践能力。
4.3 接口联调的通用套路
不管用JSP还是Vue,接口联调阶段都有几个非常实用的套路。第一是要用postman测试接口,不要直接写前端页面来测,那样出了问题说不清是后端的问题还是前端的问题。先把每个接口通过postman跑通,确认返回的数据正确,再联调前端。
第二是分页查询的参数设计。设备列表肯定要分页,不然数据多了页面崩。我的习惯是用page、limit、keyword三个参数,page是页码,limit是每页条数,keyword是搜索关键词。Controller接收这三个参数,查询时通过PageHelper分页插件实现:
@Override public PageResult<Equipment> pageQuery(int page, int limit, String keyword) { PageHelper.startPage(page, limit); List<Equipment> list = equipmentMapper.pageQuery(keyword); PageInfo<Equipment> pageInfo = new PageInfo<>(list); PageResult<Equipment> result = new PageResult<>(); result.setCount(pageInfo.getTotal()); result.setData(pageInfo.getList()); return result; }PageHelper是一个非常方便的MyBatis分页插件,底层原理是利用MyBatis的拦截器,在执行SQL前动态拼接LIMIT语句,你不用手写每一条分页SQL。毕设里能用好这个插件,也是一个可以写进论文的亮点。
5. 毕设论文怎么写才能过审
5.1 论文结构总体安排
有源码没论文照样毕不了业,而且论文的权重往往比代码高,因为评委老师主要是通过论文来评估你的工作的。实验室设备管理系统论文的标准结构一般按照软件工程的生命周期来写。
我建议的章节安排:第一章绪论,写选题背景、国内外研究现状、研究内容和意义;第二章需求分析,写可行性分析、功能需求、非功能需求;第三章系统设计,写总体架构设计、功能模块划分、数据库设计;第四章系统实现,写各功能模块的设计与实现,附核心代码和页面截图;第五章系统测试,写测试环境、测试用例、测试结果分析;最后是总结与展望。
这个结构是最经典的信息管理系统论文结构,跟SSM框架项目配合得很好。你不需要在格式上创新,按学校模板走就行,重点是把每章的内容填充扎实。
5.2 需求分析和系统设计部分的写法
需求分析是整个论文里最容易被忽视但又最重要的部分。很多同学用一两页就把功能性需求写完了,非常单薄。我建议你在写需求分析的时候,先画用例图,把管理员、教师、学生三类角色的用例全部画出来,然后针对每个用例写用例描述,包括主流程、异常流程和补充说明。比如“学生申请借用设备”的用例,你要写清楚前置条件是学生已登录,主流程是搜索设备、查看详情、点击借用、填写预计归还日期、提交申请,异常流程是设备不在库、申请被拒绝。这样写出来,需求分析部分自然就充实了。
系统设计部分重点是架构图和数据库设计。架构图建议画一张分层图,从上到下依次是视图层(JSP/Vue)、控制层(SpringMVC Controller)、业务层(Service)、持久层(MyBatis Mapper)、数据库(MySQL),每层之间标注依赖关系。这张图画好了,整个系统的技术方案一目了然。数据库设计就是把第二章的六张表逐个展示,每个字段都要写清楚含义、类型、是否允许为空、默认值,这些内容看起来很“笨”,但在论文里最见功力。
5.3 测试章节和查重降重
测试部分是很多同学直接抄,抄完还被老师问得答不上来的重灾区。我的建议是老老实实按测试用例来写,每条用例包含用例编号、测试模块、前置条件、操作步骤、预期结果、实际结果、是否通过。写十条左右的用例就够了,覆盖登录、设备管理、借用流程、审批流程、报修流程、统计查询这些核心功能。关键在于实际结果那一栏要跟你真实测试的情况一致,不要全写“通过”,偶尔写一两条“通过但响应时间超过预期”之类的改进记录,反而会让论文显得更真实。
查重降重方面,SSM项目的论文模板各大高校都司空见惯,数据库设计部分的文字重复率尤其容易爆表。我的建议是数据库设计部分的字段说明尽量用自己的话重新组织,功能模块的表述要跟你的项目实际功能形成映射,不要套用网上那些通用的功能描述。核心代码用代码格式展示,正常查重系统不会把代码算入重复率,但引用的别人写过的设计思路段落要记得标注参考文献。
6. 常见问题与排错实录
6.1 环境与依赖问题
做这个项目,第一步最容易卡住的就是环境问题。Maven依赖下载慢或者失败,是最常见的问题,因为国内访问Maven中央仓库很不稳定。解决办法是配置阿里云镜像,在Maven的settings.xml文件里加入镜像:
<mirror> <id>aliyunmaven</id> <mirrorOf>central</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/central</url> </mirror>配置完之后重新构建,下载速度会快很多。还有一个常见问题是JDK版本不一致,SSM项目通常用JDK 8,但很多新电脑默认装了JDK 17甚至更高,编译的时候会报各种奇怪的错,比如热词里提到的“源发行版17需要目标发行版17”这个错,就是IDEA的Project Structure里Project SDK和Java Compiler的Target bytecode version不匹配导致的。选SSM项目建议就用JDK 8配Tomcat 8.5或者Tomcat 9,最稳的组合别乱折腾。
6.2 MyBatis映射问题
MyBatis相关的报错在SSM项目里占据半壁江山,最常见的两个错误是“Invalid bound statement (not found)”和“Cause: org.apache.ibatis.binding.BindingException”。出现这两个错本质原因都是Mapper接口跟XML映射文件没有正确关联。排查套路如下:第一检查resources下的mapper包路径跟applicationContext.xml里配置的mapperLocations是否一致,第二检查XML文件里的namespace是否等于Mapper接口的全限定名,第三检查XML里的方法id是否跟接口方法名一模一样。这三个检查做完了,八成以上的绑定问题都能解决。
另一个很隐蔽的问题是字段映射。如果数据库字段是下划线风格(如purchase_date),而实体类属性是驼峰风格(如purchaseDate),MyBatis默认不会自动映射,导致查询结果里该字段为null。解决办法是在mybatis-config.xml里开启驼峰映射:
<configuration> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> </configuration>这个配置在SSM项目里极其常用,你提前写上去能少踩很多坑。
6.3 运行期常见异常
数据库连接不上,要么是MySQL服务没启动,要么是用户名密码不对,要么是URL配置有问题。排查思路先看报错信息里有没有“Access denied for user”或者“Communications link failure”,前者是认证问题,后者是网络或服务问题。简单来说先拿Navicat连一下数据库,如果Navicat能连上而项目连不上,那问题一定在配置里。
中文乱码是个老生常谈的问题,但每年都有人栽。要确保三处编码统一:数据库连接URL里加上characterEncoding=utf8,web.xml里配置CharacterEncodingFilter,页面里声明UTF-8。三处都做了,基本不会乱码。
启动Tomcat后访问页面404,先看控制台有没有报错,再看访问路径是否跟注解里的RequestMapping匹配。用JSP开发的同学最容易踩的坑是页面放在WEB-INF目录下,此时URL直接访问不到,必须通过Controller转发,这是正常的,不算bug。
6.4 答辩时的高频提问
最后说一下答辩准备。评委老师大概率会问这几个问题:第一,SSM框架的请求流程是怎样的?你至少要把DispatcherServlet分发给Controller,Controller调用Service,Service调用Mapper,Mapper操作数据库这条链路讲清楚。第二,为什么用声明式事务?你要能说出Spring AOP的原理,以及事务传播行为中REQUIRED是什么意思。第三,数据库中这个字段为什么设计成这个类型?这就是考察你的数据库设计基本功,所以我在第二章节强调字段设计一定要自己动脑。第四,这个系统有什么改进空间?不要回答“没有”,也别说“全部都要改进”,就说一两点具体可行的就好,比如“目前缺少消息通知功能,后续可以整合WebSocket实现审批结果的实时推送”或者“可以引入Redis缓存设备列表来提升接口响应速度”。
把这些问题提前准备好,答辩的底气和状态完全不一样。这个项目做下来,你其实已经掌握了Java Web开发的基本盘,SSM也好,Spring Boot也好,原理层面的东西都是通的。后面不管是找工作准备八股文,还是继续做更复杂的项目,这段经历都会是你最扎实的起点。最后想跟你们说一句,毕设是自己的事,源码可以拿,论文可以参考,但里面每一个配置、每一行核心代码,尽量亲手敲过、调过、折腾过。踩过的坑才是真正学到的东西,这也是写这篇东西最希望你能拿走的东西。