news 2026/9/30 5:36:29

网上作业批改系统Java+MySQL实战:从环境配置到上线部署

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
网上作业批改系统Java+MySQL实战:从环境配置到上线部署

简介:基于Java和MySQL实现的网上作业批改系统,面向Java初学者及课程设计/毕业设计开发者,提供了从后端逻辑到前端页面的完整可运行方案。资源包共265个文件,压缩后仅1.93MB,包含45个JSP页面、24个Java源文件及对应Class文件,另有CSS/JS负责界面样式与交互,SQL脚本用于快速建库,DOC/DOCX文档辅助理解设计思路。系统以管理员为核心,实现了班级信息管理、教师与学生信息管理、公告与留言管理、教学资料管理等功能模块,注重操作简便与安全防护。已有1615人学习下载,适合需要快速搭建在线作业批改场景、参考典型权限管理或多模块Web项目结构的开发者使用。

1. 网上作业批改系统JAVA+Mysql是什么:先看清这套系统到底解决谁的问题

拿到“网上作业批改系统JAVA+Mysql.zip”这个压缩包的人,通常是三种身份:要交课程设计的在校生、刚入职想找一个完整 Java Web 项目练手的初级开发,以及需要快速给客户搭演示环境的实施人员。这个标题看起来像是一份课程设计源码,但说透了,它代表一条完整的落地链路:学生在线提交作业,教师在线批改打分,管理员统一管理课程与账号,数据全部落进 MySQL。

我对这类系统的判断是:业务逻辑本身并不复杂,最容易让新手翻车的反而是环境与数据两项。JDK、Tomcat、MySQL 三个组件的版本怎么配,SQL 脚本怎么导入,连接串里的参数少写一个会报什么错,这些坑比写代码更消耗时间。所以这篇文章按“先看业务设计、再跑通本地、最后排查问题”的顺序,把一条可复现的路径完整拆开。读完你不仅能把系统跑起来,还能知道批改数据是怎么组织的、哪些参数动了会出问题、上线前还要补什么功课。

2. 从zip到能登录:把网上作业批改系统跑起来的钥匙与最小命令

拿到压缩包先别急着解压,先想清楚一件事:这套系统最常见的骨架是 JSP + Servlet + JDBC,更工程化的版本会换成 Spring MVC + MyBatis,但不管哪种,运行前提都是三样东西——JDK、Tomcat、MySQL。许多课程设计系统中,JDK 8 与 Tomcat 8.5 的组合最稳,MySQL 5.7 或 8.0 都能用,但驱动类名不同,这一步错了启动必翻车。

2.1 开跑前先核对环境版本:JDK、Tomcat、MySQL的匹配关系

先把环境匹配关系钉死,后面少走弯路。我一般按下面这张表来配:

组件推荐版本说明
JDK1.8 或 111.8 最兼容老项目;11 需要 Tomcat 9
Tomcat8.5 或 9.0与 JDK 版本对应,8.5 配 JDK8,9.0 配 JDK11
MySQL5.7 或 8.08.0 默认加密插件变化大,驱动类名也变了
JDBC 驱动5.1.x / 8.0.xMySQL5.7 用 com.mysql.jdbc.Driver;8.0 用 com.mysql.cj.jdbc.Driver

MySQL 8.0 的加密规则默认是 caching_sha2_password,老驱动连接会报认证失败;MySQL 5.7 用默认密码规则即可。如果你在 Windows 上装 MySQL 8,常见做法是下载 ZIP 解压后初始化,Windows 上 mysql 安装配置教程一般会提到 my.ini 里加default_authentication_plugin=mysql_native_password这一行,目的就是兼容老项目。Linux 上则直接apt install mysql-server或yum install mysql-community-server,装完先systemctl start mysqld。

版本核对命令也很简单,三条就能看全:

java -version mysql --version /opt/tomcat/bin/version.sh | grep "Server version"

