多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

JavaWeb学生选课系统:从环境配置到调试改造的完整指南

JavaWeb学生选课系统:从环境配置到调试改造的完整指南 简介这是一份基于JavaWeb的学生选课系统完整源码与SQL数据库脚本主要面向计算机、通信、人工智能、自动化等专业的学生与教师可用于期末课程设计、课程大作业或毕业设计参考。项目覆盖前台选课、后台管理以及登录验证、课程信息展示、选课退课、成绩录入等典型业务模块能够帮助读者理解JavaWeb项目的分层架构与前后端数据交互过程。压缩包内共198个文件包含35个Java源文件、29个JSP页面、23个JavaScript脚本、12个CSS样式文件和23个JAR依赖包另附1个SQL数据库脚本便于直接导入数据库运行整体大小仅10.41MB结构清晰且已调试测试可正常使用。目前已有437人学习下载适合作为课程设计或毕业设计的参考蓝本基础较好的开发者也可在此基础上扩展权限管理、课程评分等功能。1. 一个课程作业压缩包为什么值得你认真跑通它拿到「基于JavaWeb的学生选课系统源码sql数据库(课程作业).zip」这种命名的压缩包大概率是两种情况要么是你在挑选课程设计参考项目要么是刚下载了一份学长留下的作业想自己复现一遍。这个标题看着朴素但它恰好点中了JavaWeb课程设计里最标准的一类交付物——Java源码文件加一个SQL数据库脚本。选课系统的业务天然围绕学生、课程、选课记录三张核心表转是理解Servlet、JSP、JDBC、数据库连接池这些基础组件如何协作的绝佳样本也是面试时能直接拿出来讲的简单业务闭环。但这类压缩包的打开率往往很高跑通率却不高。原因多数不在代码本身而在JDK版本、Tomcat版本、MySQL字符集、连接串参数这些外部环境上。一个整天和框架打交道的熟手可能十分钟跑通新手却可能卡在数据库导入这一步整整一个晚上。这篇文章就从拿到压缩包后的第一步开始把环境准备、SQL导入、调试排错、功能改造、验收演示整条路走一遍帮你把这个JavaWeb课程作业真正变成自己的东西。2. 运行前的环境准备JDK、Tomcat、MySQL、IDEA 四件套怎么配不翻车2.1 先判断项目的技术形态看有没有 pom.xml 和 web.xml解压压缩包之后别急着打开IDEA先在文件管理器里看目录结构。这个动作的价值在于判断项目是用传统ServletJSP写的还是用Spring Boot写的两者后续的启动方式完全不同。判断依据就两个文件项目根目录下有没有pom.xml如果有说明它是Maven工程再看src/main/webapp/WEB-INF/下有没有web.xml传统JavaWeb项目一定会有这个文件。课程作业级别的源码里两种形态都常见纯ServletJSPJDBC的老派写法胜在结构直观适合答辩时讲清楚每个请求怎么被处理Spring Boot版本则更贴近现在的企业开发习惯。你下载的这份标题里写了JavaWeb而不是Spring Boot传统项目的概率更高但还是要以实际文件为准。判断完成后的环境选型我给你一个稳妥组合JDK 8、Tomcat 8.5、MySQL 5.7、IDEA 2022及以上版本。这套组合对老项目的兼容性最好——JDK 8对应javax.servlet命名空间Tomcat 8.5既支持老项目的部署方式又不挑系统MySQL 5.7和课程作业里最常见的JDBC驱动配合最顺。很多人在IDEA 2026创建JavaWeb项目时遇到的诡异问题十有八九是JDK版本太高导致的编译报错或Servlet API不兼容。2.2 JDK与Tomcat的安装检查一条命令确认JDK安装多数机器已经有了关键是确认版本。打开命令行执行java -version如果显示1.8.x说明就是JDK 8直接用。如果显示17、21这些高版本建议换回JDK 8。因为课程代码里可能用了老版javax.servletAPIJDK高版本编译时虽然不报错但运行期的模块化限制会让JSP编译失败。如果提示找不到命令说明没配环境变量。最省事的做法是在IDEA的项目结构里单独指定JDK路径避免改动全局环境变量影响其他软件。Tomcat不需要安装解压即用。但要注意一个常见误会很多人下载了Tomcat 10然后发现项目里的import javax.servlet.http.HttpServlet全部编译失败。这是因为Tomcat 10把命名空间从javax.*迁到了jakarta.*课程作业的老代码几乎都是javax。所以用Tomcat 8.5或9.0不要用10。配置Tomcat时在IDEA里打开Run Edit Configurations新增一个Tomcat Server Local在Application server处指定Tomcat解压目录Deployment里点加号选Artifact 你的项目名:war exploded。这样IDEA会自动启动Tomcat并部署项目不需要手动把war包扔进webapps目录。2.3 MySQL的安装与账密设置两个必须记住的参数MySQL安装时有两个参数会影响后续所有操作端口号默认3306和root账户密码。课程作业的数据库连接配置文件通常是db.properties、jdbc.properties或c3p0-config.xml里面会写死数据库地址、用户名和密码。如果你本机MySQL的密码和文件里的不一致运行时会直接报Access denied for user。这里有个实操技巧先不改配置文件直接用命令行登录MySQL把项目脚本里需要的密码设置成配置文件里的值。用root身份执行ALTER USER rootlocalhost IDENTIFIED BY 123456; FLUSH PRIVILEGES;把123456替换成配置文件里写的密码是最省事的做法。当然这只适用于本机学习环境。等你把项目跑通后自己去配置这个文件时再改成自己习惯的强密码。MySQL装好后才能在下一步导入SQL数据库文件这是后续一切的前提。2.4 导入项目到IDEA的两种方式Maven与非Maven刚才判断过有没有pom.xml这一步就分两种处理。非Maven项目直接File Open选中解压后的文件夹IDEA会提示是否信任项目选信任。然后右键项目的根目录选Add as Maven Project这个操作不要做——它不是Maven项目这么选只会让IDEA疯狂扫描然后报错。正确做法是右键src目录选择Mark Directory as Sources Root把web目录标记为Web Resources Directory。Maven项目File Open选中文件夹后IDEA检测到pom.xml会自动下载依赖。这里有个血泪经验如果下载慢或报红先检查Maven的settings.xml里有没有配置阿里云镜像。课程作业项目依赖的包数量不大但默认仓库地址在国外网络稍差就会卡在下载阶段。导入完成后的第一件事不是点运行而是先看External Libraries里有没有出现mysql-connector-java或mysql-connector-j。没有的话后面启动一定会报ClassNotFoundException: com.mysql.jdbc.Driver。传统Servlet项目的做法是把这个jar包放到WEB-INF/lib目录下检查一下压缩包里有没有带这个文件不带就得自己下载对应MySQL版本的驱动。MySQL 5.7配mysql-connector-java 5.1.49MySQL 8.0配8.0.x版本错了容易多一个Public Key Retrieval is not allowed的报错。3. 把SQL数据库脚本变成能用的数据导入流程与表结构分析3.1 认识课程作业里的SQL文件建库语句、建表语句、初始化数据压缩包里那个xxx.sql文件是整个系统的地基。用记事本或IDE打开它滚动扫一遍你会看到三类内容CREATE DATABASE开头的是建库语句CREATE TABLE开头的是建表语句INSERT INTO开头的是初始化数据。这三种语句的存在与否决定了导入方式。多数课程作业的SQL脚本会把建库和建表写在一起顶部有CREATE DATABASE IF NOT EXISTS select_course DEFAULT CHARSET utf8;后面跟着USE select_course;。这种直接执行就能完成全流程。但也有些脚本只写了建表和插入语句不带建库部分——这种情况需要你先手动创建一个空数据库否则执行时会报No database selected。字符集是导入前必须确认的点。看SQL文件的前20行找到CHARSET后面的值常见的是utf8、utf8mb4、gbk三者之一。课程作业源码多数用utf8或gbk如果脚本里写的是utf8mb4说明原作者考虑了表情符号的存储但这在选课系统里意义不大。重要的是DLL文件里建的表和你的数据库连接串必须用同一套字符集否则导入后查询中文全是问号。3.2 导入SQL文件Navicat图形化操作和命令行两种方式我一般推荐新手用Navicat因为导入完成后能直观看到表结构和数据。连接上MySQL后右键localhost连接选运行SQL文件弹窗里选中你的SQL文件注意编码那里要选成和文件一致的字符集选错会出现中文乱码。点开始后下方日志会打出每一条执行的语句看到红色的Error再处理没有红色就说明成功了。喜欢用命令行或者机器上没装Navicat的直接用MySQL自带客户端也可以命令更简单mysql -uroot -p123456 D:/coursework/select_course.sql这段命令把SQL文件的内容整体交给MySQL执行。参数含义-uroot是用户名root-p123456是密码是输入重定向把文件内容作为命令输入。路径里不要带中文和空格否则解析会出问题。执行完没有任何输出就是成功有报错就逐行看多半是文件编码声明和实际编码不一致。导入完成后验证一下数据。执行USE select_course; SHOW TABLES; SELECT COUNT(*) FROM student;第一条选择数据库第二条列出所有表名第三条统计学生表行数。如果表能列出来、统计数字不是0说明SQL数据库脚本导入成功。如果报错Unknown database说明脚本里没有CREATE DATABASE语句你还没建库。3.3 看懂四张核心表的结构比写代码更重要课程作业里的选课系统表设计通常是四张起步学生表、课程表、选课表、用户表或管理员表。下面是一个典型的表设计你可以在SQL文件里对照着找表名关键字段用途studentid, student_no, name, class_name学生基本信息courseid, course_no, course_name, credit, teacher, capacity课程信息与选课容量student_courseid, student_id, course_id, create_time选课记录多对多关系中间表sys_userid, username, password, role登录账户区分学生和管理员选课表是理解这个系统的钥匙。student_course表通过student_id和course_id把两张表关联起来业务上对应某个学生选了某门课。课程表里的capacity字段是选课人数上限很多课程作业的代码会选择忽略这个字段只在界面上显示不做超员校验——这是后面改造的重点。看SQL文件里建表语句的字段类型也有讲究。比如student_no是varchar还是int决定了学号前导零会不会被吞掉create_time是datetime还是timestamp决定了默认值怎么处理密码字段是varchar(32)还是varchar(64)能直接猜出原作者用的加密算法是MD5还是SHA-256。这些细节在你改代码时都会遇到。4. 选课系统调试避坑从启动报错到功能异常的排查手册4.1 现象Tomcat能启动但页面404 —— 原因部署路径不对项目运行起来浏览器输入http://localhost:8080Tomcat欢迎页正常但访问http://localhost:8080/你的项目名/就是404。这种问题出在IDEA的部署配置上。点击Run Edit Configurations看Deployment标签页Application context那一栏必须是/项目名和浏览器访问路径保持一致。很多教程里写的是/这样部署后项目访问路径就成了根路径你再用/项目名访问当然404。还有一种可能你项目里根本没有index.jsp或index.html默认页找不到。打开web.xml看welcome-file-list节点配的什么文件名浏览器访问项目根路径时Tomcat会按这个配置找起始页。4.2 现象登录永远提示用户名或密码错误 —— 原因密码加密方式不匹配选课系统的登录页是最容易出问题的地方。数据库里存的密码是一串32位的十六进制字符串你输入123456直接提交后端怎么比对都失败。因为原作者用MD5做了加密比对时把用户输入的值也做了一次MD5再和库里比对。但你一定先从数据库查一下比较稳妥——用SQL查SELECT username, password, role FROM sys_user WHERE username admin;如果查出来password是可见的明文问题就在别处如果是32位十六进制字符串而代码里又没有明显的MD5字样可能是注册时加密、登录时没有加密导致的不匹配或者是用了MD5盐的写法。最直接的解决方法是下单行日志在登录的Servlet里加System.out.println(输入密码: inputPassword)和System.out.println(库中密码: dbPassword)对比两次输出就知道是哪一端的处理少了步骤。4.3 现象页面中文全部是问号 —— 原因三处编码设置不一致JSP页面顶部有% page contentTypetext/html;charsetUTF-8%数据库连接串里也有characterEncodingutf8HTML的meta标签还配了charsetUTF-8这三处只要有一处不一致就会出现中文乱码。最典型的是数据库连接串漏了参数老代码里连接MySQL的URL往往只写了jdbc:mysql://localhost:3306/select_course?useSSLfalse少了characterEncodingutf8数据库返回的中文按默认字符集解析到页面就全乱了。改成jdbc:mysql://localhost:3306/select_course?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiuseUnicodetrue和characterEncodingutf8是配套的少了前者设置不生效serverTimezoneAsia/Shanghai是为了解决mysql驱动8.x报时区错误的问题5.7版本不加也行。改完连接串必须重启Tomcat连接池里的旧连接不会自动刷新。4.4 现象选课列表能显示但选课时报错 —— 原因外键约束或重复主键选课操作本质是往student_course表插入一条记录。报外键约束错误时不奇怪——student_id或course_id引用的记录不存在。但还有一种情况更容易忽略student_course表的主键是(student_id, course_id)联合主键同一个学生选择同一门课第二次会报Duplicate entry 1-3 for key PRIMARY。原作者的代码里如果没有先做查重再插入的判断这个错误必现。排查时在选课Servlet的doPost方法里找有没有类似的SELECT COUNT(*) FROM student_course WHERE student_id? AND course_id?语句没有就是漏了。这个问题放到后面改造章节细说。4.5 现象运行时报ClassNotFoundException或NoClassDefFoundError —— 原因jar包缺失或未部署com.mysql.jdbc.Driver找不到是最典型的jar包问题。课程作业里数据库驱动有三种存在形式在WEB-INF/lib目录下、在Maven的pom.xml里声明、或者干脆没有。如果在lib里但启动还是报错检查IDEA的Project Structure Artifacts看Output Layout里lib目录是否被包含进去。IDEA经常出现源码里能看到jar包但打包时没带上。最快的验证方法是看Tomcat启动日志里部署的exploded目录下WEB-INF/lib有没有这个文件。没有就手动把mysql驱动jar包复制进去重启即可生效。这种现象带点玄学色彩但只要记住运行时以Tomcat实际加载的库为准这条原则排查起来就不会跑偏。5. 从能跑到能用给课程代码补上事务、唯一约束与权限校验5.1 查重防止一个学生同一门课选两次课堂演示时最怕出现点了两次选课按钮生成了两条记录。原代码不一定做了查重这一步改造不复杂收益却很直接。找到处理选课请求的Servlet方法在INSERT之前加一次查询// 检查是否已选过这门课 String checkSql SELECT COUNT(*) FROM student_course WHERE student_id ? AND course_id ?; PreparedStatement ps conn.prepareStatement(checkSql); ps.setInt(1, studentId); ps.setInt(2, courseId); ResultSet rs ps.executeQuery(); rs.next(); int count rs.getInt(1); if (count 0) { // 已经选过直接返回提示不再插入 response.getWriter().write(你已选过该课程请勿重复操作); return; }这段代码的逻辑先按student_id和course_id两个条件查数量结果大于0说明已经选过直接结束操作返回提示信息。setInt是PreparedStatement的参数占位赋值第一个参数是SQL里问号的序号第二个是要赋的值。如果原表结构里已经有联合主键这个查重逻辑是双保险能给出更友好的提示而不是抛异常。5.2 事务与选课名额扣减并发场景下别丢数据课程作业的演示场景多是单机操作但如果你要往简历上写这个项目事务处理是加分项。选课的本质是两步操作检查课程剩余名额大于0、插入选课记录并把capacity字段减1。两步之间任何一步失败数据就会不一致。典型的改写方式是把两步包在一个事务里conn.setAutoCommit(false); // 关闭自动提交开启事务 try { // 第一步扣减课程容量先查剩余名额 String deductSql UPDATE course SET capacity capacity - 1 WHERE id ? AND capacity 0; PreparedStatement ps1 conn.prepareStatement(deductSql); ps1.setInt(1, courseId); int rows ps1.executeUpdate(); if (rows 0) { throw new RuntimeException(该课程已无剩余名额); } // 第二步插入选课记录 String insertSql INSERT INTO student_course(student_id, course_id, create_time) VALUES(?, ?, NOW()); PreparedStatement ps2 conn.prepareStatement(insertSql); ps2.setInt(1, studentId); ps2.setInt(2, courseId); ps2.executeUpdate(); conn.commit(); // 两步都成功提交事务 } catch (Exception e) { conn.rollback(); // 任何一步失败回滚前面的操作 throw e; } finally { conn.setAutoCommit(true); // 恢复自动提交避免影响后续操作 }参数说明WHERE capacity 0这句是关键它把查余额和扣余额合并成一条原子操作并发下两个请求同时进来也只有一个能更新成功。setAutoCommit(false)关闭自动提交后所有SQL都缓存在事务里只有commit()执行才真正生效。rollback()回滚后前面的UPDATE和INSERT都不会落库。这种方式能有效避免显示有余量但选不上和选上了超员两个尴尬的翻车现场。5.3 Filter拦截未登录用户不能访问选课页面选课系统的典型缺陷是退出登录后按浏览器后退键或者直接输入内部页面地址还是能访问到选课界面。业务逻辑上这不算大错但答辩时被问到权限控制怎么做的会很难堪。补一个最基础的登录过滤器public class LoginFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req (HttpServletRequest) request; HttpServletResponse resp (HttpServletResponse) response; // 从Session里取登录标记登录时存了user对象 Object user req.getSession().getAttribute(loginUser); String path req.getRequestURI(); // 放行登录页面、静态资源和登录请求本身其余全部拦截 if (user ! null || path.endsWith(login.jsp) || path.contains(/login) || path.endsWith(.css) || path.endsWith(.js)) { chain.doFilter(request, response); } else { // 没登录就重定向到登录页 resp.sendRedirect(req.getContextPath() /login.jsp); } } }这段逻辑的核心是白名单思路只有登录用户和少数几个公开资源能通过其他请求一律弹回登录页。getAttribute(loginUser)要和登录Servlet里session.setAttribute(loginUser, user)的键名保持一致键名不一致过滤器永远放行也永远拦截排查时先确认这个字符串。注册这个过滤器需要在web.xml里配置filter filter-nameloginFilter/filter-name filter-classcom.example.filter.LoginFilter/filter-class /filter filter-mapping filter-nameloginFilter/filter-name !-- 拦截所有请求除了白名单里放行的 -- url-pattern/*/url-pattern /filter-mapping/*表示拦截所有路径。过滤器链的执行顺序按filter-mapping的声明先后如果你项目里还有字符编码过滤器要把编码过滤器放在最前面先设置编码再走权限判断否则中文参数在过滤链里就乱掉了。6. 结课验收前的一小时数据回滚、环境复现与演示脚本验收前最怕的不是代码有bug而是演示时数据被自己玩坏了。选课系统演示往往要反复操作选课、退课、再选课数据库里的状态和数据会越来越乱。最稳妥的恢复办法是重新执行一遍SQL脚本把数据库恢复到初始状态。命令行操作mysql -uroot -p123456 -e DROP DATABASE IF EXISTS select_course; mysql -uroot -p123456 D:/coursework/select_course.sql第一行删除整个数据库第二行重新导入原始SQL脚本。注意-e参数表示执行完命令就退出不进入交互模式。这个操作要谨慎对待会把所有改动过的数据清空回到脚本里写的初始状态适合演示前做不适合演示中途做演示过程中数据应当保持连续。环境复现是另一个细节。你本机跑通的项目换到答辩教室的电脑上跑不出来是课程设计最常见的翻车场景。我的习惯是把三样东西放同一个目录项目源码、SQL文件、环境配置说明JDK和Tomcat的版本号、MySQL密码、连接串配置。不要求现场从零搭建但至少要保证评委或助教在另一台机器上能快速跑起来。数据库连接配置文件里的localhost和密码保持和压缩包一致不要在自己机器上调试时改掉又忘改回来。我吃过这个亏把密码改成自己的然后提交了作业老师那台机器跑出来整个系统连不上数据库。从那以后凡是带SQL数据库的作业压缩包我提交前一定重新用原始密码和原始SQL导一遍数据库再跑通一次。演示脚本提前在心里过一遍可能不够建议在白纸上写三步登录演示登录成功页、选课演示选一门课并展示列表、退课演示退掉再选顺便展示查重提示。每一步对应哪个URL、操作后看哪个页面数据变化写清楚。这种脚本只给自己看答辩时不念但心里有数就不会在台上的关键节点犹豫。数据库脚本重新导入、环境配置核对、演示路径走一遍这三件事做完这个JavaWeb学生选课系统就可以安心交出去了。希望帮到你也祝你的课程设计答辩顺利。本文还有配套的精品资源点击获取
返回列表