ARTICLE DETAIL

资讯详情

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

SpringBoot+Vue企业网络管理系统项目实战:从环境搭建到部署

SpringBoot+Vue企业网络管理系统项目实战:从环境搭建到部署 拿到这个项目我第一个想说的是别急着把代码扔进 IDEA 和 VS Code 里跑。凡是标题里写了“完整项目源码 SQL 脚本 接口文档”的 Java Web 毕设它的价值往往不在这三样东西本身而在你拿到手之后能不能用最短的时间把它跑起来、看懂它、讲清楚它。尤其是 SpringBoot Vue 这种前后端分离的组合很多同学栽在第一步的环境搭建上后面全是连锁反应。企业内部小型网络管理系统本质上是把“网络设备的台账管理”和“IP 资源的使用登记”这两块脏活累活搬到线上。以前用 Excel 记录交换机、路由器、AP 的型号和 IP时间一长数据就对不上了部门调整、人员离职设备归属根本查不清楚。这套系统要解决的就是这类真实场景里的管理问题。它不像电商、外卖那么花哨但胜在业务边界清晰、表结构好设计、前后端交互模式典型特别适合用来做 Java Web 方向的综合性练习或毕设。这篇内容我会从整体设计思路开始讲然后拆前端、后端、数据库三部分最后把部署和常见问题单独拉出来说。全程会用“这项目我拿到手之后怎么读、怎么改、怎么跑”的角度来讲尽量少说废话多给能直接上手的操作。1. 项目整体设计与技术选型1.1 为什么是 SpringBoot Vue 这个组合SpringBoot Vue 是目前 Java Web 方向最稳的组合没有之一。SpringBoot 负责后端接口和数据落地Vue 负责页面交互和展示中间通过 JSON 通信前后端各管各的开发时可以完全并行。这套架构有几个很实在的好处开发效率高SpringBoot 内置 Tomcat不用单独配置 web.xml写一个 Controller 就是一个接口。Vue 用组件化开发一个页面拆成多个 .vue 文件改动只影响局部不用重刷整个页面。分离后易维护前端只关心页面后端只关心数据。后端接口只要把返回结构固定好前端随便换都行。后续要加移动端后端接口可以完全复用。就业方向明确企业里现在大量系统都是这个技术栈做毕设用这套组合面试被问到的概率极高。这个项目选型的典型意义在于它不是那种“造轮子”的项目而是把 SpringBoot 的常用场景全走了一遍——登录鉴权、增删改查、分页查询、文件/信息录入、状态流转这些就是日常工作里用到最多的功能。1.2 “源码 SQL 脚本 接口文档”三件套意味着什么很多外行只看“源码”两个字但做项目交付的人都明白源码只是起点。真正让一个项目具备“可复制、可验收、可交接”能力的是另外两样SQL 脚本和接口文档。源码后端工程和前端工程。后端用 Maven 管理依赖前端用 npm 管理依赖拿到就能编译运行。SQL 脚本包含建库建表语句和初始化数据。有经验的开发者拿到 SQL 脚本扫一眼表结构就能判断出这个系统做了哪些业务模块、数据关系清不清楚、字段命名规不规范。接口文档说明每个接口的请求方式、路径、参数和返回结构。文档决定了前后端联调的时候是顺畅对接还是来回拉扯。对毕设来说三件套齐全的项目答辩成功率天然高一个档次。因为评委问的问题大概率绕不开“数据库几张大表”“接口怎么设计的”“部署在哪里跑起来”这三样在手等于答案都贴在你面前了。1.3 技术栈清单与版本选择心得这个项目我用下来核心依赖大致如下层级技术选型说明后端框架Spring Boot 2.x稳定生态资料最多毕设首选。不建议追 3.x 最新版很多教程和依赖对不上持久层框架MyBatis-Plus单表 CRUD 几乎不用写 SQL自带分页插件节省大量重复代码数据库MySQL 5.7 / 8.0推荐 8.0字符集用 utf8mb4支持更好安全认证Spring Security JWT无状态登录前端存 token后端拦截请求接口文档Knife4j 或 Swagger自动生成在线接口文档也能导出离线 Markdown前端框架Vue 2 Element UI成熟稳定、组件全、资料多。如果项目本身是 Vue 3 Element Plus也完全可行后面细说前端构建Vue CLI 或 ViteVue CLI 经典Vite 更轻更快看项目自带配置版本这块我踩过最大的坑就是“SpringBoot 版本太高”。有些同学拿到新项目就喜欢升级成最新版结果 MyBatis-Plus、Knife4j 的旧版本兼容不上报一堆依赖冲突。这个项目如果用 Spring Boot 2.5.x 或 2.7.x对应的 MyBatis-Plus 用 3.5.xKnife4j 用 2.x基本不会出问题。版本能用就别乱动是 Java Web 调试的第一准则。2. 核心功能模块与业务设计拆解2.1 登录认证与权限控制企业内部系统不管大小登录是第一个功能。这个项目的登录用的是 JWT 思路流程是用户输入用户名密码后端校验。校验通过后生成一个 JWT token 返回给前端。前端把 token 存到 localStorage 或 sessionStorage。之后每次请求都在请求头里带上 Authorization: Bearer token。后端通过拦截器或 Spring Security 过滤器验证 token验证不过返回 401。权限控制建议用 RBAC 模型也就是“用户 - 角色 - 菜单/权限”三张关联表。虽然“企业内部小型管理系统”看起来就一两个管理员在用但你把 RBAC 做出来答辩的时候可以说这是“面向多角色多部门的基础设计”系统的可扩展性就出来了。实际表结构一般是sys_user用户表sys_role角色表sys_menu菜单/按钮权限表sys_user_role用户与角色关系表sys_role_menu角色与菜单关系表菜单权限不用做得太复杂前端拿到用户角色后根据后端返回的菜单列表动态渲染侧边栏就够了。按钮级权限比如“只有管理员能删设备”可以在前端用指令控制同时后端接口也校验一遍。记住一个原则前端控制是体验优化后端校验才是安全底线。2.2 网络设备台账管理这是系统最核心的业务模块。内部网络里的路由器、交换机、防火墙、无线 AP、光猫等设备平时分散在各个弱电井、机柜和办公室里纸质台账根本维护不过来。设备台账模块做的事就是把这些信息录入系统数据库里一张 net_device 表就能覆盖设备编号、设备名称设备类型路由、交换、防火墙、AP 等品牌型号、序列号IP 地址、MAC 地址所属部门、所在位置状态在线/离线/维修/报废维保截止日期、备注页面端就是经典的“表格 搜索 新增/编辑弹窗 删除”结构。列表页要点在搜索条件至少支持按设备名称、IP 地址、设备类型、状态三个维度组合筛选。新增和编辑建议共用一个弹窗表单校验字段必填项IP 地址提前做格式校验避免输入非法地址。这里我补充一个技巧这类系统的导入导出功能建议直接上 EasyExcel。网络设备的批量导入是真实高频需求——原来 Excel 里的几百条设备记录不可能一条条手敲进去。做一张导入模板后端提供一个解析 Excel 的接口一次性写入数据库。这个功能做出来无论实际演示还是答辩都是加分项。2.3 IP 地址资源池管理IP 管理是网络管理系统区别于普通“增删改查”项目的辨识度所在。很多系统只做了设备台账但 IP 地址的占用情况是乱的——哪个 IP 被哪台设备用了哪个 IP 是空闲的很难查。这个项目里把 IP 管理单独做成一个模块设计思路是这样的先定义网段/VLAN比如 VLAN 10 是办公网段网段是 192.168.10.0/24。系统根据网段自动算出整个子网里所有可用 IP。用户可以选择某个 IP绑定设备或负责人完成“分配”操作。被分配的 IP 不能重复分配释放后重新回到空闲池。对应到数据库一张 net_ip_address 表就行。字段大致有IP 地址、网段 ID、状态未分配/已分配、所属设备 ID、分配时间、备注。后端在处理分配动作时要加一个并发保护防止两个人同时分到同一个 IP。最稳妥的办法是在 IP 记录上加一个 version 字段做乐观锁或者分配时用 UPDATE ... WHERE status 未分配更新影响行数为 0 就说明已被抢走提示用户重新选。前端页面可以做成带搜索和状态的表格用 tag 标签区分颜色绿色是未分配红色是已分配。这样一眼就能看清整个网段的占用率实用性很强。2.4 VLAN 与网段规划VLAN 模块和 IP 模块是联动的。建一个 VLAN填好名称和子网信息保存后系统自动生成该网段下的 IP 列表。这块的重点是后端计算子网的逻辑不要自己硬编码 IP 段处理好两个点网段边界校验起始 IP 和结束 IP 不能超出子网范围网络地址和广播地址不能分配。网段重复校验新增 VLAN 时检查网段是否有重叠避免两个 VLAN 配了同一个 C 段这在真实网络规划里是大忌。前端展示上VLAN 列表可以用“卡片 表格”结合的方式卡片展示大网段的简要信息名称、VLAN ID、网段、IP 数量、已用数量点进去看该网段下的 IP 明细。这种“主从联动”的页面交互也是答辩时可以重点聊的点。2.5 故障登记与处理流转网络管理不能只记台账还要处理“谁报障、谁处理、处理完没有”这条流程。故障模块不需要做特别复杂的状态机但至少要有这几个状态待处理用户提交故障指派给运维人员。处理中运维人员接手填写处理记录。已解决问题处理完报障人确认或系统关闭。故障单的表结构建议这样故障编号、报障人、联系电话、故障类型断网/卡顿/设备故障/其他、故障描述、紧急程度一般/紧急/非常紧急、处理人、处理说明、状态、报障时间、解决时间。前端在待处理列表里可以做“紧急程度”的高亮和排序方便运维优先处理紧急故障。后端的核心接口是“状态流转接口”注意在流转时校验状态是否合法比如“已解决”的工单不能再被置为“处理中”否则流程就乱了。3. 数据库设计与 SQL 脚本的实战解读3.1 表设计的原则与整体关系整个系统的表分为两大块系统管理相关和业务相关。系统管理相关的表就围绕 RBAC 来用户、角色、菜单、以及关联表。业务相关的表就围绕网络资源来部门、设备、网段、IP、故障。表与表之间的关联最核心的是这几个关系用户与部门多对一一个部门下有多个用户。用户与角色多对多通过中间表关联。设备与部门多对一设备归属于某个部门。设备与 IP一对一一个设备通常绑定一个 IP真实场景会有多 IP但为了管理简单主要绑定一个管理 IP。网段与 IP一对多一个网段下包含多个 IP。不要一开始就把表设计得特别复杂“小而清晰”比“大而全”更适合小型系统。如果为了体现技术含量强行加宽表、加一堆冗余字段最后只会让你自己和维护的人难受。3.2 核心表结构示例与字段说明拿设备表来说一份比较合理的 DDL 是CREATE TABLE net_device ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键, device_code varchar(64) NOT NULL COMMENT 设备编号, device_name varchar(128) NOT NULL COMMENT 设备名称, device_type varchar(32) DEFAULT NULL COMMENT 设备类型router/switch/firewall/ap, brand varchar(64) DEFAULT NULL COMMENT 品牌, model varchar(64) DEFAULT NULL COMMENT 型号, sn varchar(128) DEFAULT NULL COMMENT 序列号, ip_address varchar(32) DEFAULT NULL COMMENT 管理IP, mac_address varchar(32) DEFAULT NULL COMMENT MAC地址, dept_id bigint(20) DEFAULT NULL COMMENT 所属部门ID, location varchar(255) DEFAULT NULL COMMENT 存放位置, status tinyint(1) DEFAULT 1 COMMENT 状态1在线 2离线 3维修 4报废, warranty_date date DEFAULT NULL COMMENT 维保截止日期, remark varchar(500) DEFAULT NULL COMMENT 备注, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, deleted tinyint(1) DEFAULT 0 COMMENT 逻辑删除0正常 1删除, PRIMARY KEY (id), UNIQUE KEY uk_device_code (device_code), KEY idx_dept_id (dept_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT网络设备表;这里我特别想强调几个容易被忽略的点逻辑删除字段 deleted 一定要加。网络设备的台账不能让用户直接物理删除万一误删了记录就找不回来了。MyBatis-Plus 里配置 TableLogic删除操作自动变成 UPDATE deleted 1查询自动过滤。唯一索引要有。设备编号在业务上唯一必须加唯一索引否则录入重复数据时只能靠代码判断会漏。时间字段默认值给上。create_time 用 DEFAULT CURRENT_TIMESTAMPupdate_time 加 ON UPDATE CURRENT_TIMESTAMP省去在 Java 代码里手动 set 时间。字符集用 utf8mb4。不要用 utf8不然用户留言或故障描述里带个 emoji 表情入库就报错。IP 地址表的 DDL 有几个点和设备表不一样最关键的是要把网段 ID 和 IP 地址的联合唯一索引建上CREATE TABLE net_ip_address ( id bigint(20) NOT NULL AUTO_INCREMENT, subnet_id bigint(20) NOT NULL COMMENT 所属网段ID, ip_address varchar(32) NOT NULL COMMENT IP地址, status tinyint(1) NOT NULL DEFAULT 0 COMMENT 状态0未分配 1已分配, device_id bigint(20) DEFAULT NULL COMMENT 占用设备ID, user_name varchar(64) DEFAULT NULL COMMENT 使用人, remark varchar(200) DEFAULT NULL, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_subnet_ip (subnet_id, ip_address) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENTIP地址表;联合唯一索引是防止“同一个网段下面重复插入相同 IP”的最后一道防线。如果你只给 ip_address 建唯一索引那不同网段出现相同 IP 就会被误伤所以联合索引非常关键。3.3 SQL 脚本的导入顺序与初始化数据拿到手的 SQL 脚本一般分两种一种是全量脚本包含建库、建表、初始化数据直接导入即可一种是增量脚本只包含修改表结构或新增数据的语句。使用时的正确顺序是创建一个新的数据库比如 net_manage字符集选 utf8mb4。导入全量 SQL 脚本。对照接口文档里的“默认账号”登录系统确认初始化数据是通的。初始化数据里最重要的就是管理员账号。很多项目默认的密码是经过 MD5 加密或 BCrypt 加密的直接看表是明文“123456”实际是加密串。你不需要关心它怎么加密的直接用文档里的默认账号登录就行。但如果文档没写明默认密码可以去看初始化 SQL 里的 INSERT 语句找 admin 用户。实在不行就在 SQL 里把 password 字段改成一个你自己生成的 BCrypt 加密串再重新导入。3.4 慢 SQL 优化与索引设计心得热搜词里出现了“慢 SQL 优化”在毕设答辩环节也很容易被问到。这个项目的表数据量不大默认配置的索引基本够用但有一些优化点你要能答得上来只在 WHERE 条件、ORDER BY、连接条件的列上建索引别全表建满。像 remark 这种内容充分的字段建索引纯属浪费空间。联合索引遵循最左前缀原则。比如上面 IP 表的 (subnet_id, ip_address) 联合索引查询时如果只带 ip_address 不带 subnet_id索引用不上。避免在索引列上做计算和函数调用。比如 WHERE YEAR(create_time) 2024这种写法会让索引失效改成 create_time 2024-01-01 AND create_time 2025-01-01。分页语句别用大偏移量。比如 LIMIT 10000, 20越翻越慢可以改成基于上一页最大 ID 的游标分页。面试或者答辩的时候能把这几条讲明白比背多少理论都有说服力。4. SpringBoot 后端工程结构与接口设计实战4.1 后端工程目录结构与职责划分拿到源码后先看目录结构。一个规范的项目包结构非常清晰基本上一眼就明白每个包是干嘛的com.example.netmanage ├── NetManageApplication.java // 启动类 ├── config │ ├── CorsConfig.java // 跨域配置 │ ├── Knife4jConfig.java // 接口文档配置 │ └── MybatisPlusConfig.java // 分页插件配置 ├── controller │ ├── SysUserController.java │ ├── SysLoginController.java │ ├── NetDeviceController.java │ ├── NetSubnetController.java │ ├── NetIpAddressController.java │ └── NetFaultController.java ├── service │ ├── SysUserService.java │ ├── NetDeviceService.java │ └── ... ├── mapper │ ├── SysUserMapper.java │ └── ... ├── entity │ ├── SysUser.java │ ├── NetDevice.java │ └── ... ├── common │ ├── Result.java // 统一返回结果 │ ├── ResultCode.java // 状态码枚举 │ └── BusinessException.java // 自定义业务异常 ├── security │ ├── JwtUtil.java │ ├── JwtFilter.java │ └── SecurityConfig.java └── utils分层的核心规则是Controller 只做参数接收和结果包装Service 写业务逻辑Mapper 只做数据库操作。千万不要把业务逻辑写在 Controller 里不然别人接手时想砸电脑。统一返回结果 Result 这个类特别重要。格式建议固定成{ code: 200, message: 操作成功, data: { list: [], total: 0 } }code 为 200 是成功其他为失败。前端 axios 拦截器统一判断 code不等于 200 就弹出提示。这个约定一旦定下来前后端联调会省非常多口舌。4.2 登录鉴权与 JWT 的实现细节JWT 的代码逻辑不复杂但有几个细节容易写错生成 token 时把 userId、username 放进去后面接口要拿到当前用户信息时不用再查一遍数据库。token 加上过期时间一般设为 24 小时。不要设成永远不过期否则 token 泄漏了就等于裸奔。JwtFilter 拦截所有请求但在 SecurityConfig 里放行登录接口、接口文档路径、静态资源路径。校验失败时返回 401 状态码前端拦截到 401 后自动跳转登录页。核心拦截逻辑大概长这样protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String token request.getHeader(Authorization); if (StringUtils.hasText(token) token.startsWith(Bearer )) { Claims claims JwtUtil.parseToken(token.replace(Bearer , )); if (claims ! null) { String userId claims.get(userId, String.class); String username claims.get(username, String.class); // 存入 ThreadLocal 或 SecurityContext request.setAttribute(userId, userId); request.setAttribute(username, username); } } chain.doFilter(request, response); }JwtUtil 里封装生成和解析 token 的代码密钥用固定字符串比如your-secret-key。这种写法对毕设完全够用。生产环境密钥要放到配置中心和外部环境变量里这是后话但答辩时可以提一句显得你考虑过这个问题。4.3 MyBatis-Plus 使用技巧分页与条件查询这个项目大量使用 MyBatis-Plus它最大的价值是帮你省掉 80% 的单表 SQL。分页查询的标准写法是创建一个 Page 对象再配合 LambdaQueryWrapperpublic Result listDevices(String keyword, String status, Integer pageNum, Integer pageSize) { PageNetDevice page new Page(pageNum, pageSize); LambdaQueryWrapperNetDevice wrapper Wrappers.NetDevicelambdaQuery() .like(StringUtils.hasText(keyword), NetDevice::getDeviceName, keyword) .eq(StringUtils.hasText(status), NetDevice::getStatus, status) .orderByDesc(NetDevice::getCreateTime); netDeviceMapper.selectPage(page, wrapper); return Result.success(page); }注意pageNum 从 1 开始pageSize 是每页条数。这两个参数建议由前端统一传。后端做好默认值处理比如 pageNum 默认 1pageSize 默认 10。还要注意别让用户传一个 pageSize 99999 把全表拉出去系统做一个上限限制比如最大 100。使用 MyBatis-Plus 一定要在配置文件里加分页插件不然后端 selectPage 不会真的分页会把整张大表都查出来。这是这个项目里最常踩的坑之一在我看过的无数个“跑起来数据不对”的问题里这个占了挺大比例。4.4 接口文档Knife4j 的配置与离线导出接口文档是这个项目的另一个交付亮点。Knife4j 是 Swagger 的增强版UI 更友好还支持导出 Markdown 和离线文档。引入依赖后在启动类或配置类上加 EnableOpenApi 注解。在 Controller 上加 Api 注解在接口方法上加 ApiOperation在返回实体上加 ApiModelProperty这些注解写清楚后生成的接口文档就非常直观了。一个小习惯是每个接口都写好“参数说明”和“响应示例”不要只写一句话“根据ID查询设备”。好的接口文档基本等于代码注释强化版别人接手时不用看源码就知道参数是什么含义。接口文档的路径默认是 /doc.html测试环境直接访问就能看到所有接口列表。这里有个天然的加分项你可以在答辩现场直接打开 doc.html按分类把“登录、设备管理、IP管理”的接口点一遍评委一看就知道项目是真正做过完整设计的而不仅仅是能跑通。5. Vue 前端工程搭建与页面实现5.1 前端工程结构与开发环境配置前端工程拿到手后先确认两件事node_modules 有没有装好npm run serve 能不能正常起。很多同学卡在第一步就是 node 版本不兼容。Vue 2 项目建议 Node 14 或 16Vue 3 项目建议 Node 16 以上。版本太新的 Node比如 20跑旧 Vue 2 项目时经常报 OpenSSL 相关错误这是最常见的问题。前端目录结构一般是这样src ├── api │ ├── login.js │ ├── device.js │ ├── ip.js │ └── fault.js ├── assets ├── components │ ├── Pagination.vue │ ├── StatusTag.vue │ └── ... ├── router │ └── index.js ├── store │ └── modules │ ├── user.js │ └── app.js ├── utils │ └── request.js ├── views │ ├── login │ ├── dashboard │ ├── device │ ├── subnet │ ├── ipAddress │ ├── fault │ ├── system │ └── ... └── App.vueapi 目录下的 JS 文件建议一个模块一个文件比如 device.js 里封装设备相关的所有请求函数。不要在页面组件里直接写 axios 调用那会让代码难以维护。写的时候顺带提一句很多毕设项目为了“看起来代码多”故意把代码写在页面里实际上这是反面教材。5.2 Vue 路由设计与登录守卫路由配置里有几个关键点。一个是区分静态路由和动态路由登录页、404 页属于静态路由业务页面需要登录才能访问。另一个是路由守卫在进入任何页面前检查 localStorage 里有没有 tokenrouter.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.path /login) { next() } else if (!token) { next(/login) } else { next() } })这个守卫逻辑虽然只做了“有没有 token”的判断没有做“token 有没有过期”的实时校验但对毕设系统来说是合理的取舍。真正判断 token 是否过期可以在 axios 响应拦截器里收到 401 时再跳登录页。这样既保证了体验又不至于每次路由跳转都请求后端。另外如果你的项目用的 Vue Router 的 history 模式也就是 URL 里没有 #那么前端部署到 Nginx 时必须在配置里加上 try_files 回退配置。否则刷新页面就会 404这个坑下面部署部分我会详细讲。5.3 Axios 封装拦截器与统一错误处理axios 封装是这个项目前端代码里最值得看的部分。request.js 的逻辑大致是这样的创建 axios 实例设置 baseURL 为后端接口地址。请求拦截器里从 localStorage 取出 token带在 Authorization 请求头里。响应拦截器里先判断 HTTP 状态码如果返回 401清掉 token 并跳转登录页。再判断业务 codecode 不等于 200 时用 Element UI 的 Message 组件弹出后端返回的 message 信息。service.interceptors.response.use( (response) { const res response.data if (res.code ! 200) { Message({ type: error, message: res.message || 操作失败 }) return Promise.reject(new Error(res.message)) } return res }, (error) { if (error.response error.response.status 401) { localStorage.removeItem(token) router.push(/login) } Message({ type: error, message: 网络请求失败请稍后重试 }) return Promise.reject(error) } )这种封装的直接好处是每个页面调用接口的时候只需要关心成功之后的数据处理不用每个接口都写一遍错误提示。5.4 页面实现表格 搜索 弹窗的通用套路这个系统里的页面80% 都是“表格 搜索条件 新增/编辑弹窗”的形态。以设备列表页为例核心流程是created 生命周期里调用查询接口加载第一页数据。搜索表单绑定查询条件点“查询”按钮时把当前页重置为第 1 页重新请求。表格里加操作列每行提供“编辑”“删除”按钮。新增和编辑共用一个弹窗组件提交成功后刷新当前页数据。这里有个实用的小技巧删除操作必须加二次确认。Element UI 的 MessageBox.confirm 弹窗确认后再调用删除接口。这虽然只是几行代码但能避免不少误操作。弹窗表单的校验也值得好好写。比如 IP 地址字段使用 Element UI 的表单校验规则和自定义校验函数const checkIp (rule, value, callback) { const reg /^(\d{1,3}\.){3}\d{1,3}$/ if (!reg.test(value)) { callback(new Error(请输入合法的IP地址)) } else { callback() } }不要觉得这些都是小细节很多时候答辩现场评委就是靠这些细节判断代码是不是你自己写的、你有没有真正理解项目。6. 联调、打包部署与常见问题排查6.1 前后端联调与跨域问题的两种解法前后端分离项目联调时最典型的问题就是跨域。后端接口跑在 8080前端页面跑在 8081前端直接请求后端接口会被浏览器拦截。解决办法有两种后端加 CORS 配置在 Config 类里配置允许跨域的来源、请求头、请求方法。开发环境最简单直接。前端配置代理在 vue.config.js 里配置 devServer 的 proxy前端请求 /api 开头的路径时自动代理到后端地址。这个方案不需要动后端代码生产环境也更好处理。两种方案选哪种如果你的接口路径本身没有统一前缀建议后端加 CORS如果前端统一了 /api 前缀建议前端代理。但无论如何最终生产环境部署时如果前端资源放在 Nginx 上跨域最优雅的解法是 Nginx 反向代理把 /api 路径转发到后端服务浏览器无感知。这个方案可以作为加分项单独提一下。6.2 打包部署的几种实用方案这个项目可以按三种方式部署第一种开发环境分离部署适合学习和演示后端IDEA 直接启动 NetManageApplication运行在 8080。前端npm run serve 启动开发服务器运行在 8081。第二种前端 build 产物交给 SpringBoot 托管适合交给老师拷贝代码直接运行前端执行 npm run build产生 dist 目录。把 dist 目录下的静态资源复制到后端的 src/main/resources/static 下。重新打包后端 jar启动后直接访问 8080 端口就能看到页面。注意这种方式要求前端的路由模式必须是 hash 模式如果用了 history 模式刷新会 404。开发环境下SpringBoot 对静态资源的映射通常没问题但要确认前端请求的 baseURL 在生产和开发环境下使用不同的环境变量。第三种正规一点的前后端分离部署后端打包成 jarJava -jar 启动。前端 dist 目录放到 Nginx 的 html 目录。Nginx 配置中把 /api 路径 proxy_pass 到后端 8080 端口。三种方案按需求选演示用第二种最省事谈及“生产化”时用第三种最专业。6.3 项目常见问题速查表这个项目从拿到手到跑起来我整理了一张高频问题速查表基本覆盖 90% 的翻车现场问题现象可能原因解决办法启动类报错端口被占用8080 端口被其他进程占用使用 npx kill-port 8080 或命令行查占用的 PID 并结束数据库连接失败 Cant connectMySQL 未启动、ip/端口/密码不对、驱动版本不匹配检查 application.yml 配置尤其确认数据库名和密码中文乱码数据库连接 URL 没配置编码参数或表字符集不是 utf8mb4URL 加 characterEncodingutf8表改成 utf8mb4分页查出来全量数据MyBatis-Plus 分页插件没配置在 MybatisPlusConfig 里加 PaginationInnerInterceptor前端页面样式错乱Element UI 版本和 Vue 版本不匹配检查 Vue 2 用 element-uiVue 3 用 element-plus前端 npm install 报 OpenSSL 错误Node 版本太高和旧项目不兼容降低 Node 版本到 14/16或用 NODE_OPTIONS--openssl-legacy-provider登录一直失败默认密码记错、密码加密方式不对看 SQL 初始化脚本里的密码值或改密后重启检查密码字段是否没加密接口请求 401token 过期、请求头没带 token、拦截器放行路径没配置重新登录检查 axios 请求拦截器检查 SecurityConfig 放行路径刷新页面 404Vue Router 用了 history 模式且部署方式不对改为 hash 模式或 Nginx 配 try_files 回退跨域报错后端未配置 CORS 或前端代理没设置按上文两种方案二选一解决新增数据时间为空后端没有自动填充创建时间数据库层用 DEFAULT CURRENT_TIMESTAMP或用 MyBatis-Plus 的字段填充注解6.4 我在实际调试中积累的一些心得最后说几个自己长期做 Java Web 项目积攒下来的习惯放在这里给大家参考。拿到新项目先跑数据库再跑后端最后跑前端。这个顺序别乱。数据库起不来后端一律白搭后端接口没通前端调不通还以为是前端 bug。修改代码后频繁重启太浪费时间配置热部署。后端加上 Spring Boot DevTools前端 Vite 或 vue-cli 默认就有热更新能省下大量等待时间。不要把账号密码明文写在前端代码里。这个项目的默认密码虽然是写死的初始化数据但自己扩展功能时别图省事密码存储一律用 BCrypt 加密后的串。这是安全底线。SQL 脚本一定保留两份一份是带初始化数据的完整脚本一份是只有建表结构的纯净版。前者用来跑演示后者用来做二次开发。数据库结构一变动立刻更新脚本不然版本就乱了。另外一个特别实用的经验接口文档一定要和代码同步更新。这个项目自带了 Knife4j注解就写在代码里理论上天然同步。但如果你后来改动过接口参数务必把 ApiModelProperty 的描述也改了。文档过期比没有文档更可怕因为看文档的人会照着错的参数传。个人实操后的整体评价这个项目跑完一遍之后我的真实感受是它对初学者特别友好因为功能模块完整但复杂度可控。你既能学到 SpringBoot 的工程化分层、MyBatis-Plus 的便捷操作、JWT 登录的实现套路也能学到 Vue 组件化开发、路由守卫、axios 封装这些前端核心技能。它不是一个花里胡哨的“炫技项目”而是一个完整走完“需求分析 - 数据库设计 - 后端开发 - 前端开发 - 联调 - 部署”全流程的典型样本。如果后续你想往深处扩展有几个方向值得动手试一试给故障工单加上通知提醒功能、把设备状态改成定时任务自动探测比如定期 Ping 设备 IP、导出数据报表、引入 ECharts 展示 VLAN 的地址利用率。这些扩展点都能让项目在原有基础上再上一个台阶而且不会破坏原有的整体结构。希望这篇拆解能帮你少走一些弯路早点把项目跑起来、看明白、讲清楚。
返回列表