三条命令分别确认 JDK 编译版本、MySQL 版本和 Tomcat 主版本。版本对不上时,优先降 Tomcat 而不是升 JDK——老项目的web.xml头声明如果是 Servlet 2.5,放到 Tomcat 10 上会因为javax.servlet包路径变更而直接 404。

2.2 建库、导数据、改连接串:项目包里的SQL脚本怎么用

项目包里通常会有一个sql目录,放着建库脚本或完整备份。常见的命名是homework.sql或db_init.sql。不要双击打开复制粘贴到 Navicat 里执行,大文件容易卡死,命令行导入更稳。先建库,再导入:

mysql -h 127.0.0.1 -u root -p \ -e "CREATE DATABASE IF NOT EXISTS homework_db DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;" mysql -h 127.0.0.1 -u root -p homework_db < /path/to/homework.sql

第一条命令把库建出来,字符集直接指定 utf8mb4,把以后做中文作业内容、表情符号扩展名的文件都兼容掉。第二条命令把表结构和初始数据导入到 homework_db。-h 127.0.0.1是强制走 TCP 连接,不是走本地 socket 文件,这一步能提前绕开一个高频报错,后面避坑章节会专门讲。

导入之后,去改项目的数据库配置。常见做法是项目里有一份jdbc.properties或db.properties,内容大概是这个样子:

jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/homework_db?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true jdbc.username=root jdbc.password=123456

useSSL=false是给开发环境省事,MySQL 8 默认开 SSL,不关会报 SSL 握手异常;characterEncoding=utf8与库里指定的 utf8mb4 对齐,页面传中文不乱码;serverTimezone必加,否则 JDBC 驱动拿不到 JVM 默认时区会直接抛异常;allowPublicKeyRetrieval=true是配合 MySQL 8 的 caching_sha2_password 使用,第一次连接需要取公钥,不写也会报错。这四个参数,是这套系统能跑起来的“后悔药”组合,缺一个就多一次踩坑机会。

2.3 启动 Tomcat:用前台模式盯日志,别用启动脚本一闪而过

环境配好后,启动 Tomcat 也有讲究。很多人直接双击startup.bat或执行startup.sh,然后看到窗口一闪而过以为成功了,其实端口没起或者项目没部署。正确做法是前台运行,日志直接打到终端:

cd /opt/tomcat/bin ./catalina.sh run

前台模式的好处是启动报错当场可见,比如端口占用、类加载异常、数据库连接超时都会直接刷在终端上。看到Server startup in [xxx] milliseconds后再停掉,改回startup.sh后台启动也不迟。

浏览器访问http://localhost:8080/项目名/,项目名要看webapps目录下解压出来的文件夹名,比如webapps/homework就是http://localhost:8080/homework/。如果你改过server.xml里的端口,则对应换成新端口。到这里,能用账号密码登录进去,说明这套 JAVA+Mysql 组合的网上作业批改系统已经在本地站住了。

3. MySQL侧的核心设计:看清作业与批改数据怎么组织,再动手改

把系统跑起来只是第一步。真正要改功能、加字段、调统计,你必须看懂数据库侧的设计。网上作业批改系统说白了就是三类数据:用户、作业、批改关系。作业提交后产生一条状态记录,教师批改后更新这条记录的分数和评语,管理员的统计报表再从这些表里汇总。数据库设计不清楚,改一个功能就会牵连三张表。

3.1 用户、作业、批改三张主表:字段类型与索引怎么定

先看核心表结构。用户表区分学生、教师、管理员三种角色;作业表描述“某门课程在某个截止时间前要交什么”;批改表记录“某位学生的某份作业得了多少分”。下面是一个常见的建表脚本:

