简介:这份资源是面向计算机相关专业学生与Java Web初学者的一套完整学生信息管理系统项目,采用JSP结合SQL Server数据库、基于B/S架构实现,可用于课程设计、毕业设计或相关项目实战参考。压缩包共收录55个文件,整体约2.45MB,其中以42个JSP页面文件为核心,覆盖系统各功能模块的前端与业务逻辑,另含SQL Server数据库文件(mdf、ldf)、XML配置、class编译文件及可执行程序,并附带doc说明文档与多份PPT演示模板,方便整理设计报告与答辩材料。目前已有797人学习下载,说明该方案在同类选题中具备一定参考价值。读者可从中获得经过测试校正、可百分百成功运行的全套源码,以及配套的完整文档与演示文稿,便于快速理解系统结构、对照实现思路并完成自己的项目设计与答辩准备。
1. 从一份 JSP+SQL Server 课设说起:它到底能跑出什么
每年毕业季,总有一批同学被同一件事卡住:选题定了「学生信息管理系统」,技术栈写的是 JSP + SQL Server,真到动手时却不知道从哪一行代码开始。这个标题对应的就是一套典型的 JavaWeb 课设/毕设方案——用 JSP 做页面渲染,用 SQL Server 存学生、课程、成绩、班级这些数据,最终交付一个能登录、能增删改查、能导出成绩单的 Web 系统。它不新,甚至有点「老派」,但正因为老派,资料多、坑也集中,反而适合拿来把 JavaWeb 的完整链路走一遍。
这套东西适合谁?一是被课设逼到墙角的在校生,需要一套能讲清楚、能演示、能答辩的完整实现;二是想从 Spring Boot 回头补一补 Servlet/JSP 底层原理的初级开发者,用传统 Model2 思想把请求流转、会话管理、JDBC 连接这些基本功重新捋顺。它解决的不是高并发问题,而是「一个请求从浏览器发出,到数据库落库,再回到页面」这条链路上每一环到底发生了什么。把这条链路走通,后面换任何框架都是换皮。
2. 环境选型与最小可运行骨架:JDK、Tomcat、SQL Server 怎么配才不打架
2.1 为什么是 JSP + SQL Server 而不是别的组合
先把选型逻辑说清楚,不然后面每一步都会怀疑自己。JSP 的本质是「写起来像 HTML,跑起来是 Servlet」,容器(Tomcat)第一次访问时把它编译成.java再编译成.class,所以它天然适合做「页面里嵌一点逻辑」的课设场景。SQL Server 在高校机房和教材里出现频率极高,图形化工具(SSMS)成熟,sa账号一开就能连,对新手友好。两者组合的代价是:JSP 把 Java 代码和 HTML 混在一起,SQL Server 的驱动和端口配置比 MySQL 啰嗦,但这些都是可以一次性解决的工程问题。
常见做法是:JDK 8 或 JDK 11(别上太新的,Tomcat 8.5/9 对 JDK 17 支持要额外配置),Tomcat 9,SQL Server 2019 或 2022 开发者版,IDE 用 IntelliJ IDEA。这里有个热搜词「idea新建jsp项目」——IDEA 社区版没有内置 Web 模块,需要手动配 Facet 和 Artifact,或者直接用 Maven 的war打包方式,这是最省心的路径。
2.2 用 Maven 搭一个能跑的最小 war 骨架
不要手动去建WEB-INF目录,用 Maven 的webapp原型生成,目录结构标准,后面打包 war 不会缺文件。
# 用 Maven 原型生成 webapp 骨架,groupId 和 artifactId 按自己项目改 mvn archetype:generate \ -DgroupId=com.example \ -DartifactId=student-mis \ -DarchetypeArtifactId=maven-archetype-webapp \ -DinteractiveMode=false生成后目录里会有src/main/webapp,这就是 JSP 的根目录。接着在pom.xml里加两个依赖:JSP API 和 SQL Server JDBC 驱动。注意驱动版本要和 SQL Server 版本匹配,2019/2022 用mssql-jdbc的 9.x 或 10.x 系列。
<dependencies> <!-- JSP API,scope 必须是 provided,因为 Tomcat 自带 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> <scope>provided</scope> </dependency> <!-- SQL Server JDBC 驱动,打包进 war --> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> <version>9.4.1.jre8</version> </dependency> </dependencies>参数说明:scope=provided表示这个包由 Tomcat 提供,不打进 war,否则会和容器自带的 Servlet/JSP 类冲突,启动时报ClassCastException。mssql-jdbc的版本后缀jre8对应 JDK 8,如果项目用 JDK 11 就换成jre11。这一步做完,mvn package能打出一个 war,扔进 Tomcat 的webapps目录能访问,骨架就算立住了。
2.3 SQL Server 连接串与账号配置的三个关键参数
SQL Server 默认端口 1433,但安装时如果选了「命名实例」,端口是动态的,需要在「SQL Server 配置管理器」里把 TCP/IP 协议打开并固定端口。热搜词里「sqlserver配置管理器安装」和「sqlserver安装教程」高频出现,说明很多人卡在这一步。连接串写法:
// 连接串:数据库名、端口、加密选项三个地方最容易错 String url = "jdbc:sqlserver://localhost:1433;" + "databaseName=StudentMIS;" + "encrypt=false;" + "trustServerCertificate=true;"; String user = "sa"; String password = "你的密码"; Connection conn = DriverManager.getConnection(url, user, password);逻辑说明:encrypt=false是因为本地开发没有证书,SQL Server 2019 之后默认强制加密,不关掉会报 SSL 握手失败。trustServerCertificate=true是配合上一条用的,跳过证书校验。sa账号默认是禁用的,要在 SSMS 里「安全性 → 登录名 → sa → 状态」里启用,并设置强密码。如果连不上,先telnet localhost 1433看端口通不通,再检查 SQL Server 服务是否启动,最后看防火墙。
3. Model2 思想落地:从登录到增删改查的完整请求链路
3.1 为什么必须用 Model2 而不是在 JSP 里写 SQL
热搜词里有「按照jsp model2思想实现用户注册功能」,这说明 Model2 是课设答辩的必问点。Model1 是把 Java 代码和 SQL 直接写在 JSP 里,页面一复杂就变成一锅粥,改一个字段要翻三个文件。Model2 是 MVC:Servlet 当控制器(Controller),JSP 只负责展示(View),JavaBean 和 DAO 负责数据和业务(Model)。答辩时老师问「你的项目为什么分层」,答「为了职责分离、便于维护、JSP 里不出现 JDBC 代码」就到位了。
具体落地:建三个包,com.example.servlet放控制器,com.example.dao放数据库操作,com.example.entity放实体类。所有请求先到 Servlet,Servlet 调 DAO 拿数据,把结果塞进request.setAttribute,再forward到 JSP 渲染。
3.2 登录功能的 Servlet + DAO + JSP 三段式实现
先写实体类和 DAO。学生表假设有id、name、password、class_id四个字段。
// StudentDao.java:只负责和数据库打交道,不掺业务逻辑 public class StudentDao { public Student login(String name, String password) throws SQLException { String sql = "SELECT id, name, class_id FROM student WHERE name = ? AND password = ?"; try (Connection conn = DriverManager.getConnection(DBUtil.URL, DBUtil.USER, DBUtil.PASS); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, name); ps.setString(2, password); try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { Student s = new Student(); s.setId(rs.getInt("id")); s.setName(rs.getString("name")); s.setClassId(rs.getInt("class_id")); return s; } } } return null; } }逻辑说明:用PreparedStatement而不是Statement,是为了防 SQL 注入,这是答辩必问的安全点。try-with-resources保证连接和语句自动关闭,避免连接泄漏。参数?按顺序setString,索引从 1 开始,这是 JDBC 的规矩,写错索引会报Invalid column index。
控制器 Servlet:
// LoginServlet.java:接收表单,调 DAO,决定跳哪个页面 @WebServlet("/login") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); // 必须在取参数之前设置 String name = req.getParameter("name"); String password = req.getParameter("password"); StudentDao dao = new StudentDao(); try { Student s = dao.login(name, password); if (s != null) { req.getSession().setAttribute("user", s); // 登录态存 session resp.sendRedirect("student/list.jsp"); } else { req.setAttribute("msg", "用户名或密码错误"); req.getRequestDispatcher("login.jsp").forward(req, resp); } } catch (SQLException e) { throw new ServletException(e); } } }参数说明:setCharacterEncoding("UTF-8")必须放在getParameter之前,否则中文用户名会乱码,这是血泪经验。登录成功用sendRedirect而不是forward,是为了防止刷新页面重复提交表单。失败用forward,因为要把错误信息带回原页面。session里存user对象,后面每个需要登录的页面都从 session 里取,取不到就踢回登录页。
JSP 页面只负责展示,用 JSTL 遍历列表,不写 Java 代码:
<%-- list.jsp:只做展示,数据从 request 里取 --%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <table> <c:forEach items="${studentList}" var="s"> <tr> <td>${s.id}</td> <td>${s.name}</td> <td>${s.classId}</td> </tr> </c:forEach> </table>3.3 增删改查的 SQL 与分页参数怎么设
学生列表通常要分页,SQL Server 的分页语法和 MySQL 不一样,不能用LIMIT。SQL Server 2012 之后用OFFSET ... FETCH:
-- 第 pageNo 页,每页 pageSize 条,pageNo 从 1 开始 SELECT id, name, class_id FROM student ORDER BY id OFFSET (? - 1) * ? ROWS FETCH NEXT ? ROWS ONLY;参数说明:OFFSET后面是跳过的行数,FETCH NEXT后面是取多少行。三个?分别对应pageNo、pageSize、pageSize。注意ORDER BY是必须的,否则 SQL Server 直接报错。热搜词里「sqlserver 字符串转数字」也常出现在成绩统计场景,比如把score字段从varchar转成int求和,用CAST(score AS INT)或CONVERT(INT, score),但前提是字段里没有非数字字符,否则转换失败,要先WHERE ISNUMERIC(score) = 1过滤。
删除和修改用DELETE和UPDATE,同样用PreparedStatement。批量删除时不要拼IN (1,2,3)字符串,用IN (?,?,?)动态占位,或者循环单条删。这里有个坑:SQL Server 的DELETE如果不加WHERE会清空整表,测试时先在事务里跑,确认影响行数再提交。
4. 避坑与排查:那些让课设卡三天的具体问题
4.1 中文乱码:从 JSP 到数据库的全链路排查
现象:登录时输入中文用户名,数据库里查不到,或者页面显示问号。原因:JSP 页面、Servlet 请求、数据库连接、表字段排序规则四个地方都可能出问题。解决:JSP 页面顶部加<%@ page contentType="text/html;charset=UTF-8" %>,Servlet 里req.setCharacterEncoding("UTF-8")和resp.setContentType("text/html;charset=UTF-8"),数据库连接串加sendStringParametersAsUnicode=true,表字段用nvarchar而不是varchar。四个地方缺一个都会乱码,按顺序查。
4.2 驱动加载失败:ClassNotFoundException 的三种可能
现象:启动 Tomcat 报java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver。原因一:mssql-jdbc依赖没打进 war,检查pom.xml的scope是不是写成了provided。原因二:驱动 jar 放错了目录,应该放WEB-INF/lib下,不是 Tomcat 的lib。原因三:JDK 版本和驱动版本不匹配,jre8的驱动在 JDK 11 上可能加载失败,换成jre11版本。解决:mvn dependency:tree看依赖树,确认驱动在compile范围。
4.3 SQL Server 连接超时:端口、实例名、加密三个开关
现象:Connection refused或The TCP/IP connection to the host has failed。原因:SQL Server 的 TCP/IP 协议没启用,或者用了命名实例但连接串没写实例名。解决:打开「SQL Server 配置管理器 → SQL Server 网络配置 → 协议」,把 TCP/IP 状态改成「已启用」,双击进去在「IP 地址」标签页把IPAll的 TCP 端口设成 1433。如果用的是命名实例,连接串写成jdbc:sqlserver://localhost\\SQLEXPRESS;...,注意是两个反斜杠。加密问题见 2.3 节,encrypt=false加上。
4.4 JSP 编译报错:找不到符号或包不存在
现象:访问 JSP 时 500,日志里cannot find symbol或package does not exist。原因:JSP 里用了某个类但没import,或者依赖没打进 war。解决:JSP 顶部用<%@ page import="com.example.entity.Student" %>显式导入。如果是 Maven 项目,确认mvn package成功且 war 里有WEB-INF/lib目录。另外,JSP 里不要用var这种新语法,Tomcat 的 JSP 编译器可能不支持。
4.5 打包 war 后 404:路径和欢迎页配置
现象:war 扔进 Tomcat 后访问http://localhost:8080/student-mis/报 404。原因:web.xml里没配欢迎页,或者 Servlet 的url-pattern和访问路径对不上。解决:在web.xml里加<welcome-file-list><welcome-file>login.jsp</welcome-file></welcome-file-list>。Servlet 用@WebServlet("/login")注解时,访问路径是项目名/login,不是项目名/LoginServlet。热搜词「传统jsp项目打包war」说的就是这个环节,打包前先mvn clean,避免旧 class 文件混进去。
5. 进阶技巧:把课设做成能写进简历的项目
5.1 用过滤器统一处理编码和登录校验
每个 Servlet 都写一遍setCharacterEncoding和登录校验太蠢,用Filter一次性解决。建一个EncodingFilter实现javax.servlet.Filter,在doFilter里设置编码,再建一个AuthFilter拦截/student/*路径,检查 session 里有没有user,没有就重定向到登录页。在web.xml里配<filter-mapping>,或者用@WebFilter注解。这样新增页面不用改任何代码就自动带登录校验,答辩时这是加分项。
5.2 用数据库连接池替代每次 DriverManager
现在每次请求都DriverManager.getConnection,并发一高就崩。换成 HikariCP 或 Druid,在context.xml或web.xml里配JNDI数据源,或者直接在DBUtil里初始化一个HikariDataSource。参数上,maximumPoolSize设 10 到 20,connectionTimeout设 30000 毫秒,idleTimeout设 600000。改完之后,DAO 里从池里拿连接,用完close是还给池不是真关。这一步做完,项目从「课设」变成「能扛一点并发的小系统」。
5.3 成绩统计的 SQL 写法与导出
成绩表通常有student_id、course_id、score三个字段。统计每个学生总分:
SELECT s.name, SUM(CAST(g.score AS INT)) AS total FROM student s JOIN grade g ON s.id = g.student_id GROUP BY s.name ORDER BY total DESC;注意score如果是varchar,先CAST再SUM,否则 SQL Server 会按字符串拼接。导出 Excel 可以用 Apache POI,在 Servlet 里设response.setContentType("application/vnd.ms-excel"),把Workbook写到response.getOutputStream()。热搜词「sqlserver导出单个表的数据」也可以用 SSMS 的「导出数据」向导,但代码里导出更灵活。
5.4 一个我踩过的坑:事务没提交导致数据「消失」
最后说一个我自己的教训。早期写删除功能时,DAO 里开了事务但忘了commit,页面上显示删除成功,刷新后数据又回来了,查了半天以为是缓存。后来在finally里加conn.commit()才解决。SQL Server 默认是自动提交,但一旦手动setAutoCommit(false),就必须显式commit或rollback。这个坑让我养成了一个习惯:任何涉及写操作的 DAO 方法,先想清楚事务边界在哪,commit和rollback写在哪个catch块里。希望帮到你。
本文还有配套的精品资源,点击获取