资讯动态

Java车辆管理系统课设全解读:JSP+Servlet+MySQL+Maven

发布时间:2026/10/18 12:25:58 来源:尧图企业网站定制
简介一套基于JSP、Servlet、MySQL和Maven构建的车辆管理系统课程设计源码包面向正在准备Web开发课程设计或毕业设计的计算机专业学生以及希望快速上手Java Web项目的学习者。资源共计70个文件包含JSP页面、Java源码、XML配置文件、依赖JAR包、图片素材和项目说明文档压缩包仅5.67MB目录结构清晰可导入到IDEA中直接运行便于二次开发。项目覆盖车辆信息管理、出入场记录、状态查询等典型功能模块附带数据库car_data与数据表fixed_car的建表语句及示例数据能完整展示业务数据从MySQL存储、Servlet处理到JSP渲染的流转过程。说明文档还介绍了环境准备、部署启动与数据库初始化步骤帮助读者快速跑通整个项目。目前已有381人学习下载既能支撑课程设计报告和答辩演示也可作为毕业设计初期的代码框架与排错参考。1. Java车辆管理系统课设能跑、答辩能讲才是真资源一到课设季最怕的不是不会写代码而是代码写了一堆跑起来全是红叉。这份Java车辆管理系统课设源码就是这样一份拿来即用的兜底资源——JSPServletMySQLMaven四件套做的是停车场里最典型的固定车辆登记、查询、进出场时间管理不需要高深框架数据表和Servlet都摆得明明白白改改包名、字段名就能当课设交上去。它适合两类人正在做毕业设计、需要一份结构完整的Java Web项目做底子的学生以及刚学完Servlet、想看看真实项目怎么组织DAO、JSP和web.xml的Java学习者。下面按我拆课设的步骤从工程结构讲到数据库表再讲到增删改查和避坑保证你能跑起来。2. 项目结构与数据表先看清Maven工程和fixed_car的字段设计2.1 Maven工程的目录结构不用反编译也能找到所有代码拿到这个压缩包解压后首先看到的是pom.xml、demo2.iml、src、target这些文件。对用过IDEA的人来说demo2.iml是IDEA的模块文件target里是编译好的classes真正要看的代码全在src/main下面。打开之后的目录层次大概是src/main/java // Java源码DAO、Servlet、实体类都在这 src/main/resources // 配置文件db.properties通常放这里 src/main/webapp // JSP页面、WEB-INF/web.xml、静态资源这个结构是标准Maven布局IDEA里直接Open选中pom.xml等Maven把依赖拉完就能当成普通Web工程用。很多人习惯把类全塞在一个包底下课设老师一看目录结构就知道是抄的还是自己搭的三层分包至少显得有条理。如果依赖没自动拉下来大概率是IDEA没识别成Maven项目右键pom.xml选Add as Maven Project即可。2.2 pom.xml关键依赖哪些要打进war包哪些只需要编译期打开pom.xml能看到servlet-api、mysql-connector-java、jstl这几个关键依赖。做事得清楚它们各自的作用范围否则部署到Tomcat时会踩大坑。依赖典型坐标scope说明Servlet APIjavax.servlet:javax.servlet-apiprovided只在编译期需要Tomcat自带实现不能打进war包MySQL驱动mysql:mysql-connector-javacompile默认运行时连数据库用必须出现在WEB-INF/lib里JSTLjavax.servlet:jstlcompileJSP页面里做循环和格式化标签重点在servlet-api的scope必须是provided。Tomcat容器里已经有自己的servlet-api.jar了如果pom里不带scope打包时会把这个jar塞进WEB-INF/lib启动后经常出现类重复定义、NoSuchMethodError这类奇怪问题。mysql驱动和jstl则要保证在运行环境里能被类加载器找到最简单的方法就是让Maven默认的compile作用域把它们打进war包的lib目录。2.3 fixed_car表设计字段语义和进出场时间的关系数据库操作很直接先建car_data库再建立fixed_car表然后添加数据。表结构用到的字段类型比较有代表性特别是datetime类型的出场时间直接决定了业务逻辑怎么写。建表语句一般是CREATE DATABASE IF NOT EXISTS car_data DEFAULT CHARACTER SET utf8mb4; USE car_data; CREATE TABLE fixed_car ( car_id VARCHAR(20) NOT NULL COMMENT 车牌号, car_color VARCHAR(10) COMMENT 车辆颜色, car_owner VARCHAR(30) COMMENT 车主姓名, car_brand VARCHAR(20) COMMENT 车辆品牌, status VARCHAR(10) COMMENT 车辆状态比如临时或固定, intime DATETIME COMMENT 进场时间, outtime DATETIME COMMENT 出场时间, statusint INT COMMENT 状态标志位, PRIMARY KEY (car_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;字段名称和类型都来自项目说明其中status字段是char类型存的是临时这种文本状态statusint是int类型样例值为1一般用来做程序判断用的状态位。项目里给出的示例数据是鲁A09836灰色杜姆杜姆标志intime和outtime两个时间字段在同一天16:45:11到16:45:29看起来是一条测试用的进出场记录。字段名类型记录内容使用场景car_idchar车牌号主键唯一标识car_colorchar车辆颜色列表展示和搜索car_ownerchar车主姓名列表展示和搜索car_brandchar车辆品牌列表展示statuschar临时/固定展示和条件查询intimedatetime进场时间记录车辆进场时刻outtimedatetime出场时间记录车辆出场时刻statusintint1/0程序判断是否在场从业务上讲一辆车新登记进场时statusint设为1intime取当前时间outtime可以暂时为空车辆出场时update这条记录的outtime为当前时间再顺手把statusint改成0。这是最常见的车辆管理设计第二章后面的增删改查也都会围绕这套字段来写。2.4 从示例数据反推业务一次完整的进场出场是什么样原始数据里那条记录car_id是鲁A09836车主是杜姆杜姆品牌字段是标志status字段是临时intime和outtime靠得很近。看懂这条数据就能反推出系统的核心业务动作第一车辆进场或登记时页面表单提交车牌、颜色、车主、品牌、状态这些文本字段intime由后台在insert时用当前时间填充第二车辆出场时只需要按car_id找到记录把outtime更新为现在的时间第三列表页按车牌或车主做模糊查询时like语句里拼上输入的关键字再把结果集遍历显示。课程设计答辩时老师最喜欢问的一句就是你这个出场时间是怎么来的看过这条样例数据就知道outtime不是表单输入的而是出场操作时由程序写入的。懂了这一步整个系统的数据流就通了。3. JDBC与MySQL连接驱动、连接管理到增删改查3.1 MySQL驱动版本和db.properties连接参数项目用的是MySQL数据库年代不同的课程设计在驱动类名上有明显差异。如果是MySQL 5.x驱动类是com.mysql.jdbc.Driver如果是MySQL 8.x标准写法变成com.mysql.cj.jdbc.Driver。这个资源面对的现代环境基本是MySQL 8所以配置文件里应该是后者。drivercom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/car_data?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai usernameroot password123456核心参数解释一下characterEncodingutf8保证数据库读写不乱码useSSLfalse避免连接时警告满天飞serverTimezoneAsia/Shanghai解决MySQL 8时区导致的8小时偏差。password不是固定的如果是你自己的MySQL环境改成自己本地的密码即可。我一般会在写完db.properties之后先在命令行里测试一遍连接确认账号密码没问题再让程序去读这个文件能省一半排查时间。3.2 DbUtil工具类加载驱动、获取连接和资源关闭连接管理写成工具类几乎是Java Web课设里的标准动作。用一个静态代码块读取db.properties并注册驱动以后每个方法要连接数据库时只管调getConnection()。import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; public class DbUtil { private static String driver; private static String url; private static String username; private static String password; static { try (InputStream in DbUtil.class.getClassLoader().getResourceAsStream(db.properties)) { Properties props new Properties(); props.load(in); driver props.getProperty(driver); url props.getProperty(url); username props.getProperty(username); password props.getProperty(password); // MySQL 8 驱动加载 Class.forName(driver); } catch (Exception e) { e.printStackTrace(); throw new ExceptionInInitializerError(数据库配置加载失败); } } public static Connection getConnection() throws Exception { return DriverManager.getConnection(url, username, password); } public static void close(AutoCloseable... resources) { for (AutoCloseable res : resources) { if (res ! null) { try { res.close(); } catch (Exception ignored) { } } } } }这段逻辑不复杂重点在静态代码块只执行一次驱动注册不会重复。getConnection每次调用都新建一个物理连接课设规模完全够用不要上连接池反而增加复杂度容易翻车。close方法用了可变参数方便在一个try-catch-finally里把ResultSet、PreparedStatement、Connection一次关干净。3.3 CarDao核心方法增删改查和模糊搜索的写法Dao层是课设里最能体现基本功的部分。这里给出常用的四个方法查询列表、按条件搜索、新增、删除。新增和查询完整写出来删除和修改逻辑类似。import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; public class CarDao { // 查询全部在场车辆 public ListCar findAll() throws Exception { String sql SELECT car_id, car_color, car_owner, car_brand, status, intime, outtime, statusint FROM fixed_car ORDER BY intime DESC; ListCar list new ArrayList(); Connection conn DbUtil.getConnection(); PreparedStatement ps null; ResultSet rs null; try { ps conn.prepareStatement(sql); rs ps.executeQuery(); while (rs.next()) { Car car new Car(); car.setCarId(rs.getString(car_id)); car.setCarOwner(rs.getString(car_owner)); car.setCarColor(rs.getString(car_color)); car.setCarBrand(rs.getString(car_brand)); car.setStatus(rs.getString(status)); car.setIntime(rs.getTimestamp(intime)); car.setOuttime(rs.getTimestamp(outtime)); car.setStatusint(rs.getInt(statusint)); list.add(car); } } finally { DbUtil.close(rs, ps, conn); } return list; } // 新增车辆 public int insert(Car car) throws Exception { String sql INSERT INTO fixed_car (car_id, car_color, car_owner, car_brand, status, intime, outtime, statusint) VALUES (?, ?, ?, ?, ?, ?, ?, ?); Connection conn DbUtil.getConnection(); PreparedStatement ps null; try { ps conn.prepareStatement(sql); ps.setString(1, car.getCarId()); ps.setString(2, car.getCarColor()); ps.setString(3, car.getCarOwner()); ps.setString(4, car.getCarBrand()); ps.setString(5, car.getStatus()); ps.setTimestamp(6, car.getIntime()); ps.setTimestamp(7, car.getOuttime()); ps.setInt(8, car.getStatusint()); return ps.executeUpdate(); } finally { DbUtil.close(ps, conn); } } }两个方法都遵循同一套模板先写SQL语句再用PreparedStatement绑定?占位符最后在finally里统一资源关闭。findAll里getTimestamp拿到的java.sql.Timestamp可以直接塞进实体类的java.util.Date字段Timestamp是Date的子类不影响后续JSP页面的显示。insert方法里setTimestamp的使用很关键——很多新手这里偷懒用setString存时间文本后面做时间比较时就会处处碰壁。模糊查询常见做法是在SQL里拼LIKE条件关键字从Servlet传入Dao层。需要注意一定要用PreparedStatement传参不要直接用字符串拼接。写明车主的模糊查询条件后用ps.setString(1, % keyword %)百分号是参数的一部分SQL注入在占位符模式下没有可乘之机。3.4 时间字段的处理表单字符串转数据库datetime这是车辆管理系统里最容易踩坑的一段。JSP页面表单用datetime-local输入框提交时后端收到的是2022-12-10T16:45这种带T的字符串MySQL里的datetime又不认这个格式。常见做法是在Servlet里做一次转换import java.text.SimpleDateFormat; import java.util.Date; public class DateUtil { // 把表单里的时间字符串转成 java.sql.Timestamp public static java.sql.Timestamp parse(String timeStr) { if (timeStr null || .equals(timeStr.trim())) { return null; } try { SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm); Date date sdf.parse(timeStr.replace(T, )); return new java.sql.Timestamp(date.getTime()); } catch (Exception e) { return null; } } }SimpleDateFormat不是线程安全的放在方法内部新建实例避免并发问题。注意表单里datetime-local提交的值带T先replace成空格再parse。如果页面用的是两个分开的日期和时分输入框则要按yyyy-MM-dd HH:mm拼好再转。Java 8以后也可以改用LocalDateTime.parse加上DateTimeFormatter但课设里SimpleDateFormat更常见答辩时也更容易解释。4. Servlet与JSP流转车辆列表和出入场操作的请求链路4.1 用web.xml还是注解课设里二选一即可Servlet 3.0以后既可以用WebServlet注解也可以在web.xml里配置映射。原项目既然走的是JSPServletMaven两种方式都不会错区别在于你自己答辩时更熟悉哪种。web.xml方式如下servlet servlet-nameCarServlet/servlet-name servlet-classcom.demo.servlet.CarServlet/servlet-class /servlet servlet-mapping servlet-nameCarServlet/servlet-name url-pattern/car/url-pattern /servlet-mappingURL为/car的请求会全部进入CarServlet。如果容器版本较新Tomcat 8.5以上也可以在类上直接写WebServlet(/car)web.xml里就不需要任何servlet配置。我这里习惯用web.xml因为部署时排查映射冲突更直观而且老版本Tomcat也兼容。4.2 CarServlet集中入口doGet与doPost的分工车辆管理系统的功能集中在几个动作上查看列表、新增车辆、编辑、删除、出场登记。Servlet里用一个action参数区分操作意图代码结构会非常清晰。WebServlet(/car) public class CarServlet extends HttpServlet { private CarDao carDao new CarDao(); Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String action req.getParameter(action); if (list.equals(action)) { listCars(req, resp); } else if (delete.equals(action)) { deleteCar(req, resp); } else if (edit.equals(action)) { updateCar(req, resp); } else { listCars(req, resp); } } Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); String action req.getParameter(action); if (add.equals(action)) { addCar(req, resp); } } private void addCar(HttpServletRequest req, HttpServletResponse resp) throws IOException { Car car new Car(); car.setCarId(req.getParameter(car_id)); car.setCarColor(req.getParameter(car_color)); car.setCarOwner(req.getParameter(car_owner)); car.setCarBrand(req.getParameter(car_brand)); car.setStatus(req.getParameter(status)); // 进场时间用当前时间出场时间留空 car.setIntime(new java.sql.Timestamp(System.currentTimeMillis())); car.setOuttime(null); car.setStatusint(1); try { carDao.insert(car); } catch (Exception e) { e.printStackTrace(); resp.sendRedirect(car?actionlisterr1); return; } resp.sendRedirect(car?actionlist); } }新增车辆的逻辑要点car_id从表单拿intime不给用户填直接取系统当前时间statusint设1表示在场outtime为null。这样设计比让用户手动填时间更贴近真实业务答辩时也更好说明车辆进场时间来自系统而不是人为输入。doPost里第一行req.setCharacterEncoding(UTF-8)必须放在读取任何参数之前。这条防的是表单提交的中文乱码放写参数后面再调用就来不及了。如果项目里还配置了CharacterEncodingFilter这一行可以省略但写上也没什么坏处。4.3 JSP页面用JSTL渲染车辆列表Servlet查完数据后把List 放进request作用域再forward到JSP页面里用JSTL的c:forEach遍历。下面这段是一个简化但完整的列表页片段% page contentTypetext/html;charsetUTF-8 pageEncodingUTF-8 % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % % taglib prefixfmt urihttp://java.sun.com/jsp/jstl/fmt % html head title车辆列表/title /head body table border1 tr th车牌号/thth颜色/thth车主/th th品牌/thth状态/thth进场时间/thth操作/th /tr c:forEach items${carList} varcar tr td${car.carId}/td td${car.carColor}/td td${car.carOwner}/td td${car.carBrand}/td td${car.status}/td tdfmt:formatDate value${car.intime} patternyyyy-MM-dd HH:mm:ss//td tda hrefcar?actiondeletecar_id${car.carId}删除/a/td /tr /c:forEach /table /body /htmlcarList是Servlet里request.setAttribute(carList, list)放进去的EL表达式直接按属性名取。fmt:formatDate用来格式化Timestamp直接输出java.util.Date在页面上会显示成Wed Dec 10 16:45:11这种英文格式很难看。加上pattern之后就是标准的中文时间格式这也是课程设计页面美观度的一个小加分项。4.4 表单新增车辆的JSF交互链路列表页通常还有一个新增车辆入口可以是独立add.jsp也可以是列表页顶部的弹窗表单。表单提交路径是POST到/caraction参数为add。表单里各输入框的name必须和Servlet里req.getParameter的参数名一一对应car_id对应车牌号输入框car_color对应颜色输入框以此类推。这一步对不上Servlet里永远拿到null常见得像科目一。如果实际跑的时候发现新增后列表没变化先在Servlet入口处加一行System.out.println打印收到的参数再一步步往后查这比对着页面猜逻辑快得多。5. 课设避坑现场驱动、编码、部署与时间的五个高频问题5.1 运行时ClassNotFoundException: com.mysql.cj.jdbc.Driver现象项目启动不报错一进入查询或新增功能控制台立刻抛出ClassNotFoundException指向MySQL驱动类。原因拆解有两种可能。第一种是IDEA里pom.xml虽然写了mysql-connector-java依赖但部署配置没把Maven依赖加到Artifact里导致编译时能找到类运行时WEB-INF/lib里根本没有mysql的jar。第二种是MySQL驱动类名写错5.x时代的com.mysql.jdbc.Driver在MySQL 8驱动包下会直接报找不到。解决先确认pom里dependencies已经声明然后在IDEA右侧Maven面板执行mvn clean package解压target目录下生成的war包看WEB-INF/lib里有没有mysql-connector-java的jar。没有就右键项目选Open Module Settings在Artifacts选项卡里把Maven依赖的lib加入output root再重新部署。驱动类名统一写成com.mysql.cj.jdbc.DriverMySQL 5和8的包都能兼容。5.2 中文字符串存进MySQL后变成问号现象页面上输入灰色杜姆杜姆这些中文提交后列表显示的都是问号或者页面上直接乱码。原因属于多点失守的典型。浏览器发起的请求编码、JSP页面本身的pageEncoding、Servlet读取参数时的编码、MySQL连接的字符集参数、数据库表默认字符集任何一处不统一中文就会在某一环变成乱码后面再怎么补救都补不回来。解决从上到下统一为UTF-8。JSP第一行写pageEncodingUTF-8Servlet在doPost里先req.setCharacterEncoding(UTF-8)db.properties的url追加characterEncodingutf8建表语句里带上DEFAULT CHARSETutf8mb4最后再检查MySQL的配置文件my.ini里有没有character_set_server。谁都不确定是哪个环节的问题时按这个顺序排查基本能一次性解决。5.3 Tomcat启动不报错访问链接却一直404现象IDEA里点运行Tomcat日志正常输出但浏览器访问/list.jsp或/car时始终404甚至显示原始的目录结构。原因大概率不在代码而在IDEA的部署配置。用Maven工程跑Web项目时如果Artifacts配置成了空的或者部署的是target/classes而不是war包exploded的web根目录Tomcat就找不到任何可访问的资源。另外context path如果配置成/car_war_exploded这种长名字访问根路径也容易捣乱。解决打开Project Structure里的Artifacts先删掉有问题的项新建一个Web Application: Exploded注意把Maven的lib目录包含进WEB-INF然后回到Run Configuration的Deployment选项卡确认Application context设为/。启动后再看控制台的部署日志会列出实际部署路径和context按那个路径访问准能进。连接莫名超时的话顺便看一眼Tomcat的端口是不是被占用改了8082之类的端口也要记得按新端口访问。5.4 入库的进场时间比本地时间慢了8小时现象北京时间16:45入库数据库里存的是08:45JSP页面显示也少8小时。原因几乎都是连接参数缺了serverTimezone导致MySQL Connector/J采用UTC时区。MySQL 8的驱动在连接没指定时区时默认以服务器时区为准而服务器时区经常是UTC转换后自然差出8小时。解决在db.properties的url上明确追加serverTimezoneAsia/Shanghai并保证MySQL端time_zone不为SYSTEM且实际为东八区。更稳妥的做法是在建连接前用SET time_zone 08:00但课设阶段加serverTimezone参数已经足够了。顺手把intime在实体类里定义为java.util.Date读取用getTimestamp写入用setTimestamp字符串和数字的隐式转换坑也能绕开。改完重启Tomcat之前记得clean一下重新编译缓存里的旧class经常让人误以为没生效。5.5 连续操作几次后连接拒绝too many connections现象新增、查询多操作几次页面开始报Data source rejected establishment of connection或too many connections。原因十有八九是连接没关。查代码里有没有把DriverManager.getConnection写在一个循环或递归里更常见的是每次查询都新建Connection但finally里只关了Statement漏了Connection本身。解决养成统一的习惯数据库操作全部走DbUtil.close方法在finally里按ResultSet、Statement、Connection的顺序依次关闭。自己封装工具类时close接口接收AutoCloseable可变参数挨个遍历关闭即可。一个页面会话内大量连接被释放掉之后MySQL的max_connections通常没问题但保守起见可以把最大连接数改到500。改这个参数要登录MySQL执行set global max_connections500重启后仍会保留部分课设演示足够用。6. 答辩前再加三处小改动计数、防注入与出场登记前面章节绕了一遍核心流程这份资源本身已经有了完整的骨架。想在答辩时多讲点东西可以再加三个小功能点每一处改动不大但很能体现思考深度。第一处在列表页加一个在场车辆统计。用count(*)按statusint1聚合查询页面顶部显示当前在场车辆N辆。这个数字既直观又方便测试演示时进出场操作后数字立刻变化答辩效果很好。实现方式就是Dao里加一个countInPark()方法返回intServlet查出来后req.setAttribute(total, count)即可。public int countInPark() throws Exception { String sql SELECT count(*) FROM fixed_car WHERE statusint 1; try (Connection conn DbUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { if (rs.next()) { return rs.getInt(1); } } return 0; }这里用了try-with-resources连接和statement自动关闭。注意count返回的列用rs.getInt(1)取第一列即可不用讲太多SQL细节。第二处是搜索接口统一走PreparedStatement避免字符串拼接。模糊搜索的百分号放在参数里比如ps.setString(1, % keyword %)。如果答辩老师问为什么不用Statement你就可以理直气壮说占位符预编译防止SQL注入特殊字符不会逃逸出参数边界。第三处是出场登记。表单提交车辆出场时Servlet里拿到car_id先查这条记录的intime再update把outtime设为当前时间、statusint改为0。如果车已经出场再点出场就提示该车辆已出场。这比直接delete掉这条记录更贴近真实业务也给后续统计停车时长留下了数据基础。我拆了这么多Java Web课设项目养成了一个习惯拿到任何人的源码第一件事不是打开IDE运行而是先把数据库建出来再把pom.xml捋一遍最后再改连接参数。很多人卡在跑不起来从来不是代码逻辑的问题全是时区、编码、依赖scope这种小细节上。从那以后我每次下载Java Web课程设计项目都强制走一遍建表→查依赖→改编码的checklist翻车概率骤降。这份车辆管理系统里的坑基本都被我踩过一遍了希望你用时能少绕几个弯希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