ARTICLE DETAIL

资讯详情

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

SpringBoot+Vue软件缺陷管理系统毕业设计全解析

SpringBoot+Vue软件缺陷管理系统毕业设计全解析 简介本资源是一套面向高校计算机专业本科生的毕业设计级软件缺陷管理系统采用SpringBootVue前后端分离架构解决中小型团队缺陷提交、流转跟踪与可视化分析的实际管理需求。包内含706个文件涵盖136个JavaScript前端逻辑文件、117个数据库备份文件.zbak、53个Java后端核心类、33个Vue组件及配套CSS样式文件含violet/pink/sea等多主题皮肤整体压缩包仅3.52MB结构清晰、注释完备。已有32人下载学习适合作为课程设计参考或工程实践入门范例。读者可直接获取经多轮调试验证的完整源码、符合第三范式的MySQL 8.0数据库脚本、标准化RESTful接口文档及JDK 11/Node.js 14部署指南所有模块均支持独立运行与状态联动具备缺陷优先级分级、生命周期追踪与基础统计图表功能。1. 为什么选软件缺陷管理系统做毕业设计——选题价值与业务拆解1.1 缺陷管理比“图书管理”“购物商城”好在哪每年毕设季Java方向的学生一抓一大把题目翻来覆去就是图书管理系统、校园商城、酒店预订、在线考试。不是这些题目不能做而是做的人太多论文和答辩都很难讲出新东西。我当时选题时专门避开了这些“大路货”选了软件缺陷管理系统也就是很多公司内部叫的Bug管理系统。原因很简单这个系统有真实的业务背景几乎每家软件公司都有自己的缺陷管理平台需求明确、流程清晰而且带一个完整的业务闭环。“提交缺陷—分配处理—修复—验证—关闭”这条链路做出来整套系统的逻辑性和专业性天然就比“增删改查商城商品”高一个档次。更重要的是缺陷管理系统在答辩时特别“有话讲”。老师问“你的系统解决什么问题”你可以直接说出软件研发团队日常提Bug、派Bug、跟踪Bug的痛点老师问“系统有哪些难点”你有权限控制、状态流转、统计报表、附件上传这些非常具体的模块可以展开。这些都是图书管理系统很难提供的深度。另外一个很实际的因素开源社区里缺陷管理系统的参考实现很多比如Bugzilla、MantisBT这类老牌工具以及禅道、Jira的产品设计文档也到处都是。这意味着做需求分析的时候你可以参考成熟产品的功能设计来补充自己的方案而不是凭空想象“系统该有哪些页面”。我当时的做法是把Jira的缺陷流程截图存下来逐个页面分析功能逻辑再提炼成自己系统的需求清单效率非常高。1.2 业务闭环与角色权限一个系统里藏着完整的工作流我开发这套系统时最核心的设计思路是不只做一个“缺陷信息的增删改查”而是把缺陷的完整生命周期管理起来。所以系统里有三类核心角色测试人员提交缺陷、补充缺陷信息、验证修复结果、关闭缺陷。开发人员查看分配给自己的缺陷、更新修复状态、在缺陷下回复说明。系统管理员管理用户、管理项目、管理模块以及查看系统级别的统计报表。这三类角色是业务上的天然划分对应到系统里就是三个不同的权限边界。比如一个测试人员不应该有权修改“开发负责人”字段更不能把缺陷状态从“修复完成”改成“重新打开”这类改动只能由具备对应角色的用户操作。否则整个流程就乱套了。我在做需求分析时把这些角色的操作权限整理成了一张文案表格类似于功能测试人员开发人员管理员提交缺陷是是是修改缺陷信息是本人提交是分配给本人是分配缺陷否否是修复缺陷并更新状态否是分配给本人是验证并关闭缺陷是本人提交否是用户与项目管理否否是这张表做出来之后后端写权限控制逻辑时就有了非常清晰的依据再也不存在“写完接口之后再纠结谁能调”的问题。这也是我想提醒大家的一点需求阶段花半天把角色权限表列清楚比在代码里打十层补丁都管用。很多同学做系统上来就写PreAuthorize注解或if(roleadmin)写到后面发现这里漏了那里错了就是因为业务角色边界一开始就没理清。1.3 状态机设计让缺陷从“提交”走到“关闭”缺陷管理的核心是缺陷状态的有序流转。我设计的状态一共有这些待处理缺陷提交成功等待管理员或负责人分配。处理中开发人员已接受并开始修复。修复完成开发人员提交修复等待测试验证。验证通过测试人员验证修复成功。关闭缺陷生命周期结束。重新打开验证不通过缺陷被退回到待处理。每一个状态变化背后都对应一个操作动作。比如“修复完成”只能由开发人员发起而且前提条件是当前状态是“处理中”“重新打开”只能由测试人员发起前提条件是当前状态是“修复完成”。这种限制在业务上叫状态机约束在代码里就是一组状态迁移规则。我当时的实现方案是在后端单独写一个状态流转校验类用Map维护合法的状态迁移表public class BugStateMachine { private static final MapString, ListString TRANSITIONS new HashMap(); static { TRANSITIONS.put(待处理, Arrays.asList(处理中, 关闭)); TRANSITIONS.put(处理中, Arrays.asList(修复完成, 待处理)); TRANSITIONS.put(修复完成, Arrays.asList(验证通过, 重新打开)); TRANSITIONS.put(重新打开, Arrays.asList(处理中, 待处理)); TRANSITIONS.put(验证通过, Arrays.asList(关闭)); TRANSITIONS.put(关闭, Arrays.asList()); } public static boolean canTransition(String current, String target) { ListString allowed TRANSITIONS.get(current); return allowed ! null allowed.contains(target); } }每次更新状态前先调用canTransition校验合法才允许更新。这个方法写起来简单但效果立竿见影——它把缺陷状态的非法跳转全部拦截住了比如“待处理”直接跳到“验证通过”这种情况根本不可能发生。答辩的时候把这个状态机设计一讲老师立刻就知道你理解了业务的核心逻辑而不只是会写CRUD。2. 技术栈选型与项目初始化先搞清楚为什么这么搭2.1 SpringBoot版本选择与核心依赖这套系统的后端采用SpringBoot前端采用Vue前后端完全分离。技术选型的逻辑很简单SpringBoot是目前Java后端使用最广泛、资料最多的框架Vue则是国内前端社区最活跃的框架之一两者组合既符合当前行业技术趋势也方便我自己找资料排坑。SpringBoot的版本选择上我用的是2.7.x系列而不是最新的3.x。为什么不用3.x原因有三个SpringBoot 3.x要求JDK 17以上但很多学校的实验室和毕设答辩环境还停留在JDK 8万一答辩现场环境配置出问题非常被动。自己在网上搜到的绝大多数教程、博客、GitHub项目都是基于SpringBoot 2.x的遇到问题能搜到的解决方案更多。SpringBoot 2.7.x功能足够稳定完全满足毕设系统的需求没必要为了“新”而给自己添堵。我建议能力一般的同学直接SpringBoot 2.7.x加JDK 8这个组合最稳几乎不会踩环境兼容性的坑。如果你的机器已经装了JDK 17那也可以强行指定maven编译目标为1.8版本但这样一来Lombok、MyBatis等插件的兼容性可能出问题不建议新手折腾。后端核心依赖如下dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-validation/artifactId /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency dependency groupIdcom.auth0/groupId artifactIdjava-jwt/artifactId version3.19.2/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependencyMyBatis-Plus是我特别想推荐给毕设党用的一个库。它本质上是在MyBatis基础上做了增强把单表的增删改查、分页查询、条件构造器这些重复工作全部封装好了。你只需要定义实体类和Mapper接口继承BaseMapperT就能拥有selectById、selectPage、insert、updateById这些基础方法不需要手写SQL。这对于做管理系统这类“大量单表增删改查”的项目来说能节省至少三分之一的时间。当然多表关联查询还是要手写SQL我的做法是使用MyBatis-Plus的分页插件搭配Select注解直接写自定义SQL两种方式切换起来非常顺畅。2.2 数据库选型与连接配置数据库方面我选了MySQL 8.0这是目前最主流的选择稳定、资料多、IDE支持好。缺点是安装包比较大机器配置低的同学跑起来会有一些卡顿但毕设场景完全够用。这里有个很多人忽略的细节字符集和时区配置一定要在连接串里写清楚。我最初就是因为没配时区后端拿到的数据库时间和本地时间差了8个小时排查了半天才发现是serverTimezone的问题。正确的配置如下spring: datasource: url: jdbc:mysql://localhost:3306/bug_system?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue username: root password: yourpassword driver-class-name: com.mysql.cj.jdbc.DriverallowPublicKeyRetrievaltrue这个参数容易被忽略MySQL 8.0默认使用caching_sha2_password插件如果不加这个参数某些版本的驱动连接时会报Public Key Retrieval is not allowed错误。写配置时一次性带上能省掉一个隐蔽的坑。另外我强烈建议在本地开发时把MyBatis-Plus的SQL日志打开这样控制台能直接打印出每一条执行的SQL语句排查问题非常直观mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl2.3 Vue项目结构与前端工程化配置前端我用的是Vue 2.6 Element UI的组合没有选择Vue 3。原因和后端选择SpringBoot 2.x一样Vue 3虽然已经推出很久但Element UI的Vue 3版本Element Plus在当时的生态成熟度和教程数量上不如Vue 2 Element UI的组合稳定。对毕设来说稳定大于一切。前端项目我使用Vue CLI创建目录结构大致如下src ├── api/ # 按模块拆分的接口请求 │ ├── auth.js │ ├── bug.js │ ├── project.js │ └── user.js ├── assets/ # 静态资源 ├── components/ # 公共组件 ├── router/ # 路由配置 ├── store/ # Vuex状态管理 ├── utils/ # 工具函数如request.js封装axios ├── views/ # 页面组件 │ ├── login/ │ ├── bug/ │ ├── project/ │ └── dashboard/ └── App.vue前端创建完成后我做的第一件事不是写页面而是封装request.js——基于axios的统一请求工具。这个封装的必要性在于所有请求都必须携带JWT Token、所有响应都统一处理异常状态码、所有结果都自动解包。如果不做这层封装后面写几十个接口调用时会重复写一大堆样板代码。import axios from axios import { Message } from element-ui import router from /router const request axios.create({ baseURL: process.env.VUE_APP_BASE_URL || http://localhost:8080/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( response { const res response.data if (res.code ! 200) { Message.error(res.message || 请求失败) if (res.code 401) { localStorage.removeItem(token) router.push(/login) } return Promise.reject(new Error(res.message)) } return res.data }, error { Message.error(error.message || 网络异常) return Promise.reject(error) } ) export default request这段封装的逻辑很直白请求前从localStorage拿Token塞到请求头响应后统一判断业务状态码401就跳回登录页。所有页面里的接口调用都通过request这个实例发出既统一又干净。3. 数据库设计这套系统的灵魂所在3.1 核心表结构从用户到缺陷的完整关系链数据库设计是这套系统里我最花心思的部分。之前带过几个学弟的毕设看过太多“一张主表打天下”的设计——把用户、缺陷、项目、评论全塞进两三个表里写到后面自己都分不清谁是谁。缺陷管理系统的数据规模不大但表之间的关联关系必须清晰。我的核心表一共七张分别是sys_user用户表账号密码、姓名、角色、状态。sys_project项目表系统里的项目/产品。sys_module项目下的模块表和项目是多对一关系。sys_bug缺陷表记录缺陷的标题、描述、状态、优先级、严重程度、指派人等。sys_bug_comment缺陷评论表记录开发人员和测试人员的沟通记录。sys_bug_log缺陷操作日志表记录每次状态变更、字段变更的历史。sys_bug_attachment附件表保存缺陷截图等附件的路径。以sys_bug表为例字段设计如下字段名类型说明idbigint主键自增bug_novarchar(32)缺陷编号形如BUG-20240516-001titlevarchar(200)标题descriptiontext详细描述statusvarchar(20)状态待处理/处理中/修复完成/验证通过/关闭/重新打开priorityvarchar(10)优先级紧急/高/中/低severityvarchar(10)严重程度致命/严重/一般/轻微project_idbigint所属项目module_idbigint所属模块reporter_idbigint提交人assignee_idbigint当前处理人create_timedatetime创建时间update_timedatetime更新时间这份表结构基本都是从成熟的缺陷管理工具里提炼出来的该有的业务字段都覆盖了。特别说明一下bug_no这个字段很多同学会直接拿自增id当缺陷编号但业务上缺陷编号通常是一个有规则的可读编号比如“BUG-20240516-001”这样在沟通和邮件里引用时非常直观。实现方式也不复杂在新增缺陷后根据当前日期和当天已创建的缺陷数量拼接生成即可。3.2 索引设计与查询优化思路缺陷表是系统中最核心、查询频率最高的表而且它的查询是典型的“多条件组合筛选”——按项目筛选、按状态筛选、按指派人筛选、按关键字搜索。为了让这些组合查询都保持高效我在设计索引时没有盲目加索引而是按照查询模式来设计。最常出现的查询条件就是project_id status assignee_id的组合筛选所以我建了一个联合索引ALTER TABLE sys_bug ADD INDEX idx_project_status_assignee (project_id, status, assignee_id);联合索引的字段顺序是有讲究的。按查询条件的选择性和区分度来看project_id的区分度最高放在最左边其次是status最后是assignee_id。如果条件不含project_idMySQL不会走这个联合索引但这种情况在系统里非常少见因为缺陷列表页总归要选项目。另外create_time字段也建了索引用于支撑按时间统计缺陷数量的报表查询ALTER TABLE sys_bug ADD INDEX idx_create_time (create_time);对于毕设系统来说这个索引规模已经完全够用不需要再考虑什么分区分表的问题。但答辩时老师可能会问“如果数据量达到百万级你的索引还够用吗”这个问题的答案你心里要有数——百万级数据量下简单的单表查询加线上索引依然能扛但如果要做复杂的多维统计就该考虑定时汇总表或引入数仓工具了。3.3 数据库初始化脚本与测试数据别偷懒很多同学写数据库脚本时只建表不插数据结果前端页面打开列表空荡荡的展示效果非常差。我强烈建议在SQL脚本中预置一份完整的测试数据3个测试账号管理员、测试人员、开发人员各一个密码统一为123456记得用MD5或BCrypt加密后的密文。2~3个项目每个项目下2~3个模块。10条左右覆盖不同状态的缺陷记录保证列表页和统计图表都有数据可看。每个缺陷至少配1条评论和2~3条操作日志让详情页有内容可展示。这些测试数据不仅让你的演示效果好看更重要的是对于系统自测非常有用——你可以在本地把所有功能挨个跑一遍确认列表、详情、流程跳转都正常。数据库脚本我还有一个建议用可视化工具连接MySQL以后直接执行一个完整的init.sql脚本而不是一句句复制SQL执行。具体操作是在Navicat或DataGrip中打开SQL文件选择目标数据库点击执行即可。这样整个初始化过程是幂等的可以反复执行不怕出错。4. 后端核心模块的实现登录鉴权与缺陷流转4.1 JWT登录鉴权与RBAC权限控制登录鉴权我用了JWT这是目前前后端分离项目的主流方案。核心思路是用户输入账号密码登录成功后后端生成一个包含用户id和角色信息的Token返回给前端前端保存Token之后每次请求在请求头中带上后端解析Token识别用户身份。JWT的依赖引入在配置里已经写了生成Token的逻辑大致如下public String generateToken(User user) { Algorithm algorithm Algorithm.HMAC256(secretKey); String token JWT.create() .withClaim(userId, user.getId()) .withClaim(role, user.getRole()) .withExpiresAt(new Date(System.currentTimeMillis() 24 * 60 * 60 * 1000)) .sign(algorithm); return token; }解析Token也不复杂在拦截器里完成。我写了一个JwtInterceptor注册到SpringMVC的拦截器链中让所有/api/**请求都经过这个拦截器。拦截器解析Token得到用户ID从数据库中查出用户信息放入ThreadLocal后面的Controller就能直接拿到当前登录用户。这样每个接口就不用自己处理“当前操作者是谁”的问题。权限控制我采用注解方式实现。自定义一个RequireRole注解配合Spring AOP切面去校验当前用户是否拥有指定角色Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface RequireRole { String value(); }然后在需要权限控制的接口上标注即可PostMapping(/assign) RequireRole(ADMIN) public Result assignBug(RequestBody AssignRequest request) { // 分配缺陷 }这样做的好处是权限逻辑集中在AOP切面中不会散落在业务代码里。答辩时老师问“你的权限怎么控制的”你直接回答“基于JWT的登录态识别加基于AOP的角色校验”再简单说明两者如何配合这个回答的完整性就很高了。4.2 缺陷CRUD与状态流转的代码实现缺陷模块的后端接口大体包括创建、分页查询、详情、更新、状态流转、评论、记录日志。核心难点不在CRUD本身而在“状态流转时怎么保证数据一致”。我的做法是所有状态流转操作都集中在BugService中通过一个transitionBug方法完成这个方法内部依次执行根据当前状态和期望目标状态调用状态机校验合法性。校验操作人是否有权限执行该操作。更新缺陷状态和操作人字段。写入操作日志。以“提交修复”为例核心逻辑是Transactional public void submitFix(Long bugId, Long userId) { Bug bug bugMapper.selectById(bugId); if (bug null) { throw new BusinessException(缺陷不存在); } if (!bug.getAssigneeId().equals(userId)) { throw new BusinessException(只能修复分配给自己的缺陷); } if (!BugStateMachine.canTransition(bug.getStatus(), 修复完成)) { throw new BusinessException(当前状态不允许执行此操作); } bug.setStatus(修复完成); bug.setUpdateTime(new Date()); bugMapper.updateById(bug); BugLog log new BugLog(); log.setBugId(bugId); log.setOperatorId(userId); log.setAction(提交修复); log.setDetail(状态从 bug.getStatus() 变更为修复完成); bugLogMapper.insert(log); }这里有个细节值得强调Transactional事务注解一定要加。因为更新状态和写日志是两步操作如果更新完状态后写日志失败没有事务的话数据库里就出现了“状态变了但没记录”的不一致状态。对这个系统来说日志很重要它不仅是答辩的展示点也是实际操作中追溯问题最直接的凭证。4.3 统计报表接口用一条SQL算清缺陷趋势缺陷管理系统的另一个亮点模块是统计报表。我实现了三个维度的统计各状态缺陷数量、各严重程度分布、近7天新增缺陷趋势。统计查询不需要写复杂的代码用SQL聚合就能完成。比如统计各状态数量的SQLSELECT status, COUNT(*) AS total FROM sys_bug WHERE project_id #{projectId} GROUP BY status;近7天新增缺陷趋势的SQLSELECT DATE(create_time) AS day, COUNT(*) AS total FROM sys_bug WHERE create_time DATE_SUB(CURDATE(), INTERVAL 6 DAY) GROUP BY DATE(create_time) ORDER BY day;这些接口返回给前端后前端基于ECharts画环形图和柱状图展示效果非常好看。而且这个模块在答辩时是“加分神器”因为大部分管理系统只有表格你多了可视化图表一下子就显得系统“智能”了不少。当然做这个模块的时候要注意后端返回的数据结构要设计得合理最好直接以name和value的结构返回前端不用再做二次数据重组。4.4 操作日志审计追溯不能省操作日志模块是我坚持保留的一个模块虽然它让代码量多了不少但对缺陷管理系统来说日志不是附加功能而是刚需——当一个缺陷被错误修改后你需要知道是谁、在什么时间、做了什么操作。日志表的数据来源就是上一节提到的各种状态流转和修改操作。我设定了几类重要的操作动作创建缺陷状态变更分配处理人评论编辑严重程度/优先级每次执行这些操作时都会把操作人、操作时间、操作内容、操作前后的关键字段值写入日志表。详情页展示缺陷时把日志列表按时间倒序排在评论下方就形成了一条完整的“缺陷时间线”。这个设计参考了Jira的活动日志做出来后系统专业度立刻提升一个档次。5. 前端页面与交互Vue的实战细节5.1 登录页与路由守卫前端页面的开发我严格按照“先搭框架再填页面”的顺序。登录页是所有页面的入口表单验证用了Element UI自带的校验规则账号密码不能为空密码长度不少于6位。登录成功后将Token和用户信息写入Vuex和localStorage然后跳转到首页。路由守卫的逻辑是前端权限控制的第一道门槛router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.path /login) { next() } else { if (!token) { next(/login) } else { next() } } })这个守卫只能判断“是否登录”前端页面上的按钮级权限还需要配合后端接口的返回结果来控制。比如开发人员登录后缺陷详情页的“验证通过”按钮不应该显示或点击无效。我的做法是根据用户角色在页面里用v-if判断按钮是否渲染虽然简单但实际效果完全够用。5.2 缺陷列表页搜索、分页、多条件筛选缺陷列表是整个系统里交互最复杂的页面。顶部是筛选区域包括项目下拉选择、状态下拉选择、指派人下拉选择、关键字输入框。下面是一个表格展示缺陷编号、标题、项目、状态、优先级、严重程度、指派人、更新时间。再下面就是分页。我用了Vue的computed属性来动态生成搜索参数对象组件内搜索条件变化自动请求接口。这里有一个细节list查询接口的状态筛选、项目筛选等条件通过axios的params传参对应到后端的MyBatis-Plus条件构造器可以非常优雅地完成动态条件拼接Override public PageResultBugVO pageQuery(BugPageQuery query) { PageBug page new Page(query.getPageNum(), query.getPageSize()); LambdaQueryWrapperBug wrapper new LambdaQueryWrapper(); wrapper.eq(query.getProjectId() ! null, Bug::getProjectId, query.getProjectId()) .eq(StringUtils.hasText(query.getStatus()), Bug::getStatus, query.getStatus()) .eq(query.getAssigneeId() ! null, Bug::getAssigneeId, query.getAssigneeId()) .like(StringUtils.hasText(query.getKeyword()), Bug::getTitle, query.getKeyword()) .orderByDesc(Bug::getUpdateTime); PageBug result bugMapper.selectPage(page, wrapper); return convertToPageResult(result); }用LambdaQueryWrapper的好处是条件可以按需拼接不需要为每个查询场景单独写一条SQL。代码看起来简洁也能有效防止SQL注入——因为参数都是预编译绑定不会拼接到SQL字符串里。5.3 缺陷详情与评论回复时间线的形成缺陷详情页参考了很多成熟系统的布局左侧是基本信息右侧是评论区。基本信息区展示标题、描述、项目、模块、状态、优先级、严重程度、提交人、指派人、创建时间和更新时间信息非常完整。管理员或当前处理人可以在这里进行状态流转操作。评论区则按时间正序展示评论记录每条评论展示评论人、评论时间、评论内容。再往下是操作日志列表展示每一次状态变更格式就是“张三 在 2024-05-16 14:30 将状态从处理中修改为修复完成”。这样一来评论和日志结合缺陷的完整生命周期就像时间线一样展示在眼前。前端实现评论区的核心是处理好“提交评论后刷新列表并清空输入框”这个交互。我使用了this.$refs.commentForm.resetFields()重置表单再重新调用loadDetail()接口刷新整个详情数据。这里要注意的是刷新不能刷掉用户正在看的Tab页签状态所以我用activeTab变量记录当前选中的Tab刷新后重新赋值。5.4 数据可视化ECharts图表模块的真实写法统计报表页面主要由三个图表构成我都使用了ECharts的Vue封装版本vue-echarts。刚开始我直接用原生ECharts写后来发现组件销毁时如果不手动dispose浏览器会出现内存泄漏警告于是改成了vue-echarts用法简化成了template v-chart :optionoption autoresize / /template script import { use } from echarts/core import { CanvasRenderer } from echarts/renderers import { PieChart, BarChart } from echarts/charts import { TitleComponent, TooltipComponent, LegendComponent } from echarts/components import VChart from vue-echarts use([CanvasRenderer, PieChart, BarChart, TitleComponent, TooltipComponent, LegendComponent]) export default { components: { VChart }, props: { option: { type: Object, required: true } } } /script这个组件的option由父组件从接口返回的数据动态生成图表风格和颜色统一设计过整体视觉效果比默认样式好看很多。建议这部分后端返回的数据结构就按[{ name: 待处理, value: 5 }]这种格式设计前端直接赋给ECharts的data字段即可省去大量数据转换代码。6. 部署、自测与答辩中的几个关键坑6.1 后端打包与Linux部署的常见问题开发完成之后你需要把后端打包成可执行的jar包。这里有一个非常典型的坑如果本地开发时没有做环境区分打出来的jar包里包含的是本地数据库的配置部署到服务器后连不上远程数据库。我建议在application.yml中把数据库地址、Redis地址等配置用占位符代替并在打包时通过--spring.profiles.activeprod指定生产环境配置文件mvn clean package -DskipTests java -jar bug-system-0.0.1.jar --spring.profiles.activeprod在Linux服务器上部署时Java进程最好用nohup启动日志输出到文件方便排查问题nohup java -jar bug-system-0.0.1.jar --spring.profiles.activeprod app.log 21 前端打包则是典型的Vue CLI流程npm run build后会生成dist目录里面是纯静态文件。把dist目录下的内容上传到服务器配置Nginx将/路径指向这个目录同时把/api路径反向代理到后端的8080端口server { listen 80; server_name your-domain.com; root /usr/share/nginx/html; index index.html; location / { 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; } }try_files $uri $uri/ /index.html;这一行特别关键它保证前端路由使用history模式时刷新非首页路径不会出现404。6.2 附件上传与本地上传后的路径管理附件上传这个模块有一个容易踩的小坑。我一开始很简单地使用绝对路径“D:/upload/”来保存上传的文件但把系统部署到Linux服务器时路径就完全不适用了。后来我改成了相对路径在上传接口中把文件保存在项目目录下的uploads/文件夹中并通过WebMvc配置一个静态资源映射这样无论系统部署在哪个操作系统都能正常展示附件图片Override public void addResourceHandlers(ResourceHandlerRegistry registry) { String uploadPath System.getProperty(user.dir) /uploads/; registry.addResourceHandler(/uploads/**) .addResourceLocations(file: uploadPath); }这里的System.getProperty(user.dir)获取的是当前Java进程的工作目录在本地运行是指项目根目录在服务器上运行时是jar包所在目录。这样处理之后附件路径就不用再区分环境了。6.3 答辩时老师最爱问的几个问题及应对思路最后聊一聊答辩。做了这么久毕设你肯定希望答辩时不仅“把系统演示完”还能“被问到问题时不慌”。我总结一下老师对这个题目最常问的几个问题问题一为什么选择SpringBoot和Vue而不是SSH/SSM这种传统框架回答思路SpringBoot简化了配置和部署Vue实现了前后端分离开发和维护效率都更高。可以再补一句“前后端分离也是目前企业主流的开发模式”让回答有落地感。问题二缺陷状态是怎么控制的如果两个用户同时操作同一个缺陷怎么办回答思路先讲状态机设计再讲乐观锁或版本号控制。我的实现是更新时带上version字段通过UPDATE ... WHERE version #{version}如果更新影响行数为0说明有人改了数据抛出异常让用户刷新重试。这个回答会显得非常专业。问题三系统的性能瓶颈在哪里怎么优化回答思路可以从数据库索引、查询优化、前端懒加载、图片压缩几个方向回答。不需要真的做过性能测试但要有自己的思考比如“当前系统的瓶颈主要在报表查询上如果数据量大可以引入定时汇总表”。问题四这个系统和禅道/Jira相比有什么不足回答思路不要硬吹自己的系统比商业软件好。诚实承认在功能完整度、消息通知、自定义流程等方面还有不足但强调系统的核心流程完整、扩展性良好后续可以继续迭代。这种回答反而让老师觉得你对自己的项目有清醒的认知。6.4 踩坑总结几条让初学者抓狂但很容易避免的坑最后再分享几个我实际踩过、也帮学弟们排查过无数次的坑。第一个是端口占用。本地启动SpringBoot时如果报Port 8080 was already in use在Windows下用netstat -ano | findstr 8080找到占用进程的PID再用taskkill /PID 对应PID /F杀掉进程即可。这种问题几乎每个做过SpringBoot开发的人都遇到过知道怎么解决很重要。第二个是数据库编码。很多同学建库时用了默认字符集latin1导致存中文变成乱码。解决方法很简单建库时指定utf8mb4字符集CREATE DATABASE bug_system DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;这里多说一句utf8mb4是utf8的超集能存emoji等四字节字符现代项目都用utf8mb4而不是utf8。第三个是前端跨域问题。本地开发时前端跑在http://localhost:8081后端跑在http://localhost:8080两者端口不同会触发跨域。解决方案是后端加一个CORS配置类或者更简单的方式是在前端vue.config.js中配置开发代理module.exports { devServer: { port: 8081, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } }这样前端开发和后端调试完全隔离也不会被跨域问题困扰。第四个是本地数据库和服务器数据库版本不一致导致的问题。比如本地用的MySQL 8.0服务器的MySQL是5.7两者在时间类型、默认值表达式上有细微差异。解决办法是尽量让两边的MySQL版本保持一致至少大版本号一致。我的建议是服务器上也用MySQL 8.0这样最省事。第五个是前端npm install装包失败。这种情况在中国大陆网络环境下特别常见解决方式是把npm源切换为阿里镜像npm config set registry https://registry.npmmirror.com设置完之后再npm install速度和成功率都会有明显提升。这个配置只影响当前机器的npm源不会影响任何项目代码。做毕设这件事做得越深入越能体会到一个道理大部分看似高深的技术难点拆开看都是一个个普通的问题。SpringBoot和Vue组合开发缺陷管理系统本身没有用到任何高深的技术但只要你把业务逻辑想清楚、把流程做完整、把细节处理到位出来的作品就能在答辩中脱颖而出。希望这篇内容能帮你把整条路走得更顺少踩几个我当年踩过的坑。本文还有配套的精品资源点击获取
返回列表