拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

SpringBoot+Vue航班进出港管理系统源码解析与部署实战

SpringBoot+Vue航班进出港管理系统源码解析与部署实战

很多机场相关的项目,刚开始接触时会觉得业务复杂,其实拆解下来无非是“航班进港”和“航班出港”两条主线,中间再穿插停机位、登机口、旅客、行李这些信息。最近我把一个完整的航班进出港管理系统源码整理出来,技术栈是SpringBoot + Vue + MySQL,前端页面、后端接口、数据库脚本全部齐全,导入就能跑。这篇文章不打算只扔个下载链接,而是认真拆一拆这套系统的设计思路、源码结构和真正的运行步骤,顺便把我在实际部署中踩过的坑也一并写出来。如果你正需要做课程设计、毕业设计,或者想学习前后端分离项目的完整落地流程,这套源码和这篇解析应该能帮你省下不少时间。

1. 这系统到底是干什么的?先理清业务边界

这种“管理系统”最容易写得泛,航班进来出去都记录一下,但如果没有业务规则,代码写出来就是一个CRUD。所以在看源码之前,我建议大家先弄清楚业务边界。航班进出港系统表面上是信息管理,实际上围绕的是一架飞机从计划到落地、从落地到再次起飞的全生命周期状态。

1.1 核心业务场景:进港与出港

所谓进港航班,就是飞机降落后的一系列流程:航班落地、滑行到停机位、旅客下机、行李卸下、机组离场。出港航班则是旅客值机、行李装载、机组就位、飞机滑出、起飞。这套系统要管理的不是飞机本身,而是围绕航班产生的数据:航班计划、实时状态、预计时间、实际时间、停机位、登机口、廊桥、行李转盘等。

系统里维护一张航班计划表,包含航班号、航空公司、航线、预计进港或出港时间。业务上还要区分“计划状态”和“实际状态”。比如计划进港时间是09:30,实际进港时间是09:45,这里就得记录延误原因,方便后续统计准点率。我现在提供的源码把计划时间和实际时间拆成了两个时间字段,状态字段单独维护,这样能够展示航班动态,也能做简单的延误分析。

1.2 用户角色与流程拆解

我见过不少新手拿到需求后直接建表写接口,结果做着做着发现用户、权限、日志全都粘在一起。实际上,这套系统的参与者通常可以分成四类:调度员、值机员、登机口服务员、系统管理员。调度员看整体航班态势,能修改停机位和登机口;值机员处理出港旅客和行李;登机口服务员需要看到登机开始时间、未登机人数;管理员则负责账号、航司、基础数据维护。

流程拆开后,后端接口其实都围绕几个核心资源:航班、用户、角色、航班状态变更记录。业务状态变更是重点,不是简单地改一个字段,而是要记录谁在什么时间把航班从什么状态改到了什么状态,这样出了问题才能回溯。源码里的“航班状态变更日志表”就起了这个作用,前端每一次点击“状态更新”,后端都会在事务里同时更新航班主表和日志表,保证数据一致性。

这里我补充一句:如果只是做课程设计或者毕设,业务边界可以简化,把状态变更记录做成一张操作日志表就够了。如果要做成生产系统,可能还要引入工作流引擎,但那是另一个量级的工作,我们不在这套入门源码里硬塞复杂概念。

2. 技术选型:为什么是SpringBoot + Vue + MySQL?

很多初学者会问,做这种项目为什么选这套组合。直接说结论:它恰好是当前Java技术栈里成本最低、资料最多、前后端分离最成熟的组合。不要盲目追新,选技术栈要看团队熟悉度和问题适配度,这套源码的目标是“开箱即跑”,所以选型的第一原则是稳定。

2.1 后端选型的取舍

SpringBoot对比传统SSH或SSM,最大的优势是“约定大于配置”。比如整合MyBatis,只需要引入starter,写几个配置项。网上教程一搜一大把,遇到问题也能快速找到解决方案。对于航班进出港这种业务模型相对固定的系统,SpringBoot的生命周期管理、依赖注入、事务注解都非常够用。

我在源码里用的是SpringBoot 2.x,配合Maven做依赖管理,JDK版本固定为1.8。为什么这么选?因为SpringBoot 3.x从JDK17起步,很多老教程不适用,对新手并不友好。这套源码里所有依赖都锁定了版本,比如MyBatis、Lombok、JWT等,直接还原即可。如果你已经装了JDK 17甚至更高版本,跑的时候注意切换Project SDK到1.8,或者把pom.xml里的java.version改成你自己的版本,但那样可能会遇到一些兼容问题,建议还是按源码的版本来。

2.2 前端选型的理由

