ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

JavaWeb学生成绩管理系统:从数据库设计到期末答辩完整实战

JavaWeb学生成绩管理系统:从数据库设计到期末答辩完整实战 简介一份JavaWeb学生成绩管理系统源码与配套数据库面向计算机专业在校生和需要项目实战的初学者可当作课程设计或期末大作业的高分参考。系统覆盖学生信息管理、教师信息管理、成绩录入与统计、考试安排等核心模块前台页面与后台逻辑分层清晰以Servlet/JSP为主实现前后端交互结构贴近课堂所学技术栈也便于理解Web项目从建库到页面的开发流程。压缩包共353个文件包含Java源码、JSP页面、CSS样式、JavaScript脚本、SQL数据库脚本、jar依赖包以及docx说明文档另有png/gif等界面素材与图标整体约9.85MB目录按源码、页面、数据库与文档分类存放导入部署方便。该项目已有810人学习下载系导师指导后评分98分的实际大作业借助完整工程与初始化脚本读者可快速跑通流程并借鉴分层设计思路用于完成相似课题或积累实战经验。1. 为什么 JavaWeb 学生成绩管理系统是期末作业里最容易拿高分的那一个期末大作业里学生成绩管理系统是 JavaWeb 方向出现频率最高的题目没有之一。这个系统天然覆盖了 JavaWeb 的全部核心考点JavaBean 封装、Servlet 请求处理、JSP 页面渲染、JDBC 操作 MySQL、会话追踪、角色权限控制以及数据库设计里的多表关联。一个能跑通、能演示、能答辩的系统等于把一学期的知识点全部串了一遍这也是老师每年都爱布置这道题的原因。这套系统的数据模型不复杂业务逻辑清晰——学生查成绩、教师录成绩、管理员管理账号三条线就能讲清楚。对于想拿高分的同学来说难点从来不是“功能做不出来”而是数据库设计是否规范、权限控制是否严密、代码是否能在别人的电脑上直接跑起来。一个 98 分的项目不是功能堆得多而是每一层都能经得起追问。这篇笔记把从建库到答辩的完整路径拆开讲。你有 JavaWeb 基础最好没有也不怕跟着步骤把源码和数据库跑通再理解每一段代码在干什么期末答辩时你对答如流。整个系统说白了就是数据库的增删改查但增删改查背后的业务规则和边界处理才是评分拉开差距的地方。2. 先把架构立住学生成绩管理系统的三层拆分与选型2.1 三层架构里每一层该放什么决定你后面好不好改很多同学拿到题目第一反应是找源码找到源码第一件事是改首页的学校名字然后跑起来就看效果。这个思路在交作业层面能过关但答辩时很容易翻车。老师问“你这个业务的权限是怎么控制的”你说“好像过滤器里写的”场面会很尴尬。学生成绩管理系统最常见的分层是表现层、业务层、数据访问层。表现层是 JSP 页面和 Servlet负责接收请求、渲染页面业务层是 Service 接口和实现类负责把“录入成绩”“修改密码”“查询平均分”这些动作变成可以被事务包裹的逻辑数据访问层是 DAOData Access Object只负责拼 SQL、执行 SQL、把结果集封装成 JavaBean。这个结构的好处是当你要把 JDBC 换成 MyBatis或者把 JSP 换成前后端分离时只需要动数据访问层业务逻辑和页面基本不用改。我带的实训小组里有一个同学最开始把所有代码写在 Servlet 里一个 doPost 写了 300 行后期加一个“按班级导出成绩”的功能花了两天——因为每一处都要去改原先的逻辑。后来我让他重构拆成三层之后同样的功能半天就完成了。如果你拿到一份源码发现 Servlet 里有大段大段的 JDBC 代码趁早重构不然你答辩前修改功能时会极其痛苦。2.2 选型JSP Servlet MySQL 是期末作业性价比最高的组合学生成绩管理系统用纯 JSP/Servlet 还是用 SSMSpring SpringMVC MyBatis框架是很多人的纠结点。我的建议是如果你的课程学的是 JSP/Servlet就用原生技术做如果课程明确要求框架再上 SSM。对比项JSP ServletSSM 框架学习曲线平缓每一步都显式陡峭需要理解 Spring 容器和依赖注入期末展示好讲链路清晰需要额外解释框架机制容易翻车环境配置Tomcat MySQL 即可Maven 多个依赖版本兼容性坑多踩坑概率低高光环境就能耗掉三天适合场景课程用原生教学的作业课程明确要求框架原因很简单。第一期末大作业的评分核心是“你能讲清楚”原生的 Servlet 和 JSP 每一步都是显式的请求怎么进来、怎么转发、怎么回显你都能对着代码讲。框架帮你封装了太多东西答辩时一句话答不上来就容易露怯。第二环境配置简单。原生 JavaWeb 只需要 Tomcat MySQL IDEASSM 还要配 Spring 版本兼容、MyBatis 映射文件、Maven 依赖冲突光环境的坑就能耗掉你三天很多同学最后不是死在功能上是死在 Spring 版本和 JDK 版本不兼容的报错上。如果你搜到的源码是 Spring Boot 版本也不要慌。Spring Boot 和原生 JavaWeb 在业务逻辑层面是相通的差别主要在请求入口的写法。下面讲的数据库设计和业务逻辑两种技术栈都能直接套用。2.3 数据库设计学生、教师、管理员、课程、成绩五张表打底学生成绩管理系统的数据库设计是答辩时老师第一眼要看的东西。见过太多同学只用一张成绩表字段是学号、姓名、课程、分数。这样的表能跑但老师会追问“如果学生转专业了姓名去哪里改”“如果系统里有两个叫张伟的同学怎么区分”答不出来分数就悬了。规范的做法是五张表学生表student、教师表teacher、管理员表admin、课程表course、成绩表score。学生表存学号、姓名、性别、班级、专业学号做主键教师表存工号、姓名、所授课程管理员表存账号和密码课程表存课程编号和课程名成绩表存学号、课程编号、分数、学期用学号和课程编号做联合主键同时这两个字段是外键分别指向学生表和课程表。这里有一个很关键的点成绩表里绝对不能冗余姓名和课程名。查询时用 JOIN 去关联这不仅是范式的要求更直接关系到你后面做“成绩排名”“平均分统计”时 SQL 好不好写。把两表设计成多对多关系的同学写分组聚合时很容易写出笛卡尔积的结果而不自知。另外建议加一个学期字段这样系统能区分不同学期的成绩答辩时也是一句话能讲清楚的优点。3. 动手复现从数据库脚本到能跑通的最小系统3.1 建库建表一份能直接在你电脑上跑的 MySQL 脚本拿到源码的第一步永远是先看数据库脚本能不能在你的 MySQL 版本上直接执行。下面这份脚本是学生成绩管理系统的基础版本包含五张表和少量测试数据MySQL 5.7 和 8.0 都能直接跑。-- 创建数据库指定 utf8mb4 字符集避免中文乱码 CREATE DATABASE IF NOT EXISTS student_score DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE student_score; -- 学生表学号做唯一标识班级和专业用普通字段 CREATE TABLE student ( stu_no VARCHAR(20) PRIMARY KEY COMMENT 学号, stu_name VARCHAR(50) NOT NULL COMMENT 姓名, stu_gender CHAR(2) DEFAULT 男 COMMENT 性别, stu_class VARCHAR(50) COMMENT 班级, stu_major VARCHAR(50) COMMENT 专业, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB; -- 教师表工号做主键教师和课程的关系在这个 demo 里简化处理 CREATE TABLE teacher ( teach_no VARCHAR(20) PRIMARY KEY COMMENT 教师工号, teach_name VARCHAR(50) NOT NULL COMMENT 姓名, teach_course VARCHAR(50) COMMENT 所授课程编号, teach_pwd VARCHAR(100) NOT NULL COMMENT 登录密码 ) ENGINEInnoDB; -- 管理员表系统登录入口 CREATE TABLE admin ( admin_no VARCHAR(20) PRIMARY KEY COMMENT 管理员账号, admin_pwd VARCHAR(100) NOT NULL COMMENT 密码 ) ENGINEInnoDB; -- 课程表 CREATE TABLE course ( course_no VARCHAR(20) PRIMARY KEY COMMENT 课程编号, course_name VARCHAR(100) NOT NULL COMMENT 课程名称, credit DECIMAL(3,1) COMMENT 学分 ) ENGINEInnoDB; -- 成绩表联合主键确保同一学生同一课程只有一个成绩记录 CREATE TABLE score ( stu_no VARCHAR(20) NOT NULL, course_no VARCHAR(20) NOT NULL, score DECIMAL(5,2) COMMENT 分数, semester VARCHAR(20) COMMENT 学期如 2024-2025-1, PRIMARY KEY (stu_no, course_no), FOREIGN KEY (stu_no) REFERENCES student(stu_no), FOREIGN KEY (course_no) REFERENCES course(course_no) ) ENGINEInnoDB; -- 插入测试数据注意外键插入顺序先主表再从表 INSERT INTO student VALUES (2024001,张伟,男,计科2401,计算机科学与技术,NOW()); INSERT INTO course VALUES (C001,JavaWeb程序设计,3.0); INSERT INTO score VALUES (2024001,C001,91.5,2024-2025-1);这段脚本有几个细节值得注意。字符集用utf8mb4而不是utf8因为 utf8 在 MySQL 里最多只支持 3 字节遇到特殊字符会报错而 utf8mb4 是完整的 UTF-8 支持。成绩表用联合主键而不是单独加一个自增 id是从业务上保证“同一个学生同一门课只能有一条成绩”这是数据库设计规范里最常被考察的点。插入测试数据时注意外键顺序先插学生再插课程最后插成绩否则外键约束会报错。很多同学在这一步踩坑后以为是 MySQL 版本问题其实是插入顺序的问题。提示如果你手里是一份学长学姐传下来的源码数据库脚本里的表名可能有前缀比如 t_student不要急着改先看清楚代码里 DAO 层的 SQL 写的什么表名保持一致比“规范命名”更重要。3.2 数据库连接JDBC 和连接池两种写法都要会学生成绩管理系统里最核心的代码是数据库访问部分。期末作业一般只需要 JDBC 的基础写法但如果你在源码里看到了连接池配置也要能讲明白两者的区别。// DBUtil.java - JDBC 基础版连接工具类 package com.score.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { // 把数据库连接信息集中管理方便修改 private static final String URL jdbc:mysql://localhost:3306/student_score?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 123456; static { try { // 加载驱动MySQL 8.x 之后驱动类名变成 com.mysql.cj.jdbc.Driver Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, java.sql.Statement stmt, java.sql.ResultSet rs) { // 关闭顺序先关结果集再关 Statement最后关 Connection try { if (rs ! null) rs.close(); } catch (SQLException e) { e.printStackTrace(); } try { if (stmt ! null) stmt.close(); } catch (SQLException e) { e.printStackTrace(); } try { if (conn ! null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }这段代码每个同学都应该能默写出来。URL 里的serverTimezoneAsia/Shanghai是排查数据库连接报错的常客——很多同学用的 MySQL 8.0 和 JDBC 驱动版本不一致不指定时区会直接连不上。useSSLfalse是为了避免本地开发时 SSL 握手报错。关闭资源的顺序也有讲究ResultSet 不关Statement 关不掉连接池里的连接迟早被耗尽。如果你在源码里看到的是 C3P0 或 Druid 连接池配置那是生产环境的标配。连接池的核心思路是复用数据库连接不用每次请求都重新建立物理连接。Druid 在 JavaWeb 项目里最常用它的配置一般在一个druid.properties文件里包含初始连接数、最大连接数、最大等待时间这几个参数。理解到这一层答辩时老师问“为什么用连接池”你能答出“减少连接创建和销毁的开销提升高并发场景下的响应速度”就过关了。3.3 登录与权限控制三种角色怎么在同一个系统里各走各的门学生、教师、管理员三种角色登录后看到的菜单不一样这是学生成绩管理系统评分的分水岭。实现方式有过滤器Filter和拦截器两种原生 JavaWeb 用过滤器做最清晰。// AuthFilter.java - 登录状态校验与角色路由 package com.score.filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class AuthFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req (HttpServletRequest) request; HttpServletResponse resp (HttpServletResponse) response; // 设置请求和响应的编码解决中文乱码 req.setCharacterEncoding(UTF-8); resp.setCharacterEncoding(UTF-8); // 放行登录页面和静态资源 String uri req.getRequestURI(); if (uri.endsWith(login.jsp) || uri.endsWith(.css) || uri.endsWith(.js)) { chain.doFilter(request, response); return; } // 核心逻辑Session 里没有用户就跳回登录页 HttpSession session req.getSession(false); if (session null || session.getAttribute(user) null) { resp.sendRedirect(req.getContextPath() /login.jsp); return; } // 角色检查管理员请求管理页面时验证角色 String role (String) session.getAttribute(role); if (uri.contains(/admin/) !admin.equals(role)) { resp.sendRedirect(req.getContextPath() /login.jsp); return; } chain.doFilter(request, response); } }过滤器解决的是“没登录能不能访问页面”的问题核心是 Session 里有没有用户对象。很多同学的翻车点在getSession(false)——传 false 表示如果当前没有 Session 就返回 null而不是新建一个。如果写成getSession()每个请求都会创建一个新 Session登录校验形同虚设。角色控制有一个容易踩的坑不要把角色判断逻辑散落在每个 JSP 页面里。正确做法是像上面这样把“是否放行”集中在过滤器里判断JSP 页面只管展示。之前见过一个项目在 5 个 JSP 页面里各写了一份if(role.equals(admin))的判断后来要加一个“教务处长”角色改了三个小时还没改全。过滤器里还顺手解决了编码问题一举两得。3.4 成绩录入与查询三张表 JOIN 起来的正确姿势成绩查询是系统里最核心的功能也是答辩时老师最可能让你现场写 SQL 的环节。学生查自己的成绩教师查自己课程的成绩管理员查全校成绩三种查询对应三种 SQL但背后的表关联逻辑是一样的。-- 查询某学生的所有成绩含课程名和学分 SELECT c.course_name, c.credit, s.score, s.semester FROM score s JOIN course c ON s.course_no c.course_no WHERE s.stu_no 2024001 ORDER BY s.semester DESC, c.course_no; -- 查询某门课的平均分按班级分组 SELECT st.stu_class, ROUND(AVG(s.score), 2) AS avg_score FROM score s JOIN student st ON s.stu_no st.stu_no WHERE s.course_no C001 GROUP BY st.stu_class; -- 查询某学生的成绩排名 SELECT stu.stu_no, stu.stu_name, ROUND(AVG(s.score), 2) AS avg_score FROM score s JOIN student stu ON s.stu_no stu.stu_no WHERE s.semester 2024-2025-1 GROUP BY stu.stu_no, stu.stu_name ORDER BY avg_score DESC;这三条 SQL 覆盖了期末答辩 80% 的追问场景。第一条是基础的多表关联注意字段名前加表别名避免两张表里都有course_no时产生歧义。第二条的GROUP BY按班级分组求平均分是数据库课程里分组聚合的经典考点。第三条稍微进阶涉及分组和排序。写这几条 SQL 时血泪经验是ROUND(AVG(s.score), 2)里的AVG会忽略 NULL 值。如果某个学生某门课缺考录入时把分数留空了平均分算出来会偏高。更严谨的做法是先处理空值或者把缺考统一记为 0保证统计口径一致。答辩时主动提这一点老师会觉得你对数据的边界情况有意识。提示DAO 层拼接 SQL 时千万不要用字符串拼接用户输入要用 PreparedStatement 的占位符。这不仅是为了防止 SQL 注入更是因为占位符会让 SQL 预编译一次重复执行性能更好。很多期末项目的成绩查询页面能注入老师一眼就能看出来。4. 期末作业防翻车指南五个高频坑和对应的排查方法4.1 数据库连接失败时区、驱动、端口三个雷区现象Tomcat 启动正常浏览器打开页面一点“登录”就报Communications link failure或者Public Key Retrieval is not allowed。原因90% 的情况是 JDBC URL 配置不对。MySQL 8.x 之后驱动类从com.mysql.jdbc.Driver改成了com.mysql.cj.jdbc.DriverURL 里必须加serverTimezone参数否则驱动不知道当前时区连接直接失败。Public Key Retrieval is not allowed这个报错则是 MySQL 8.x 的认证插件导致的在 URL 末尾加allowPublicKeyRetrievaltrue即可解决。解决把连接 URL 改成下面这个完整版本——jdbc:mysql://localhost:3306/student_score?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8allowPublicKeyRetrievaltrue还有一个小概率的坑端口不是 3306。如果你电脑上装了多个 MySQL 实例或者用的是 XAMPP 自带的 MySQL端口可能被改成 3307 或 3308检查一下DriverManager.getConnection里的端口号。4.2 页面中文全部乱码编码过滤器没生效现象页面上的“学生成绩管理系统”显示成一段乱码数据库里的中文倒是正常的。原因JSP 页面声明的是 UTF-8但 Servlet 接收请求时没有设置请求编码或者 MySQL 连接字符串没加characterEncodingutf8。三个环节只要有一个断掉中文就乱。很多同学觉得乱码是玄学其实每个环节的编码都不复杂只是漏掉一个就要排查半天。解决在过滤器里加请求编码设置前面 AuthFilter 代码里已经写了在 JSP 页面顶部加% page contentTypetext/html;charsetUTF-8 languagejava %再把 HTML 的meta charsetUTF-8也写上。MySQL 建库时用utf8mb4连接 URL 里加characterEncodingutf8这三处都对了基本不会再乱码。4.3 JSP 页面风格完全没生效静态资源被过滤器拦截了现象页面功能正常但 CSS 样式全部丢失页面上只有文字没有排版图片也加载不出来。原因这个坑很隐蔽。你写了登录过滤器但没有放行.css和.js结尾的静态资源请求过滤器判断 Session 里没有用户直接把样式文件请求重定向回了登录页。解决在过滤器里加一个判断像前面代码里的uri.endsWith(.css)就返回放行。注意 JSP 页面引用 CSS 时要写${pageContext.request.contextPath}/css/style.css不要写相对路径css/style.css否则从二级目录的页面引用会找不到文件。4.4 项目在室友电脑上跑不起来绝对路径和连接配置写死了现象自己电脑上跑得好好的把代码发给同学同学报ClassNotFoundException或者数据库连不上。原因数据库密码写死在DBUtil.java里同学的 MySQL 密码不一样或者web.xml里配置的欢迎页路径带了自己的磁盘路径。解决数据库账号密码单独放在一个配置类里或者写成常量集中管理告诉同学改一个地方就行。代码里任何地方不要出现D:\xxx这样的绝对路径所有文件路径都用相对于项目的路径。Tomcat 的部署配置里项目名称不要写自己的学号缩写否则同学访问地址和你不一样也会踩坑。4.5 IDEA 运行 JavaWeb 项目Artifact 配置不对导致 404现象在 IDEA 里点了运行浏览器打开是 404控制台没有任何报错Tomcat 正常启动。原因JavaWeb 项目在 IDEA 里运行的机制是 Web Application 的 Artifact 被部署到 Tomcat。如果 Artifact 的名称和 URL 根路径不一致或者依赖的库没有打包进去Tomcat 能启动但找不到你的 Servlet。这是 IDEA 运行 JavaWeb 项目配置里最隐蔽的坑不报错但是全 404。解决打开 Project Structure快捷键 CtrlAltShiftS在 Artifacts 里确认 Web Application Exploded 的 Output Layout 里包含lib目录下的所有 jar 包。Run Configuration 里 Deployment 的 Application context 填/student_score或项目名和浏览器访问地址保持一致。编解码的设置也要看一下VM options 里加上-Dfile.encodingUTF-8能避免控制台乱码干扰判断。5. 从 90 分到 98 分三个让老师眼前一亮的加分功能5.1 数据可视化用 JFreeChart 生成成绩分布图基础版的学生成绩管理系统的页面全是表格哪怕做得好看一点也只是表格。但要往上拿分你需要一个图表——成绩分布直方图、某门课的平均分折线图这些数据可视化的东西会让答辩现场的气氛完全不一样。%-- score_chart.jsp - 在 JSP 页面中动态生成成绩分布图 --% % page importorg.jfree.chart.ChartFactory % % page importorg.jfree.chart.ChartUtilities % % page importorg.jfree.chart.JFreeChart % % page importorg.jfree.data.category.DefaultCategoryDataset % % page importjava.io.OutputStream % % // 从 DAO 层获取每个分数段的人数是关键这里简化展示 DefaultCategoryDataset dataset new DefaultCategoryDataset(); dataset.addValue(5, 人数, 90-100); dataset.addValue(12, 人数, 80-89); dataset.addValue(8, 人数, 70-79); dataset.addValue(3, 人数, 60-69); dataset.addValue(1, 人数, 不及格); JFreeChart chart ChartFactory.createBarChart( JavaWeb 课程成绩分布, // 图表标题 分数段, // 横轴标签 人数, // 纵轴标签 dataset // 数据 ); // 设置图片输出格式和编码中文不乱码的关键 response.setContentType(image/png); OutputStream outStream response.getOutputStream(); ChartUtilities.writeChartAsPNG(outStream, chart, 600, 400); outStream.close(); %这个方案生成的图表直接在img srcscore_chart.jsp里引用不需要额外的前端图表库。JFreeChart 的中文显示有一个大坑默认字体不支持中文图表里的中文标题会显示成方块。解决方法是调用chart.getTitle().setFont(new Font(宋体, Font.BOLD, 18))把标题、横轴、纵轴的字体都改成中文字体。更现代的做法是用 ECharts 在前端画图后端返回 JSON 数据。但期末作业里答辩老师更认可 JFreeChart 这类能和 JavaWeb 直接绑定的方案——因为你能当场讲清楚数据流是“数据库 → JavaBean → 图表”而不是直接引用别人写好的前端组件。5.2 导出 Excel用 Apache POI 把成绩单导出来期末作业里“导出成绩单”这个功能是加分项因为它触及了 JavaWeb 里一个很容易被忽略的问题文件下载时的中文文件名编码。// ExportScoreServlet.java - 导出 Excel 成绩单 package com.score.servlet; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import java.net.URLEncoder; import java.util.List; WebServlet(/exportScore) public class ExportScoreServlet extends HttpServlet { Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 创建 Excel 工作簿 Workbook workbook new XSSFWorkbook(); Sheet sheet workbook.createSheet(成绩单); // 创建表头行 String[] headers {学号, 姓名, 课程, 分数, 学期}; Row headerRow sheet.createRow(0); for (int i 0; i headers.length; i) { headerRow.createCell(i).setCellValue(headers[i]); } // 从数据库读取成绩数据逐行写入 // 这里省略了 DAO 调用实际项目用 ScoreDAO 查询 // ListScoreBean list new ScoreDAO().findAll(); // int rowNum 1; // for (ScoreBean bean : list) { ... } // 关键设置响应头中文文件名必须 URL 编码 resp.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); String fileName URLEncoder.encode(学生成绩单.xlsx, UTF-8); resp.setHeader(Content-Disposition, attachment; filename\ fileName \); OutputStream out resp.getOutputStream(); workbook.write(out); workbook.close(); out.close(); } }这个功能的两个考点是POI 的XSSFWorkbook用于生成 2007 格式的 xlsxHSSFWorkbook对应老版 xls中文文件名如果不做URLEncoder.encode浏览器下载时文件名会变成一串乱码或者直接报错。这两个细节在答辩时主动讲出来老师的印象分会直线上升。5.3 答辩必追的三个问题准备好就能稳过期末大作业的答辩环节老师通常会问三个方向的问题。第一个是“为什么这样设计数据库”——你要能说清楚为什么成绩表用联合主键而不是自增主键外键的作用是什么删了外键会怎样。第二个是“Session 的生命周期”——登录后 Session 什么时候创建、什么时候失效、退出登录时要不要调session.invalidate()以及关闭浏览器后 Session 还在不在。第三个是“这个系统如果上线哪里可能会崩”——高并发下连接池不够用怎么办这需要你至少说出“扩大连接池配置”和“增加缓存层”两个方向再扯上数据库查询优化里的索引基本就稳了。6. 一个让我后悔了许久的习惯先写页面还是先写数据库我的第一个 JavaWeb 大作业是先用 JSP 把页面全部写完才开始建表。结果页面里需要显示“班级平均分”表里没有班级字段需要显示“课程学分”成绩表里没有关联课程整个页面和数据对不上最后改了三轮页面结构。后来我换了一个习惯拿到题目先画表关系和字段再写页面的假数据最后才动手写真实代码。这个顺序的好处是建表的时候你已经把所有需要展示的字段想清楚了页面写假数据的时候你会发现哪些地方需要 JOIN、哪些地方需要聚合计算。数据库设计这件事画半个小时 ER 图比写半天代码再返工要快得多。而且答辩时你能把这张 ER 图打印出来给老师看这本身就是加分项。如果你手头有黑马 JavaWeb 课程的笔记里面关于 Session 生命周期和过滤器链的部分是这个系统的理论基础答辩前翻一翻。另一个我保留至今的习惯是每次改完代码第一步先看 Tomcat 控制台有没有异常第二步打开浏览器按用户角色走一遍流程第三步打开数据库看数据有没有被正确写入。这套流程走完功能才算真正改完不是编译通过就完事。学生成绩管理系统的代码量其实不大核心逻辑不超过一千行难点在于你对每一段代码的理解。如果你现在能照着这篇笔记把数据库脚本跑起来、把过滤器逻辑讲清楚、把三条核心 SQL 默写出来98 分不是靠运气是靠你把每一步都踩实了。希望帮到你。本文还有配套的精品资源点击获取
返回列表