尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

SpringBoot+Vue密接者跟踪系统:毕业设计前后端分离实战解析

发布时间:2026/9/24 22:28:14

资讯中心
01
ARTICLE

SpringBoot+Vue密接者跟踪系统:毕业设计前后端分离实战解析

SpringBoot+Vue密接者跟踪系统:毕业设计前后端分离实战解析
每年毕业设计选题季总有一批同学被某某管理系统这类题目绊住。公共卫生事件相关的跟踪管理类项目更是长盛不衰比如这套SpringBootVue 新冠病毒密接者跟踪系统管理平台几乎每个学校都能碰到几个选类似题目的。原因很实在——业务逻辑清楚、需求明确、技术栈通用拿来做毕设或者课设既能展示前后端分离开发能力又不会因为业务太复杂导致做不完。但这恰恰是问题所在。题目看着简单实际做起来很多人卡在了密接判定逻辑怎么设计健康状态怎么流转隔离解除条件是什么这些看似不起眼的地方。一套能完整运行的源码价值就在于把这些问题落地成了具体代码。这篇博文我就从完整项目的角度出发把这套基于Java SpringBoot MySQL Vue的技术方案从头到尾拆一遍包括数据模型设计、后端权限与业务逻辑、前端页面组织、本地部署步骤以及答辩时老师最爱追问的技术点。无论你是想拿这套源码当基础改造成自己的毕设还是单纯想学习一个前后端分离项目的完整写法都能在文章里找到对应的部分。1. 先聊清楚这类跟踪管理平台究竟在做什么很多同学拿到项目第一反应是打开代码跑起来跑完就不知道该干嘛了。这其实是本末倒置。做毕设也好课设也罢第一步一定是对业务的完整理解。你只有知道这个系统要解决什么问题才能在上千行代码里不迷路。1.1 从业务角度看密接者跟踪系统要解决哪几个核心问题密接者跟踪本质上做的是信息登记、关系追踪、状态流转、统计上报这四件事。信息登记很好理解密接人员的基本身份信息、联系方式、居住地址、密接发生的时间和地点这些原始数据是整个系统的基石。没有准确的登记后续一切分析都是空谈。关系追踪是这套系统的灵魂。所谓密接总得知道是和谁密接、在什么场景下密接、当天还有哪些人可能在同一个场所。所以数据模型里不光要有人员表还要有密接批次密接地点这类关联维度。举个例子一列动车上有密接者A那同一节车厢的人甚至同车厢前后三排的人都会被打上密接或次密接标签这就是一个批次的概念。状态流转则决定了系统的动态性。一个密接人员从观察中到已解除中间可能要经历核酸结果更新、体温指标录入、症状变化、隔离延长期等环节。如果状态设计成死字段系统就失去了跟踪的意义。统计上报是给管理者看的。每天新增多少人、解除多少人、还在观察的有多少、分布在哪里这些数据要能实时汇总。如果全靠人工数那系统存在的价值就大打折扣了。1.2 为什么 SpringBoot Vue 会成为这类项目的首选组合技术选型不是越新越好而是越稳越好尤其是毕设这种以展示能力为首要目标的场景。SpringBoot在前几年就已经是Java后端的事实标准。它把SprngMVC、MyBatis、Tomcat、JSON序列化这些组件整合成了一套自动配置你不需要再写繁琐的web.xml不用手动配一堆Bean一条main方法启动一个web服务。对没接触过SSH那套老框架的学生来说学习曲线友好得多。而SpringBoot 2.x在国内教程资源极多遇到问题一搜就有答案。Vue在前端的地位也类似。Vue 2 Element UI这套组合在中文社区沉淀了大量现成组件和示例代码表格、表单、弹窗、分页、权限按钮基本全是拿来即用。而且Vue的响应式数据绑定对于做管理后台这类数据展示型页面来说开发效率远高于手写原生DOM操作。还有一个实际考量后端Java、前端Vue两者语法不同、职责清晰正好能在答辩时讲出前后端分离架构这个亮点。如果选择JSP Servlet那套老方案技术过于老旧答辩时很难讲出彩如果选Python Django又没法突出你Java课程的学习成果。所以SpringBoot Vue是多数计算机专业学生的最优解MySQL做存储则是免费、轻量、好迁移的稳妥选择压根不需要上Oracle或SQL Server。1.3 这套系统最终交付的功能清单长什么样一个完整的密接者跟踪管理平台功能上至少要覆盖这些模块用户管理管理员、网格员录入人员、普通查询用户等角色不同人看到的菜单和操作权限不同。密接人员登记新增、编辑、查询、删除密接人员信息支持姓名、身份证、手机号、密接地点等条件组合查询。健康监测管理录入每天的体温、核酸结果、症状等形成个人健康档案。隔离信息管理给密接人员分配隔离地点、记录隔离开始和结束时间、更新隔离状态。轨迹管理记录密接人员的活动地点和轨迹时间线用于排查二次传播风险。数据统计首页用图表柱状图直观展示密接人员新增趋势、状态分布、隔离点入住情况。公告通知后台发布管理通知前端首页展示。系统管理菜单权限、操作日志、数据字典等底座功能。这些模块并不算复杂但都围绕着密接人员全生命周期管理这条主线串起来。理解了这条主线再看代码就会顺畅很多。2. 数据模型是一切的基础密接者跟踪系统的表设计思路骨架搭稳了才谈得上装修。关系型数据库里表结构设计决定了整个系统能做什么、不能做什么。我见过太多项目代码写到一半发现字段不够用、表之间关联不起来最后只能推倒重来。下面这块内容是整个项目的地基需要花时间看仔细。2.1 核心实体与关系梳理十张表撑起一个系统这套项目的数据模型不复杂核心实体可以归纳为以下几个用户表sys_user系统的登录账号关联角色。角色表sys_role与用户角色关系表sys_user_role实现多角色权限控制。密接人员表contact_person整个系统的中心表存的是密接者的基本信息。健康监测表health_record与密接人员是一对多关系一个人每天可以有多条记录。隔离信息表isolation_info与密接人员一对一或一对多因为一个人可能被多次隔离。轨迹表contact_trace记录密接人员的活动轨迹。密接关联表close_contact_rel记录该人员与确诊病例/疑似病例的关联关系以及密接批次。公告表sys_notice站内通知。日志表sys_log操作日志。实体之间的关系其实就两大核心链路一条是人→健康记录→隔离信息→轨迹的状态链路另一条是人→密接关联批次→同批次其他人的传播链路。前者解决这个人现在身体状况如何、隔离到什么时候后者解决这个人是怎么被关联进来的、和他同批次的人还有哪些。2.2 核心建表SQL解读字段类型和约束不是你随便写写就行的很多同学建表全凭感觉id一律int时间一律varchar身份证号也用int存结果数据一大或者条件一复杂就翻车。我们现在以三张核心表为例看一下这套系统里字段应该怎么设计。用户表CREATE TABLE sys_user ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 主键, username VARCHAR(50) NOT NULL UNIQUE COMMENT 登录账号, password VARCHAR(100) NOT NULL COMMENT 密码MD5加密存储, real_name VARCHAR(50) COMMENT 真实姓名, phone VARCHAR(20) COMMENT 手机号, role_id BIGINT COMMENT 角色ID, status TINYINT DEFAULT 1 COMMENT 状态1启用 0禁用, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT系统用户表;这里有个细节值得注意密码字段用了varchar(100)而不是varchar(32)。因为你在实际项目中几乎不可能用明文存储密码MD5加密后是32位但如果后续升级成加盐MD5或者BCrypt哈希字符串长度会变长提前留足空间能省掉数据库变更的麻烦。另外id用BIGINT而不是INT也是考虑到数据量增长和MaxInt溢出问题。密接人员表是整个系统的核心字段设计务必一次到位CREATE TABLE contact_person ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 主键, batch_no VARCHAR(30) COMMENT 密接批次编号同时段同场所密接归为一批, name VARCHAR(50) COMMENT 姓名, id_card VARCHAR(18) COMMENT 身份证号用定长字符串, gender TINYINT COMMENT 性别1男 2女, age INT COMMENT 年龄, phone VARCHAR(20) COMMENT 联系电话, address VARCHAR(200) COMMENT 现居住地址, contact_type TINYINT COMMENT 密接类型1密接 2次密接, contact_time DATETIME COMMENT 密接发生时间, contact_location VARCHAR(200) COMMENT 密接地点/场景, linked_case_no VARCHAR(50) COMMENT 关联病例编号, status TINYINT DEFAULT 0 COMMENT 管理状态0观察中 1已解除 2已确诊, isolation_location VARCHAR(200) COMMENT 隔离地点, isolation_start DATETIME COMMENT 隔离开始时间, isolation_end DATETIME COMMENT 隔离结束时间, remark VARCHAR(500) COMMENT 备注, create_by VARCHAR(50) COMMENT 登记人, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 登记时间, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT密接人员表;身份证号用varchar(18)而不是整型这是一条必须记住的准则。一是身份证号是18位纯数字都超出int范围了二是身份证号末尾可能有X三是它本质上是个标识符不是用来做数值运算的压根不应该用数值类型。健康监测表CREATE TABLE health_record ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 主键, contact_id BIGINT NOT NULL COMMENT 关联密接人员ID, record_date DATE NOT NULL COMMENT 记录日期, temperature DECIMAL(4,1) COMMENT 体温保留一位小数范围0.0~99.9, nucleic_acid_result TINYINT COMMENT 核酸结果1阴性 2阳性 3待检测, symptom VARCHAR(200) COMMENT 症状描述咳嗽/乏力/发热等, record_by VARCHAR(50) COMMENT 记录人, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT健康监测记录表;体温字段用DECIMAL(4,1)而不是float/double这个选择有讲究。浮点类型存在精度问题用来存金额、体温这类需要精确比较的数据很容易踩坑DECIMAL是定点数底层按字符串存储参与计算不会丢失精度。DECIMAL(4,1)表示总位数4位、小数1位最大能存999.9存体温完全够用。2.3 设计表结构时最容易犯的错误我替你们踩过第一是缺少批次维度。最初的版本里密接人员表就是一个孤立的名单没有batch_no字段导致后来想做同车次人员集中展示时发现无从查起。后来加了batch_no字段再把同批次人员用同样代码串起来这个功能才落地。所以做这类系统一定要提前想清楚数据之间的聚类属性。第二是时间字段用varchar存。有人喜欢把时间转成字符串直接塞进数据库想着反正页面展示就是字符串。真到了要按日期范围查询、按月份统计的时候varchar的比较逻辑会让SQL写到怀疑人生。DATETIME字段加上索引查询效率和准确性完全不是一个量级。第三是外键约束滥用。很多人为了表现自己懂数据库到处加FOREIGN KEY结果删除密接人员的时候各种关联表启用了外键约束导致删除失败。这套系统的健康记录、隔离信息、轨迹表都关联了contact_id但如果业务上允许删除人员同时清除其关联数据那就应该在代码里手动处理子表数据而不是交给数据库外键去管。外键会让关联操作变得很刚性实际互联网项目里外键用得越来越少逻辑外键仅保留关联ID不建物理约束反而是主流做法。3. 后端实现从登录鉴权到密接关系链的完整落地逻辑表设计好了接下来就是后端代码。SpringBoot项目的代码结构无非就是那么几层但每层职责必须清晰。很多人写着写着把SQL拼在Controller里后面想改个查询条件累到不行。这里我会把这套系统的后端实现脉络捋一遍。3.1 项目分层controller、service、mapper各自该干什么一个标准的SpringBoot工程按功能分包通常长这样com.example.tracing ├── config # 配置类CORS、拦截器、WebMvcConfig ├── controller # 接口层接收参数、调用service、返回结果 ├── service # 业务层业务逻辑处理、事务控制 ├── mapper # 数据访问层MyBatis的Mapper接口 ├── entity # 实体类与数据表一一对应 ├── dto # 数据传输对象接收前端参数、返回给前端的VO ├── common # 公共类统一返回结果、异常处理、常量 ├── utils # 工具类JWT工具、日期工具 └── interceptor # 拦截器登录校验、日志记录Controller层要做的只有三件事接收参数、校验参数合法性、调用Service后把结果包装成统一格式返回。业务逻辑应该全部下沉到Service层。Service层是开发中花时间最多的地方。比如登记一个密接人员这个接口不能只是往contact_person表insert一条记录就完事它要完成的事情包括校验身份证号格式、生成或匹配密接批次号、插入健康监测初始记录、写入操作日志。这一串动作就是一个事务任何一步失败都应该整体回滚。Mapper层就纯粹是数据库操作MyBatis的XML文件里写SQL或注解SQL。不要在这里面写业务判断不然分层的意义就没了。3.2 统一返回结果与全局异常处理前后端分离项目的一个重要约定是接口返回格式固定。前端拿到响应先看code再取data这样写统一的响应拦截器才顺手。Data public class ResultT { private Integer code; // 200成功500失败401未登录 private String message; // 提示信息 private T data; // 业务数据 public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(操作成功); result.setData(data); return result; } public static T ResultT error(String message) { ResultT result new Result(); result.setCode(500); result.setMessage(message); return result; } public static T ResultT unauthorized() { ResultT result new Result(); result.setCode(401); result.setMessage(未登录或登录已过期); return result; } }再配合一个全局异常处理器RestControllerAdvice把业务异常和系统异常统一拦截前端永远能拿到结构一致的错误信息而不是看到一坨堆栈。这一步做得好联调时能省不少口水仗。3.3 JWT登录鉴权这套系统的权限控制是怎么串起来的毕设项目用Session还是JWT我的观点是哪怕你最终用了Session也要把JWT的思路讲明白因为答辩老师大概率会问。这套系统采用的是JWT方案核心流程是这样的用户提交用户名密码到/login接口后端校验成功后生成一个有效期为24小时的token里面封装了userId、username和roleId返回给前端。前端存到localStorage里后续每次请求都在请求头带上token: xxx。后端自定义了一个拦截器在请求进入Controller之前拦截所有非登录接口解析token、校验有效期如果token异常就返回401让前端跳回登录页。工具类核心代码如下public class JwtUtil { // 密钥实际项目中应放到配置文件并定期更换 private static final String SECRET your-secret-key-change-me; private static final long EXPIRE_TIME 24 * 60 * 60 * 1000; // 24小时 public static String createToken(Long userId, String username, Long roleId) { return Jwts.builder() .claim(userId, userId) .claim(username, username) .claim(roleId, roleId) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() EXPIRE_TIME)) .signWith(SignatureAlgorithm.HS256, SECRET) .compact(); } public static Claims parseToken(String token) { return Jwts.parser() .setSigningKey(SECRET) .parseClaimsJws(token) .getBody(); } }拦截器里的逻辑也很直接从请求头拿token解析失败就返回401成功后把userId存到request的attribute里后续的Service层就能拿到当前操作人是谁。密码加密这块我不建议明文存储最简单的做法是用MD5加盐。Spring自带的DigestUtils.md5DigestAsHex可以把密码和盐值拼起来加密例如digest(密码123456 salt)。虽然MD5现在不算安全等级最高的算法但用于毕设项目加上对比其他加密方式的思考反而能成为答辩加分项。3.4 密接人员登记与批次管理核心业务代码的完整思路新增密接人员是这套系统里最大的一个事务接口。它背后不止一次插入操作Transactional(rollbackFor Exception.class) public Long addContactPerson(ContactPersonDTO dto) { // 1. 入参校验身份证号正则校验 if (!IdCardUtil.isValid(dto.getIdCard())) { throw new BizException(身份证号格式不正确); } // 2. 生成批次号如果相同密接地点和时间段已经有了批次则沿用否则新建 String batchNo contactPersonMapper.findBatchNoByLocationAndTime( dto.getContactLocation(), dto.getContactTime()); if (batchNo null) { batchNo P DateUtil.format(new Date(), yyyyMMddHHmmss) RandomUtil.randomNumbers(4); } // 3. 插入密接人员主记录 ContactPerson person new ContactPerson(); BeanUtils.copyProperties(dto, person); person.setBatchNo(batchNo); person.setStatus(0); // 默认观察中 contactPersonMapper.insert(person); // 4. 初始化一条健康监测记录 HealthRecord record new HealthRecord(); record.setContactId(person.getId()); record.setRecordDate(new Date()); record.setTemperature(dto.getTemperature()); record.setNucleicAcidResult(dto.getNucleicAcidResult()); healthRecordMapper.insert(record); // 5. 写入操作日志 sysLogService.log(新增密接人员, person.getName(), batch batchNo); return person.getId(); }这一步是代码里最容易和面试官聊起来的地方。你可以延伸讲为什么用事务因为主记录插入成功但健康记录插入失败会导致数据不一致一条密接人员没有初始健康记录后续状态判断就会出问题。Transactional加在service方法上Spring就能保证这些操作要么全部成功要么全部回滚。3.5 健康状态流转从观察中到已解除的判断逻辑密接人员的状态不是靠人工去改的而是跟着业务操作自动流转。这套系统的核心规则是这样的登记时状态默认为0观察中。每次录入健康记录时如果核酸结果为阳性状态直接变为2已确诊并在隔离信息表中更新结束时间。隔离到期且最近连续两次核酸结果为阴性状态变为1已解除。管理员也可以在页面上手动解除隔离但需要填写解除原因。这里有一个值得注意的设计状态字段虽然冗余存储了但它的更新都是在Service层通过明确的方法触发的而不是谁都能随手update一下。这样后续想加操作审计就有据可查。4. 前端页面Vue Element UI 下最省力的实现方式后端接口出来了前端就是把这些接口的数据填到页面上。Vue做的管理后台套路感强、可复制性高只要掌握了目录结构和几个核心模式开发速度会非常快。4.1 页面原型与组件拆分这套系统的前端页面大概包含以下路由页面路由路径功能说明登录页/login账号密码登录存储token控制台/dashboard统计卡片加趋势图密接人员管理/contact/list列表、新增、编辑、删除、详情健康监测/contact/health/:id查看某人的健康记录新增记录隔离信息管理/isolation/list隔离点与隔离状态概览轨迹管理/trace/list密接者的行程轨迹时间线公告管理/notice/list公告的增删改查系统管理/system/user用户管理、角色管理、日志查询组件拆分的思路是按页面拆每个页面一个文件夹页面内公共的部分再抽成组件。比如详情弹窗、人员表单、健康记录表格在密接人员管理模块里都是可以独立复用的组件。Vue目录结构src ├── api # 接口请求定义按模块拆分 │ ├── login.js │ ├── contact.js │ └── ... ├── assets # 静态资源 ├── components # 公共组件 ├── router # 路由配置 ├── store # 状态管理 ├── utils # 公共工具request.js封装、日期格式化 └── views # 页面视图4.2 axios 封装与路由守卫这一步决定了联调是否痛苦axios如果直接用每个页面都要重复写baseURL、设置请求头、处理错误提示代码会非常啰嗦。所以工程里通常会统一封装一个request实例// utils/request.js import axios from axios import { Message } from element-ui import router from /router const request axios.create({ baseURL: /api, timeout: 10000 }) // 请求拦截器自动携带token request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[token] token } return config }) // 响应拦截器统一处理code request.interceptors.response.use( response { const res response.data if (res.code 200) { return res.data } else if (res.code 401) { localStorage.removeItem(token) router.push(/login) return Promise.reject(new Error(登录已过期)) } else { Message.error(res.message || 操作失败) return Promise.reject(new Error(res.message)) } }, error { Message.error(网络请求异常) return Promise.reject(error) } ) export default request路由守卫则负责前端访问拦截// router/index.js router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.path /login) { next() } else if (!token) { next(/login) } else { next() } })这两段代码加起来不到40行却能让整个前端的接口调用变得异常清爽。页面里调接口只需要import request from /utils/request export function getContactPage(params) { return request.get(/contact/page, { params }) } export function addContact(data) { return request.post(/contact/add, data) }4.3 密接人员管理页最典型的一个表格弹窗实现密接人员列表页是这套系统的门面。它的结构是顶部筛选区姓名、状态、批次号、密接地点、中间操作按钮新增、导出、核心表格区、底部翻页器。Element UI的el-table和el-pagination搭配使用代码结构大概是el-table :datatableData border stripe v-loadingloading el-table-column propbatchNo label批次编号 width170 / el-table-column propname label姓名 width120 / el-table-column propidCard label身份证号 width180 / el-table-column propcontactLocation label密接地点 / el-table-column label当前状态 width100 template slot-scopescope el-tag :typestatusTagType(scope.row.status) {{ statusText(scope.row.status) }} /el-tag /template /el-table-column el-table-column label操作 width280 fixedright template slot-scopescope el-button sizemini clickshowDetail(scope.row)详情/el-button el-button sizemini typewarning clickshowHealth(scope.row)健康记录/el-button el-button sizemini typedanger clickhandleDelete(scope.row)删除/el-button /template /el-table-column /el-table状态字段用el-tag展示可以一眼看出当前人员处于什么阶段观察中黄色、已解除绿色、已确诊红色。这个交互虽然简单却在答辩演示时非常加分因为评审老师不用点进详情就能看到业务状态的直观呈现。新增和编辑是一个抽屉(drawer)或弹窗(dialog)里面的表单组件用el-form配合rules做校验。身份证号18位、手机号11位、体温范围36.0-42.0这些规则都可以在rules里声明。这里有个小技巧体温输入框可以用el-input-number限制精度为1位小数从源头杜绝用户填出36.55这种不合法数据。4.4 统计图表让首页在答辩时一眼抓住眼球首页控制台的统计图我用的是ECharts。Vue 2项目里直接安装echarts依赖在mounted钩子里初始化图表实例即可。柱状图展示近7天新增密接人员数量饼图展示当前密接人员状态分布折线图展示每日体温异常人数趋势。ECharts的option配置并不复杂真正要处理的是数据格式后端统计接口返回的通常是[{date: 2024-05-01, count: 3}]这种结构前端要用JavaScript的map方法把它拆成xAxis的data和series的data两个数组再塞给ECharts。答辩时老师最可能问你的图表数据是实时从数据库查的还是写死的你如果说写死的印象分会大打折扣。所以这个页面的数据源一定得是在mounted里调用后端统计接口动态获取的哪怕数据少也要把链路打通。5. 本地跑通项目的完整过程与踩坑记录说句实在话拿到别人写的项目源码最折磨人的往往不是读代码而是把环境跑起来。前前后后帮同学调试过几十次环境问题我把最容易出问题的地方集中讲一讲。5.1 环境准备与版本选择这套技术栈对应的推荐环境如下软件推荐版本备注JDK1.88u202以上不要用JDK 17跑SpringBoot 2.x老项目会有兼容性问题Maven3.6.3镜像建议配置阿里云镜像MySQL5.7或8.0两者都可注意驱动版本不同Node.js14.x或16.x高版本Node跑Vue 2 webpack老项目容易报openssl错误前端包管理npm或yarn推荐用yarn安装速度更快JDK版本坑我遇到过太多次。很多同学的机器上装的是JDK 17甚至21直接跑SpringBoot 2.3以下的老项目启动就会报UnsupportedClassVersionError或CGLIB相关错误。网上教程让你把SpringBoot升到2.7结果MyBatis等依赖又出现新兼容问题越改越乱。最稳妥的方案就是JDK 1.8跑到底。5.2 从零导入到页面出现完整步骤第一步初始化数据库。用Navicat或命令行执行项目中的.sql文件执行完确认表是否生成、是否插入了默认管理员账号。第二步修改后端配置。打开src/main/resources/application.yml把数据源地址、账号、密码改成自己的端口默认8080不动也行。第三步启动后端。在项目根目录执行mvn spring-boot:run或者用IDEA打开项目后直接运行主类。看到Started Application in xxx seconds说明启动成功。第四步启动前端。进入前端目录先npm install安装依赖再npm run dev启动开发服务。默认端口通常是8081或8082浏览器打开后就能看到登录页。第五步联调配置。前端项目中vue.config.js里通常会配置一个devServer的proxy把/api开头的请求代理到后端8080端口。如果页面能打开但接口报404大概率是这里的proxy配置或后端上下文路径对不上。5.3 最容易翻车的5个问题与解决方案第一个是数据库连接时报Public Key Retrieval is not allowed。这个报错常见于MySQL 8.0解决方式是在连接串后面加allowPublicKeyRetrievaltrueuseSSLfalse。第二个是前端npm install卡死或报ERR! ERESOLVE。npm 7以上的依赖解析策略变严格了很多Vue 2老项目会冲突。解决方式简单粗暴删掉node_modules和package-lock.json换成yarn install一次过的概率要大很多。第三个是后端启动时端口被占用。8080被其他的服务占了报Port already in use。解决方式是看哪个进程占用的或者直接改application.yml里的server.port换个端口前端proxy要跟着改。第四个是前端页面能打开但所有接口都超时。排查思路先用浏览器F12看Network面板请求URL到底打到哪个地址去了。如果打到了前端开发服务器的端口而不是后端8080说明proxy没生效检查vue.config.js的配置格式和devServer是否重启过。第五个是时间字段差8小时。这是因为MySQL serverTimezone没有配置成Asia/Shanghai连接串里加serverTimezoneAsia/Shanghai同时在SpringBoot中配置Jackson的时区。不解决这个问题前端页面上看到的登记时间永远比实际慢8小时。5.4 修改成本项目的技巧换皮与加功能很多同学拿了源码想把它改成自己的作品最省钱省力的方式是换皮而不是重写。换皮包含三层数据库里的初始数据换成自己编造的示例数据姓名、地点、病例编号都换掉前端页面标题、系统名称、Logo、登录页背景换成自己的后端项目名、包名、controller里的注释文案做一遍整体替换。这三步做完项目外观就完全是你的了。加功能是更高级的改法。推荐从导入导出批量标记解除这两个方向入手。比如用EasyExcel插件给密接人员列表加一个Excel导出功能后端写一个导出接口前端加一个按钮整个链路不算复杂但很显工作量答辩时讲起来也容易。6. 答辩前瞻老师最常问的几个技术问题项目做完不是终点能讲清楚才是真正的收获。答辩时间通常只有5-10分钟老师的问题往往集中在几个固定方向上。提前把这些问题想明白比临场发挥要靠谱得多。6.1 为什么选这套技术栈回答思路不能只说因为网上教程多。更好的回答是分两层讲一层是个人能力匹配——Java是专业主修课程SpringBoot是目前企业主流的后端框架Vue是当前前后端分离开发中占有率最高的前端框架用主修语言做项目能体现课程成果另一层是业务匹配——密接者跟踪系统的核心是数据处理和状态流转SpringBoot MyBatis MySQL这套组合在结构化数据处理上非常成熟Vue则适合快速搭建管理后台。6.2 登录状态是怎么保持的和Session有什么区别这道题是Java Web方向的高频问题。结合这套系统你只需要把JWT的完整流程讲清楚登录成功后后端签发token前端存浏览器请求时放在请求头后端拦截器校验。核心区别在于Session是服务器端内存保存状态JWT是无状态的服务器不需要存session天然适合前后端分离和水平扩展。6.3 密接人员的数据之间是怎么关联的回答时要落到具体表和具体字段上健康记录表通过contact_id外键关联contact_person隔离信息表通过contact_id关联轨迹表也是通过contact_id关联。而同一个批次的人员则通过batch_no字段相连。这里强调一个一对多和多对一的设计思想再举一个具体查询例子比如查出某一病例的所有密接者这条SQL怎么写。6.4 如果数据量变大了这套系统哪里会先扛不住怎么优化这是个很好的加分题说明你有思考过系统的边界。候选回答思路包括contact_person表的查询字段如name、id_card、status加索引目前分页用的是LIMIT在数据量超过百万之后可以用游标分页替代数据库连接池参数调整高频统计查询加Redis缓存最终读写分离加MyBatis多数据源。不建议把答案说得太散挑两三个点展开即可。面试官或老师想听到的是你有从单机到分布式演进的认知框架不是让你真把集群搭起来。6.5 项目里碰到过的最大的坑是什么被问到这个问题时千万不要说没遇到过什么问题显得项目太假。讲一个真实的、可复现的坑反而加分。比如可以讲排查时间字段差8小时的过程数据库时区、JDBC驱动的serverTimezone参数、Jackson序列化时区三层配置都要对齐只改一处根本没效果。这种小故事能让老师觉得项目确实是你一步步调出来的。我自己在做类似项目时最大的感受是这类管理系统的代码量并不大真正的门槛在于把人与人、人跟状态、状态跟时间之间的关系理清楚。如果你正准备拿这套源码做毕设花一个晚上把表结构和核心Service层的代码过一遍远比直接跑到页面点几下要有用得多。答辩那天老师问的每一个问题其实都藏在这些你看过的代码里。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。