
简介这是一套基于JavaWeb的在线学习系统采用B/S结构后台以JSP、Servlet、JDBC为主配合MySQL数据库覆盖管理员、教师、学生三种角色实现专业班级管理、学生与教师管理、作业发布与下载、公告留言、在线自测、资料下载、教学视频查看等功能适合计算机相关专业毕业设计或Java学习者开展项目实战。资源包共3个文件含完整项目源码zip、MySQL数据库脚本sql及项目说明txt总大小约23.22MB目录结构清晰便于导入Eclipse与Tomcat环境部署运行。项目经过严格调试确保可直接运行并附开发工具、数据库脚本和说明文档能帮助读者快速理解前后端逻辑与权限设计可直接作为毕设使用或在其基础上扩展功能。目前已有6373人学习下载适合需要快速搭建在线学习平台、积累JavaWeb开发经验的读者。1. 一个JavaWeb在线学习系统毕设到底在拼什么源码、脚本与跑通之间的距离带过几届毕业设计你会发现“基于JavaWeb的在线学习系统”是最稳也最卷的选题之一。它不惊艳但结构完整有用户角色、有课程内容、有学习行为记录能把 Servlet、JSP、MySQL 和前端页面串成一条能演示的完整链路。很多同学拿到这类项目源码数据库脚本后第一反应是直接导入 IDEA 点运行结果十有八九卡在环境匹配、数据库连不上、访问 404 这些地方。这篇文章不聊虚的按我平时带项目验收的顺序把模块设计、IDEA 运行配置、数据库脚本导入、排障和答辩前改造一次讲完。适合准备交毕设的人也适合想拿这套题练手的人。2. 先把在线学习系统拆成模块角色、课程与学习记录的数据结构拿到源码第一步不要急着跑先打开数据库脚本看表结构。表结构是整套代码的地基地基不对后面所有排查都是白费。很多 JavaWeb 项目完整案例的 MySQL 脚本里表都是现成的但你得看懂它因为答辩时老师第一件事就是让你讲表设计。理解表结构还有一个实际好处改配置、改页面时你知道哪些字段会被拼进 SQL不会把“业务问题”误判成“代码问题”。2.1 三种角色一张用户表还是三张表我见过的毕设里最常见的错误是把学生、教师、管理员做成三张独立表登录时先去判断角色再查对应表登录逻辑写得又长又容易漏。常见做法是用一张 user 表加 role 字段来区分角色因为登录认证只关心账号密码角色只是后续授权的一个标记。这样的设计在答辩时也更容易讲清楚用户改角色就 UPDATE 一个字段不用动三张表。CREATE TABLE user ( id int NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 登录账号, password varchar(64) NOT NULL COMMENT 密码建议MD5或加盐, role tinyint NOT NULL DEFAULT 2 COMMENT 角色1管理员 2学生 3教师, nickname varchar(50) DEFAULT NULL COMMENT 显示昵称, created_at datetime DEFAULT CURRENT_TIMESTAMP COMMENT 注册时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表;字段说明AUTO_INCREMENT 让主键自增UNIQUE KEY 保证用户名唯一登录时按 username 查一定只有一条记录password 长度留到 64 是因为常见的 MD5/SHA-256 散列结果都是这个量级。如果你遇到用明文密码的源码答辩前一定要改成散列否则这就是送分给老师挑刺。role 用 tinyint 比 varchar 省空间但代码里要有明确注释不然这块就成了黑匣子。一张 user 表只解决认证问题。学生要存学号、班级教师要存工号、职称这些扩展字段不要直接堆在 user 表里建议拆成 student_info 和 teacher_info 两张子表用 user_id 关联。理由也简单在线学习系统里一个用户可能同时是学生和助教角色调整时只需要在子表里加一条记录而不是改 user 表结构。这样设计的另一个好处体现在权限拦截器上。登录成功后从 session 里取出 user再根据 role 字段决定跳转到学生首页、教师后台还是管理员后台一个 switch 就写完不会出现“老师登录后走学生逻辑”这种低级 bug。如果你拿到的源码不是这个结构也不需要重写只要保证登录功能正常把角色判断逻辑抽出来单独讲就行。2.2 课程、章节、学习记录核心表的关系与字段在线学习系统的业务核心是“课程-章节-学习记录”这条链。课程表保存课程基本信息章节表挂到课程下面学习记录表把学生和章节关联起来这就是最小可运行的模型。再加课程分配表教师与课程关系和评论表就是一个能撑起演示的完整结构。CREATE TABLE course ( id int NOT NULL AUTO_INCREMENT, title varchar(100) NOT NULL COMMENT 课程标题, teacher_id int NOT NULL COMMENT 教师用户ID, cover varchar(255) DEFAULT NULL COMMENT 封面图路径, description text COMMENT 课程简介, status tinyint DEFAULT 1 COMMENT 0未发布 1已发布, created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_teacher (teacher_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT课程表;course 表里为什么存 teacher_id 而不是 teacher 姓名因为姓名是可变化的名字变了会导致历史数据不一致。查询时通过 JOIN user 表把教师昵称带出来即可。status 字段很有用学生端只查 status1 的课程管理员后台可以保留未发布的草稿课程。很多源码没有这个字段演示“发布课程”功能时还要临时 UPDATE 数据很被动。学习记录表是整场答辩的加分点老师一定会问“你系统怎么知道用户学了多少”。设计时要注意“记录粒度”是按课程记一条总进度还是按章节记明细。按章节记更合理因为视频播放进度第几分钟是挂在章节上的。CREATE TABLE study_record ( id int NOT NULL AUTO_INCREMENT, student_id int NOT NULL COMMENT 学生用户ID, chapter_id int NOT NULL COMMENT 章节ID, course_id int NOT NULL COMMENT 课程ID冗余字段方便统计, duration int DEFAULT 0 COMMENT 本次学习时长秒, last_position int DEFAULT 0 COMMENT 视频播放进度秒, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_student_chapter (student_id, chapter_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学习记录表;注意 study_record 里的 UNIQUE KEY它的意思是“一个学生针对一个章节只保留一条记录”适合记录最后播放位置和累计时长。如果业务想保留每次学习的完整历史这个唯一索引就得去掉改成每次插入新记录统计时再聚合。两种设计都能自圆其说关键是别让表和代码逻辑互相矛盾——我就见过表结构有唯一索引代码里却每次都 INSERT结果日志里全是 Duplicate entry 报警。章节表 chapter 我一般建议包含 course_id、title、video_url、content、sort_order 五个核心字段。sort_order 尤其重要它决定课程内容的播放顺序如果在代码里按 id 排序后续在后台插播章节时顺序就乱了。这一层是纯设计话题但每次带学生改项目我都发现先画一张“表关系图”再去改代码效率至少翻一倍。2.3 数据库脚本里该预置哪些数据拿到数据库脚本先别急着执行用记事本打开看三样东西开头是不是有 CREATE DATABASE中间有没有 DROP TABLE尾部有没有 INSERT INTO。前两个决定执行方式第三个决定这个脚本是不是“空壳”。很多所谓数据库脚本只有建表语句没有初始化数据这种脚本执行完只能得到一个空库登录页面永远提示用户不存在。按我的习惯脚本里至少要预置 1 个管理员、2 个教师、2 个学生、3 门课程每门课程挂 5 个左右的章节。这是演示的底线数据。管理员账号一般是 admin/admin123 或 admin/123456教师和学生对应用户名 teacher01、student01。预置数据的 SQL 大概是这样的INSERT INTO user (id, username, password, role, nickname) VALUES (1, admin, 25f9e794323b453885f5181f1b624d0b, 1, 系统管理员), (2, teacher01, 25f9e794323b453885f5181f1b624d0b, 3, 王老师), (3, student01, 25f9e794323b453885f5181f1b624d0b, 2, 李同学);这里密码串是 MD5(123456) 的结果如果你在源码里发现密码校验是这种写法直接用同一个散列串就能对上。坑在于有些项目用了加盐比如对“123456 salt”做散列那脚本里的密码必须重新按相同规则生成否则登录永远报错你还会以为数据库连错了。查这个事最快的方法是看源码里注册功能那段找到密码加密的函数拿它生成初始化数据。如果脚本里没有预置数据也不要硬编。先看源码里有没有 test 包或 sql 目录里面往往藏着第二份脚本。都没有的话建议自己写一个简单的 DataInitializer在项目启动时判断 user 表为空就插入管理员这样比手动往库塞数据更可控。这种“项目源码数据库脚本”的毕设数据脚本的完整度直接决定你能不能跑通值得多花十分钟检查。3. 用IDEA运行JavaWeb项目环境版本、连接配置与Tomcat部署项目导入后一屏红字十有八九不是代码问题是环境版本不匹配。IDEA 运行 JavaWeb 项目的配置看起来简单其实每一步都有对应的坑JDK 和 Maven 对应不上依赖下不下来MySQL 驱动版本和数据库版本不匹配连接报错Tomcat 的 Application context 配错项目起来也是 404。按下面的顺序过一遍能省掉大半的启动问题。3.1 环境版本核对JDK、Maven、Tomcat和MySQL先对齐先看项目根目录有没有 pom.xml再决定怎么导入。有 pom.xml 就是 Maven 工程导入后依赖会自动下载没有 pom.xml 但有 lib 目录就是传统 Web 工程需要手动加 Libraries。这个判断错了后面 Actions 全是白费。常见稳定组合如下组件老项目常见组合新一点的项目常见组合JDK1.81.8 或 11Maven3.6.33.8Tomcat8.59.0MySQL5.78.0JDK 17 能不能跑如果是纯 ServletJSP 项目勉强能跑但如果是基于老版本 Spring 的反射和模块化会有一堆麻烦。我的底线是只要 pom.xml 里没有写 Spring Boot 版本一律先按 JDK 8 配。因为目前大量毕设源码就是照着黑马 JavaWeb 笔记那套 ServletJSPMySQL 的结构写的JDK 8 最省心。Maven 是第一道坎。默认中央仓库在国内下载很慢建议在 Maven 安装目录的 conf/settings.xml 里加镜像mirror idaliyunmaven/id mirrorOfcentral/mirrorOf urlhttps://maven.aliyun.com/repository/central/url /mirror这段配置的意思是把所有中央仓库的请求转发到阿里云镜像下载依赖的速度会明显改善。加入后记得重启 IDEA 或点 Maven 面板的刷新按钮让新配置生效。如果项目里还有一些私有依赖依赖不到最快的方式是问提供源码的人要整个 lib 目录而不是在网上找同名 jar 乱塞。导入时注意如果源码根目录有 pom.xml用 IDEA 的 Open 直接选这个文件等右下角 Maven 面板加载完再动手如果没有 pom.xml说明是普通 Web 工程源码里应该有 lib 目录这时要用 Project Structure 里的 Libraries 把 lib 加进去。这个判断决定了后面二十分钟是顺畅还是原地打转。3.2 修改数据库连接配置jdbc.properties里最容易翻车的三个参数老项目的数据源配置通常在 src/main/resources 下的 jdbc.properties 或 db.properties 里SSM 项目还有一个 applicationContext.xml 引用它。改之前先全局搜索“jdbc:mysql”把出现这个字符串的文件都找出来防止漏改。有的源码把数据库配置放在 db.properties有的放在 jdbc.properties还有的写在 spring-dao.xml 里全局搜索是最稳的。jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/online_learning?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue jdbc.usernameroot jdbc.password123456驱动类名要跟装的 MySQL 版本匹配。MySQL 5.7 用 com.mysql.jdbc.Driver 没问题MySQL 8.0 就必须换成 com.mysql.cj.jdbc.Driver同时 URL 上补 serverTimezone 和 allowPublicKeyRetrieval。不然启动时大概率报 SSL 连接警告或者 Public Key Retrieval is not allowed错误信息很唬人其实参数加上就好了。URL 里的 useUnicode 和 characterEncoding 是给 JDBC 用的编码开关跟数据库表字符集是两回事两层都要设。连接池配置也要看一眼。如果源码里用的连接池是 DBCP配置项是 dbcp.driverClassName 这类前缀用 Druid 的话可能是 druid.driverClassName。你光改 jdbc.driver 没用因为项目实际读的是连接池指定的键。排查办法很简单在 IDEA 里按住 Ctrl 点配置类看它到底 set 了哪个属性名。另外password 里如果含特殊字符比如 或 #在 properties 文件里要转义或直接改用代码配置否则 URL 解析会截断。这个小问题我见过两次表现形式都是“本地能连打包后连不上”其实是配置文件的编码问题把密码搞坏了。3.3 Tomcat部署Artifact、依赖和启动顺序部署步骤按顺序走一般不会出问题打开 File - Project Structure - Artifacts确认有 Web Application Exploded没有就点 添加打开 Run - Edit Configurations点 选 Tomcat Server - Local在 Deployment 页签添加 Artifact把 Application context 设为 /online-learning确认 Server 页签的 Tomcat 路径指向本地解压的 Tomcat不是 IDEA 自带的那个启动前先启动 MySQL再点 Tomcat 的 Debug 按钮。这里最容易忽略的是第三步的 Application context。它决定访问地址如果 IDE 里是 /online_learning_war_exploded而你访问时用了别的路径结果就是 404。建议所有资源链接都用相对路径或者 JSP 里的 ${pageContext.request.contextPath}不要写死。启动后先别急着开浏览器看 IDEA 底部 Tomcat 日志。看到“Server startup”再访问 http://localhost:8080/online-learning/。如果出现 ClassNotFoundException回到 Project Structure 里把依赖 Jar 加到 Artifact 的 lib 下如果出现 Connection refused回到 3.2 节检查数据库服务有没有起来。如果项目带 Maven每次改 pom.xml 后要点 Maven 面板的 Reload否则新依赖不会进到 Artifact 里这也算一个经典假故障。4. 数据库脚本导入与验证从执行到登录一条线走通数据库脚本不是双击就能用的。这一章解决的是“脚本到底怎么导、导完怎么确认、登录通了之后还要查什么”三个问题。很多项目源码本身没问题卡就卡在脚本导入这一步要么库名不对要么缺数据要么执行了一半报错还不知道。4.1 导入SQL脚本前先确认库名、字符集和执行顺序先把 .sql 文件用编辑器打开看前 20 行。如果开头有 CREATE DATABASE那你直接执行这个文件库会被自动创建如果只有 CREATE TABLE你需要先手动建库再执行文件。很多同学把第二种当成第一种报“No database selected”时一脸懵。我最常用的导入方式是命令行干净利落:mysql -u root -p online_learning online_learning.sql命令说明-u 指定用户名-p 表示需要输入密码online_learning 是目标库名 把脚本文件内容重定向给 mysql 客户端执行。如果你在 MySQL 8.0 里用 root 登录默认用 caching_sha2_password 认证命令行一般没问题倒是 Navicat 老版本会报错升级客户端就好。用 Navicat 的操作顺序是先新建数据库 online_learning字符集选 utf8mb4排序规则选 utf8mb4_general_ci然后右键数据库 - 运行 SQL 文件选脚本执行。字符集选 utf8mb4 而不是 utf8是因为在线学习系统里课程简介、评论都可能出现 Emojiutf8 存不下四个字节的字符。执行完并不算完。要看有没有报错特别是中途终止。很多脚本里带了 DROP TABLE IF EXISTS重复执行没问题但如果你用的是新版本 MySQL脚本里的某个数据类型被丢弃了Navicat 会弹一个错误窗口然后剩下的语句都不跑。这时先 DROP DATABASE online_learning 再重建重新导入一次不要在破损的库上打补丁。提示执行 SQL 脚本前建议先备份原文件因为错误地在已有库上执行带 DROP 的脚本会清空你之前的演示数据。4.2 验证脚本执行结果表数量、初始化数据和测试账号验证脚本是否成功不需要启动项目三条 SQL 就够SHOW TABLES; SELECT id, username, role FROM user; SELECT COUNT(*) AS course_count FROM course;第一句看表结构是否齐全在线学习系统少说也有 5 到 6 张核心表第二句看用户表里有没有管理员和测试账号第三句看课程表有没有数据。如果 SHOW TABLES 能列出表但 SELECT 结果是空说明脚本里只有结构没有数据你得回到第 2 章去补初始化数据或者在源码里找 seed 脚本。这里要提一个高频问题很多同学用 IDEA 自带的数据库工具导出脚本导出时默认只导出 Structure不导出 Data。结果发给别人后对方导入只有一个空库。如果你是“数据库脚本”的提供者记得导出时勾选 Structure and Data如果你是接收者先问一句“有没有带数据”。这种交接问题不是技术问题但卡住人最狠。这里对应的正是“idea 导出数据库脚本”这个操作里最容易被忽略的选项。如果导入时报错位置很靠后比如第 800 行附近多半是某个 INSERT 语句里包含特殊字符引号、反斜杠而脚本本身没有正确处理转义。此时不要手动去改文件重新找一个正规的导出脚本或者用 mysqldump 重新生成。手工改 800 行前的 SQL 是很蠢的做法改完这行又错下行浪费时间。脚本导入成功后的自查清单SHOW TABLES 的表数量和你读源码时理解的业务是否一致user 表至少有 3 条记录course 表至少有 1 条可以演示的课程项目配置里的库名和脚本创建的库名完全一致大小写也要一致。这四条都过基本可以进登录测试。4.3 登录测试能进首页不代表项目真的通了项目启动后先访问登录页用 admin 预置密码登录看能不能跳转到后台。这一步过了很多人就以为项目已经通了其实还早。在线学习系统至少有三个角色每个角色的登录跳转和权限范围都不一样你得把 admin、teacher01、student01 三个账号全部走一遍。登录异常时看 IDEA 的 Console 是最高效的路径。常见三种情况Tomcat 日志打出 SQLException说明数据库连接或 SQL 语句有问题日志里只有 404那多半是拦截器或过滤器把请求拦了页面能打开但样式全丢说明静态资源路径写死这个在第 5 章细说。有一个细节容易被忽略登录成功后跳转到“学生首页”但首页里如果调用了某个接口而这个接口又需要额外的参数比如当前课程 ID你第一次访问很可能报 500。解决办法不是改代码而是在演示前把常用数据准备好比如先让 student01 选一门课产生一条学习记录这样首页就不会出现空指针。数据库脚本导入到这步基本算成功。但“能跑”和“能演示”之间还有一层窗户纸就是下一章的五个大坑。5. 避坑排查JavaWeb在线学习系统最常翻车的5个坑这一章全部来自实际带项目时踩过的坑。每个问题都按现象、原因、解决三步写你可以直接对照排查。5.1 MySQL 8.0连接报错时区、SSL和驱动三连现象Tomcat 启动时报 Cannot create PoolableConnectionFactory 或者 Communications link failure有时候还会看到类似 unrecognized time zone 的提示。原因MySQL 8.0 的驱动和时区处理方式变了。老驱动 com.mysql.jdbc.Driver 不兼容 8.0URL 里没有 serverTimezone 时连接器不会主动猜时区直接抛异常。SSL 握手默认开启如果服务端没配置证书又会产生一堆警告甚至误报失败。解决按 3.2 节的写法替换驱动类URL 加 serverTimezoneAsia/Shanghai、useSSLfalse、allowPublicKeyRetrievaltrue。这三个参数属于“一次配好天下太平”型值得记在笔记里。如果你用的是 Druid 或 HikariCP 连接池参数位置在连接池配置里逻辑一样。5.2 中文乱码从JSP到数据库每一层都要看现象登录后学生姓名变成 ???课程简介乱码或者往数据库插入中文后查出来是一串问号。原因乱码是链路上某一层编码不一致。常见是 JSP 页面没有声明 UTF-8Tomcat 的 URIEncoding 还是默认的 ISO-8859-1JDBC URL 里没带 characterEncodingutf8表结构用了 latin1。四个环节有一个不对中文就会出问题。解决JSP 文件头加 % page contentTypetext/html;charsetUTF-8 %Tomcat 的 conf/server.xml 里给 Connector 加 URIEncodingUTF-8JDBC URL 带上 characterEncodingutf8建库建表统一 utf8mb4。四层都改完后把旧数据清掉重导因为已经变成乱码的数据不会自己恢复。注意改完字符集后已存在的乱码数据不会自动变成中文需要清表重导或 UPDATE 重写。5.3 Tomcat端口占用或访问404现象启动时弹窗 Address already in use: JVM_Bind或者启动成功但访问任何页面都 404。原因8080 端口被其他程序占了常见是之前启动的 Tomcat 没关干净或者别的进程占了端口404 则是访问路径和 Deployment 里的 Application context 不一致。解决端口占用就改 Tomcat 端口在 Run Configuration 里把 HTTP port 改成 8081或者去 conf/server.xml 改。404 问题先确认访问路径是不是 http://localhost:8080/项目名/然后看 Artifact 里有没有 index.jsp 或登录页。经验是一旦改过 Application context浏览器要硬刷新因为浏览器缓存里记着旧路径欺骗性很强。5.4 数据库连接池连不上参数配置像黑匣子现象项目启动后卡住过几十秒报 Connection refused 或者 wait_timeout 超时有时候重启一次又好了。原因连接池的 initialSize 太大MySQL 最大连接数不够或者 MySQL 服务端 wait_timeout 把空闲连接断了连接池没有做有效性检测还有可能是本机 MySQL 只监听了 127.0.0.1而配置里写了 localhost 解析到 ::1IPv6 和 IPv4 不一致导致连不上。解决先用命令行 mysql -u root -p 确认能本地登录再把连接池的 validationQuery 设置为 SELECT 1Druid 配置里 testWhileIdle 保持 true最后把 JDBC 的 host 改成 127.0.0.1。以前带学生连接池参数调不动时我都会让他把这些配置删掉重写因为这种黑匣子问题看日志比猜配置快。5.5 代码里的绝对路径与静态资源丢失现象登录后首页图片全裂CSS 样式没加载控制台有很多 Failed to load resource: 404或者点击跳转时 URL 里出现 C:/ 开头的磁盘路径。原因源码写死了 /upload/xxx 或 C:/images/xxx部署到 Tomcat 后上下文路径不同资源找不到。常见于把上传文件存在项目根目录下的项目换一台机器路径就不对了。解决全局搜索代码里的 C:、/upload、/static把所有资源引用改成相对路径或 ${pageContext.request.contextPath}。文件上传保存路径抽成配置项不要写死在 Java 类里。这是我最想给后来人留的“后悔药”拿到源码第一天就搜绝对路径能少走半天弯路。6. 从能跑到能答辩两个改造技巧和演示路线项目能跑通只是及格答辩时老师更愿意看到你有一点自己的东西。加一个登录拦截器是成本最低的提升也是权限控制里最直观的一段代码。6.1 加一个登录拦截器把权限控制讲清楚public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; Object user request.getSession().getAttribute(loginUser); if (user null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } chain.doFilter(request, response); }这段 Filter 的意思很直白session 里没有 loginUser 就重定向到登录页有就放行。在 web.xml 里给需要保护的路径配置 filter-mapping再把不同角色的入口分别跳转权限模块就能在答辩时讲两分钟。代码只有十行但比背一堆框架概念更能让老师相信你理解了这个系统的访问控制。6.2 答辩演示的数据准备与演示路线演示翻车通常不是功能坏了而是数据没准备。我会在演示文档第一页写上所有测试账号然后按这条路线走管理员登录后创建课程并分配给教师教师登录后上传课程章节学生登录后选课、播放视频、产生学习记录最后回到管理员后台看统计。这条路线把三个角色和核心业务全串起来了。说句实话在线学习系统不缺功能缺的是把功能串成故事的意识。我见过太多人拿着空数据库上讲台讲到“选课”的时候页面上什么都没有。现在我带项目第一件事就是帮学生把演示数据备齐账号密码写在演示文档第一页。希望帮到你。本文还有配套的精品资源点击获取