简介:这是一套完整的JavaWeb学生选课系统项目源码,适用于高校课程设计与毕业设计实践,面向Java初学者及Web开发入门者,解决教务管理类系统从开发到部署的全流程学习需求。资源包共305个文件,涵盖37个核心Java业务类、18个JSP页面、40个CSS样式文件、110张界面截图(PNG),以及SQL建库脚本、Eclipse工程配置文件和MySQL数据库文件等,整体压缩后仅6.94MB,结构清晰、模块分明。已有3558人学习下载,配套提供B站实操视频教程(含IDEA导入与运行详解)及图文部署指南,覆盖学生、教师、管理员三角色完整权限体系,包含选课、成绩管理、公告发布、班级课程维护等典型业务逻辑,代码规范、注释充分,便于二次开发与功能扩展。
1. 项目概述与价值定位
最近在整理硬盘里的老项目,翻出来一个当年带学生做毕业设计时用的JavaWeb学生选课系统。这个项目虽然技术栈不算新潮,但胜在结构完整、功能闭环,从数据库设计到前端页面一应俱全,特别适合正在学习JavaWeb开发、需要找一个完整项目来练手或者作为课程设计/毕业设计参考的同学。我发现网上很多所谓的“完整项目”源码,要么缺东少西跑不起来,要么部署步骤写得云里雾里,让初学者望而却步。所以,我决定把这个老项目重新整理一下,不仅提供清晰的源码,还会配上详细的图文步骤,甚至录制一个完整的视频部署教程,目标就是让你拿到手后,能真正地在自己的电脑上把项目跑起来,看到效果,理解每一行代码背后的逻辑。
这个选课系统涵盖了学生、教师、管理员三种角色。学生可以查看可选课程、进行选课、退课,查看个人课表;教师可以发布自己教授的课程、管理选课学生名单、录入成绩;管理员则负责管理学生和教师的基础信息、管理整个系统的课程库。技术栈是经典的JavaWeb“三件套”:Servlet + JSP + JDBC,数据库用的是MySQL,开发工具是IntelliJ IDEA。这套组合是理解JavaWeb开发基石的最佳路径,没有太多花哨的框架,能让你把HTTP请求、会话管理、数据库连接这些核心概念吃透。接下来,我会从环境准备开始,一步步带你完成整个项目的部署和运行。
2. 本地开发环境全链路搭建
在开始导入代码之前,一个干净、版本匹配的开发环境是成功的第一步。很多部署失败的问题,根源都出在环境配置上。这里我会详细说明每个环节的选型理由和关键配置点。
2.1 JDK版本选择与安装验证
项目基于Servlet规范开发,对JDK版本有一定要求。我推荐使用JDK 8或JDK 11这两个长期支持(LTS)版本。JDK 8兼容性最广,几乎所有老项目都能无缝运行;JDK 11则是目前企业级应用仍在广泛使用的版本,性能和安全更新更有保障。不建议使用最新的JDK 17或更高版本,可能会遇到一些旧版本库的兼容性问题。
安装完成后,关键一步是验证环境变量。打开命令行(Windows的CMD或PowerShell,Mac/Linux的Terminal),依次输入以下命令:
java -version javac -version这两个命令分别用于检查Java运行环境和编译器的版本。你需要确保它们的输出版本号一致,并且都是以“1.8”或“11”开头。如果只配置了JAVA_HOME而没有将%JAVA_HOME%\bin添加到系统的PATH环境变量中,可能会出现java命令可用但javac不可用的情况,这会导致后续项目无法编译。
注意:如果你电脑上安装了多个JDK,需要确认当前命令行环境下生效的是哪一个。可以通过
where java(Windows)或which java(Mac/Linux)命令查看实际调用的java程序路径。
2.2 MySQL数据库部署与初始化
数据库我们选择MySQL 5.7或8.0版本。对于初学者,我强烈建议使用MySQL Installer(Windows)或直接下载MySQL Community Server压缩包进行安装。安装过程中,请牢记你设置的root用户密码,这是后续连接数据库的钥匙。
安装完成后,我们需要创建本项目专用的数据库和用户。不推荐直接使用root用户来连接应用,这有安全风险。打开MySQL命令行客户端或使用MySQL Workbench这类图形化工具,执行以下SQL语句:
-- 创建数据库,字符集使用utf8mb4以支持完整的UTF-8编码(包括表情符号) CREATE DATABASE IF NOT EXISTS `course_selection_db` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 创建一个新用户,并设置密码 CREATE USER 'course_user'@'localhost' IDENTIFIED BY 'YourStrongPassword123!'; -- 授予该用户对course_selection_db数据库的所有权限 GRANT ALL PRIVILEGES ON `course_selection_db`.* TO 'course_user'@'localhost'; -- 刷新权限,使授权生效 FLUSH PRIVILEGES;执行成功后,你就拥有了一个名为course_selection_db的数据库,和一个专门用于访问它的用户course_user。记住这里设置的密码,需要填入项目配置文件中。
2.3 IDE与Web服务器准备
集成开发环境(IDE)选用IntelliJ IDEA Ultimate版或Community版均可。Ultimate版对Java Web开发支持更友好,自带Tomcat集成和数据库工具。Community版需要手动配置,但完全够用。
Web服务器我们使用Apache Tomcat 9。这是与Servlet 4.0规范对应的稳定版本,对JDK 8和11支持良好。去Apache官网下载“zip”或“tar.gz”格式的压缩包,解压到任意目录即可,例如D:\dev\tomcat-9.0.xx。这就是所谓的“绿色版”,无需安装。
接下来是关键的IDE配置:在IDEA中配置Tomcat。打开IDEA,进入File -> Settings -> Build, Execution, Deployment -> Application Servers,点击“+”号,选择“Tomcat Server”。在“Tomcat Home”一项中,浏览并选中你刚才解压的Tomcat根目录。IDEA会自动识别版本。配置好后,你可以在IDEA的右上角运行配置下拉菜单中看到“Tomcat 9.0.xx”的选项,这为后续一键启动项目打下了基础。
3. 项目源码结构与核心配置解析
拿到项目源码压缩包后,首先解压。用IDEA打开项目根文件夹。正确的项目结构是理解一切的基础,我带你快速过一遍关键目录和文件。
3.1 项目目录树与模块功能
一个标准的JavaWeb项目通常呈现如下结构(部分非核心目录已省略):
StudentCourseSystem/ ├── src/ # Java源代码目录 │ ├── main/ │ │ ├── java/ # 核心Java类 │ │ │ ├── com.example.dao/ # 数据访问层(DAO),封装所有数据库操作 │ │ │ ├── com.example.model/ # 实体类(Model),对应数据库表,如Student, Course, Teacher │ │ │ ├── com.example.service/# 业务逻辑层(Service),处理复杂业务规则 │ │ │ └── com.example.servlet/# 控制器(Servlet),接收HTTP请求,调用Service,转发JSP │ │ └── webapp/ # Web应用资源目录 │ │ ├── WEB-INF/ │ │ │ ├── web.xml # 核心部署描述文件,配置Servlet、过滤器等 │ │ │ └── lib/ # 项目依赖的第三方JAR包,如MySQL驱动、JSTL标签库 │ │ ├── css/ # 样式表文件 │ │ ├── js/ # JavaScript文件 │ │ ├── images/ # 图片资源 │ │ └── *.jsp # JSP视图文件,位于webapp根目录或子目录下 ├── pom.xml # Maven项目配置文件(如果项目是Maven构建) └── README.md # 项目说明文档对于非Maven的普通JavaWeb项目,lib文件夹下的JAR包需要手动管理。本项目必须包含mysql-connector-java-xxx.jar(数据库驱动)和jstl.jar、standard.jar(JSTL标签库,用于在JSP中简化代码)。请检查WEB-INF/lib下是否存在这些文件,如果缺失,需要自行下载对应版本放入。
3.2 数据库连接池配置详解
数据库连接是Web应用的命脉。直接使用DriverManager获取连接在并发场景下性能极差且不稳定,因此我们采用连接池技术。本项目使用一种简单实现的连接池(或可能是DBCP、C3P0),其配置通常放在一个DBUtil或ConnectionPool类中,或者位于WEB-INF/classes下的.properties配置文件中。
你需要找到数据库连接配置的部分,核心是四个参数:
// 通常以这种形式出现在代码的静态块或配置文件中 private static final String DRIVER = "com.mysql.cj.jdbc.Driver"; private static final String URL = "jdbc:mysql://localhost:3306/course_selection_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai"; private static final String USERNAME = "course_user"; private static final String PASSWORD = "YourStrongPassword123!";关键点解析:
- DRIVER:
com.mysql.cj.jdbc.Driver是MySQL 8.0及以后版本的驱动类名。如果你用的是MySQL 5.7,驱动类名可能是com.mysql.jdbc.Driver。如果启动时报“ClassNotFoundException”指向驱动类,就需要检查并修改这个值。 - URL:
jdbc:mysql://localhost:3306/course_selection_db是连接字符串。localhost指数据库服务器在本机,如果数据库安装在另一台机器或使用Docker,需替换为对应的IP地址。3306是MySQL默认端口。course_selection_db是数据库名,务必与你创建的库名一致。 - 参数:
useUnicode=true&characterEncoding=utf8确保正确处理中文。useSSL=false在本地开发环境通常关闭SSL连接以简化配置。serverTimezone=Asia/Shanghai设置时区,避免时间字段出现时差问题,这个参数对MySQL 8.0尤其重要。 - USERNAME/PASSWORD: 填入你之前创建的
course_user及其密码。
3.3 数据库脚本导入与表结构分析
光有数据库和连接配置还不够,我们需要创建具体的表结构和初始数据。在项目根目录或sql文件夹下,你应该能找到名为course_selection_db.sql或init_database.sql的文件。这个文件包含了创建所有表(如student,teacher,admin,course,student_course选课关系表等)的CREATE TABLE语句,以及可能存在的初始数据INSERT语句。
使用MySQL命令行或图形化工具(如Navicat、MySQL Workbench)连接数据库后,执行这个SQL文件。执行成功后,查看数据库,应该能看到一系列表。理解这些表的结构和关系至关重要:
student表:存储学生信息,主键可能是学号(student_id)或自增ID。course表:存储课程信息,包含课程ID、名称、学分、授课教师ID(外键关联teacher表)、容量等。teacher表:存储教师信息。student_course表:这是选课系统的核心,是一个“关联表”或“中间表”。它至少包含student_id和course_id两个外键,共同作为联合主键,表示一个学生选了一门课。还可能包含score字段记录成绩。 这种“学生-课程”的多对多关系,正是通过student_course这张关联表来实现的。理解这一点,对看懂后续业务逻辑代码很有帮助。
4. 在IDEA中部署与运行项目
环境就绪,源码和数据库也准备好了,现在让我们把项目“跑”起来。这一步是将静态代码变成动态应用的关键。
4.1 配置项目模块与依赖
首先,确保IDEA正确识别了这是一个Web项目。在IDEA中,右键点击项目根目录,选择Open Module Settings(或按F4)。在Project Structure对话框中:
- 在
Project标签页,确认Project SDK是你安装的JDK(如1.8)。 - 在
Modules标签页,选中你的项目模块。在右侧的Sources标签页,确保src目录被标记为蓝色(Sources根)。在Paths标签页,确认Compiler output指向一个合理的输出目录(如项目根目录/target/classes对于Maven项目,或out/production/项目名对于普通项目)。 - 最关键的一步在
Dependencies标签页。你需要确保Module SDK正确,并且所有必需的JAR包都在依赖列表中。对于普通Web项目,你需要点击“+”号,选择JARs or directories,然后导航到WEB-INF/lib目录,全选里面的JAR包添加进来。这样IDEA在编译时才能找到这些库。
4.2 配置Tomcat运行/调试配置
点击IDEA右上角运行配置下拉菜单(通常显示为“Add Configuration…”),选择Edit Configurations。点击“+”号,选择Tomcat Server -> Local。
- Server标签页:确认
Application server指向你之前配置好的Tomcat 9。可以勾选After launch启动浏览器,并设置默认打开的浏览器和URL(例如http://localhost:8080/你的项目上下文路径)。 - Deployment标签页:点击“+”号,选择
Artifact。如果你的项目正确配置,这里应该会列出可部署的工件,通常是一个带有:war或:war exploded后缀的选项。务必选择带有exploded(展开)的版本。exploded意味着IDEA会直接使用编译输出的目录结构进行部署,支持热部署(修改代码、JSP或静态资源后,无需重启Tomcat,仅需重新编译或刷新页面即可生效),极大提升开发调试效率。而war包每次修改都需要重新打包部署。 - 在
Application context输入框中,设置项目的上下文路径(Context Path)。例如,设置为/course,那么应用访问地址就是http://localhost:8080/course。你可以简化为/,这样访问根目录即可,但要注意可能与Tomcat默认主页冲突。
4.3 启动服务器与首次访问
配置完成后,点击OK保存。然后点击IDEA工具栏的绿色运行按钮或调试按钮。IDEA会开始构建项目,并将项目部署到内置的Tomcat,然后启动Tomcat服务器。观察下方的Run或Services工具窗口,看到类似[Tomcat] Started Server startup in [xxxx] milliseconds的日志,即表示启动成功。
打开浏览器,访问你配置的地址,如http://localhost:8080/。你应该能看到系统的登录页面。这是第一个里程碑。尝试使用项目sql脚本中提供的初始账号(例如,管理员账号admin/密码123456,学生账号1001/密码123等)进行登录。如果成功进入系统首页,恭喜你,项目部署的核心流程已经走通。
5. 图文部署教程:从零到一的每一步截图
为了应对可能出现的各种环境差异和报错,我准备了详细的图文步骤。这里用文字描述关键节点的截图内容和操作要点,你可以对照操作。
第一步:IDEA导入项目。截图显示IDEA启动后,选择Open or Import,浏览到项目解压后的文件夹,点击OK。关键点:IDEA可能会提示“这是一个Maven项目,是否导入?”如果项目根目录有pom.xml,选择“作为Maven项目导入”;如果没有,选择“作为普通项目打开”。
第二步:检查项目结构。截图显示IDEA左侧的Project视图,目录树应如前文所述般清晰。重点检查WEB-INF/lib文件夹是否展开,里面应有mysql驱动等JAR包。如果lib文件夹是空的(图标上可能有感叹号),则需要手动添加。
第三步:配置数据库连接。截图显示找到src目录下的数据库工具类(如DBUtil.java),代码编辑器区域高亮显示URL、USERNAME、PASSWORD等字符串。在旁边用箭头标注:“修改此处为你的数据库信息”。
第四步:执行SQL脚本。截图显示MySQL Workbench的查询窗口,左侧导航栏已连接到course_selection_db。右侧SQL编辑器中打开了init.sql文件,点击工具栏的“闪电”图标执行。下方结果窗口显示“Query OK, 0 rows affected”或类似成功信息,并且左侧表列表刷新出新的表。
第五步:配置Tomcat。截图显示Run/Debug Configurations对话框的Deployment标签页。Artifact列表里,项目名:war exploded被选中并高亮。下方Application context设置为/。旁边有文字提示:“务必选择带‘exploded’的工件,支持热部署”。
第六步:启动与访问。截图显示IDEA运行后,下方Run窗口的日志,最后几行是Tomcat启动成功的标志。浏览器窗口并排显示,地址栏为http://localhost:8080/,页面已显示系统的登录界面。
6. 常见部署故障排查与解决
即使按照步骤操作,也可能会遇到问题。下面我列出几个最常见的“坑”及其解决方案。
6.1 “404 - 未找到”错误分析
访问http://localhost:8080/出现404,这是最高频的问题。
- 检查上下文路径:首先确认你访问的URL是否正确。如果你在Tomcat配置中将
Application context设为了/course,那么你需要访问http://localhost:8080/course。如果设为/,则直接访问http://localhost:8080。Tomcat默认占用8080端口,如果端口被修改,也需要相应调整。 - 检查项目是否成功部署:打开Tomcat的管理页面
http://localhost:8080/manager/html(需要配置Tomcat用户角色,详见Tomcat文档),查看“Applications”列表里是否有你的项目。或者,直接去Tomcat的webapps目录(位于你解压的Tomcat文件夹内),看是否有以你项目名或上下文路径命名的文件夹(或WAR包)。如果IDEA使用的是exploded部署,你会在webapps下看到一个名为ROOT(如果上下文是/)或你的上下文名的文件夹,里面应有WEB-INF等结构。 - 检查默认欢迎页面:在项目的
web.xml中,通常配置了<welcome-file-list>,指定了如index.jsp、login.jsp等为欢迎文件。请确保webapp根目录下存在这些文件。
6.2 “500 - 内部服务器错误”与数据库连接问题
登录或进行数据库操作时出现500错误,控制台(IDEA的Run窗口或Tomcat的logs/catalina.out日志文件)会打印详细的异常堆栈信息,这是解决问题的关键。
- ClassNotFoundException: com.mysql.jdbc.Driver:驱动类未找到。原因:
WEB-INF/lib下没有mysql连接器的JAR包,或者JAR包版本与代码中DRIVER字符串不匹配(如用MySQL 8的驱动类去连接MySQL 5)。解决:检查lib目录,确保有mysql-connector-java-xxx.jar文件。核对驱动类名,MySQL 5.x通常是com.mysql.jdbc.Driver,MySQL 8.x是com.mysql.cj.jdbc.Driver。 - Communications link failure或Access denied for user:数据库连接失败。原因:数据库服务未启动、连接URL写错(IP、端口、数据库名)、用户名密码错误、或数据库用户权限不足。解决:首先确保MySQL服务已启动(可在服务管理器中查看)。使用数据库客户端(如MySQL Workbench)尝试用项目配置中的用户名密码连接,验证其有效性。检查连接URL中的数据库名是否已创建。
- The server time zone value ‘xxx’ is unrecognized:时区问题,常见于MySQL 8.0。解决:在数据库连接URL后加上
&serverTimezone=Asia/Shanghai(或GMT%2B8等其他东八区表示法)。
6.3 中文乱码问题全方位处理
中文乱码可能出现在浏览器页面显示、浏览器提交数据到后台、后台数据存入数据库或从数据库读出等多个环节。
- JSP页面显示乱码:确保JSP文件本身以UTF-8编码保存(IDEA右下角可查看和更改文件编码)。在JSP页面头部添加:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>。 - 表单提交乱码:对于POST请求,在Servlet的
doPost方法最开头,添加request.setCharacterEncoding("UTF-8");。对于GET请求,Tomcat 8.5以上版本默认已较好处理,若仍有问题,可能需要修改Tomcat的server.xml中Connector的URIEncoding="UTF-8"属性。 - 数据库乱码:确保三处统一为UTF-8:
- 数据库层面:创建数据库时指定了
CHARACTER SET utf8mb4。 - 连接层面:JDBC URL中包含了
useUnicode=true&characterEncoding=UTF-8(注意,这里写UTF-8,而非utf8)。 - 表层面:建表语句中,字符串字段(VARCHAR, TEXT)的字符集也应是
utf8mb4。
- 数据库层面:创建数据库时指定了
7. 项目核心功能模块代码走读
项目跑起来后,我们可以深入代码,理解其实现逻辑。这里选取几个核心流程进行走读。
7.1 用户登录与会话管理流程
登录是系统的入口。我们跟踪login.jsp表单提交后的过程。
- 前端提交:
login.jsp中的表单<form action="LoginServlet" method="post">,会将用户名和密码提交到名为LoginServlet的Servlet。 - Servlet处理:在
src下的LoginServlet类中,doPost方法会通过request.getParameter()获取用户名和密码。然后,调用UserService(业务逻辑层)的login方法进行验证。 - 业务逻辑与数据访问:
UserService的login方法内部,会调用UserDao(数据访问层)的方法,执行类似SELECT * FROM user WHERE username=? AND password=?的SQL查询(实际中密码应是加密存储的,这里示例可能为明文对比)。 - 会话创建:如果查询到用户,
LoginServlet会通过HttpSession session = request.getSession();获取当前会话(如果不存在则创建),并将用户对象(如User或Student)存入session中,例如session.setAttribute("currentUser", user);。然后重定向到主页(response.sendRedirect("index.jsp"))。 - 权限过滤:系统通常有一个
Filter(过滤器),配置在web.xml中,拦截所有请求(除了登录、注册等公开页面)。在Filter的doFilter方法里,它会检查session中是否存在currentUser属性。如果不存在,则说明用户未登录,直接重定向到登录页面。这就是基本的权限控制。
7.2 学生选课业务逻辑与并发控制
选课是系统的核心业务,涉及业务规则和简单的并发控制。
- 业务规则校验:在
CourseSelectionServlet中,当学生点击选课,Servlet会调用CourseService.selectCourse(studentId, courseId)。Service层需要执行一系列校验:- 课程是否存在且状态为“可选”。
- 学生是否已选过该课程(防止重复选课)。
- 课程当前已选人数是否小于容量(
selected < capacity)。 - 学生已选总学分是否超过上限(如有此规则)。 这些校验通常需要在同一个数据库事务中完成,以确保数据一致性。
- “先查后改”的并发问题:典型的选课逻辑是:先查询课程当前已选人数
selected,判断selected < capacity,如果成立,则执行UPDATE course SET selected = selected + 1 WHERE course_id = ?。在高并发下,多个线程可能同时读到相同的selected值(比如49,容量50),都判断通过,然后都去执行UPDATE,导致最终selected变成51,超出了容量。这就是“超卖”问题。 - 解决方案:一种简单有效的办法是在SQL的WHERE条件中加入容量检查。将更新语句改为:
这条SQL是原子的。执行后,检查数据库返回的“受影响行数”(JDBC中UPDATE course SET selected = selected + 1 WHERE course_id = ? AND selected < capacityexecuteUpdate()的返回值)。如果返回1,表示更新成功,选课成功;如果返回0,表示条件不满足(已满),选课失败。这样就将“查询-判断-更新”的非原子操作,变成了一个原子操作,有效防止了并发超卖。Service层代码需要根据这个返回值来决定是插入选课记录,还是返回“课程已满”的错误信息。
7.3 数据库事务在成绩录入中的应用
教师录入成绩时,可能涉及更新student_course表中的成绩字段,同时可能需要更新学生总绩点(GPA)等衍生数据。这些操作应该在一个事务中完成。 在Servlet中,我们通常不直接处理事务,而是交给Service层。在GradeService.enterGrade方法中,伪代码如下:
public boolean enterGrade(int studentId, int courseId, float score) { Connection conn = null; try { conn = DBUtil.getConnection(); // 从连接池获取连接 conn.setAutoCommit(false); // 开启事务(关闭自动提交) // 操作1:更新选课表中的成绩 GradeDao.updateGrade(conn, studentId, courseId, score); // 操作2:重新计算并更新学生的平均绩点 StudentDao.updateGPA(conn, studentId); conn.commit(); // 提交事务 return true; } catch (SQLException e) { if (conn != null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } // 回滚事务 } e.printStackTrace(); return false; } finally { DBUtil.closeConnection(conn); // 将连接归还给连接池 } }关键点:setAutoCommit(false)、commit()、rollback(),以及同一个事务必须使用同一个Connection对象,因此需要将conn作为参数传递给各个Dao方法。这样才能保证这两步操作要么全部成功,要么全部失败,避免出现成绩更新了但GPA未更新的数据不一致状态。
8. 项目扩展与优化思路
基础功能跑通后,你可以基于此项目进行扩展和优化,这会让你的学习更深入,项目经验也更亮眼。
8.1 前端界面美化与交互增强
原项目前端可能比较简单,使用原生JSP和基础CSS。你可以引入前端框架来大幅提升体验。
- 引入Bootstrap:这是最快的方式。下载Bootstrap的CSS和JS文件,放入项目的
webapp/css和webapp/js目录,或在JSP页面中直接引用CDN链接。使用Bootstrap的栅格系统、组件(导航栏、表格、按钮、表单、模态框)可以快速构建出现代化、响应式的界面。例如,将课程列表用Bootstrap的卡片(Card)组件展示,选课按钮用不同的颜色状态表示。 - 使用AJAX优化体验:将部分同步请求改为异步。例如,学生点击“选课”按钮,不必刷新整个页面。可以使用原生JavaScript的
XMLHttpRequest或更简单的fetchAPI,或者引入jQuery的$.ajax,向一个专门的Servlet(如AjaxSelectCourseServlet)发送请求。该Servlet处理完成后,返回JSON格式的结果(如{"success": true, "message": "选课成功"}或{"success": false, "message": "课程已满"})。前端JavaScript根据返回的JSON结果,动态更新页面上的提示信息或按钮状态。这能极大提升操作流畅度。
8.2 架构演进:引入Maven与Spring框架
当前项目是传统的JSP/Servlet结构,依赖管理手动进行。可以尝试将其改造为Maven项目,并逐步引入Spring框架。
- Maven化:在项目根目录创建
pom.xml文件。将WEB-INF/lib下的JAR包依赖,转换为Maven的<dependencies>。例如:
使用Maven后,IDEA可以自动下载和管理依赖,项目结构也更标准。<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> - 引入Spring MVC:用Spring MVC替代原生的Servlet。首先在
pom.xml中添加Spring MVC相关依赖。然后,配置web.xml,使用DispatcherServlet作为前端控制器。创建Spring的配置文件(如spring-mvc.xml),启用注解驱动(<mvc:annotation-driven/>),配置视图解析器(将Controller返回的字符串映射到/WEB-INF/views/下的JSP文件)。最后,将原来的Servlet改造成带有@Controller注解的类,其中的方法使用@RequestMapping来映射请求。Spring的IoC容器还能帮你管理Service和Dao层的对象,通过@Autowired进行依赖注入,代码会更简洁、更解耦。
8.3 安全性与性能考量实践
- 密码安全:当前项目中的密码很可能是明文存储和比较的,这是严重的安全隐患。必须改用哈希加盐的方式存储密码。例如,使用BCrypt算法。在用户注册或修改密码时,调用
BCrypt.hashpw(plainPassword, BCrypt.gensalt())生成哈希值存入数据库。在登录验证时,调用BCrypt.checkpw(plainPassword, storedHash)进行比对。Java中可以使用spring-security-crypto库或独立的jBCrypt库。 - SQL注入防护:检查所有Dao层的代码,是否使用了
Statement进行字符串拼接来构造SQL。如果是,必须全部改为使用PreparedStatement。PreparedStatement使用占位符?,能从根本上防止SQL注入攻击。这是Web开发必须养成的习惯。 - 连接池优化:如果项目使用的是简单的自实现连接池,可以考虑替换为成熟的HikariCP或Druid。以HikariCP为例,它性能极高。引入其JAR包后,在代码中配置
HikariConfig并创建HikariDataSource,用它来提供数据库连接。在DBUtil中,将原来的获取连接方式改为从HikariCP数据源中获取。这能显著提升高并发下的数据库访问性能。 - 日志记录:添加日志框架,如SLF4J + Logback。在关键业务节点(登录成功/失败、选课、成绩录入)、异常捕获处记录日志,而不是简单使用
System.out.println或e.printStackTrace()。这有助于线上问题的排查和审计。
本文还有配套的精品资源,点击获取