尧图精选

基于SSM框架的校园车辆管理系统实战:从数据库设计到部署上线

🕒 发布时间:2026/9/23 21:28:58 📁 来源:尧图网络
简介这是一份基于SSM框架SpringSpringMVCMyBatis实现的校园车辆管理系统完整源码项目适合Java初学者、毕业设计学生或需要快速搭建车辆管理后台的开发者。项目已通过严格调试可在IDEA或Eclipse中直接运行配套MySQL 5.7数据库脚本包含管理员与员工两种角色功能覆盖用户登录注册、个人中心、车主管理、取车泊车、车位管理、车辆记录统计、月份报表与饼图、系统公告管理等模块界面基于JSPCSSJS操作直观便于二次开发。压缩包整体约10.68MB内含项目源码和数据库脚本等核心文件解压后即可对照学习SSM整合流程、权限角色设计以及图表统计的实际应用。目前已有68人学习下载适合作为毕业设计参考或SSM框架综合练习项目能帮助读者快速掌握从数据库设计到前后端联调的全过程。1. 校园车辆管理这件事为什么值得用 SSM 做一遍如果你在大三或大四十有八九会被一门叫“Java 课程设计”或“毕业设计”的课拦住题目里带着“基于 XX 框架实现 XX 管理系统”。基于 SSM 框架实现的校园车辆管理系统就是这类题目里最典型、也是最“稳”的一个业务够清楚技术栈够主流做完能写进简历也能直接当毕业设计交差。SSM 指的是 Spring SpringMVC MyBatis 三件套B/S 架构意味着你只需要一个浏览器就能访问系统不用装客户端。这套东西在高校课设和中小企业后台管理系统里用了十几年资料多、坑少、找人问也容易。它解决的问题很直白把校园里进出车辆的信息、车位分配、访客登记、费用统计从 Excel 和纸质台账里搬到网页上让保安和后勤不用再翻本子。适合谁做适合学过 Java Web、会一点 MySQL、但没完整做过一个项目的学生也适合想快速搭一个可用后台管理系统练手的初级开发者。这篇文章不讲虚的直接把表结构、核心代码、部署命令和那些能让你少熬三个通宵的坑一次讲完。2. SSM 三件套和 B/S 架构选型为什么这个组合至今没过时2.1 Spring、SpringMVC、MyBatis 各自在系统里扮演什么角色很多新手把 SSM 当成一个整体来学结果 xml 配置了一堆还是分不清每个框架干了什么。我习惯用一个比喻Spring 是公司的行政部管着所有对象的创建、销毁和依赖关系SpringMVC 是前台接待所有 HTTP 请求先到它这里由它转发给对应的业务部门ControllerMyBatis 是数据专员你写 SQL 它帮你发你查完它帮你把结果封装成 Java 对象。在校园车辆管理系统里这个分工特别清晰。车辆登记、出入记录、费用结算这些业务底层都要操作数据库表。用 Spring 管理 Service 和 Mapper 的实例避免到处 new 对象用 SpringMVC 接收前端页面发来的请求比如用户点击“添加车辆”按钮表单数据就通过 POST 请求到 Controller用 MyBatis 写车辆表的增删改查你只需要关注 SQL 本身不用写一堆 JDBC 连接的样板代码。这套组合的好处是边界分明。Controller 里只写参数接收和页面跳转Service 里写业务判断比如“此车辆是否已登记”“该车位是否被占用”Mapper 里只放 SQL 语句。项目报错了看报错信息落在哪一层基本就知道去哪改。2.2 B/S 架构在校园场景的三个决定性优势B/S 架构也就是 Browser/Server所有业务逻辑和数据处理都在服务器端完成客户端只需要一个浏览器。选它做校园车辆管理系统不是因为它流行而是这个场景下的需求它都能接住。第一零客户端部署。门卫室的电脑、后勤办公室的旧电脑只要能开浏览器就能用不用每台机器装 Java 环境或专用软件。对非计算机专业的后勤人员来说打开网址登录就能用学习成本几乎为零。第二集中式维护。系统升级或修 bug只改服务器上的代码部署一次所有用户立刻用上新版本。这对学校这种没有专职运维团队的场景非常重要。第三数据集中存储。所有车辆登记信息、出入记录都存在服务器数据库里不会因为某台电脑坏了而丢失也方便做月度、季度报表统计。当然 B/S 架构也有短板最典型的是对网络有要求。如果学校网络不稳定操作会出现卡顿或提交失败。但校园网基础设施到今天已经足够成熟这个问题在真实部署中基本可以被忽略。如果实在不放心可以在表单提交后加上“提交成功”的反馈提示并定时备份数据库。2.3 从零搭建项目骨架Maven 工程和三层分包结构我见过太多学生把 SSM 项目做成一个巨型包所有类堆在一起最后自己都找不到代码。从搭项目的第一分钟起分包就要按三层结构来。先创建一个标准的 Maven Web 工程Java Resource 下的包结构如下com.campus.vehicle ├── controller # 控制层接收请求 ├── service # 业务层处理逻辑 │ └── impl # 业务实现类 ├── mapper # MyBatis Mapper 接口 ├── entity # 实体类对应数据库表 ├── common # 通用工具类、常量类 └── config # 配置类如验证码、拦截器!-- pom.xml 中必须引入的核心依赖 -- dependencies !-- Spring核心 -- dependency groupIdorg.springframework/groupId artifactIdspring-context/artifactId version5.3.27/version /dependency !-- SpringMVC -- dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version5.3.27/version /dependency !-- MyBatis 以及 Spring 整合包 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.5.13/version /dependency dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version2.1.0/version /dependency !-- MySQL 驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency /dependencies这里注意 Spring 版本和 JDK 版本要匹配。JDK 8 用 Spring 5.3.x 没问题如果你本机是 JDK 11 或更高建议直接上 Spring 6.x但那样又需要 Jakarta EE 的命名空间课设阶段不建议混用。MySQL 驱动用 8.0.x 时数据库连接 URL 必须带serverTimezoneAsia/Shanghai否则会时报时区错误。分包结构确定了后面每写一个功能就知道代码该往哪放不会出现 Controller 里写 SQL 这种让人头大的情况。3. 数据库设计车辆、车位、进出记录三张核心表一次讲透3.1 需求拆解到底需要哪几张表不做需求分析直接建表是课设翻车的第一大原因。校园车辆管理系统你先把业务场景捋一遍车辆要登记谁的车、什么车牌、什么颜色车位要管理哪些车位是固定车位、哪些是临时车位车辆进出门要记录进门时间、出门时间可能还要收费教职工免费校外车按时收费。顺着这些场景拆核心表至少要有四张车辆信息表、车主信息表、车位信息表、进出记录表。另外为了统计方便还应该有一张收费记录表记录每辆车进出一次应该交多少钱、是否已支付。我第一次做这类系统时把权限管理也塞了进来结果搞出了六张表最后光写增删改查就写了一周。课设阶段不要贪多把核心业务做扎实比做大而全更重要。你可以把车主信息合并进车辆表教职工信息用owner_type字段区分即可但进出记录表一定要独立因为这是整个系统数据量增长最快的表也是后期做报表统计的数据来源。3.2 每张表的字段设计和建表 SQL-- 车辆信息表 CREATE TABLE tb_vehicle ( id int(11) NOT NULL AUTO_INCREMENT COMMENT 主键, plate_number varchar(20) NOT NULL COMMENT 车牌号如 京A12345, owner_name varchar(50) NOT NULL COMMENT 车主姓名, owner_dept varchar(100) DEFAULT NULL COMMENT 所属院系/部门, owner_phone varchar(20) DEFAULT NULL COMMENT 联系电话, vehicle_type tinyint(4) DEFAULT 1 COMMENT 车辆类型1-教职工2-学生3-访客, status tinyint(4) DEFAULT 1 COMMENT 状态1-正常0-注销, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 登记时间, PRIMARY KEY (id), UNIQUE KEY uk_plate (plate_number) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT车辆信息表;-- 进出记录表 CREATE TABLE tb_in_out_record ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 记录ID, plate_number varchar(20) NOT NULL COMMENT 车牌号, in_time datetime DEFAULT NULL COMMENT 进场时间, out_time datetime DEFAULT NULL COMMENT 离场时间, parking_id int(11) DEFAULT NULL COMMENT 停车位ID, fee decimal(10,2) DEFAULT 0.00 COMMENT 本次费用, status tinyint(4) DEFAULT 0 COMMENT 状态0-在场1-已离场, PRIMARY KEY (id), KEY idx_plate_time (plate_number,in_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT进出记录表;建表时有几个细节值得注意。车牌号字段必须加唯一索引因为同一辆车的登记信息不能重复。进出记录表的id用 bigint 而不是 int因为出入记录表的数据量会持续增长int 上限 21 亿看着虽大但做统计查询时 bigint 的索引性能更稳。所有金额字段用 decimal(10,2)千万不要用 float否则会出现 0.10.20.30000000000000004 这种让你怀疑人生的计算误差。字符集一律用 utf8mb4不要用 utf8。现在校园里偶尔会有车牌号带生僻字或特殊符号的情况utf8mb4 才能完整支持。如果你已经建了表用的是 utf8可以通过ALTER TABLE tb_vehicle CONVERT TO CHARACTER SET utf8mb4;一条命令转过来。3.3 扩展表设计车位表和收费规则怎么联动车位管理是这个系统里容易被忽略但实际使用频率很高的模块。校园里车位分两种固定车位按月或按学期分配给教职工访客车位按小时计费。两种模式在同一套系统里怎么设计我建议统一走“进出记录表 费用规则表”的思路。-- 车位信息表 CREATE TABLE tb_parking_space ( id int(11) NOT NULL AUTO_INCREMENT COMMENT 车位ID, space_code varchar(20) NOT NULL COMMENT 车位编号如 A-101, area varchar(50) DEFAULT NULL COMMENT 所属区域如东门停车场, space_type tinyint(4) DEFAULT 1 COMMENT 类型1-固定2-临时, holder_id int(11) DEFAULT NULL COMMENT 固定车位持有者ID来自车辆表, status tinyint(4) DEFAULT 0 COMMENT 状态0-空闲1-占用, PRIMARY KEY (id), UNIQUE KEY uk_space_code (space_code) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT车位信息表;进出记录的parking_id关联车位表车辆进门时分配一个空闲车位出场时把车位状态改回空闲。收费规则我一般不建议单独建表直接写在 Service 层的常量里就行比如“固定车辆免费、临时车辆前 30 分钟免费、超过后每小时 5 元”。这是因为课设阶段收费计算逻辑不会频繁变建表反而增加了联表查询的复杂度。如果你想用配置化的方式在tb_system_config表里存一个 key-value 配置即可不要为此单独建规则引擎。外键要不要建实体外键我建议物理上不建逻辑上通过字段关联。原因很简单学校给学生作业配置的 MySQL 版本可能较老外键约束在删除关联数据时经常报错而你原本是想在 Service 层做逻辑判断的。用代码保证数据一致性比数据库的物理外键更灵活也更容易排查。4. 从登录到出入登记核心功能模块的代码实现与参数说明4.1 用户登录与权限拦截最容易被低估的一个模块很多课设项目登录功能就是验证一下用户名密码然后跳转页面但实际评分老师很看重“权限”这个点。校园车辆管理系统里至少要有两种角色管理员可以看所有出入记录和费用统计普通保安只能操作车辆登记和进出登记。权限控制怎么做用 SpringMVC 的拦截器HandlerInterceptor在请求进入 Controller 之前判断当前登录人的角色。// 登录拦截器核心代码 public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 获取 session 中保存的登录用户 Object user request.getSession().getAttribute(loginUser); if (user null) { // 未登录跳转到登录页 response.sendRedirect(request.getContextPath() /login); return false; } // 如果是管理员请求路径检查角色 String uri request.getRequestURI(); if (uri.contains(/admin/)) { SysUser loginUser (SysUser) user; if (!ADMIN.equals(loginUser.getRole())) { response.setContentType(text/html;charsetutf-8); response.getWriter().write(scriptalert(无权限访问);history.back();/script); return false; } } return true; } }这段代码的逻辑分三步先从 session 里取用户对象取不到就说明没登录重定向到登录页取到了再判断请求路径是否包含/admin/包含就继续校验角色角色不匹配就返回一个弹窗提示。注意这里用了response.getWriter().write()直接输出一段 HTML而不是跳转到错误页这样用户能立刻看到提示体验更好。在 spring-mvc.xml 中注册拦截器时要配置排除名单——登录页面本身、登录请求、静态资源css、js、图片不需要拦截。否则会出现你还没登录就想加载样式结果样式文件也被拦截器挡了的情况。这个坑我踩过印象极其深刻页面打开是纯 HTML 没有任何样式控制台报 302 重定向排查了大半天才发现是拦截器把静态资源也拦了。4.2 车辆登记与分页查询用 MyBatis 动态 SQL 解决多条件搜索管理页面几乎都需要“多条件筛选 分页列表”。车辆管理页面的搜索条件通常有三个车牌号模糊查询、车主姓名模糊查询、车辆类型精确查询。三个条件组合起来怎么写 SQL如果用 JDBC你得手动拼接字符串还要考虑关键字注入风险但在 MyBatis 里用动态标签就能干净解决。!-- VehicleMapper.xml 中的多条件查询 -- select idselectVehicleList resultTypecom.campus.vehicle.entity.Vehicle SELECT id, plate_number, owner_name, owner_dept, owner_phone, vehicle_type, status, create_time FROM tb_vehicle where if testplateNumber ! null and plateNumber ! AND plate_number LIKE CONCAT(%, #{plateNumber}, %) /if if testownerName ! null and ownerName ! AND owner_name LIKE CONCAT(%, #{ownerName}, %) /if if testvehicleType ! null AND vehicle_type #{vehicleType} /if /where ORDER BY create_time DESC LIMIT #{offset}, #{pageSize} /select// Service 层调用代码 public PageResultVehicle queryVehicleList(String plateNumber, String ownerName, Integer vehicleType, int pageNum, int pageSize) { MapString, Object params new HashMap(); params.put(plateNumber, plateNumber); params.put(ownerName, ownerName); params.put(vehicleType, vehicleType); // 计算偏移量第 2 页每页 10 条offset 就是 10 params.put(offset, (pageNum - 1) * pageSize); params.put(pageSize, pageSize); ListVehicle list vehicleMapper.selectVehicleList(params); int total vehicleMapper.countVehicleList(params); return new PageResult(list, total, pageNum, pageSize); }这段代码里的LIMIT #{offset}, #{pageSize}是分页核心。注意 MyBatis 的#{}用的是预编译占位符传进来的值都会被 JDBC 的PreparedStatement处理不会出现 SQL 注入问题如果你图省事用${}拼接搜索框里输入% OR 11 --就能把你的数据表整个拖出来这个危险性不是开玩笑。分页参数建议每次查询先算总记录数再算总页数。前端页面需要知道总页数才能渲染分页按钮。很多初学者只查了当前页的数据忘了查总数结果页面下方“共 23 条 / 第 1/3 页”的信息永远显示不对。上面的代码里专门写了countVehicleList方法就是干这件事的别忘了在 Mapper 里配套写好。4.3 车辆进出登记事务处理让“进”和“出”不留脏数据车辆进出的核心操作是进门时插入一条进出记录并把状态置为“在场”出门时更新这条记录写入离场时间并计算费用。这个操作必须放在同一个事务里因为如果插入记录成功但更新车位状态失败车就“凭空消失”了——记录显示在场车位显示空闲数据就对不上了。// 车辆出场登记的核心逻辑 Transactional(rollbackFor Exception.class) public boolean vehicleOut(String plateNumber, int parkingId) { // 1. 查询当前在场记录 InOutRecord record inOutRecordMapper.selectByPlateAndStatus(plateNumber, 0); if (record null) { throw new BusinessException(该车辆没有在场记录请确认车牌号是否正确); } // 2. 计算停车费用 long minutes Duration.between(record.getInTime(), LocalDateTime.now()).toMinutes(); BigDecimal fee calculateFee(minutes, plateNumber); // 3. 更新进出记录为已离场 inOutRecordMapper.updateOutInfo(record.getId(), LocalDateTime.now(), fee, 1); // 4. 释放车位 parkingSpaceMapper.updateStatus(parkingId, 0, null); return true; }这里Transactional注解是 Spring 声明式事务的入口rollbackFor Exception.class意思是任何异常都回滚千万不要只写Transactional不加参数因为 Spring 默认只回滚 RuntimeException 和 Error如果你在方法里抛的是自定义BusinessException继承自 Exception事务不会回滚数据库就会留下半截脏数据。费用计算逻辑calculateFee方法里要区分车辆类型教职工车辆免费学生车辆前 1 小时免费、之后每小时 2 元上限 10 元访客车辆每半小时 3 元、上限 50 元。这类规则是业务层的判断写在 Service 里维护起来最方便。时间段计算用Duration.between计算出的分钟数除 60 向上取整作为计费小时数避免出现“停车 1 分钟计费 1 元”这种让用户骂街的情况。4.4 数据可视化统计报表模块怎么用一条 SQL 搞定管理员希望能看到“本月进出车流量趋势”和“车辆类型占比”怎么做新手最容易踩的坑是在 Java 代码里把数据库里的几千条记录全查出来然后 for 循环统计。数据量小的时候没问题但数据量一上来接口响应会越来越慢而且代码写起来也啰嗦。更好的做法是用 SQL 直接聚合。-- 按天统计本月每天的车流量 SELECT DATE_FORMAT(in_time, %Y-%m-%d) AS date_day, COUNT(*) AS total_count FROM tb_in_out_record WHERE in_time DATE_FORMAT(CURDATE(), %Y-%m-01) AND status 1 GROUP BY DATE_FORMAT(in_time, %Y-%m-%d) ORDER BY date_day;MySQL 的DATE_FORMAT函数可以把时间格式化成你想要的粒度GROUP BY自动按天分组统计效率远高于 Java 层 for 循环。统计结果用一个 VO 类接收属性就是dateDay和totalCount前端用 ECharts 渲染成折线图即可。类似地车辆类型占比可以这样写SELECT vehicle_type, COUNT(*) FROM tb_vehicle GROUP BY vehicle_type。查询结果就是两列类型编码和数量在 Java 层把编码翻译成中文描述1-教职工、2-学生、3-访客传给前端画饼图。记住一个原则凡是数据库能算的不要拿到 Java 里算。SQL 聚合是数据库的强项一条语句顶你几十行循环。5. 本地跑通到部署上线环境配置、常见报错与避坑实录5.1 开发环境清单和数据库初始化这个系统需要的开发环境非常标准JDK 8、Maven 3.6、Tomcat 8.5 或 9.0、MySQL 5.7 或 8.0、IDEA 或者 Eclipse。JDK 版本最好 1.8因为大部分网上能找到的 SSM 教程和依赖版本都是基于 JDK 8 验证的。如果你机器上装了 JDK 17可能会在编译时遇到IllegalAccessError或者module not found的问题那种错误在课设阶段很难排查直接换回 JDK 8 最省事。拿到项目源码后第一步不是启动而是初始化数据库。用 Navicat 或命令行执行项目里的init.sql脚本创建数据库和表结构并插入一条初始管理员账号。这里有个顺序问题必须先建库再建表因为建表语句开头可能用了USE campus_vehicle;这样的语句。如果提示数据库不存在先执行CREATE DATABASE campus_vehicle DEFAULT CHARACTER SET utf8mb4;。数据库连接配置在jdbc.properties文件里。改三个地方数据库地址、用户名、密码。如果是本地跑地址通常是jdbc:mysql://localhost:3306/campus_vehicle?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue。这里useSSLfalse和allowPublicKeyRetrievaltrue是两个容易被忽略的坑前者在 MySQL 8.0 默认开启 SSL本地开发没配置证书会打印一堆警告后者在第一次连接时如果不加会报Public Key Retrieval is not allowed错误。5.2 三个高频启动报错现象、原因、解决我见过的学生项目里启动期报错 80% 集中在下面三个每个都附上排查路径。报错一ClassNotFoundException: org.springframework.web.context.ContextLoaderListener。现象是 Tomcat 一启动就报这个错原因几乎都是 Maven 依赖没有部署到 Tomcat 的 lib 目录。解决方式是IDEA 中双击项目名打开 Project Structure在 Artifacts 里把lib目录添加为 Web-INF/lib 的依赖来源。简单说你本地 Maven 仓库有 Spring 的 jar 包但 Tomcat 运行时没带上。这个错让我第一次熬夜到凌晨两点后来发现编译后的WEB-INF/lib空空的才知道 IDEA 默认不会自动把 Maven 依赖放进 war 包。报错二Invalid bound statement (not found). 是 MyBatis 的 Mapper 接口和 XML 文件没有对应上。常见原因有两种第一XML 文件没放在 Mapper 接口同一个包路径下MyBatis 默认会去同包路径找 XML第二mybatis-config.xml里忘记配置mapper resourcecom/campus/vehicle/mapper/VehicleMapper.xml/。如果用的是 Spring 整合还要检查有没有在 Spring 配置里加property namemapperLocations valueclasspath*:mapper/*.xml/。排查时先看 target 目录里有没有编译后的 XML没有就说明资源没打包进去需要在 pom.xml 里加资源配置。报错三Cannot create PoolableConnectionFactory。这个是数据库连接失败。百分之八十是因为 MySQL 服务没启动或者密码不对。先命令行执行mysql -uroot -p测试能不能连上能连上再去检查 jdbc.properties 的用户名密码是否一样。另外检查 MySQL 版本和驱动版本是否兼容MySQL 5.7 配驱动 8.0 可以反过来把 MySQL 8.0 配驱动 5.1 就会报com.mysql.jdbc.Driver找不到因为新版本驱动类名改成了com.mysql.cj.jdbc.Driver。5.3 性能与安全连接池参数和预防 SQL 注入的最佳实践SSM 项目里配置数据库连接池常见做法是用druid连接池。在spring-dao.xml里配置 DruidDataSource有几个参数值得专门调试。initialSize5是启动时初始连接数maxActive20是最大连接数maxWait60000是获取连接的等待超时时间毫秒。如果系统部署后高并发下偶尔报GetConnectionTimeoutException基本就是 maxActive 太小或 maxWait 太短。校园车辆管理系统并发量其实不高20 个连接绰绰有余。数据库账号权限方面建议不要用 root 直连项目的生产环境。新建一个专用账号只授予SELECT, INSERT, UPDATE, DELETE权限表级别授权到项目自己的库。这样即使项目代码被拿到攻击者也拿不到服务器上其他数据库的内容。操作上很简单用下面的 SQL 在 MySQL 里创建CREATE USER campus_applocalhost IDENTIFIED BY 你的强密码; GRANT SELECT, INSERT, UPDATE, DELETE ON campus_vehicle.* TO campus_applocalhost; FLUSH PRIVILEGES;至于预防 SQL 注入最有效的就是你一直在用的#{}预编译。不过有两个地方要特别当心排序字段和动态表名。如果前端传了sortField和sortOrder接受的参数可能会被拼进 SQL。常见的做法是白名单校验比如// 排序字段白名单防止 SQL 注入 String[] allowedSortFields {id, create_time, plate_number}; if (!Arrays.asList(allowedSortFields).contains(sortField)) { sortField id; // 非法字段重置为默认值 }这样一来即使用户手动构造请求传入了危险值也不会进入 SQL 语句。安全这个东西课设可能不查但如果你把项目写进简历面试官一定会问“你怎么防止 SQL 注入”——到时候能答出上面的白名单思路比只背概念有用得多。5.4 部署 Linux 服务器的完整命令流从打 war 包到 Nginx 反向代理项目本地跑通后部署到服务器才是真正“交付”的状态。在 IDEA 右侧 Maven 面板执行package命令target 目录下生成campus-vehicle.war。把 war 包上传到 Linux 服务器 Tomcat 的 webapps 目录重启 Tomcat 即可。# 服务端部署命令流CentOS / Ubuntu 通用 cd /opt # 上传 war 包使用 scp 或宝塔面板上传均可 scp campus-vehicle.war useryour-server-ip:/opt/tomcat/webapps/ # 停止 Tomcat /opt/tomcat/bin/shutdown.sh # 清除旧的解压目录避免文件残留 rm -rf /opt/tomcat/webapps/campus-vehicle* # 启动 Tomcat /opt/tomcat/bin/startup.sh # 实时查看启动日志确认无报错 tail -f /opt/tomcat/logs/catalina.outTomcat 启动后默认端口是 8080实际使用中我更推荐在前面加一层 Nginx把端口映射到 80。原因有两个第一浏览器输入 IP 直接访问不用带:8080方便非技术用户第二Nginx 可以提供更细粒度的访问控制和静态资源缓存替 Tomcat 分担压力。# Nginx 反向代理配置 server { listen 80; server_name your-domain-or-ip; # 静态资源由 Nginx 直接返回不经过 Tomcat location /static/ { alias /opt/tomcat/webapps/campus-vehicle/static/; expires 30d; } # 动态请求转发到 Tomcat location / { proxy_pass http://127.0.0.1:8080/campus-vehicle/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }proxy_pass后面的 URL 要注意带不带路径的差别。带路径比如/campus-vehicle/表示把请求转发到 Tomcat 的这个 context 路径下不带路径则保留原始请求路径。如果你的系统有多个应用部署在一个 Tomcat 里带路径方式更清晰。配完 Nginx 后执行nginx -s reload加载配置再用浏览器访问服务器 IP能看到登录页就说明部署成功。5.5 避坑实录5 个让我印象深刻的翻车现场坑一MyBatis 字段映射“玄学”问题。现象Java 实体类里定义了ownerName属性数据库字段是owner_name查询出来ownerName一直是 null。原因MyBatis 默认只做同名映射owner_name映射不到ownerName。解决方式有两种SQL 里写别名SELECT owner_name AS ownerName或者配置mapUnderscoreToCamelCasetrue。后者是全局配置一处搞定settings setting namemapUnderscoreToCamelCase valuetrue/ /settings坑二MySQL 8.0 驱动导致的日期类型报错。现象插入日期时控制台报Data truncation: Incorrect datetime value。原因Java 传进来的java.util.Date和 MySQL 的datetime类型在时区或格式上不一致。解决实体类里把日期属性全部用java.time.LocalDateTime配合 MyBatis 的jdbcTypeTIMESTAMP使用这类问题能根除。坑三前端中文乱码问题。现象页面提交中文到数据库后显示问号。原因tomcat 默认请求编码不是 UTF-8。解决在 Tomcat 的server.xml的 Connector 节点加URIEncodingUTF-8同时在 web.xml 里配置 SpringMVC 的字符编码过滤器。两个地方都要配只配一个都会出问题。坑四java.lang.OutOfMemoryError: PermGen space。现象Tomcat 启动或项目运行一段时间后内存溢出。原因Tomcat 8 之前默认永久代太小。解决修改catalina.sh里的JAVA_OPTS增加-XX:MaxPermSize256m。如果你用的 Tomcat 9 或更新的版本会出现的是Metaspace而不是PermGen参数也要换成-XX:MaxMetaspaceSize256m别搞混了。坑五修改代码后页面看不到效果。现象改了一个 Controller 的返回值或页面标题刷新浏览器没有变化。原因IDEA 增量编译没触发或者 Tomcat 还在跑旧版本的类。解决执行Build Rebuild Project然后强制重启 Tomcat。如果还不行删掉 target 目录重新 package。这种情况别去纠结代码错误九成是编译缓存的问题。6. 让课设变成“能拿得出手”的作品从演示视频到扩展思考项目开发到能跑通只是完成了 60 分的工作。如果想要在答辩时拿到高分或者让这个项目真正成为简历上的亮点你还需要在几个方面做“收尾动作”。这些动作不复杂但能把你的项目从“能运行”提升到“像产品”。第一个动作是写一份清晰的 README。内容包括项目简介、技术栈、运行环境、部署步骤、默认账号、功能清单。这份文档的价值在于任何一个陌生人照着步骤能把它跑起来。很多应届生把项目链接给面试官后面试官第一步就是看 README如果写得好面试官对你代码组织能力的判断会直接上一个大台阶。第二个动作是准备一套完整的数据演示。系统里不要只留几条测试数据要生成 200 条以上的出入记录覆盖近三个月的日期范围。这样演示分页查询、月报表统计、费用汇总时页面上才有东西看。演示的时候管理员账号进系统的第一件事就是看数据图表几条数据画出来的图表非常寒酸。第三个动作是录制一段 5 到 8 分钟的演示视频。按“系统登录 → 车辆登记 → 车辆进出 → 车位管理 → 统计报表”的顺序操作配合简单讲解。课设答辩现场时间有限评委不一定有空细看代码一段节奏清晰的演示视频能帮你在最短时间内把功能亮点全部展示出来。至于扩展思考有三个方向是我认为性价比最高的第一把分页查询从手写 LIMIT 改成 PageHelper 插件代码量会少很多第二在车辆出场登记时接入车牌识别 API 的模拟接口把“手动输入车牌”变成“自动识别”这个改进在答辩时非常加分第三把统计报表的数据导出功能加上用 POI 生成 Excel 文件因为用户在任何管理系统中都有“导出数据”的刚性需求。我曾经在一个课设项目里因为“导出 Excel 功能”被评委专门表扬当场给了额外加分。理由很简单大家都在做增删改查只有你想到了用户在实际使用时最需要什么。从做“能跑的系统”到做“好用的系统”这中间的差距不是框架深度而是你有没有把自己代入到用户场景里思考问题。做这个项目最大的体验是SSM 虽然老了但把它的分层思想吃透你去看 Spring Boot 项目会特别快因为本质上 Spring Boot 只是把 Spring 的繁琐配置自动化了核心的 Controller-Service-Mapper 三层架构没有变化。希望这篇笔记能帮你在做项目时少走一些弯路把时间省下来打磨真正有价值的东西。祝你好运。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →