ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

JavaWeb课设实战:网上评教系统JSP+Servlet+MySQL全解析

JavaWeb课设实战:网上评教系统JSP+Servlet+MySQL全解析 简介面向正在学习JavaWeb开发的初、中级读者这套基于JavaEE的网上评教系统项目以JSPServletMySQL构建完整业务闭环覆盖从用户登录、课程选择到评教打分的主要环节适用于课程设计、毕业设计或项目实训。资源包共651个文件压缩包约11.71MB内部以JSP动态页面、CSS样式表、GIF界面演示图、JavaScript交互脚本和SQL数据库脚本为主还附有classpath、project等工程配置便于导入IDE后直接运行和二次开发。目前已有110人学习浏览。从内容预览可见项目包含多处功能页面的样式体系与页面结构结合源码和数据库脚本可完整还原网上评教系统的开发思路包括用户角色权限、课程与教师信息管理、评教评分逻辑、JDBC数据持久化以及MVC分层架构组织。对于希望掌握JSP网站设计或快速搭建同类教务系统的读者这是一份结构清晰、可直接落地运行的完整学习素材能帮助理解企业级JavaWeb应用从数据表设计到前端展示的典型实现。1. 网上评教系统为什么一个十几张 JSP 页面的课设让那么多人翻车拿到“基于JavaEE的网上评教系统_JSP网站设计_MySQL数据库设计.rar”这个名字基本能猜出它是什么来路高校里最常见的 JavaWeb 课程设计题目压缩包里装着一个用 JSP Servlet MySQL 搭的师生互评网站。网上评教系统的核心业务很直接——学生登录后给任课教师打分、写评语教师登录后查看评分结果管理员负责维护课程信息和统计报表。功能一眼能看完但真要做出来并跑起来涉及的角色权限、数据表关联、Servlet 跳转和部署排错每一步都有坑。这篇文章就按一个可交付的课设标准把技术选型、数据库设计、Servlet 实现和部署排查整条链路讲清楚适合正在做同类题目、或者想快速上手 JavaWeb 完整项目的读者跟着复现。2. 技术栈选型JavaEE 组合拳为什么还没被 Spring Boot 完全取代网上评教系统这类项目最常见的检索叫法是“javaweb 项目完整案例 mysql”说明它的定位就是教科书式的 Java Web 全链路演示。JSP 负责页面展示、Servlet 负责请求控制、MySQL 负责持久化存储这套组合看起来笨重却几乎是课程设计和毕业答辩的默认答案。2.1 JavaEE 在这里到底指什么严格说这个标题里的 JavaEE 并不是完整的 EJB、JMS 那套企业级规范而是 Java Web 开发中用到的那一截Servlet、JSP、JDBC 以及 Tomcat 容器。教育资源里说的“JavaEE”多数时候就是指这种三层架构下的 Web 应用开发。很多学生把 JavaEE 理解成必须用 SSH 或 SSM 框架其实对于评教系统这种 CRUD 为主的项目Servlet JSP 就已经能覆盖全部需求。选择这套技术栈的理由很实际Servlet 能直观展示请求生命周期答辩时讲得清楚不会被追问框架底层原理。JSP 本身就是模板引擎服务端渲染页面.jsp文件直接放 WebRoot 下就能被 Tomcat 编译执行没有前端打包的概念。MySQL 免费、安装资料多出问题时热搜词里随便一搜就是完整教程包括“mysql 8.0 安装配置”“mysql 5.7.44 安装过程详细”这类保姆级内容。相比 Spring Boot用 JSP 还有一个实际优势部署物就是一个 WAR 包或整个 Web 目录扔到 Tomcat 的 webapps 里就能跑不涉及内嵌服务器和外置服务器混用的困惑。如果换成 Spring Boot JSP 的组合反而要额外处理 JSP 在 jar 包和 war 包下的编译差异对新手来说更容易翻车。2.2 JSP 和 Servlet 在这个系统里的分工边界评教系统最常见的错误是 JSP 里写大量 Java 代码页面和逻辑完全耦合。正确的分工是JSP 只做渲染Servlet 只做控制业务与数据库操作放进独立的 Java 类里。三层结构在代码层面就是三个包下面是一个标准的包结构src/ ├── com/edu/rating/ │ ├── controller/ # Servlet只干三件事收参、调服务、跳转 │ │ ├── LoginServlet.java │ │ ├── StudentRatingServlet.java │ │ └── TeacherQueryServlet.java │ ├── service/ # 业务层处理评分、统计、权限校验 │ │ ├── RatingService.java │ │ └── CourseService.java │ ├── dao/ # 数据访问层封装 JDBC 操作 │ │ ├── UserDao.java │ │ └── RatingDao.java │ └── util/ │ ├── DBUtil.java # 数据库连接工具 │ └── StringUtil.java └── webapp/ # JSP 页面与静态资源 ├── WEB-INF/ │ ├── web.xml │ └── lib/mysql-connector-java.jar ├── login.jsp ├── student/ │ ├── rating_list.jsp │ └── rating_submit.jsp └── teacher/ └── rating_result.jsp这个包结构里每个类都只做一件事controller 里不写 SQLdao 里不写 HTMLjsp 页面里不写业务判断。比如登录页面提交表单后由LoginServlet接收参数调用UserService按用户名和角色身份查询再把结果用request.getRequestDispatcher(...).forward(...)跳转。工程化程度不高但足够让答辩老师一眼看出项目结构是清楚的。2.3 为什么这个项目值得用手工 JDBC 而不是 ORMJavaWeb 课设阶段很多人纠结要不要上 MyBatis。评教系统一共五六张表每张表就两三个主要查询MyBatis 的配置成本可能比写 JDBC 还高。JDBC 五个步骤——加载驱动、获取连接、预编译语句、执行查询、释放资源——写一次就熟悉一次面试被问到“JDBC 和 ORM 框架的区别”时也有真实体验垫底。这里的取舍是用 MySQL 的常用命令比如show tables;、desc rating;查看表结构配合少量手写 JDBC 增删改查能让整个项目的数据流转全程透明。如果最终论文里想强调工程性可以加一层数据库连接池。阿里巴巴的 Druid 包很小替换DriverManager.getConnection()的逻辑只需要十几行效果却是“启动慢但运行稳”。这种小优化写进课设文档里比单纯多写两个页面要有说服力。3. 搭建开发环境JDK、Tomcat、MySQL 8.0 的版本配对与踩坑网上评教系统对环境的要求不高但版本配对一旦出错最典型的症状就是 Tomcat 起不来或 JSP 页面报错。常见做法是 JDK 1.8 Tomcat 8.5/9 MySQL 8.0这个组合资料最多问题也最好查。3.1 JDK 与 Tomcat 的版本匹配老生常谈但不得不谈JDK 版本和 Tomcat 版本需要严格对应。Tomcat 8.5 支持 JDK 8 到 JDK 11Tomcat 9 支持 JDK 8 到 JDK 17如果用 JDK 17 配 Tomcat 8.5启动时有可能出现UnsupportedClassVersionError或 HTTPSession 相关的兼容异常。稳妥的选择是 JDK 8 Tomcat 8.5因为大部分课设参考代码都是用 JDK 8 编译的避免把时间耗在无意义的版本升级上。装 JDK 时注意一个高频翻车点安装路径不能有空格和中文。C:\Program Files\Java虽然是默认路径但某些老版本 JSP 编译脚本对带空格的路径处理不友好环境变量也容易配错。我一般会改成D:\Java\jdk1.8.0_291这样的短路径然后把JAVA_HOME和Path配好命令行验证java -version javac -version echo %JAVA_HOME% startup.batstartup.bat是 Tomcat 的启动脚本双击后如果闪退多半是JAVA_HOME没设对。验证 Tomcat 是否起来了用curl http://localhost:8080看返回状态或者直接打开浏览器访问。顺带提一下编辑器选择。如果不想装体积庞大的 IDEA用 VSCode 写 JSP 工程也完全可行安装 Java Extension Pack 就能获得语法提示再装一个 Tomcat for Java 插件直接启动调试。热词里“vscode 配置 javaee 语言环境”指的就是这套插件组合对课设来说绰绰有余。3.2 MySQL 安装时的三个关键参数MySQL 安装是这套系统里最容易提前劝退人的环节。热词里“mysql 安装教程 8.0”“mysql 安装配置教程”刷屏不是没理由的安装过程中几个默认选项如果没改后面连接数据库时全是坑。重点看三个地方字符集必须选utf8mb4默认的utf8在 MySQL 8.0 里存不了完整的中文和 emojiJSP 页面显示评语时会出现?或乱码。认证方式选Use Strong Password Encryption这是 8.0 默认的caching_sha2_password如果你的 JDBC 驱动版本太旧连接时会报Public Key Retrieval is not allowed后面在 URL 里加allowPublicKeyRetrievaltrue解决。端口保持 3306但要确认本机没有其他 MySQL 实例占用。曾经遇到一次net start mysql后服务一直显示“服务无法启动”最后排查发现是另一个残留 MySQL 进程占用了 3306。安装完成后用命令行验证能不能正常登录顺手创建课设专用的数据库和用户mysql -u root -p CREATE DATABASE rating_system DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER rating_userlocalhost IDENTIFIED BY Rating2024; GRANT ALL PRIVILEGES ON rating_system.* TO rating_userlocalhost; FLUSH PRIVILEGES;这里单独建一个用户而不是直接用 root是为了让项目的 DBUtil 配置贴近真实生产环境。后面部署到别的机器时只需要改一个配置文件不用动系统级账号。如果在本机用 Docker 装 MySQL要点是端口映射要写成-p 3306:3306否则宿主机连接时会报Cant connect to MySQL server。Docker 安装 MySQL 失败很多时候不是镜像问题而是忘记挂载配置导致字符集不对。4. 数据库设计网上评教系统的核心不是页面而是表和索引如果一个评教系统翻车十有八九是评教记录表设计出了问题。页面写错了可以改表结构错了意味着所有关联查询都得重写。在设计阶段多花半小时后面少熬夜。4.1 五张核心表对应完整评教流程学生评教一次需要知道“评的是哪门课、哪个老师、打几分、什么时候评的”所以最基础的表结构是五张学生表、教师表、课程表、评教指标表、评教记录表。用户名和密码可以统一放在用户表里用角色字段区分学生和教师也可以直接拆开看你论文里怎么定义。下面用user表承载登录信息student、teacher两张表存各自扩展信息CREATE TABLE sys_user ( user_id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL, role VARCHAR(20) NOT NULL COMMENT STUDENT/TEACHER/ADMIN, real_name VARCHAR(50) COMMENT JSP 个人信息展示页面里的姓名, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE course ( course_id INT PRIMARY KEY AUTO_INCREMENT, course_name VARCHAR(100) NOT NULL, teacher_id INT NOT NULL, semester VARCHAR(20) NOT NULL COMMENT 如 2024-2025-1, KEY idx_teacher_id (teacher_id), CONSTRAINT fk_course_teacher FOREIGN KEY (teacher_id) REFERENCES sys_user(user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE rating_record ( rating_id INT PRIMARY KEY AUTO_INCREMENT, student_id INT NOT NULL, course_id INT NOT NULL, teacher_id INT NOT NULL, score TINYINT NOT NULL COMMENT 1-10 分, comment TEXT, rated_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_student_course (student_id, course_id), CONSTRAINT fk_rating_student FOREIGN KEY (student_id) REFERENCES sys_user(user_id), CONSTRAINT fk_rating_course FOREIGN KEY (course_id) REFERENCES course(course_id), CONSTRAINT fk_rating_teacher FOREIGN KEY (teacher_id) REFERENCES sys_user(user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这段 DDL 里有几个设计和建表的关键点。sys_user用role区分三种身份教师既是登录用户又是课程归属者所以course.teacher_id指向sys_user而不是单独建一张教师表。rating_record的核心在最后一行UNIQUE KEY它从数据库层面保证同一个学生对同一门课程只能提交一次评教这比在 Servlet 里写逻辑判断可靠得多可以彻底堵住重复提交的漏洞。三个外键的设计在课设阶段是有争议的。外键能保证数据完整性但也会带来一个问题删除用户时可能会被约束卡住比如删学生时rating_record里还有记录就删不掉。我的处理策略是保留外键用于答辩讲解和说明关系但实际开发中可以把外键去掉只留普通索引。如果选择了保留测试时就不要去删除有评教记录的用户否则会不断踩级联删除的坑。4.2 评教结果统计的 SQL 写法评教系统的最终交付物是统计报表核心 SQL 就两种写法。第一种是查某位教师所有课程的平均分。第二种是查全局教师排名。前者用于教师端个人结果展示后者用于管理员端的汇总页。正确写法如下SELECT c.course_name, AVG(r.score) AS avg_score, COUNT(r.rating_id) AS rating_count FROM course c LEFT JOIN rating_record r ON c.course_id r.course_id WHERE c.teacher_id 1 GROUP BY c.course_id, c.course_name ORDER BY avg_score DESC;注意这里用的是LEFT JOIN而不是INNER JOIN原因是如果某门课程还没有学生评教INNER JOIN会把这门课整个丢掉教师端页面上就看不到这门课这是个隐蔽的查漏问题。GROUP BY c.course_id, c.course_name这种写法在 MySQL 8.0 下不会报错因为course_name功能依赖于course_id但如果换用 5.7 且开启了ONLY_FULL_GROUP_BY就一定要把c.course_name也放进GROUP BY。排名统计自然要处理AVG和ORDER BY的组合。这里有一个容易忽略的坑平均值默认保留四位小数展示在 JSP 页面上可能显示成9.5000想保留一位小数就得在 SQL 里用CAST(AVG(r.score) AS DECIMAL(3,1))或者在 Java 里用BigDecimal格式化。两种方案都行但放 SQL 里做更简单JSP 端就不需要写格式化代码了。如果需求是按总评分人数排序再按平均分排序ORDER BY里加两项ORDER BY COUNT(r.rating_id) DESC, avg_score DESC先看谁评得多再看谁分高。4.3 用什么手段保障统计效率评教系统数据量不大一张rating_record表通常只有几百上千条记录索引的意义不大。但如果要支撑全校几千学生同时评教就需要考虑索引和只查一次数据库的优化。前面 DDL 里已经建了idx_teacher_id和联合唯一键查询WHERE teacher_id?和WHERE student_id? AND course_id?都能命中索引。需要额外注意的是评教记录表的时间字段rated_at只用于展示和按学期分组SQL 里尽量用DATE_FORMAT(rated_at,%Y-%m)做月度统计不要在这个字段上加函数后查询否则索引失效。存储过程在这个系统里可用可不用。如果把“每位教师的平均分排行”写成存储过程能减少 Servlet 端的 SQL 拼接但课设阶段维护起来反而麻烦修改一次逻辑就要重新执行一次脚本。我一般更愿意把统计 SQL 直接写在 DAO 层以参数形式传teacherId或semester。面试如果被问到存储过程的优缺点手边正好有这个项目可以当例子讨论。5. 核心功能实现从 JSP 登录页到评分完成的三个关键代码块这一章是真正的动手环节。网上评教系统的页面逻辑比较固定学生登录后看到待评课程列表点进任一门课打分写评语提交后刷新列表状态教师登录后看到所授课程得分。整个过程拆开来就是登录校验、选课列表、评分提交三件事对应三个必须写对的代码块。5.1 JDBC 工具类所有页面的数据入口不管用 JSP 写什么页面都要先拿到数据库连接。最常见的做法是写一个DBUtil工具类把连接的创建和关闭集中处理。下面是精简但可直接运行的版本public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/rating_system ?useSSLfalseuseUnicodetruecharacterEncodingutf8 allowPublicKeyRetrievaltrueserverTimezoneAsia/Shanghai; private static final String USER rating_user; private static final String PASSWORD Rating2024; static { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError(MySQL JDBC 驱动未找到); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, PreparedStatement ps, ResultSet rs) { if (rs ! null) try { rs.close(); } catch (SQLException ignored) {} if (ps ! null) try { ps.close(); } catch (SQLException ignored) {} if (conn ! null) try { conn.close(); } catch (SQLException ignored) {} } }每个参数在这里都有明确用途缺一个都会在运行期翻车。characterEncodingutf8是 JSP 页面写中文评语不乱码的底线useSSLfalse避免 MySQL 8.0 默认连接时做 SSL 握手导致控制台刷警告serverTimezoneAsia/Shanghai解决 MySQL 8.0 与 JDK 时区不一致导致的日期偏差。如果漏了allowPublicKeyRetrievaltrue连接时会直接抛Public Key Retrieval is not allowed异常而且这个问题在修改密码加密规则之前是绕不过去的。这段代码还需要注意的是连接资源的释放。每个 DAO 方法的 finally 里都必须调用close()不能偷懒。一个 Servlet 请求同时打开两个连接的场景在这个系统里很常见比如评分页要查询课程信息、又要检查是否已评过如果连接不关Tomcat 跑一上午连接池就耗尽页面会越来越慢直到完全无响应。5.2 登录拦截与 Session 校验一个 JSP 网站如果没有登录拦截那它只是一个页面集合不是一个系统。网上评教系统分为学生端、教师端、管理员端三种角色各只能访问自己的功能模块所以登录后 Session 里的角色身份必须统一用。登录 Servlet 的骨架WebServlet(/login) public class LoginServlet extends HttpServlet { Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username req.getParameter(username); String password req.getParameter(password); User user new UserDao().findByUsernameAndPassword(username, password); if (user null) { req.setAttribute(error, 用户名或密码错误); req.getRequestDispatcher(/login.jsp).forward(req, resp); return; } HttpSession session req.getSession(); session.setAttribute(loginUser, user); session.setMaxInactiveInterval(30 * 60); resp.sendRedirect(resolveHomePage(user.getRole())); } private String resolveHomePage(String role) { if (TEACHER.equals(role)) return teacher/index.jsp; if (ADMIN.equals(role)) return admin/index.jsp; return student/index.jsp; } }逻辑很简单但有一个细节常被忽略登录成功后用sendRedirect而不是forward。原因很简单如果用forward跳转学生按 F5 刷新页面时浏览器会重复提交上一次的 POST 表单轻则弹确认框重则重复评教。redirect会改变浏览器地址栏刷新时只会重新请求student/index.jsp这在 jsp 页面加载完刷新一次的体验上更正常。第二处细节是密码存储。课设系统直接明文存密文比对也说得过去但如果想拿得出手密码字段存 MD5 或 BCrypt 哈希登录时先把req.getParameter(password)哈希再校验。代码多几行但能在答辩时讲出“系统安全”的设计思考比把精力全花在页面样式上高明得多。5.3 评分提交时的事务处理与并发控制评教提交这个操作在整个系统中最特殊它同时涉及写入评教记录和更新课程评教状态两步必须保证要么都成功要么都失败。很多课设项目在这里不处理事务导致学生提交时提示失败但成绩已经写进去重复提交又报唯一键冲突。处理方案是使用 MySQL 事务把 Service 层方法加上以下逻辑Connection conn DBUtil.getConnection(); conn.setAutoCommit(false); try { RatingDao dao new RatingDao(); dao.insertRating(conn, rating); dao.updateCourseStatus(conn, rating.getCourseId()); conn.commit(); } catch (SQLException e) { conn.rollback(); throw new RuntimeException(评教保存失败数据已回滚, e); } finally { conn.setAutoCommit(true); DBUtil.close(conn, null, null); }这个代码块要点是把conn传入 DAO 方法而不是在 DAO 里自己获取新连接否则commit和rollback管不到另一条连接上的操作。setAutoCommit(false)表示手动管理事务两个操作都在同一个物理连接上执行。如果第二步updateCourseStatus失败第一步的insertRating也会被回滚不会留下半截数据。这一步值得在项目报告里专门写一段因为它是评教系统区别于普通 CRUD 页面的核心。并发方面需要注意的是 MySQL 的锁机制。两个学生同时对同一门课程提交评教数据库的UNIQUE KEY uk_student_course会挡住第二个请求但如果先查后插就可能出现竞态。把事务隔离级别保持默认REPEATABLE READ即可不需要手动加FOR UPDATE。用唯一索引兜底是最省心的做法。6. 部署避坑与验证把整个系统打包扔进 Tomcat 的正确姿势所有代码写完最后一步是部署。网上评教系统的部署包含两个动作把 JSP 项目变成可运行的 Web 应用、把 MySQL 数据脚本导入目标数据库。这一步卡住的概率比写代码还高因为问题往往出在环境而不是逻辑上。6.1 导出 WAR 包与初始化数据库用 IDEA 的 Build Artifact 打出rating_system.war放到 Tomcat 的 webapps 目录启动 Tomcat 会自动解压。数据库初始化分两步用 Navicat 或命令行执行都不是问题mysql -u root -p rating_system.sql cp rating_system.war /path/to/tomcat/webapps/ cd /path/to/tomcat/bin ./startup.shrating_system.sql文件里应该包含建库建表语句和初始用户数据。需要注意的是 SQL 文件本身的字符集Windows 下用记事本另存为 UTF-8否则导入时中文注释会变成乱码影响建表语句的执行。导入再执行SHOW TABLES;检查一遍是不是五张表都在这一步比后面查代码省时间得多。6.2 三个高频部署报错的排查顺序部署阶段问题集中在三个点遇到的概率几乎是百分之百。第一个现象JSP 页面打开白屏或直接报 500Tomcat 控制台出ClassNotFoundException: com.mysql.jdbc.Driver。原因几乎可以肯定是mysql-connector-java.jar没有放到WEB-INF/lib下。解决方法是把驱动 jar 复制进WEB-INF/lib重启 Tomcat。如果项目里用了独立 Tomcat 而不是 IDE 内置的还要确认 IDE 部署的是 exploded war 目录改 lib 后要重新构建。第二个现象页面能登录但所有中文变成?号。原因要分三层排查MySQL 数据库字符集是 utf8mb4、JDBC 连接串带characterEncodingutf8、JSP 页面顶部声明pageEncodingUTF-8。任何一层没设置都会乱码。从客户看到的?反推大多数情况是连接串丢了characterEncoding参数补上重启就好。测试阶段可以用“mysql 常用命令”里的SHOW VARIABLES LIKE character_set_%;先确认库层设置。第三个现象学生提交第二次评教时报唯一键冲突界面提示 500 或写入了重复记录。发生原因有两种可能一是建表时漏了UNIQUE KEY导致数据库允许重复二是 Servlet 跳转用了forward而非redirect刷新时重复提交表单。解决分别对应修改表结构或修改跳转逻辑。这里就是整条链路里最典型的排查顺序先看控制台报错再判断是 SQL 层面还是逻辑层面。验证系统是否跑通不用看页面多好看只看一条链路学生账号登录 → 看到待评课程列表 → 打分提交 → 教师账号登录 → 能看到该门课成绩变化。跑通这一条剩下都是锦上添花。如果时间有余可以顺手做一个按学期筛选统计结果的功能这是评教系统在答辩时最容易引起讨论的点。整个项目做下来最深的体感是这套方案的代码量不大真正耗时全在环境、编码和部署的细节上。每当我以为“明明都按教程配好了”最终都会发现某个参数不一致。希望这篇笔记能帮你在同样的坑前面少绕几步一次跑通。本文还有配套的精品资源点击获取
返回列表