前端用Vue,而且是用Vue 2 + Element UI。有人可能觉得Vue 3都出来这么久了,为什么还用Vue 2。原因很简单:这个项目追求的是“可直接运行”和“入门友好”。Vue 2的生态非常成熟,Element UI组件库直接引入就能用,表格、表单、对话框这些管理系统的标配组件全部现成,不需要额外配置。Vue CLI创建工程、npm install、npm run serve三步走。对于想学习前后端分离的人来说,Vue 2的门槛比Vue 3的组合式API低很多。

就算以后你想迁移到Vue 3,也不用推倒重来。核心的Axios封装、路由配置、状态管理思路是一致的。迁移时主要改的是模板语法和组件库,业务逻辑可以原样保留。

2.3 数据库设计要点

MySQL选5.7或8.0都可以,这套源码提供了完整的建库脚本,包含初始化数据。核心表有:flight_info(航班信息表)、airline(航空公司表)、user(用户表)、role(角色表)、flight_status_log(航班状态变更日志)、flight_gate(登机口/停机位分配表)。

以航班信息表为例,关键字段包括flight_no(航班号)、flight_type(进港/出港标记,0是进港,1是出港)、plan_start_time(计划起飞时间)、plan_arrive_time(计划到达时间)、actual_start_time(实际起飞时间)、actual_arrive_time(实际到达时间)、gate_id(停机位或登机口ID)、status(当前状态)。注意这里设计了一对多关系:一个航班可能有多条状态日志,所以log表里用flight_id做外键。好的数据库设计应该是业务驱动,而不是字段堆积。比如要查“当前所有延误航班”,最直接的方式就是让status标记为delay,同时记录delay_reason字段。我在脚本里预置了几条模拟数据,方便运行后直接看到效果。

2.4 源码目录结构快速索引

拿到源码后,第一件事是看目录。后端工程airport-server采用常见的包结构:controller、service、mapper、entity、common、config。controller放接口入口,service放业务逻辑,mapper是MyBatis的数据访问层,entity是数据库表对应的实体,common里放统一返回结果和异常处理,config里放跨域配置、Jackson配置等。前端工程vue-airport分得也很清楚:views放页面,router放路由,api放接口请求封装,utils放Axios和工具函数,components放公共组件。这种结构不复杂,但对新手来说很友好,哪里有什么基本一眼就能找到。

3. 核心功能模块与源码解析

理解了整体结构,我们再深入源码看模块实现。这套系统的核心价值不在花哨的界面,而在几个关键模块的完整闭环。

3.1 航班信息管理模块

这是系统的基础模块,包含航班的新增、修改、删除、分页查询、条件查询。后端Controller层使用RESTful风格,例如:

  • GET /api/flight/list 分页查询
  • POST /api/flight/add
  • PUT /api/flight/update
  • DELETE /api/flight/delete/{id}

Service层使用MyBatis操作数据库,Mapper接口里编写了带条件的动态SQL。注意分页参数page和limit来自前端,后端查询时把总数和列表数据一起封装成Result对象返回。为什么用统一返回对象?因为前后端分离模式下,前端需要知道请求是否成功,以及返回的数据结构是否一致。前端封装了一个request.js,用Axios统一拦截response,如果后端返回code不为200,直接弹出错误提示。这样业务代码里就不需要每次都写error分支。

这里给你一个Mapper动态SQL的简要示例:

<select id="selectFlightPage" resultType="com.example.entity.FlightInfo"> SELECT * FROM flight_info <where> <if test="flightNo != null and flightNo != ''"> AND flight_no LIKE CONCAT('%', #{flightNo}, '%') </if> <if test="flightType != null"> AND flight_type = #{flightType} </if> </where> ORDER BY plan_arrive_time DESC </select>

这种写法可以避免拼接字符串的引号问题,也方便扩展查询条件。新手特别喜欢用“SELECT *”拼一堆条件,一旦字段多就容易写错,用MyBatis的动态SQL会规范很多。

3.2 进出港动态与状态流转

进出港动态是这套系统的重头戏。简化后的状态机其实并不复杂:

进港航班流程:计划进港 -> 已降落 -> 已停靠 -> 旅客下机完成 -> 已离港。

出港航班流程:计划出港 -> 值机开始 -> 登机开始 -> 已起飞。

后端使用status字段表示当前状态,每次状态变更前校验当前状态是否合法。比如一个已起飞的航班不能再改为计划出港,否则就报错。变更之后插入一条日志,记录变更前状态、变更后状态、操作人、变更时间。这个校验逻辑放在Service层,用if判断先查一次旧的status,再比对允许的状态转换表。虽然比直接update多查一次数据库,但换来的数据准确性是完全值得的。

前端对应的页面是航班动态列表。我用表格显示当前状态标签,颜色区分:绿色是正常,橙色是延误,灰色是已结束。点“状态更新”按钮会弹出一个下拉框,选择要变更到的下一个状态,前端把目标状态传给后端,后端完成校验并更新。这里有个细节:每次状态变更后,前端要重新拉取列表,不要在前端本地改数据。否则会出现多人操作时数据不同步的问题。

3.3 用户权限与登录

系统登录用JWT做无状态鉴权。用户输入用户名密码,后端返回一个token,前端存放在localStorage中。后续每次请求都在Header里带token,后端通过拦截器校验。拦截器中放行了登录接口和静态资源,其他接口一律校验token。下面是一段简单的拦截器配置逻辑:

public class JwtInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getMethod().equals("OPTIONS")) { return true; } String token = request.getHeader("Authorization"); if (token == null || !JwtUtil.verify(token)) { response.setStatus(401); return false; } return true; } }

权限控制做的是RBAC,一个用户对应一个角色,一个角色拥有多个菜单权限。菜单权限用前端路由的方式控制,后端只返回当前用户拥有的菜单列表。这样做的原因是前端能动态生成路由菜单,后端不用每个接口单独判断角色,只要在分配菜单时控制好粒度,大部分接口的权限就自然生效了。源码里默认有两个账号:管理员admin/admin123,普通调度员dispatch/123456,运行后可以直接登录体验权限差异。

3.4 前端页面交互与接口联调

前端页面主要分登录页、主页、航班管理页、航班动态页、用户管理页。主页左侧是菜单栏,右侧是内容区域。航班管理页使用Element UI的el-table展示数据,支持分页、查询。航班动态页有一个“状态更新”操作,点开后弹出选项。用户管理页目前只有管理员能访问,可以新增用户、绑定角色。这些页面看起来简单,但覆盖了后台管理系统最常见的交互:表格、表单、弹窗、消息提示、路由守卫、Token失效处理。

我还特意做了一个路由守卫:当本地没有token时,访问任何页面都会跳回登录页。这个逻辑置在router的beforeEach里,很多新手容易忽略,导致页面刷新后直接跳到空路由或者登录页的问题。现在源码里已经处理好了,你可以直接参考。

4. 拿来即用:从部署到运行的完整步骤

这个部分最重要。很多源码下载下来,明明说“可直接运行”,结果一堆人装不上,原因往往是环境变量不对或者MySQL版本兼容问题。我列了一份完整步骤,建议按顺序操作。

4.1 环境准备与基础工具

需要准备的工具包括:JDK 1.8、Maven 3.6+、MySQL 5.7或8.0、Node.js 14+、Vue CLI 4.5及以上、IDEA或Eclipse。建议用IDEA,因为其对Maven和SpringBoot的支持最省心。打开IDEA时选择“Open”,定位到后端项目的根目录,等待Maven自动解析依赖。第一次导入会比较慢,因为要下载大量jar包,如果进度卡住,检查一下Maven仓库镜像和网络。

MySQL需要提前建好数据库,执行sql目录下的airport.sql脚本。脚本里包含建表和插入数据语句。这里容易出错的地方是MySQL 8.0的密码加密方式变了,连接时可能提示认证失败。我的源码默认适配的是MySQL 5.7,如果你用8.x,需要把驱动改成com.mysql.cj.jdbc.Driver,同时去掉连接串里的useSSL=false,或者改成true。最简单的方式:安装MySQL 5.7,按默认配置装完即可。

4.2 后端启动配置与验证

后端工程里最重要的配置文件是application.yml:

