简介:这是一套基于SSM框架的学校录取查询系统项目源码,面向计算机相关专业学生及需要Java项目实战练习的学习者,可用于高校志愿填报录取场景的课程设计或毕业设计参考。资源包共3个文件,包含2个zip压缩包与1个sql数据库脚本,整体约29.72MB,其中zip内为完整项目源码与项目说明文档,sql文件用于快速导入数据库结构与初始数据。系统采用Spring、SpringMVC、MyBatis后端技术,前端使用JSP、HTML、CSS、JavaScript、jQuery与H-ui框架,数据库为MySQL,基于MVC与B/S架构,开发环境支持Eclipse或IDEA、Tomcat。功能上区分用户与管理员两种角色,前台涵盖网站首页、新闻公告、报考指南、院校信息、留言板、注册登录、个人中心、历年招生信息与意见反馈等模块,后台则提供管理员信息、用户信息、网站栏目与内容、院校信息、专业类型与专业信息、历年招生信息、意见反馈及留言交流回复等管理功能。项目经过严格调试,可帮助读者理解SSM整合流程、MVC分层设计与数据库表结构,适合作为Java Web入门到进阶的实战参考。目前已有97人学习。
1. 从一份 JSP+SSM 录取查询系统源码说起:它到底能解决什么
每年毕业季前两个月,总有人来问我:手上有份「jsp ssm 学校录取查询系统」的源码包,数据库脚本、项目说明、软件工具都齐了,但打开一看不知道从哪下手,改个字段就报 500,答辩前一周还在调 Tomcat。这篇就按一线做法,把这类高校志愿填报录取系统的落地路径拆开讲清楚——它本质是一套基于 JSP 视图层、Spring + SpringMVC + MyBatis 业务层的 Java Web 项目,核心业务是考生查录取结果、管理员维护院校专业与录取数据。适合三类人:拿它做毕设需要跑通并改出自己东西的学生、想补一个完整 SSM 实战案例的 Java 初学者、以及需要快速搭一套信息查询类 Web 系统的开发者。下面从环境、分层、核心业务、避坑到进阶,一步步来。
2. 把源码跑起来:JDK、Tomcat、MySQL 与 SSM 依赖的版本对齐
拿到源码包第一件事不是读代码,是让它在本地跑起来。SSM 项目跑不起来,九成问题出在版本和目录结构上,而不是业务逻辑。这一章先把运行环境钉死,再讲怎么导入和启动。
2.1 环境清单与版本选择
这类毕设级 SSM 项目通常基于 JDK 8、Tomcat 8.5、MySQL 5.7 这套组合,Spring 4.x 或 5.x。不要一上来就上 JDK 17 和 Tomcat 10,JSP 在 Tomcat 10 之后因为 Jakarta EE 命名空间变更(javax 改 jakarta)会大面积报错,这是最常见的翻车点。
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | 1.8 | SSM 老项目对高版本兼容差 |
| Tomcat | 8.5.x | 支持 javax.servlet,JSP 正常 |
| MySQL | 5.7.x | 驱动用 5.1.x 或 8.0.x 需对应改 URL |
| Maven | 3.6+ | 用于拉依赖,非 Maven 项目可跳过 |
| IDE | IDEA / Eclipse | 需配置 Artifact 与 Tomcat |
Java 环境变量配置是新手第一道坎:JAVA_HOME 指向 JDK 根目录,Path 里加 %JAVA_HOME%\bin,配完在命令行敲java -version和javac -version都能出版本号才算过。只配了 java 没配 javac,说明只装了 JRE,编译会失败。
2.2 导入项目与数据库初始化
先建库再导数据,顺序反了会因外键或字符集报错。数据库脚本一般在源码包的 sql 目录下,用命令行导入最稳:
# 登录 MySQL,创建数据库并指定字符集,避免中文乱码 mysql -u root -p -e "CREATE DATABASE admission_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" # 导入项目自带的数据库脚本 mysql -u root -p admission_db < ./sql/admission_db.sql # 验证表是否导入成功 mysql -u root -p -e "USE admission_db; SHOW TABLES;"逻辑说明:第一条命令建库时显式指定 utf8mb4,是因为很多老脚本默认 latin1,导入后中文院校名会变问号。第二条把脚本灌进指定库。第三条确认表结构存在。参数上,-u是用户名,-p后回车再输密码,不要直接把密码写在命令里。
数据库连不上时,先看jdbc.properties或db.properties里的 URL、用户名、密码三件套。MySQL 8 的驱动类名是com.mysql.cj.jdbc.Driver,URL 要带serverTimezone=Asia/Shanghai,否则报时区错误;MySQL 5.7 用com.mysql.jdbc.Driver即可。
2.3 配置 Tomcat 并启动
在 IDEA 里配置 Tomcat 时,Deployment 选项卡要添加 Artifact,且 Application context 建议设为/或/admission,访问路径要和 controller 里的映射对上。启动后控制台出现Server startup in xxx ms才算成功。如果报ClassNotFoundException,多半是依赖没进WEB-INF/lib,非 Maven 项目要手动把 jar 拷进去;Maven 项目则检查 pom 里 servlet-api 的 scope 是不是 provided。
提示:启动前先确认 8080 端口没被占用,被占用时 Tomcat 会静默失败或报 BindException,换端口或杀掉占用进程。
3. SSM 三层怎么分工:JSP 视图、Spring 容器与 MyBatis 映射的协作
跑起来之后要能改,改之前得看懂分层。SSM 的价值就在于职责清晰,改一个查询功能通常只动三四个文件,前提是你知道每个文件管什么。
3.1 分层结构与请求流转
一次「查询录取结果」的请求,流转路径是这样的:浏览器请求 → web.xml 里 DispatcherServlet 拦截 → SpringMVC 根据@RequestMapping找到对应 Controller → Controller 调 Service → Service 调 Mapper 接口 → MyBatis 通过 XML 映射执行 SQL → 结果逐层返回 → Controller 把数据放进 Model → 转发到 JSP 渲染。
对应到目录,典型结构是:
controller/:接收参数、组织返回,不写业务逻辑service/与service/impl/:业务规则、事务控制mapper/(或 dao):接口,与 XML 一一对应entity/:与数据库表对应的实体类src/main/webapp/WEB-INF/jsp/:JSP 页面resources/:spring、springmvc、mybatis 三个配置文件
新手最容易犯的错是把 SQL 写进 Controller,或者 Service 里直接 new 一个 Mapper。SSM 靠 Spring 的依赖注入把对象串起来,手动 new 会导致事务失效。
3.2 三个配置文件的关键项
applicationContext.xml管 Spring 容器,负责数据源、SqlSessionFactory、事务和 Service 扫描;springmvc.xml管 Web 层,负责 Controller 扫描、视图解析器和注解驱动;mybatis-config.xml管 MyBatis 全局设置,比如驼峰映射。
<!-- springmvc.xml 中的视图解析器,决定 JSP 路径拼接规则 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 前缀:JSP 存放目录 --> <property name="prefix" value="/WEB-INF/jsp/"/> <!-- 后缀:文件扩展名 --> <property name="suffix" value=".jsp"/> </bean>逻辑说明:Controller 里返回字符串"result",视图解析器会拼成/WEB-INF/jsp/result.jsp。参数 prefix 和 suffix 必须和实际目录一致,否则报 404。很多人改了 JSP 目录却忘了同步这里,页面就是出不来。
MyBatis 的驼峰映射建议在mybatis-config.xml里开启,这样数据库的user_name能自动映射到实体的userName,省掉大量 resultMap 配置:
<settings> <!-- 开启驼峰命名自动映射,减少手动 resultMap --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>3.3 用 MyBatis 写一个录取结果查询
以「考生输入准考证号查录取结果」为例,Mapper 接口和 XML 要成对出现。
// AdmissionMapper.java 接口,方法名与 XML 中的 id 对应 public interface AdmissionMapper { // 根据准考证号查询录取记录 Admission queryByExamNo(@Param("examNo") String examNo); }<!-- AdmissionMapper.xml,namespace 必须指向接口全限定名 --> <mapper namespace="com.example.mapper.AdmissionMapper"> <select id="queryByExamNo" resultType="com.example.entity.Admission"> SELECT id, exam_no, student_name, college_name, major_name, admit_status FROM t_admission WHERE exam_no = #{examNo} </select> </mapper>逻辑说明:namespace写错会报Invalid bound statement,这是 MyBatis 最高频的报错。#{}是预编译占位符,能防 SQL 注入;${}是字符串拼接,只在动态表名等场景用,查询条件绝不能用。resultType指向实体类,字段靠驼峰映射自动对应。
Service 层加事务注解,保证查询和后续状态更新的一致性:
@Service public class AdmissionServiceImpl implements AdmissionService { @Autowired private AdmissionMapper admissionMapper; @Override @Transactional(readOnly = true) // 只读事务,提升查询性能 public Admission queryByExamNo(String examNo) { return admissionMapper.queryByExamNo(examNo); } }参数说明:@Transactional(readOnly = true)告诉数据库这是只读操作,能减少锁开销。写操作则去掉 readOnly,并在方法内处理异常回滚。
4. 志愿填报与录取状态流转:业务表设计和核心逻辑
查询只是展示,真正体现系统价值的是志愿填报和录取状态的管理。这部分设计不好,后期改需求会非常痛苦。
4.1 核心表结构与字段含义
一套录取查询系统通常围绕四张表转:考生表、院校专业表、志愿表、录取结果表。字段设计要预留状态位,别用中文直接存状态。
| 表名 | 关键字段 | 说明 |
|---|---|---|
| t_student | id, exam_no, name, score | 考生基本信息与分数 |
| t_college_major | id, college_name, major_name, plan_num | 院校专业及招生计划数 |
| t_volunteer | id, student_id, major_id, order_no, status | 志愿顺序与状态 |
| t_admission | id, exam_no, major_id, admit_status | 录取结果 |
status字段用数字或英文枚举,比如 0 待审核、1 已投档、2 已录取、3 已退档,前端展示时再转中文。直接存「已录取」这种中文,后期做统计和条件判断会很难受。
4.2 志愿填报的提交与校验
填报的核心是「一个考生同一批次不能重复填同一专业」和「志愿顺序不能重复」。校验放在 Service 层,不要只靠前端。
@Override @Transactional public void submitVolunteer(Long studentId, List<Volunteer> volunteers) { // 先清空该考生旧志愿,避免重复提交累积脏数据 volunteerMapper.deleteByStudentId(studentId); Set<Integer> orderSet = new HashSet<>(); for (Volunteer v : volunteers) { // 校验志愿顺序是否重复 if (!orderSet.add(v.getOrderNo())) { throw new RuntimeException("志愿顺序重复:" + v.getOrderNo()); } v.setStudentId(studentId); v.setStatus(0); // 初始状态:待审核 volunteerMapper.insert(v); } }逻辑说明:先删后插是常见的「覆盖式提交」策略,简单可靠。orderSet.add返回 false 说明顺序号已存在,直接抛异常触发事务回滚,保证要么全成功要么全失败。参数上,studentId从登录会话取,不要信任前端传的,否则能改别人志愿。
4.3 录取状态更新与并发注意
录取结果批量导入或管理员手动更新时,要注意并发。两个管理员同时改同一条记录,后提交的会覆盖前者。简单做法是加乐观锁版本号字段:
-- 更新录取状态时带上版本号,版本不匹配则更新 0 行 UPDATE t_admission SET admit_status = #{status}, version = version + 1 WHERE id = #{id} AND version = #{version};逻辑说明:执行后判断影响行数,为 0 说明数据已被他人修改,提示用户刷新重试。这是最轻量的并发控制,比悲观锁对查询性能影响小。参数 version 从查询时一并取出,随表单提交回来。
5. 避坑与排查:JSP+SSM 项目最常见的五类翻车
这一章全是血泪经验,每条按现象、原因、解决写,遇到问题对号入座。
5.1 中文乱码
现象:页面显示问号或乱码,数据库里也是乱码。原因:三层都可能出问题——JSP 页面编码、请求编码、数据库连接编码。解决:JSP 顶部加<%@ page contentType="text/html;charset=UTF-8" %>;web.xml 配 CharacterEncodingFilter 强制 UTF-8;数据库连接 URL 加useUnicode=true&characterEncoding=utf8;建库时用 utf8mb4。四处都对齐才彻底。
5.2 Invalid bound statement
现象:启动正常,一调 Mapper 就报Invalid bound statement (not found)。原因:XML 的 namespace 和接口全限定名不一致,或方法名与 XML 的 id 对不上,或 XML 没被扫描到。解决:逐字核对 namespace 和 id;检查applicationContext.xml里 mapperLocations 的路径通配符是否覆盖到 XML 所在目录。
5.3 静态资源 404
现象:JSP 能打开,但 CSS、JS、图片全 404。原因:DispatcherServlet 拦截了所有请求,包括静态资源。解决:在 springmvc.xml 里加<mvc:default-servlet-handler/>或<mvc:resources mapping="/static/**" location="/static/"/>,把静态资源交给默认 Servlet 处理。
5.4 事务不生效
现象:Service 里抛异常了,但数据库数据没回滚。原因:常见三种——方法不是 public、同类内部方法直接调用、异常被 catch 没抛出。解决:事务方法必须是 public;内部调用要走代理对象;捕获异常后要么重新抛出 RuntimeException,要么手动TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()。
5.5 修改字段后查询报错
现象:给表加了个字段,实体也加了,但查询报列名错误或映射不上。原因:XML 里用了SELECT *但 resultMap 没更新,或驼峰映射没开导致新字段映射不上。解决:查询尽量显式列出字段;确认mapUnderscoreToCamelCase已开启;改了表结构同步改实体和 XML,三处缺一不可。
6. 从能跑到能改:二次开发与答辩演示的实用技巧
跑通只是起点,毕设要的是你能讲清楚改了什么、为什么这么改。这一章给几个能直接用的进阶做法。
第一个技巧是给查询加分页。录取结果动辄几百条,一次全查出来页面卡、内存也吃紧。用 PageHelper 最省事,在 pom 引入依赖后,Service 里一行代码搞定:
@Override public PageInfo<Admission> queryByPage(int pageNum, int pageSize) { // 开启分页,紧跟其后的第一条查询会被自动改写 PageHelper.startPage(pageNum, pageSize); List<Admission> list = admissionMapper.queryAll(); // 包装成分页对象,含总记录数、总页数 return new PageInfo<>(list); }逻辑说明:startPage只对紧随其后的第一次查询生效,中间不能插入其他查询。参数 pageNum 从 1 开始,pageSize 建议 10 到 20。返回的 PageInfo 直接给 JSP 遍历,前端拿 total 渲染页码。
第二个技巧是答辩演示前准备一份「数据剧本」。手动往数据库塞几条典型记录:一条已录取、一条待审核、一条查无结果。演示时按顺序走一遍,比现场随机点更能体现系统完整性。用 SQL 批量插入比一条条点界面快得多:
-- 批量插入演示用录取数据,注意字段与表结构对齐 INSERT INTO t_admission (exam_no, student_name, college_name, major_name, admit_status) VALUES ('2024001', '张三', '示例大学', '计算机科学与技术', 2), ('2024002', '李四', '示例大学', '软件工程', 1), ('2024003', '王五', '示例学院', '数据科学', 0);第三个技巧是学会看日志定位问题。SSM 项目报错时,控制台最上面那几行Caused by才是根因,别被最外层的异常描述带偏。MyBatis 的 SQL 日志建议在 mybatis-config.xml 里打开,能看到实际执行的 SQL 和参数,排查映射问题一目了然。
我自己做这类项目最大的教训是:别急着改业务,先把环境版本钉死、把一条查询链路从 JSP 到数据库完整走通,再动手加功能。很多人一上来就改需求,结果环境问题和技术问题混在一起,排查成本翻倍。先让它跑,再让它对,最后让它好,这个顺序别乱。希望帮到你。
本文还有配套的精品资源,点击获取