多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Spring Boot+Vue+MyBatis装饰工程管理系统实战解析

Spring Boot+Vue+MyBatis装饰工程管理系统实战解析 1. 项目概述与价值定位1.1 这套系统到底解决什么问题我在做Java服务端开发的十年里接触过大量工程项目管理场景。说实话市面上号称“工程项目管理系统”的开源项目不少但真正能落地、能直接部署、架构不过时的真的是凤毛麟角。大部分项目要么是十几年前的SSH架构要么前后端不分家要么数据库设计粗糙到让你怀疑人生。这次要聊的这套企业级Spring Boot装饰工程管理系统从技术栈到功能设计都属于当前主流梯队非常适合三类人第一类是准备做毕业设计或课程设计的在校生第二类是中小型装饰公司想低成本上信息化系统第三类是Java全栈开发者想找个完整的实战项目来参考学习。系统完整覆盖了一个装饰工程项目从立项到验收的核心业务流程不是那种只有登录注册和简单CRUD的玩具项目。先说技术栈Spring Boot Vue MyBatis MySQL这套组合在Java后端开发里属于黄金搭配。Spring Boot负责快速构建服务端Vue处理前端交互MyBatis管理数据持久层MySQL做数据存储。前后端完全分离符合现代企业级开发的标准模式。拿到源码后直接开箱即用配置文件改一下数据库连接就能跑起来这一点对新手极其友好。1.2 为什么选择这套技术架构可能有人会问现在微服务那么火为什么不直接用Spring Cloud Alibaba那一套这个问题我每次都会被问到。答案很简单微服务有微服务的适用场景单体架构有单体架构的价值。对于中小型装饰工程公司的管理系统来说用户量可能就是几十到几百人并发量远没有到需要拆分的程度。用微服务反而会引入服务注册、配置中心、网关、分布式事务等一堆复杂度运维成本和技术门槛都会直线上升。Spring Boot MyBatis的组合在工程类项目里依然有很强的存在感原因在于MyBatis对复杂SQL的掌控粒度比JPA更细。装饰工程管理里常有各种多表关联查询、报表统计、条件动态拼接用MyBatis的XML映射文件写起来非常顺手性能优化也好把控。Vue作为前端框架上手曲线平缓组件化开发适合这种模块较多的管理系统。MySQL则是中小型项目最稳妥的数据库选择部署简单、社区活跃、出了问题网上随便一搜就有答案。2. 核心功能模块拆解与设计思路2.1 从业务场景反推功能设计拿到源码之后我第一件事就是先看数据库表结构因为表结构最能反映一套系统的业务边界。这套系统的表设计覆盖了装饰工程管理的一条完整链路客户信息、项目立项、合同管理、施工进度、材料采购、竣工验收、款项收支。每个模块表之间的外键关联关系清晰没有那种为了凑数量而设计的冗余表。功能上系统主要分为两大端管理后台和前端展示。管理后台是核心围绕项目生命周期展开。客户管理模块记录了业主或甲方的基本信息、联系方式、需求描述这是整个业务链的起点。没有客户信息后面的项目立项就无从谈起。项目立项模块则关联客户信息记录项目名称、负责人、预算金额、开工日期、预计完工日期这些关键字段并且给每个项目分配一个唯一的项目编号方便后续追踪。合同管理和款项管理这两个模块是配套的体现了装饰工程行业的特殊性。装饰工程的合同一般分阶段付款开工付一笔、中期付一笔、验收后结清尾款。系统里将合同信息和每一笔收款记录都做了关联能直观看到某个项目合同总额是多少已收款多少还有多少尾款没到账。这个功能对装饰公司老板来说非常实用现金流管理是这类企业最关心的事之一。施工进度和材料采购模块则是项目的执行层面。进度管理支持按里程碑节点来记录比如水电改造、泥瓦工进场、木工制作、油漆施工、安装收尾。每个节点可以填写实际完成日期和完成情况。材料采购则记录了每批材料的名称、规格、数量、供应商、采购价格和项目关联起来方便核算每个项目的材料成本。竣工验收和报表统计模块是收尾环节。验收功能记录验收时间、验收结果、存在的问题及整改情况。报表统计模块则将上述所有数据进行汇总比如按月度统计项目的开工数量、完工数量按项目统计成本支出和合同收入帮助管理层做经营分析。2.2 权限设计与安全机制管理系统最忌讳的就是所有用户权限一样谁都能看财务数据。这套系统设计了基于角色的访问控制RBAC核心就是用户表、角色表、权限表以及用户角色关联表、角色权限关联表这五张表。管理员可以创建不同角色给角色分配菜单权限和操作权限再把角色赋予具体用户。比如项目经理角色只能看到自己负责的项目和对应的施工进度财务角色才能查看合同款项信息。登录模块使用了JWTJSON Web Token做身份认证。用户登录成功后服务端签发一个Token返回给前端前端将它存储在本地并在后续每次请求的Header中携带。服务端拦截器会校验Token的合法性和有效期同时从Token中解析出用户ID和角色信息来鉴权。这种无状态认证方式在前后端分离架构中是主流方案相比传统Session方案更适合Vue这类SPA应用。密码安全方面源码采用的是BCrypt加密算法存储用户密码。BCrypt是一种自带盐值的哈希算法每次加密结果都不同即使两个用户密码相同存储的哈希值也不一样。攻击者即使拿到数据库也无法通过彩虹表逆向破解。这个细节很多开源项目做得不到位往往还是明文存储或简单的MD5加密这套系统在这点上做得比较到位。3. 环境搭建与源码部署实战3.1 开发环境准备部署这套系统前需要先把基础环境准备好。我的建议是严格按照下面这个环境清单来避免版本不一致导致莫名其妙的问题。JDK使用8或11都行Spring Boot 2.x版本对这两个版本支持良好。MySQL推荐5.7或8.0新建数据库时注意统一字符集为utf8mb4这个字符集能完整支持中文和一些特殊符号的存储。Node.js需要14以上版本因为项目中Vue CLI构建工具对Node版本有要求。组件推荐版本说明JDK1.8或11建议用11长期支持版本Maven3.6后端依赖管理工具MySQL5.7或8.0生产环境推荐8.0Node.js14.0vue-cli构建所需Lombok插件1.18.xIDEA中需安装插件数据库初始化部分源码中应该带了SQL脚本文件直接在MySQL中执行即可。执行前注意先创建数据库实例比如CREATE DATABASE decoration DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;然后切换到该数据库后执行SQL脚本。脚本里包含了建表语句和基础数据比如默认管理员账号、角色权限数据等。3.2 后端启动流程后端项目用IDEA打开后等Maven下载完依赖修改application.yml中的数据库连接信息。这里有个细节要特别注意MySQL 8.0以上版本的驱动类名和连接URL与5.7版本不同。8.0版本的驱动类是com.mysql.cj.jdbc.DriverURL还需要添加时区参数serverTimezoneAsia/Shanghai否则启动时会报时区错误。spring: datasource: url: jdbc:mysql://localhost:3306/decoration?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: yourpassword driver-class-name: com.mysql.cj.jdbc.Driver确认配置无误后启动主启动类。Spring Boot内嵌了Tomcat容器不需要额外安装直接就能跑起来。看到Started Application in x seconds的日志就说明启动成功。后端默认端口一般是8080可以在application.yml中通过server.port属性修改。如果想在前台界面测试接口浏览器直接访问http://localhost:8080即可看到后端返回的JSON消息。3.3 前端启动流程前端项目目录通常是frontend或vue-admin之类的名字。在IDEA中可以直接打开该目录也可能需要单独用Visual Studio Code打开。首先执行npm install安装所有依赖。这里提醒一句npm安装依赖时如果网速较慢或下载失败可以把镜像源切换到国内源npm config set registry https://registry.npmmirror.com安装完成后执行npm run dev启动开发服务器。Vue CLI默认监听8080端口如果后端也在8080就需要在vue.config.js中修改前端端口比如改为8081或者9527同时配置devServer.proxy将API请求代理到后端地址。代理配置是前后端联调的关键没有它就会出现跨域导致的请求失败问题。devServer: { port: 9527, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }浏览器访问http://localhost:9527就能看到登录页面。用初始化脚本中自带的管理员账号登录即可进入系统主界面。从一开始的注册登录到进入首页看到统计数据面板整个过程如果顺利的话十几分钟就能完成。如果在这一步遇到白屏、接口404、跨域报错等问题别急后面会逐一排查。4. 代码结构分析与核心业务实现4.1 后端分层架构解析这套系统的后端分层是标准的Controller-Service-Mapper三层结构看包名就一目了然controller负责接收和响应HTTP请求service和service.impl负责业务逻辑处理mapper接口配合XML文件负责数据库操作entity包放数据库实体类common包放通用工具类、统一返回结果、异常处理等。以项目创建功能为例请求进来后先由ProjectController接收参数调用ProjectService.createProject()方法。Service层负责构造完整的数据模型生成项目编号校验必填字段保存项目实体同时可能还要写入一条操作日志。Service层处理完后调用ProjectMapper.insert()将数据持久化。三层架构的好处是职责分明Controller只管参数接收和结果返回Service只管业务逻辑Mapper只管SQL。后续要改动数据库字段只需要调整Mapper相关部分。实体类的设计上也值得说一句。每个实体类上都用了Data注解这是Lombok的特性自动生成getter/setter方法让代码量大幅缩减。表字段和实体属性之间通过驼峰映射mybatis-plus或MyBatis的配置中开启了map-underscore-to-camel-case: true所以数据库字段project_name能自动映射到实体属性projectName这对减少重复工作量帮助很大。4.2 前端页面与核心交互逻辑Vue端采用了经典的vue-router加vuex结构。访问控制通过前端路由守卫实现每次页面跳转前检查本地是否存有Token如果没登录就强制跳转到登录页。动态路由管理是另一个亮点登录成功后根据用户角色获取可访问的菜单列表动态生成路由这样不同角色进入系统后看到的菜单不同和后台权限控制形成一个双保险。项目列表页是典型的数据密集型页面使用了el-tableElement UI的表格组件来展示项目数据。表格上方提供了查询表单支持按项目名称、项目状态、时间范围等条件筛选数据。查询按钮触发后前端将筛选条件作为请求参数传给后端后端通过MyBatis动态SQL完成条件查询。这样既减少了传输数据量又提高了查询效率。表单页面的开发采用了表单校验机制比如项目立项表单中项目名称被设置为必填项项目预算必须为数字且大于0。Element UI的表单校验规则在rules中定义在提交按钮的validate()方法中触发验证。这些细节体验上虽然微妙但对保障数据质量非常重要。4.3 MyBatis核心SQL与动态查询MyBatis在项目持久层部分起到了关键作用。以项目分页查询为例Service层接收pageNum和pageSize两个分页参数通过MyBatis的分页插件PageHelper自动生成统计查询和分页查询使用起来非常灵活。实际项目中还可以对复杂SQL进行调优比如使用if和where标签实现动态条件查询核心逻辑是相对固定的select idselectProjectPage resultTypecom.example.entity.Project SELECT * FROM project where if testname ! null and name.trim() ! AND project_name LIKE CONCAT(%, #{name}, %) /if if teststatus ! null and status ! AND project_status #{status} /if if testownerId ! null AND project_owner_id #{ownerId} /if /where ORDER BY create_time DESC /select这种动态SQL写法在实际开发中几乎是必用的技能因为工程管理系统里筛选条件组合太多。如果没有MyBatis这种标签机制就得手动拼接SQL字符串代码会变得非常丑陋且容易出SQL注入漏洞。对上段代码有一个地方需要留意LIKE CONCAT(%, #{name}, %)而不是直接在SQL中写LIKE %${name}%前者使用预编译占位符避免SQL注入风险这是必须养成的习惯。5. 常见问题排查与性能调优心得5.1 启动与联调阶段的高频问题我在本地跑这套系统时遇到了几个比较经典的问题这里梳理成一个速查表方便直接对照解决。问题表现可能原因解决方案后端启动报数据库连接超时数据库未启动或密码错误检查MySQL服务状态核对application.yml中的账号密码后端启动报时区错误MySQL 8.0驱动与时区参数缺失URL中添加serverTimezoneAsia/Shanghainpm install报错依赖下载超时或镜像源不稳定切换镜像源至npmmirror删除node_modules重新安装登录后页面空白或菜单加载不出来后端与前端端口未打通或跨域检查代理配置确认前端请求的API前缀和后端一致上传文件失败或路径错误配置文件中的上传路径不存在配置文件里设置绝对路径并手动创建目录Token过期后操作无响应拦截器未配置Token刷新机制前端统一在请求拦截器中处理401状态码并跳转登录页其中跨域问题是前后端分离项目里出现频率最高的问题。开发环境用代理解决生产环境有两条路一是把前后端部署在同一个域名下通过Nginx反向代理把API路径转发到后端二是在后端添加CORS全局配置允许指定域名跨域访问。推荐生产环境用Nginx方案这种方案也顺带解决了静态文件服务问题。5.2 性能优化建议项目跑通之后可以做一些优化让它更适合生产环境。数据库连接池配置是第一步Spring Boot默认使用HikariCP这个连接池性能已经很优秀了但默认的maximum-pool-size是10对中小型企业几十人同时在线完全够用。如果预计并发较高可以调大到30-50同时设置合理的connection-timeout避免连接池耗尽导致请求排队耗时。查询性能上重点检查WHERE条件中常用字段是否建了索引。比如project表的create_time、project_statuscontract表的contract_no这些都是高频查询条件没索引会走全表扫描数据量到十万级后查询会明显变慢。在Navicat中用EXPLAIN SELECT ...可以快速确认索引是否生效。前端性能方面Vue项目体积压缩可以做得更细将第三方库如Element UI在vue.config.js中配置为CDN引入减少打包体积。webpack-bundle-analyzer插件可以看到包体积构成对于大体积的库单独分离可以显著提升首屏加载速度。毕竟装饰公司用户用的可能是老旧电脑加载快一点体验会好很多。5.3 功能扩展思路与二次开发方向如果要把这套系统真正用于商业项目有几个扩展方向很值得做。第一是加入工作流引擎比如Flowable或Activiti把项目审批流程立项审批、合同审批、变更审批固化成可配置的流程模板。目前开源版本的审批可能是简单的方式引入了工作流引擎后审批流转、节点代理、流程追踪都会专业很多。第二个方向是做移动端兼容。装饰工地的项目经理和施工人员经常在工地现场不可能随身带电脑。可以做一个基于H5的移动端精简版只保留进度上报、材料验收、现场拍照上传这些高频功能前端用Vue的移动端适配方案或者uniapp实现后端接口复用现有的成本很低。第三个方向是数据权限精细化。现在的RBAC是功能权限但装饰公司往往有多个项目存在于不同地区应当做数据权限控制让项目经理只能看到自己所在区域或自己负责的项目。这个可以通过MyBatis的拦截器自动在SQL中追加数据范围条件来实现不需要在每个业务代码中重复写权限判断。6. 源码部署之外项目管理思维技术层面跑通只是第一步拿到源码后我更建议大家去思考设计者背后的业务逻辑。比如为什么合同和款项要单独拆表而不合并进项目表为什么每个项目要维护一个负责人字段为什么材料采购要记录供应商信息。这些表结构设计的背后是装饰工程行业真实存在的信息追踪需求和成本控制诉求。以材料采购为例很多装饰公司最大的利润流失点就在材料管理上采购价格不透明、材料浪费严重、损耗无法量化。系统里将每个项目的材料采购和成本核算联动就是为了掐住这个利润流失点。如果在二次开发时能将材料成本与项目预算实时对比当材料支出超过预算一定比例时自动预警这套系统就能从一个记录工具升级为经营决策辅助工具。权限设计方面更值得深入思考。不同岗位的人需要看到的信息范围是不同的财务人员看的是回款比例和利润率公司管理层看的是多项目进度汇总项目经理看的是每个节点的完成状态。系统中的数据权限和菜单权限并非简单的技术手段它在某种程度上也映射了企业内部的管理规则。权限设计的背后是人、流程和决策权之间的安排这一点在系统上线培训时要和客户讲通透。7. 部署到服务器的注意事项如果你打算把这套系统真正放到公网服务器上运行几人可以提前了解几个关键操作。后端项目打包时用mvn package命令生成可执行的JAR包因为有内嵌Tomcat所以可以直接用java -jar xxx.jar启动。为了让应用在服务器重启后自动拉起建议使用systemd配置守护进程。前端项目打包执行npm run build生成静态文件到dist目录。然后将dist目录下的文件复制到Nginx配置的站点根目录中并在Nginx中配置API反向代理server { listen 80; server_name yourdomain.com; location / { root /var/www/decoration; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }try_files $uri $uri/ /index.html这一行配置很重要因为Vue是单页应用前端路由使用History模式时刷新子页面URL会返回404这行配置会让Vue接管路由处理逻辑。还有proxy_pass后面的地址对应后端JAR包的监听地址请根据实际配置来调整。另外数据库安全性不容忽视生产环境的数据库账号不要直接用root应当单独创建一个业务账号只授予必要的数据库权限最大程度避免因为误操作删库或SQL注入引起的风险。8. 选型和避坑的几点个人体会拿到了这套源码我依然想根据实际情况给学习者一些建议。第一拿到源码以后不要急着跑起来先看README。这套源码可能有详细的部署说明按照说明来能避免走很多弯路。如果源码没有README就按我上面的流程走一遍从数据库导入开始。第二建议在数据库设计阶段认真读表结构注释把每张表的关系理清楚。能用纸笔画出项目整体架构图是非常好的习惯。我见过太多开发者对着一个现成系统改三五天连哪些表是核心表都说不清楚出了问题很难定位。第三前端依赖的版本兼容问题是最折磨人的。如果你用的是Node.js 17以上版本某些情况下npm run dev可能会有OpenSSL相关的错误提示常见的解决方案是控制Node版本到16或者在启动命令中加上NODE_OPTIONS--openssl-legacy-provider具体根据你的Node版本选择对应的方式即可不必死记硬背。第四Spring Boot版本升级也可能带来兼容问题。比如当前项目用的是2.x版本如果你非要改用Spring Boot 3.x那么JDK需要升级到17MyBatis相关starter的依赖坐标也需要调整否则会出现类找不到的报错。除非有很强的理由否则建议保持原项目架构不变。代码这个东西跑起来只是开始真正理解其逻辑和设计思路才算是把项目吃透了。这套Spring Boot装饰工程管理系统源码作为学习脚手架和业务参考价值都在架构和流程的组织上多花时间研究一定会收获超出代码之外的东西。我自己在实际操作中最大的体会是拿到任何一套开源系统第一周是在搭建环境和熟悉代码第二周才开始对业务逻辑有感觉到第三周时你才会发现哪些地方完全可以换个方式设计。别指望一个周末就把一套企业级系统完全吃透慢慢来反而会比较快。
返回列表