CREATE TABLE t_user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, account VARCHAR(32) NOT NULL UNIQUE, role TINYINT NOT NULL COMMENT '1学生 2教师 3管理员', password_hash VARCHAR(64) NOT NULL, real_name VARCHAR(32) DEFAULT '' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE t_homework ( id BIGINT PRIMARY KEY AUTO_INCREMENT, course_id BIGINT NOT NULL, title VARCHAR(128) NOT NULL, deadline DATETIME NOT NULL, creator_id BIGINT NOT NULL, INDEX idx_course_id (course_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE t_review ( id BIGINT PRIMARY KEY AUTO_INCREMENT, homework_id BIGINT NOT NULL, student_id BIGINT NOT NULL, submit_time DATETIME DEFAULT NULL, file_path VARCHAR(255) DEFAULT '', score DECIMAL(5,2) DEFAULT NULL, comment TEXT, status TINYINT NOT NULL DEFAULT 0 COMMENT '0待批改 1已批改 2已退回', reviewed_by BIGINT DEFAULT NULL, reviewed_at DATETIME DEFAULT NULL, UNIQUE KEY uk_homework_student (homework_id, student_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

t_review表是整个系统的关键。首先,唯一键uk_homework_student保证同一个学生对同一份作业只能有一条记录,这是防止重复提交的数据库级护栏。其次,status字段承担状态流转,0、1、2 三个值就能表达“待批改、已批改、已退回”的完整生命周期。score DECIMAL(5,2)能存到三位整数加两位小数,课程设计场景足够;如果以后要存百分制加权分,也不用加精度。

索引方面,t_homework的idx_course_id是为“按课程列表展示作业”服务的,t_review上homework_id与student_id的组合唯一索引同时充当了查询索引。这里不要盲目加索引,作业批改系统的数据量级在万级以下,索引过多反而拖慢写入。MySQL 排序和联结在这种量级上没有任何压力,不需要分区,也不需要引入中间表。

3.2 用存储过程统计提交率与平均分:把复杂查询收进数据库

业务上有个高频需求:教师想看“这门课有多少人交了、平均分多少”。如果都在 Java 代码里写循环查询,一次统计要发几十条 SQL,数据库连接池都被拖慢。常见做法是把统计逻辑写进存储过程,应用层只调一个CALL语句。

DELIMITER $$ CREATE PROCEDURE sp_course_stats(IN p_course_id INT) BEGIN SELECT c.course_name, COUNT(DISTINCT u.id) AS total_students, COUNT(DISTINCT CASE WHEN r.status = 1 THEN r.student_id END) AS submitted, ROUND(AVG(CASE WHEN r.status = 1 THEN r.score END), 2) AS avg_score FROM t_course c JOIN t_user u ON u.role = 1 LEFT JOIN t_homework h ON h.course_id = c.id LEFT JOIN t_review r ON r.homework_id = h.id AND r.student_id = u.id WHERE c.id = p_course_id GROUP BY c.course_name; END$$ DELIMITER ;

两个细节要注意。第一,DELIMITER是命令行客户端的语法,Navicat 里执行时可以去掉DELIMITER那两行。第二,调用时直接CALL sp_course_stats(1),参数是课程 ID。这里的LEFT JOIN是关键——如果某学生没交作业,t_review里没有对应记录,内联结会把他丢掉,统计就偏了。

存储过程不是越多越好,把“一条 SQL 能查清的多表关联”写成过程是过度设计;但像这种提交率统计涉及三张表关联,且会被多个页面重复调用,放进数据库反而让 Java 代码更干净。

3.3 数据库连接池参数:这五个值决定系统能扛多少并发

系统跑起来后最容易出现的隐患是连接池配置不合理。很多新手项目直接用 JDBC 直连,每次请求都DriverManager.getConnection(),数据库连接创建非常昂贵,几十个人同时交作业就会卡死。所以要引入连接池,Druid 是 Java Web 项目里最常见的选择。

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/homework_db?useSSL=false&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="123456"/> <property name="initialSize" value="5"/> <property name="maxActive" value="20"/> <property name="minIdle" value="5"/> <property name="maxWait" value="60000"/> <property name="validationQuery" value="SELECT 1"/> </bean>

参数没调好,系统在线人数 50 以内可能完全正常,一上实训课 100 人同时交作业就崩。我一般建议课程设计系统用initialSize=5,够支撑启动时的基础连接;maxActive=20对应一个班 40 人同时操作绰绰有余;minIdle=5保持最低空闲连接,避免请求突发时要现建连接;maxWait=60000毫秒,请求拿不到连接最多等 60 秒就报超时,而不是无限阻塞把线程池拖死;validationQuery=SELECT 1是让连接池定期检测连接是否存活,MySQL 8 的 wait_timeout 默认 8 小时,空闲连接容易被服务端回收,没有心跳检测就会拿到失效连接。

这套 MySQL 连接池配置直接决定了系统的稳定上限。项目里如果是 c3p0 或 HikariCP,参数名不同但思路一致——核心就是“最小连接数、最大连接数、等待超时、探活语句”这四个维度。

4. 批改业务的核心链路:上传、判分与状态流转改在哪

系统跑通、数据库看清之后,大多数人的真实需求是改功能:限制文件类型、加一个退回重交、按班级导出成绩。这些都落在批改业务链路里。这条链路包括三块:学生上传、教师批改、状态更新。

4.1 学生端上传作业:文件存磁盘,数据库只存路径

作业上传是批改系统的入口,也是新手最容易写错的地方。常见错误是把文件转成 Base64 字符串存进 MySQL 的 TEXT 字段,几 MB 的文档就会让表膨胀、查询变慢。正确做法是文件落磁盘,数据库只记录文件的相对路径。

@WebServlet("/upload") public class UploadServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); Part filePart = req.getPart("file"); long studentId = Long.parseLong(req.getParameter("studentId")); long homeworkId = Long.parseLong(req.getParameter("homeworkId")); // 文件命名规则:学号_作业ID_时间戳.扩展名,防止重名覆盖 String ext = getExtension(filePart.getSubmittedFileName()); String fileName = studentId + "_" + homeworkId + "_" + System.currentTimeMillis() + "." + ext; // 常见做法:存到 webapps 外的独立目录,避免重启丢文件 String basePath = "/data/homework_files"; File dir = new File(basePath); if (!dir.exists()) { dir.mkdirs(); } filePart.write(basePath + File.separator + fileName); // 更新 t_review 表的 file_path 和 status,状态改为 0(待批改) ReviewDao dao = new ReviewDao(); dao.markSubmitted(studentId, homeworkId, fileName); } }

这段代码有两个关键点。第一,文件名用“学号 + 作业 ID + 时间戳”拼出来,既保证唯一又方便排查“谁交的哪份作业”;只用原始文件名的话,两个班各有一个“张三”、文件都叫“作业1.docx”,必覆盖。第二,文件写到 webapps 目录之外,这样 Tomcat 重启或重新部署 war 包时文件不会丢,后面迁移存储也只是改一个基础路径的事。

数据库里的file_path存相对路径,前端展示时再拼完整下载地址。filePart.write()是 Servlet 3.0 的 Part 接口写文件的方法,比较适合课程设计代码量;真实生产再换成FileOutputStream分批写,区别在于大文件上传内存占用更可控。

4.2 教师端批改与评分:一条 UPDATE 完成状态流转

教师端批改页面做的事很简单:显示待批改列表,点开一份作业,填写分数和评语,提交。后端对应就是更新t_review表的一条记录。

public boolean reviewHomework(long reviewId, BigDecimal score, String comment, long teacherId) { String sql = "UPDATE t_review " + "SET score = ?, comment = ?, status = 1, " + "reviewed_by = ?, reviewed_at = NOW() " + "WHERE id = ? AND status = 0"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setBigDecimal(1, score); ps.setString(2, comment); ps.setLong(3, teacherId); ps.setLong(4, reviewId); return ps.executeUpdate() == 1; } catch (SQLException e) { throw new RuntimeException("批改失败,请检查连接池状态", e); } }

注意 SQL 里的AND status = 0条件——这是在数据库层面保证只有“待批改”状态的记录才能被批改。两个老师同时打开同一份作业,后提交的人会因为条件不匹配而更新 0 行,避免互相覆盖。这个设计比在 Java 代码里加 synchronized 更可靠,因为并发控制放到了数据库的原子层面,这正是 java 面试题里常问的“数据一致性”的朴素实现。

PreparedStatement这里必须用,不能用字符串拼接 SQL。作业批语是自由文本,学生完全可以在评语里写一段' OR '1'='1之类的注入语句,拼接 SQL 直接就把查询条件改了。用setBigDecimal和setString绑定参数,从根上断绝注入可能,同时 BigDecimal 还避免了浮点运算的精度误差。

4.3 成绩排名与不及格预警:用 MySQL 排序把统计页撑起来

批改完成后,教师端通常要按成绩排名看整体情况。这条 SQL 覆盖了“按分数倒序、同分按学号升序”的二级排序场景:

SELECT s.real_name AS student_name, r.score, r.comment FROM t_review r JOIN t_user s ON s.id = r.student_id WHERE r.homework_id = 5 AND r.status = 1 ORDER BY r.score DESC, s.account ASC LIMIT 50;

ORDER BY r.score DESC做分数降序,s.account ASC作为次级排序让同分学生按学号排列,输出结果稳定可预期。LIMIT 50在这里是保护性写法,先只取前 50 名给页面第一屏,避免一次渲染几千行。统计页再配合第 3 章的存储过程,提交率、平均分、最高分这些指标就能一站查全。

这里有一个容易忽视的边界:status = 1的条件不能省。如果不加,状态为 2(已退回)的作业也会带着一个旧分数参与排名,未批改的记录score为 NULL,在排序中会被排在最后,造成排名数据污染。写统计 SQL 时把“只统计已批改”当作默认前提,就能避免这个逻辑黑洞。

5. 跑这套JAVA+Mysql系统常见的5个坑:从启动到上线的排查清单

环境类问题占这类系统排障的八成以上。以下五条是我接手网上作业批改系统时最常碰见的坑,按出现频率排序,每条都按“现象 → 原因 → 解决”写,可以直接照着排查。

5.1 mysql ssl连接错误:启动时握手失败的惯犯

现象:Tomcat 启动日志报Communications link failure,Caused by 是SSLHandshakeException或提示Establishing SSL connection without server's identity verification is not recommended。

原因:MySQL 8.0 默认开启 SSL 连接,客户端尝试加密握手但证书验证不过;MySQL 5.7 在某些发行版上也会出现类似告警。项目里的连接串没有显式声明是否使用 SSL,驱动就按默认行为加密。

解决:开发环境在 JDBC 连接串上加useSSL=false。如果 MySQL 8.0 还报Public Key Retrieval is not allowed,再加allowPublicKeyRetrieval=true。完整连接串在第 2.2 节已经给出,直接抄用。生产环境不建议关 SSL,但生产排错时可以先临时加这两个参数定位是不是 SSL 引发的,确认后再配置证书。

5.2 ERROR 2002 (HY000):can't connect to local MySQL server through socket '/tmp/mysql.sock'

现象:命令行执行mysql -u root -p直接报ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)。

原因:客户端默认走 socket 文件连接,但服务端 socket 路径不在/tmp/mysql.sock。常见于 MySQL 5.7 通过源码或 RPM 安装,socket 被配置到/var/lib/mysql/mysql.sock或/var/run/mysqld/mysqld.sock;另一种可能是 mysqld 压根没启动。

解决:先确认服务是否在跑:

systemctl status mysqld # 或 service mysql status

没跑就启动;跑了还报错,就改用 TCP 方式连接,避开 socket 路径问题:

mysql -h 127.0.0.1 -P 3306 -u root -p

-h 127.0.0.1强制走 TCP,这是最快绕过 socket 路径差异的命令。根源修复则要在/etc/my.cnf里找到socket=配置,把客户端[client]段的 socket 路径指到与[mysqld]段一致。正因为这个坑高频,我在第 2.2 节的建库命令里刻意用了-h 127.0.0.1,就是提前避开它。

5.3 中文乱码:连接串、表字符集、页面编码三处不一致

现象:作业标题明明是中文,页面上显示成问号;或者数据库里查出来正常,页面渲染乱码。

原因:乱码从来不是一处问题,而是三处没对齐。连接串里的characterEncoding、MySQL 表默认字符集、JSP 页面的pageEncoding各自为政,任何一处是 latin1 或 GBK 都会出乱码。

解决:三层统一为 UTF-8。连接串加useUnicode=true&characterEncoding=utf8;建表时指定DEFAULT CHARSET=utf8mb4;JSP 页面头部写<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>。另外,如果用了过滤器,request.setCharacterEncoding("UTF-8")要放在读取任何请求参数之前。检查顺序是:先看数据库里存的值对不对,再看页面请求进来了没有,最后看响应输出编码。数据库里已是乱码的话,改完代码后要重新导入数据,不要指望已有脏数据自动恢复。

5.4 页面偶发超时:连接池耗尽而不是程序死循环

现象:系统运行一段时间后,某个页面偶尔卡住,等 30 秒以上才报错,Tomcat 日志出现Connection is not available, request timed out after 30000ms。

原因:获取的数据库连接没归还。最常见是代码里只conn.createStatement()不关conn,或者查询抛异常后没有走 finally 释放连接。连接池maxActive=20,每次请求漏掉一条连接,20 个请求后池子就空了。

解决:先用第 3.3 节的连接池配置,把maxWait设为可见超时,让问题暴露而不是无限等待。然后用这段固定写法检查自己的 DAO:

try (Connection conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery()) { // 业务处理 } catch (SQLException e) { throw new RuntimeException("查询失败", e); }

Java 7 的 try-with-resources 会自动关闭Connection、PreparedStatement、ResultSet三个资源,且关闭顺序与创建顺序相反。这是我在所有课程设计代码评审里必查的点——只要看到手动finally里只关了conn没关rs和ps,基本就是连接池耗尽的定时炸弹。

5.5 端口被占用:地址已在使用中

现象:Tomcat 启动即失败,日志报Address already in use: JVM_Bind;MySQL 启动失败报Bind on TCP/IP port: 3306。

原因:本机已有另一个进程占用了 8080 或 3306。常见于开发机装过多个版本的 Tomcat、MySQL 服务自启动,或 IDE 内嵌的 Tomcat 没停干净。

解决:先找到占用进程,再决定是杀进程还是改端口。

# Linux / macOS lsof -i:8080 # Windows netstat -ano | findstr 8080

找到 PID 后按需处理。不改杀进程的话,Tomcat 的端口在conf/server.xml里统一改三个地方:<Connector port="8080">的 HTTP 端口,以及两个port="8005"、port="8009"的关闭与 AJP 端口。许多人只改了 8080 忘改 8005,照样启动失败。改端口后访问地址同步变化,这个坑在演示环境翻车率极高。

6. 上线前最该做的三件事:验证数据、预编译防注入、把war部署到Linux

系统能在本机跑通只能算“能演示”,要真正投入使用,还差一轮验证和加固。我接这类系统时,上线前必做三件事:造数据验证统计、检查 SQL 注入、把部署环境从 Windows 迁到 Linux。

第一,用 Navicat 批量造数据验证成绩排名和存储过程是否按预期工作。在t_review表里插入 60 个学生的成绩记录,故意构造同分、缺考、退回三种边界数据,然后执行第 4.3 节的排名 SQL,看同分学生的排序是否按学号稳定输出。这一步能发现 SQL 条件里的逻辑漏洞,比上线后等真实用户踩雷成本低得多。

第二,全项目检索字符串拼接 SQL 的地方。最直接的办法是搜" + "出现在 SQL 字符串里的代码:

// 错误写法:字符串拼接用户输入 String sql = "SELECT * FROM t_user WHERE account = '" + account + "'"; // 正确写法:预编译绑定参数 String sql = "SELECT * FROM t_user WHERE account = ?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, account);

课程设计项目往往赶工,登录接口、查询接口最容易出现这种注入点。哪怕是内部系统,一条' OR '1'='1就能以第一个用户的身份登录,必须全部改成PreparedStatement参数绑定。

第三,部署到 Linux 服务器。课程设计系统的量级不需要微服务,把项目打成 war 包放到 Tomcat 的webapps目录即可。MySQL 也迁到同一台服务器或独立数据库机,迁移时用mysqldump导出再导入:

mysqldump -h 127.0.0.1 -u root -p homework_db > homework_backup.sql mysql -h 目标服务器IP -u root -p homework_db < homework_backup.sql

我现在的习惯是:先把连接串里的useSSL、characterEncoding、serverTimezone三个参数钉死再启动服务,省得后面查乱码查到怀疑人生;再在连接池的maxWait上留一个可见的超时值,让连接泄漏问题尽早暴露而不是卡到用户投诉。环境归环境,代码归代码,两者分开排查,这套 JAVA+Mysql 的网上作业批改系统才能真正从“能跑”变成“能扛”。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 5:36:08

文旅项目实践:文旅营销与游客管理系统搭建方案

文旅项目实践&#xff1a;文旅营销与游客管理系统搭建方案 随着文旅行业数字化转型持续深入&#xff0c;单纯的票务预约系统已经无法满足景区经营需求。景区不仅需要完成游客入园管控&#xff0c;还需要通过营销活动吸引客流、沉淀游客资产&#xff0c;同时实现游客全生命周期管…

作者头像 李华
网站建设 2026/9/30 5:35:52

AI Skills技能库实战指南:从安装到编写SKILL.md

说实话&#xff0c;我第一眼见“Skills”这个词&#xff0c;是在 Matt Pocock 的视频和仓库里。当时心里想的和很多人一样&#xff1a;这不就是“技能”的英文复数嘛&#xff0c;八成又是 AI 圈包装出来的新概念。直到我真的把一个社区技能装进 Claude Code&#xff0c;又照着同…

作者头像 李华
网站建设 2026/9/30 5:35:45

Jev 模型实战:TypeSafe AI 如何实现结构化决策与概率输出

1. 从"不说话"的模型说起&#xff1a;Jev 到底在解决什么问题第一次看到 Jev 这个项目的时候&#xff0c;我脑子里冒出来的第一个疑问是&#xff1a;一个"不说话"的模型&#xff0c;到底能干什么&#xff1f;我们已经被各种对话式 AI 训练得习惯了——你问…

作者头像 李华
网站建设 2026/9/30 5:35:43

软件国产化迁移:C/C++编译链接适配实战指南

1. 迁移这件事&#xff0c;为什么卡在编译链接这一关1.1 “能编译≠能跑”&#xff1a;迁移难度的第一课去年接手一个软件国产化迁移项目时&#xff0c;技术负责人问我&#xff0c;那个C写的核心服务迁到自主平台要多长时间。我嘴比脑子快&#xff0c;直接回了句“两周应该够了…

作者头像 李华
网站建设 2026/9/30 5:35:41

RAG实战:从基础管道到Agentic RAG,解决知识割裂与提升命中率

1. RAG 到底在解决什么问题1.1 大模型的两个“天生缺陷”与知识割裂做 AI Agent 的人应该都有过这种体会&#xff1a;你把一个 Agent 接到业务里&#xff0c;它聊得头头是道&#xff0c;一落到具体数据上就开始胡编。比如我问它“我们公司去年 Q3 华东区的退货率是多少”&#…

作者头像 李华
网站建设 2026/9/30 5:35:36

1.73亿token账单拆解:大模型API计费逻辑与缓存优化实战

1. 一笔1.73亿token的账单&#xff0c;到底该怎么算九月份我用WorkBuddy跑了一整个月的高强度任务&#xff0c;月底看后台统计的时候愣了一下——1.73亿token。这个数字放在个人开发者身上不算小&#xff0c;放在小团队里也算得上中等偏上的用量。当时第一反应就是&#xff1a;…

作者头像 李华