尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
前后端分离的中小型制造企业质量管理系统实战:SpringBoot+Vue+MyBatis+MySQL
做了这么多年制造业信息化我一直觉得质量管理系统是中小企业最容易忽略、又最值得投资的一块。前几个月正好把一个“前后端分离的中小型制造企业质量管理系统”从零整理到了可部署状态技术栈就是最经典的 SpringBoot Vue MyBatis MySQL整套源码加部署步骤都沉淀下来了。今天就把这套系统的设计思路、核心模块、关键代码、部署实操以及踩过的坑一次性讲清楚。这篇内容不是那种“演示用的 CRUD 玩具”而是按真实工厂质量管理流程去设计的来料检验、过程巡检、成品检验、不合格品处置、质量追溯、统计报表都有落地。适合正在学前后端分离项目的同学参考也适合小工厂的IT人员直接拿去改改就用。1. 为什么是质量管理系统为什么是这套技术栈1.1 中小制造企业的质量管理到底要管什么先说业务。中小型制造企业最常见的质量痛点就三个批次出了问题找不到源头、检验记录靠纸质表格最后堆成山、月底统计合格率全靠Excel手工拉数据。一套质量管理系统要解决的就是把“检验—记录—判定—处置—追溯—统计”这条链跑通。拆开来看核心业务大概这六个板块来料检验IQC原材料到货后质检员按检验标准抽检记录供应商、到货批次、抽检数量、不合格数量、检验结论。过程检验IPQC生产过程中的首件检验、巡检记录出现异常能及时拦截不让不良品流到下一道工序。成品检验FQC/OQC产线完工后、入库或发货前的最终检验判定合格、不合格或者让步接收。不合格品管理对判退、返工、返修、报废、让步接收的产品做登记记录处置方式和原因分析。质量追溯通过生产批号、订单号反向查原料批次、检验记录、操作人员一旦客诉能在最短时间内定位问题范围。统计报表按产品、按供应商、按日期维度统计来料合格率、过程合格率、成品合格率、缺陷类型分布给管理者做改进决策。如果你接触过工厂的质检流程就会明白这些模块互相之间是有依赖的来料检验不录好后面的过程追溯就断链不合格品不记录原因统计报表做了也是空的。所以数据模型的关联设计比页面数量重要得多。1.2 技术选型SpringBoot Vue MyBatis MySQL 的理由先说后端。SpringBoot 在 Java 生态里几乎是中小型管理系统的事实标准它的一大好处是“约定大于配置”你不需要像以前 SSM 时代那样写一堆 XML 配置起步快社区资料也最全。MyBatis 作为持久层框架相比 JPA/Hibernate 更轻、更可控尤其是质量管理这类报表查询多、多表关联多、SQL 经常要针对特殊统计逻辑定制的场景手写 SQL 反而比 ORM 自动生成更放心。前端选择 Vue 而不是 React对于很多从后台管理系统入手的团队来说更平滑。Vue 的单文件组件、指令系统、双向绑定学习曲线相对平缓而且 Element Plus 这类组件库对表格、表单、弹窗这些后台高频场景覆盖得很到位两三天就能把一套带增删改查的页面搭出来。MySQL 更不用多说中小制造企业的数据量级也就百万条以内单机 MySQL 8 完全扛得住稳定性和运维成本都合适。这套组合在“开发效率、运行性能、招人难度”三者之间找到了一个最适合中小团队的平衡点。有人会问为什么不用若依框架直接改若依确实是很好的脚手架但它是通用后台管理系统带了大量和工作流相关的功能对只想专注质量业务、想彻底搞懂每一行代码的开发者来说反而有点重。这个项目选择自己搭基础权限和登录核心模块全部围绕质量业务定制学习成本更低二次开发也更灵活。1.3 前后端分离的取舍前后端分离是这个项目最明显的一个架构特征。前端 Vue 项目独立开发、独立构建通过 HTTP 接口和 SpringBoot 后端通信两边不共享会话。分离带来的最大好处有两个一是前端开发和后端开发可以并行推进只要提前把接口文档约定好二是部署弹性更好前端静态文件交给 Nginx 托管后端作为一个 Java 进程独立跑任何一边要升级都不需要停整体服务。当然代价也清楚跨域问题躲不掉、Token 鉴权得自己搞、前端打包后刷新 404 这些“分离病”都要处理。这些坑我在后面部署章节会逐个给解决方案。对于想系统学习前后端分离项目套路的人来说这套系统倒是绝佳的练手样本。2. 从业务需求到表结构质量系统的骨架设计2.1 六大核心模块与业务闭环系统模块划分不建议按传统软件开发那样单纯按功能拆而是按“一条质量业务流”来拆基础数据维护物料、供应商、客户、检验标准→ 检验记录录入来料/过程/成品→ 不合格品处理 → 质量追溯 → 统计报表 → 用户权限管理贯穿全局。这样设计后哪怕是一个只做过几个页面的新手也能一眼看出数据是怎么流动的检验员录完一张来料检验单数据落到检验记录表这张单子如果判不合格系统自动生成一条不合格品待处理记录质量主管在用户界面进行处置登记处置完成后追溯模块就能以供应商、物料、批次为线索把整条链串起来月底统计报表从这些表里聚合数据生成合格率趋势图和缺陷分布图。必须注意的一个设计原则是核心业务表必须保留“业务状态”字段比如检验单的状态可以设计为草稿、已提交、已审核。中小企业最容易出现的情况是质检员录错了想要改如果只有一条业务记录没有状态流转改数据就没有依据。加上状态字段后草稿状态随便改、已提交状态要主管审核才能改这个约束在质量管理体系审核里会非常有用。2.2 数据库表结构与关键字段设计数据库命名用的前缀区分模块sys_系统管理、base_基础资料、qc_质量检验、trace_追溯。下面这张表是核心表清单都是我实测后整理出来的设计字段做了精简展示表名用途关键字段sys_user用户表id, username, password, real_name, dept_id, statussys_role角色表id, role_code, role_namesys_user_role用户角色关联user_id, role_idbase_supplier供应商表id, supplier_code, supplier_name, contact_person, phone, statusbase_material物料表id, material_code, material_name, spec, unit, default_check_planqc_check_item检验项目表id, item_code, item_name, item_type, upper_limit, lower_limit, unitqc_incoming_inspection来料检验主表id, inspection_no, supplier_id, material_id, batch_no, arrival_date, inspector, sample_qty, qualified_qty, unqualified_qty, conclusion, statusqc_incoming_inspection_detail来料检验明细表id, inspection_id, check_item_id, check_value, check_result, remarkqc_process_inspection过程检验表id, inspection_no, work_order_no, process_name, product_id, inspection_type, inspector, result, statusqc_product_inspection成品检验表id, inspection_no, product_id, batch_no, order_no, inspector, qualified_qty, unqualified_qty, conclusion, statusqc_nonconforming不合格品记录表id, source_type, source_no, product_id, batch_no, defect_code, defect_desc, disposition, responsible_dept, handle_result, handle_usertrace_batch批号追溯表id, batch_no, material_id, product_id, supplier_id, work_order_no, related_order_no, create_time有几个字段我特别强调一下。batch_no批号是整个追溯链的核心所有检验记录和流转记录都要保留这个字段。批号规则最好在上线前就定死比如“日期产线班次流水号”例如20250610-A-01-001不要等录了几千条数据再改规则那时候改数据会改到怀疑人生。inspection_no检验单号建议使用独立序列不要依赖自增主键。自增主键在并发高的时候拿不到“下一个号”而且单号会暴露数据量。我用的是“前缀 年月日 随机三位/序列”比如IQC20250610001在代码里加一个synchronized方法生成足够中小企业的并发量。conclusion字段采用字典值PASS/FAIL/RETURN不要直接存中文。qc_incoming_inspection_detail这种明细表不追求“录入快”但检测值和判定结果一定要分开存因为后面统计“哪个检验项最容易不合格”完全依赖明细表的数据。2.3 前后端接口约定与统一返回体前后端分离项目最容易乱的就是接口。我的做法是规定所有接口走/api前缀Controller 里全部返回一个统一的ResultT对象结构是code200成功、401未登录、500服务异常、msg、data三件套。后端这样定义public class ResultT { private Integer code; private String msg; private T data; public static T ResultT ok(T data) { ResultT r new Result(); r.setCode(200); r.setMsg(success); r.setData(data); return r; } public static T ResultT error(String msg) { ResultT r new Result(); r.setCode(500); r.setMsg(msg); return r; } }前端所有请求都统一经过封装好的request工具只处理Result结构。这样前后端对接的时候接口列表只需要看 Controller 的方法名和请求方式不用各写一套文档。分页接口也统一返回PageResultT包含records、total、current、size四个固定字段。分页逻辑我使用了 PageHelper 插件PageHelper.startPage(page, size)后面紧跟查询方法即可插件自动拦截 SQL 生成 limit 语句和 count 查询对中小项目来说省事又可靠。3. 后端实现SpringBoot MyBatis 的核心代码笔记3.1 项目结构搭建与基础配置后端工程我用 IDEA 创建Spring Boot 版本选择 2.7.18JDK 用的 1.8。这里有一个经验不要一上来就选最新的 Spring Boot 3.x。Spring Boot 3 把javax.servlet换成jakarta.servlet很多网上的旧教程代码直接拿来用会报ClassNotFoundExceptionMyBatis 相关依赖也要跟着升版本排查起来很费时间。除非你没有历史包袱否则用 2.7.x 是最稳的组合。核心依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.1/version /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency dependency groupIdcom.github.pagehelper/groupId artifactIdpagehelper-spring-boot-starter/artifactId version1.4.7/version /dependency注意mysql-connector-j这个是新版坐标旧教程里的mysql-connector-java坐标虽然还能用但官方已经把它归并进来了。对应驱动类也要用com.mysql.cj.jdbc.Driver。application.yml的关键配置server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/qms?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: Asia/Shanghai mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.qms.entity configuration: map-underscore-to-camel-case: truemap-underscore-to-camel-case必须开数据表的batch_no才能自动映射到 Java 实体类的batchNo不然每个查询都要手写resultMap工作量翻倍。serverTimezoneAsia/Shanghai和useSSLfalse是 MySQL 8 时代最常见的两个坑不写时区在 JDBC 连接时报错不关 SSL 虽然能连但控制台会刷一大段警告。3.2 登录鉴权与JWT Token处理前后端分离项目不能依赖 Session我用 JWT 做登录鉴权。流程很简单用户提交用户名密码后端校验通过后生成一个 token 返回给前端前端把 token 存到 localStorage每次请求在 Header 里带Authorization: Bearer token后端用一个拦截器统一校验。JWT 工具类核心逻辑public class JwtUtil { private static final String SECRET qms-secret-key-please-change-in-production; private static final long EXPIRE 1000 * 60 * 60 * 12; public static String createToken(Integer userId, String username) { return Jwts.builder() .setSubject(username) .claim(userId, userId) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() EXPIRE)) .signWith(SignatureAlgorithm.HS256, SECRET) .compact(); } public static Claims parseToken(String token) { return Jwts.parser() .setSigningKey(SECRET) .parseClaimsJws(token) .getBody(); } }拦截器里需要把/api/login放行其余接口都校验 token。校验失败统一返回 401前端收到 401 就自动跳到登录页。这部分值得细说因为很多初学者把 token 校验写在每个 Controller 里代码重复又容易漏。拦截器一注册所有接口自动生效Configuration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new JwtInterceptor()) .addPathPatterns(/api/**) .excludePathPatterns(/api/login, /api/captcha); } }3.3 检验单模块的完整实现思路拿来料检验单举例这个模块包含主表加明细表两张表。保存时要保证事务主表插入后拿到自增主键再把明细列表逐条插入任何一个明细失败都要回滚。Service 层核心代码Transactional(rollbackFor Exception.class) public void createInspection(IncomingInspectionDTO dto) { QcIncomingInspection master new QcIncomingInspection(); BeanUtils.copyProperties(dto, master); master.setInspectionNo(generateInspectionNo()); master.setStatus(SUBMITTED); incomingInspectionMapper.insert(master); for (InspectionDetailDTO item : dto.getItems()) { InspectionDetail detail new InspectionDetail(); detail.setInspectionId(master.getId()); detail.setCheckItemId(item.getCheckItemId()); detail.setCheckValue(item.getCheckValue()); detail.setCheckResult(judge(item.getCheckItemId(), item.getCheckValue())); detailMapper.insert(detail); } }判定逻辑judge()是调检验项目表里配置的上限下限去比的这样换产品、换标准时不用改代码改数据就行。真实工厂里检验项标准经常变把标准配置化是这套系统能用下去的一个前提。查询列表时用联表查询把检验单主表关联供应商表和物料表PageHelper 分页代码如下select idpageQuery resultTypecom.example.qms.entity.vo.IncomingInspectionVO SELECT t.*, s.supplier_name, m.material_name FROM qc_incoming_inspection t LEFT JOIN base_supplier s ON t.supplier_id s.id LEFT JOIN base_material m ON t.material_id m.id where if testbatchNo ! null and batchNo ! AND t.batch_no LIKE CONCAT(%, #{batchNo}, %) /if if testsupplierId ! null AND t.supplier_id #{supplierId} /if /where ORDER BY t.create_time DESC /selectif标签里的动态 SQL 是 MyBatis 最有价值的地方条件判断自动拼接不需要为“有筛选条件/无筛选条件”写两套 SQL。但注意文本比较要写and batchNo ! 不能只写and batchNo ! null。3.4 MyBatis 使用中的几个经验点第一个经验是批量插入。质量检验明细通常一次几十上百条循环逐条 insert 性能差也麻烦。用 MyBatis 的foreach一次拼一条批量 INSERT 最方便insert idbatchInsert parameterTypelist INSERT INTO qc_incoming_inspection_detail (inspection_id, check_item_id, check_value, check_result, remark) VALUES foreach collectionlist itemitem separator, (#{item.inspectionId}, #{item.checkItemId}, #{item.checkValue}, #{item.checkResult}, #{item.remark}) /foreach /insert第二个经验是只要遇到多表联查或者报表统计一定要先写 SQL 到数据库客户端里跑通再往 Mapper XML 里搬。直接在项目里调试 SQL 效率太低报错信息也不直观。我在 IDEA 里装了 MyBatis Log Plugin 插件把 MyBatis 生成的完整 SQL 打印出来看控制台输出这个方便mybatis: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl第三个经验是关于缓存的。MyBatis 一级缓存默认开启范围是一个 SqlSession在同一个 SqlSession 内连续查两次相同 SQL 会命中缓存。一级缓存我觉得不用管它反而是二级缓存要小心它默认关闭如果在多表联查的 Mapper 上开启一旦关联的其他表数据变了缓存不会自动失效很容易查出脏数据。质量管理系统这种查询条件复杂、数据实时性要求又高的项目二级缓存建议直接保持默认关闭性能不够再加 Redis。4. 前端实现Vue 项目与接口联调4.1 项目初始化与目录规划前端用的是 Vue 3 Vite Element Plus Pinia Vue Router。创建项目不要太老套地拿 Vue CLI现在初始化项目直接用npm create vitelatest qms-web -- --template vue然后安装依赖cd qms-web npm install npm install vue-router4 pinia axios element-plusNode 版本建议 16.13 以上实测 Vite 5 在 Node 14 下会直接报错。npm 安装依赖如果慢可以配置镜像源npm config set registry https://registry.npmmirror.com这属于常规操作能省下很多等待时间。目录规划上我的习惯是按“模块”划分而不是按“文件类型”堆src/ ├── api/ # 接口请求统一放这里 │ ├── login.js │ ├── incoming.js │ └── report.js ├── assets/ # 静态资源 ├── components/ # 通用组件 ├── layout/ # 主框架布局 ├── router/ # 路由配置 ├── store/ # Pinia 状态 ├── views/ # 页面 │ ├── login/ │ ├── quality/incoming/ │ ├── quality/process/ │ ├── quality/product/ │ ├── quality/nonconforming/ │ └── report/ └── utils/ # 工具函数、axios封装api目录下每个文件导出对应模块的接口函数页面里只调用函数、不直接写 axios这样后端接口地址调整时只改一个文件。4.2 axios 封装、Token 处理与路由守卫请求封装是整个前端联调的核心。直接上代码import axios from axios import { ElMessage } from element-plus import router from /router const request axios.create({ baseURL: /api, timeout: 10000 }) request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }) request.interceptors.response.use( res { const data res.data if (data.code 200) return data if (data.code 401) { localStorage.removeItem(token) router.push(/login) ElMessage.warning(登录已过期请重新登录) return Promise.reject(new Error(unauthorized)) } ElMessage.error(data.msg || 请求失败) return Promise.reject(new Error(data.msg)) }, err { ElMessage.error(网络异常请检查后端服务) return Promise.reject(err) } ) export default request这里强烈建议在baseURL写/api而不是写死http://localhost:8080/api。开发时靠 Vite 代理把/api转发到后端生产时靠 Nginx 反向代理同样转发代码仓库里不需要因为环境不同而去改接口地址。很多新手项目写死 localhost换一台机器部署就一脸懵就因为这里没有处理好。路由守卫逻辑要兜底未登录的页面访问router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.path /login) { next() return } if (!token) { next(/login) return } next() })这部分配合后端 JWT 拦截器就构成了一套完整的鉴权闭环前端没 token 进不去页面后端没 token 或 token 过期接口返回 401前端收到 401 自动清 token 回登录页。4.3 检验录入、分页查询与报表展示检验录入页面是质检员每天用最多的页面设计上最重要的不是炫酷而是“少点几下鼠标”。我的做法是主表字段放顶部表单明细项用可动态增删的表格填写完一行自动追加一行空行最后一次性提交。分页查询用 Element Plus 的 el-table 加 el-pagination请求page参数变化时重新加载数据el-pagination v-model:current-pagequeryParams.page v-model:page-sizequeryParams.size :totaltotal layouttotal, sizes, prev, pager, next changeloadData /报表模块用 ECharts 画折线图和柱状图展示合格率趋势、缺陷分布。图表数据接口由后端 SQL 聚合比如按月份统计合格率SQL 大概长这样SELECT DATE_FORMAT(create_time, %Y-%m) AS month, COUNT(*) AS total_count, SUM(CASE WHEN conclusion PASS THEN 1 ELSE 0 END) AS pass_count FROM qc_product_inspection WHERE create_time #{startDate} GROUP BY DATE_FORMAT(create_time, %Y-%m) ORDER BY month前端图表只负责展示复杂的统计尽量下沉到 SQL不要让前端去把原始数据再加工一遍不然数据量大了页面会卡。5. 部署实操从源码到可访问的系统5.1 环境准备JDK、MySQL、Node、Nginx后端运行环境需要 JDK 1.8 Maven 3.6前端构建需要 Node.js 16数据库用 MySQL 8。MySQL 的安装我建议用免安装版 zip 包最适合服务器环境解压后修改my.ini然后执行mysqld --initialize-insecure初始化root 默认空密码再net start mysql启动服务。比起安装版免安装版没有图形化向导干扰路径自己可控出了问题也好排查。安装版向导有时候装完找不到配置文件反而不好处理。Java 后端部署直接打 jar 包运行这是 Spring Boot 最舒服的部署方式不需要装 Tomcatmvn clean package -DskipTests java -jar target/qms-system.jar --spring.profiles.activeprodNginx 用来托管前端静态文件和做反向代理安装好后目录结构大概是/usr/share/nginx/html放前端 dist 内容。5.2 数据库初始化与配置文件调整源码包里的sql/qms_init.sql是完整初始化脚本包含建库、建表、初始账号数据。首次部署先执行mysql -u root -p qms_init.sql默认初始账号是admin / admin123首次登录后建议立刻改密码。生产环境配置建议把账号密码、数据库地址放到application-prod.yml里用启动参数指定避免把生产密码写进源码仓库。5.3 后端打包与启动打包前重点关注三件事一是依赖能不能正常拉到私服二是测试类会不会因为连不上数据库而报错三是application-prod.yml里的数据库密码是否已改。启动命令建议用 nohupnohup java -jar qms-system.jar --spring.profiles.activeprod logs/qms.log 21 日志文件独立存放后面出问题有据可查。启动后用curl http://localhost:8080/api/login验证后端是否正常。常见启动失败原因无非端口被占用netstat -ano | findstr 8080查一下或者改 server.port、数据库连接不上检查地址、账号、密码、MySQL 服务状态、驱动类找不到检查依赖坐标。这三个排查掉后端一定能起来。5.4 前端构建与 Nginx 配置前端构建npm install npm run build构建产物在dist目录。把dist里的文件上传到服务器 Nginx 的 html 目录。Nginx 配置是整个前后端分离部署最关键的地方提供一份可用的配置server { listen 80; server_name localhost; root /usr/share/nginx/html; index 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; } location / { try_files $uri $uri/ /index.html; } }location /api/把所有后端接口反向代理到 SpringBoot 进程浏览器里所有请求都走同一个域名彻底消除跨域问题。try_files $uri $uri/ /index.html是 Vue Router 的 history 模式刷新 404 的解决方案如果不需要保留 url 语义也可以在代码里改成 hash 模式连这行都不用配。5.5 前后端联调与访问验证部署完成后验证流程浏览器打开http://服务器IP→ 跳登录页 → 用 admin 登录 → 进检验录入页面新增一条来料检验单 → 提交后端 → 在列表页看到数据 → 打开报表页看统计数据。全流程通了这套系统就算正式跑起来了。这里提醒一个很多人会忽略的问题云服务器安全组、服务器自带防火墙都要放行 80 端口。以前帮朋友排查过很多次代码完全没问题就是访问不了最后发现是安全组没开端口。检查顺序先本机curl再局域网 IP 访问最后再考虑公网映射。6. 常见问题与排查技巧实录6.1 开发环境跨域与Vite代理配置开发时前端和后端端口不同第一道坎就是跨域。解法不是在后端加CrossOrigin或者写一堆 CORS 配置类的代码那只是治标。最干净的方式是用 Vite 代理// vite.config.js export default defineConfig({ server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } })这样前端代码里的/api/login在开发时会被 Vite 服务转发到localhost:8080浏览器认为请求发给了同源的前端服务器跨域问题根本不存在。后端不需要额外配 CORS生产环境也不依赖它。6.2 Vue 打包后的两个经典问题第一个是打包后页面白屏、资源 404。大多数情况是静态资源路径用了绝对路径/assets/xxx部署在子路径下就找不到。解决办法是在vite.config.js里设置base: ./让资源路径变成相对路径。第二个是打包后刷新页面 404。如果前端路由用了 history 模式刷新时请求会发给 NginxNginx 找不到对应文件就回 404。前面 Nginx 配置里的try_files ... /index.html就是针对这个问题如果实在不想折腾 Nginx把路由模式改成 hash 也能解决URL 会多个#/对内部管理系统完全不影响使用。另外打包后布局异常这个问题多半是父容器没有约束宽度或者某台机器浏览器版本过旧导致现代 CSS 特性没生效先检查启动时有没有报错再逐级看样式。6.3 MySQL 8 连接与账号授权问题MySQL 8 用caching_sha2_password作为默认认证插件老的 MySQL 驱动和部分客户端工具会连不上、报Public Key Retrieval is not allowed。解决方法是 JDBC URL 加上allowPublicKeyRetrievaltrueuseSSLfalse同时在授权时也可以考虑创建使用mysql_native_password插件的账号。还有一个小坑是 MySQL 8 默认只在本机监听 3306如果后端部署在其他服务器需要检查bind-address配置并创建一个允许远程访问的账号CREATE USER qms% IDENTIFIED BY qms123456; GRANT ALL PRIVILEGES ON qms.* TO qms%; FLUSH PRIVILEGES;6.4 MyBatis 动态 SQL 的隐藏坑热词里有一条“mybatis 单个数字字符比较”这个我遇到过说出来都是泪。在if testtype 1.toString()这种写法里直接把单个字符放到上比较很可能不生效。原因是 MyBatis 的 OGNL 表达式解析对1会当作char类型处理和字符串1比较时结果不可预期。以后写这种条件判断要么写成下面这样if testtype ! null and type 1.toString()要么在 Java 代码里先处理好再传一个布尔值进来。避免在 XML 里写单个字符的等值判断就少踩一个坑。6.5 Spring Boot 版本太高引发的连锁反应我在 3.1 节就提醒过版本问题这里再展开。Spring Boot 3.x 是一次大版本跃迁最明显的是javax包名全面替换为jakarta。如果你在网上拷贝的代码里有import javax.servlet.*在 Spring Boot 3 项目里直接编译不通过。同时 MyBatis 的 starter 版本、PageHelper 版本、各种工具类都要选适配 Spring Boot 3 的版本误配低版本会出现奇怪的启动异常。这套质量系统的源码是按 Spring Boot 2.7.x 编写的用户直接用配套依赖即可如果你对 Spring Boot 3 的差异不熟悉不建议贸然升级。写在最后再分享一点实际使用中的经验。质量管理系统上线后能不能被工厂真正用起来关键不在功能列表有多全而在录入是否高效、报表是否看得懂。建议先从来料检验和成品检验两个模块推起跑顺了再加过程检验和不合格品管理不要想一口吃成胖子。质检员一天要录很多单据交互上一定要尽量少点几次鼠标明细项能默认就默认检验结论能自动判定就自动判定。批号的规则一定要在上线前和车间、仓库、生管几个部门对齐这是整个追溯体系的命脉。还有就是定期备份数据库中小工厂往往没有专职DBA我用的是一个简单的定时任务每天夜里mysqldump一次出过一次事故的人会懂这件事有多重要。整套系统从设计到落地前后花了大概三周时间。单一技术栈并不是什么新鲜东西但把它组合成一个贴合制造业质量管理场景的完整闭环再整理成一套可部署的源码和文档这件事本身就是价值。如果在部署或二次开发中遇到问题欢迎按项目文档里的思路先自查很多问题都能在配置层面找到答案。
RELATED

相关推荐

TypeScript与Java深度对比:从类型系统到工程实践

TypeScript与Java深度对比:从类型系统到工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/15 4:54:09
深入解析 EIP-1702:以太坊通用账户版本化方案(Generalized Account Versioning Scheme)

深入解析 EIP-1702:以太坊通用账户版本化方案(Generalized Account Versioning Scheme)

深入解析 EIP-1702:以太坊通用账户版本化方案(Generalized Account Versioning Scheme) 【免费下载链接】EIPs The Ethereum Improvement Proposal repository 项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs EIP-1702&#…

📅 2026/9/15 4:54:09
ArmorPaint:实时PBR纹理绘制与Git协同工作流

ArmorPaint:实时PBR纹理绘制与Git协同工作流

1. ArmorPaint 是什么?一个被严重低估的实时PBR纹理绘制工作流ArmorPaint 这个名字乍一听像某种军事装备或游戏MOD工具,但其实它是一个开源、跨平台、基于GPU加速的实时PBR纹理绘制软件——准确说,是目前唯一能真正把“在3D模型表面直接画材质…

📅 2026/9/15 4:54:09
MORE NEWS

更多资讯

📰

Obsidian同步方案对比:坚果云WebDAV与官方Sync的实战选择

Obsidian 的同步问题,几乎每个深度用户都会在某一天突然面对。笔记越写越多,手机、办公电脑、家里台式机三处要同时维护,这时候没有一套好用的同步方案,整个知识库就成了定时炸弹——不是这端忘了改,就是那端覆盖了旧版…

📰

GAPSO:解决PSO早熟收敛的高维多峰优化工程方案

简介:本资源是一套完整的GAPSO(Global and Adaptive Particle Swarm Optimization)混合优化算法实现代码与配套说明,面向智能优化、智能算法研究及工程优化领域的高校师生、科研人员与算法工程师。资源聚焦解决传统PSO易陷局部最优…

📰

PHP星座运势查询系统开发:日期判定、随机运势与MySQL存储

简介:一份PHP实例开发源码,帮助学习者实现星座运势查询系统。项目围绕用户输入出生日期、判断星座、返回当日运势的核心流程,覆盖前端交互表单、PHP后端处理、PDO/MySQL数据读写、日期计算与安全防范等Web开发关键知识点,适合PHP初…

📰

基于知识图谱的中医药智能问答系统:从Neo4j建模到Cypher查询实践

简介:面向中医药领域知识图谱与智能问答系统的学习者,这份资源是一套完整的Python项目实现,覆盖知识图谱构建、实体识别、实体链接、路径过滤与推理等关键流程,适合作为相关大作业或毕业设计的参考。包内共11个文件,包…

📰

微信支付V3 SpringBoot实战:签名、验签与回调处理全解析

简介:这是一套基于Spring Boot框架开发的微信小程序微信支付第三代后端源码,面向需要快速接入微信支付能力的小程序开发者与后端工程师,覆盖统一下单、支付回调验签、订单查询等核心流程,可直接参考其接口设计与参数处理方式。压缩…

📰

前后端分离的中小型制造企业质量管理系统实战:SpringBoot+Vue+MyBatis+MySQL

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