server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/airport?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 mybatis: mapper-locations: classpath:mapper/*.xml

这里的密码一定要换成你自己的MySQL密码。Mapper XML放在resources/mapper目录里,MyBatis会自动扫描。启动主类,看到“Started ... in xxx seconds”就表示成功。如果端口被占用,启动日志会提示,可以改成8081。后端启动后,浏览器访问http://localhost:8080/api/health,如果返回一个JSON,就说明连通了。

4.3 前端启动配置与联调

前端工程在vue-airport目录。打开命令行,cd到这个目录,先执行npm install安装依赖。如果网络不太好,建议把npm源切换成国内镜像。这一步可能会等几分钟,看到node_modules目录生成就没问题。

然后执行npm run serve,默认端口是8080。如果8080已经被后端占了,Vue CLI会询问是否换一个端口,选择yes。然后访问提示的地址。前端的baseURL在src/utils/request.js里配置,默认是http://localhost:8080。如果你后端端口改过,这里也要对应改掉。

跑通后的完整测试流程:登录页输入admin/admin123,进入系统后能看到航班列表、动态页面、用户管理菜单;查询一个航班,点击状态更新,列表实时刷新;退出登录后访问其他页面会被拦截回登录页。我把这些测试点也写进了文档,方便你拿它做验收。

4.4 常见启动命令速查

为了方便排序,我把日常用到的命令整理成一个小表:

操作命令
后端启动mvn spring-boot:run
后端打包mvn clean package
前端安装依赖npm install
前端开发启动npm run serve
前端打包npm run build

前端打包后会把静态资源生成到dist目录,如果你想把前后端部署到同一个服务上,可以用Nginx反向代理,也可以把dist目录直接放到SpringBoot的static资源目录里。不过在这套源码的开发阶段,分别启动更符合我们调试的习惯。

5. 实战中容易踩的坑

我整理了一圈平时被问得最多的问题,做成速查表,如果你运行时报错,先在这里找答案。

5.1 时间与展示数据差了8个小时

最常见的问题是数据库存的时间和页面展示的时间差了8个小时。原因通常是时区设置不一致。解决方式是数据库的连接URL加上serverTimezone=Asia/Shanghai,并且Jackson配置time-zone: GMT+8。如果还是不对,检查MySQL时区,执行show variables like '%time_zone%',如果显示系统时区不对,可以set global time_zone='+8:00'。

还有一点,前端如果有对比需求,建议统一用时间戳传输,前端再格式化为本地时间,避免格式混乱。这套源码为了直观展示,直接用字符串时间,所以你看到的都是“yyyy-MM-dd HH:mm:ss”格式。

5.2 npm install报错或卡住

npm install报错一般有三种情况:一是Node版本太低或太高,二是网络问题,三是依赖版本冲突。先确认node -v,最好是14到16之间的版本。Vue 2项目在Node 18下有些老依赖会警告,但不一定致命。如果卡在node-sass编译,这套源码里已经去掉了node-sass,改用sass,所以不需要单独安装Python和C++编译工具。npm源切换成淘宝镜像后再试,通常能解决大部分网络造成的卡顿。

如果npm run serve启动后页面空白,打开控制台看看是不是有import路径错误。Vue CLI对路径的解析和大小写敏感,Windows环境格外明显,比如components写成Component就很容易白屏。

5.3 跨域与端口占用

前端页面访问后端接口时,如果不出意外会报跨域。我提供的后端代码里已经加了CORS配置,允许所有来源、所有方法。如果你自己重写后端,记得加一个WebMvcConfigurer设置CorsFilter,不然前端请求会被浏览器拦截。

端口占用则简单,后端8080被占用时,可以用lsof -i:8080查看进程,或者直接改端口。前端同理,修改vue.config.js里的devServer.port即可。需要注意的是,改了端口之后,前端的request.js里的baseURL也要保持和当前端口一致。

5.4 MyBatis映射文件报错

如果你自己改了Mapper,最容易出现的问题是namespace路径和接口不匹配。源码里mapper-locations指向classpath:mapper/*.xml,XML文件的路径必须和resources/mapper目录保持一致。当你新增一个接口方法但没在XML里写对应SQL时,启动时不会报错,但调用接口会报Invalid bound statement。排查思路是先看控制台的Mapper扫描日志,再看方法名是否严格一致。

6. 从“能跑”到“好用”:后续还能怎么改

这套源码作为课程设计或毕设代码,展示一个完整的前后端分离项目,完全够用。但如果你想要在里面加一点能写在简历上的亮点,或者未来往生产级方向升级,这里有几个实操性很强的方向。

6.1 生产化改造的优先级

真实环境中,航班进出港系统通常要接入外部数据源,比如订票系统、空管系统、航司系统。源码里目前是手动录入航班,你需要增加定时任务从Excel或接口同步数据。然后是性能层面:航班量大的时候,分页查询可能变慢,可以给常见的查询字段加索引,用Redis缓存航班列表和用户权限。安全层面要增加密码加密盐值、操作审计、登录失败锁定。这些改造每一项都不复杂,但加起来能把项目的完整度拉高一个档次。

6.2 值得尝试的功能扩展

我提供一个扩展思路:把航班统计做成图表,前端用ECharts展示每日出港准点率、延误航班Top10航司。后端增加统计接口,用MyBatis写聚合SQL。这种扩展代码量不大,但价值感很强,而且也很适合写进论文或课程总结里。

另一个扩展思路是接入地图,展示航线的飞行轨迹。可以基于Leaflet或OpenLayers,把出发机场和到达机场的位置显示在地图上。这个比较考验地图数据,但做出来很直观。如果你对地图技术不熟,也可以做简单的列表式看板,用卡片展示当前航班动态,数据实时刷新,同样能体现系统的实时能力。

最后,我个人的经验是,拿到一个开源源码之后,不要一上来就改前端效果或者增加新页面,而是先把数据库表结构吃透,明白每个表之间的关联,再动手改良。这样花不了多少时间,后面改起代码来会顺畅很多。希望这篇文章能帮你把这套航班进出港管理系统真正跑起来,也祝你从源码里学到更多东西。

返回列表