尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

SpringBoot+Vue爱心公益平台毕设全解析:数据库设计到答辩技巧

SpringBoot+Vue爱心公益平台毕设全解析:数据库设计到答辩技巧 先说句实在话。每年毕设季群里问得最多的就是有没有SpringBootVue的源码、公益类网站好不好做。今天就拿这个SpringBootVue 绿城郑州爱心公益网站管理平台当例子从业务设计到前后端实现再到答辩准备把整个项目掰开揉碎讲一遍。标题里带绿城郑州说明这是一个带有地域色彩的公益平台——这类网站非常适合做毕设业务真实、规模适中、技术栈主流而且演示时故事线特别容易讲清楚。无论你手里已经拿到了这套源码准备二次开发还是打算从零自己搭一个同款这篇内容都能帮你少走很多弯路。1. 为什么这个选题能打公益平台的业务边界与技术选型逻辑1.1 这个平台到底做什么答辩时怎么讲清楚业务很多同学拿到项目第一件事就是急着跑代码结果内存一报错就慌了。其实不管你跑不跑得起来先把业务的逻辑链条捋顺才是最重要的因为答辩老师第一个问题往往就是你这个系统是干嘛的有哪些角色爱心公益网站管理平台核心是一个典型的信息发布业务管理双端系统前台门户面向普通访客/注册用户展示公益活动、查看公益资讯、了解爱心捐赠情况、注册登录、在线报名活动、查看个人报名记录。后台管理面向管理员维护活动的发布与上下架、审核报名申请、管理新闻资讯、管理用户账号、查看捐赠数据、操控首页轮播图。一句话给答辩老师讲清楚这是一个连接公益组织和热心市民的信息化管理平台用技术手段让公益活动从发布、报名、执行到数据汇总的全流程都留痕、可管、可查。为什么说这个业务边界选得好因为它的核心业务只有三个闭环活动报名闭环、资讯发布闭环、捐赠记录闭环。每个闭环都不复杂但都有状态流转、有权限控制、有列表分页正好覆盖了毕设评分标准里需要的所有功能点又不会像电商系统那样因为订单流程、支付回调、库存并发而做到一半想哭。1.2 SpringBootVueMySQL这套组合为什么放在今天依然能打技术栈这种东西不见得越新越好关键看是否主流、是否好解释、是否资料够多。SpringBoot是当前Java后端开发的绝对主力框架面试问、工作用、教程遍地是。选它意味着你随便搜一个问题都能找到答案这对毕设周期里的你来说是隐形的救命稻草。Vue同样如此前后端分离是现在企业开发的标准姿势用Vue做管理后台和门户页面组件化开发效率高而且Vue Router、Vuex/Pinia、Axios生态成熟不需要你造轮子。MySQL更不用多说开源、免费、几乎所有高校都教过SQL基础答辩时老师想刁难你都很难找到切入点。这三个组合起来还有一个极大的隐蔽优势部署成本低、演示环境要求低。你的笔记本只要能跑起来IDEA和VSCode整个项目就不会有跑不动的问题。相比一些需要Redis、RabbitMQ、ElasticSearch等高阶中间件的项目SpringBootVueMySQL这套纯基础组合在演示时几乎不会出现环境崩了的意外。1.3 拿到源码后先看懂这三层结构再动手改假设你现在手里已经有一套这样的源码我的建议是压缩包先别急着解压运行而是按下面这个顺序去读结构后端SpringBoot工程找src/main/java下的包结构。正常的项目会分成controller控制层、service业务层、mapper数据访问层、entity/pojo实体类、config配置类、common/util公共类与工具类。看明白一个请求从Controller进来之后是怎么一步步走到数据库的。前端Vue工程找src/views页面、src/api后端接口封装、src/router路由配置、src/store全局状态、src/utilsaxios封装等。理解页面是怎么通过API调后端、拿到数据再绑定的。数据库找.sql后缀的脚本文件用Navicat或MySQL命令行导入之后把每张表的注释过一遍这个步骤直接决定了你能不能回答出关于表结构的问题。我见过很多同学源码下载了一堆最后问一句你这个项目用了哪些表都答不上来。先结构后代码先数据后逻辑这才是用源码做毕设的正确姿势。2. 数据库设计公益项目的表结构就是你的答辩底气2.1 用户、角色、权限三张表用RBAC模型还是简化版公益网站的角色通常不会太多一般就是普通用户和管理员两种。很多毕设级别的项目用的是简化版RBAC基于角色的权限访问控制用户表sys_user里放一个role字段用0和1区分管理员和普通用户。但如果你想在答辩时展示更完整的工程设计能力建议做成标准三件套sys_user用户表主键ID、用户名、密码BCrypt加密后的密文、昵称、手机号、头像URL、角色ID、状态启用/禁用、创建时间。sys_role角色表角色ID、角色名称、角色标识符如ROLE_ADMIN。sys_user_role用户角色关联表用户ID、角色ID。为什么推荐带关联表因为评委问如果以后要加一个志愿者队长角色你怎么改时你只需要答在角色表加一条记录给用户绑定新角色然后再在代码里根据角色标识符控制权限——这个答案说完老师基本就满意了。如果你的设计里写死了role字段这个问题你就得现场改代码心态直接崩。登录密码的存储也是一个高频提问点。如果你源码里用的是MD5建议改成BCryptPasswordEncoder这是Spring Security里自带的安全加密器同一个密码每次加密生成的密文都不一样能防彩虹表攻击。你不需要把Spring Security整套引进来只需要在项目里注入这个加密器对象改一下注册和登录的校验逻辑就行。这一步改动很小但写在论文安全设计那一节非常加分。2.2 公益活动的生命周期从发布到报名到执行活动表activity是整个系统的核心枢纽字段设计直接反映了你对业务的理解深度。一张合格的活动表至少包含以下内容字段名类型含义idbigint主键titlevarchar活动名称cover_imagevarchar封面图URLcontenttext活动详情富文本或纯文本locationvarchar活动地点start_timedatetime开始时间end_timedatetime结束时间signup_startdatetime报名开始时间signup_enddatetime报名截止时间max_peopleint人数上限signup_countint当前已报名人数statustinyint状态0草稿、1报名中、2进行中、3已结束create_timedatetime创建时间update_timedatetime更新时间deletedtinyint逻辑删除标记这里有个特别容易被忽略的细节状态字段不要直接在前端写死而是由后端根据当前时间和报名时间自动计算。比如你可以用一个定时任务每分钟扫描一次把到了start_time的活动改成进行中把过了end_time的改成已结束。如果不想引入定时任务也可以在查询接口里动态计算status now() end_time ? 3 : (now() start_time ? 2 : 1)。报名表activity_signup要记录报名ID、活动ID、用户ID、报名时间、状态待审核/已通过/已取消、签到状态未签到/已签到、签到时间。这张表同时关联用户和活动属于典型的多对多关联表如果你后面还要做我的志愿服务时长功能可以在这张表上加一个hours字段活动结束后由管理员统一录入。2.3 捐赠板块的数据闭环不只是记录一笔钱很多同学的公益网站一到捐赠模块就只做一张donation表捐赠人、金额、时间、留言。功能倒是能跑但答辩时显得单薄。我建议你把捐赠扩展成两条线第一条线是捐赠项目donation_project比如关爱留守儿童助学计划、社区长者食堂补贴。每个项目有名称、简介、目标金额、已筹集金额、封面图、发起时间、结束时间。用户点进去看详情选择捐给哪个项目、捐多少钱、留不留真实姓名和寄语。第二条线是捐赠流水donation_record关联用户ID、项目ID、捐赠金额、是否匿名、留言内容、支付方式线下转账/线上模拟、支付状态待确认/已完成、支付凭证截图。管理员在后台看到每一笔待确认的流水核实凭证后点击确认到账已筹集金额自动累加。这个设计的精妙之处在于捐赠不再是一个孤立的新增操作而是一个有状态流转的业务。你在论文里可以写设计了项目维度的资金募集聚合和流水维度的明细追溯实现捐赠数据的可审计、可追溯——这句话一出来评委就知道你不是只学了CRUD。2.4 几个容易忽略的字段设计细节数据库表设计的时候有几个不起眼的细节特别能体现工程素养统一使用逻辑删除所有业务表都加deleted字段删除操作一律走UPDATE ... SET deleted 1。这样用户误删活动后管理员还能在回收站里恢复不至于数据一删就没了。MyBatis-Plus里直接TableLogic注解就能实现成本极低。时间字段统一用datetime不要用timestampdatetime范围更大不受2038年问题影响而且MySQL 8.0以后datetime支持毫秒精度够用且省心。create_time和update_time要么在Java代码里统一填充要么在数据库里设置DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP千万别在每个Service实现里手动new Date()重复代码多了容易忘漏一个字段就埋个雷。金额字段用decimal(10,2)不要用float/double这个几乎是必考题。float和double是浮点数存金额会有精度误差比如99.9 0.1可能等于100.000000001。decimal是精确小数类型做账务数据必须用它。3. 后端SpringBoot核心模块实现从登录鉴权到业务闭环3.1 基于JWT拦截器实现登录状态管理公益网站的前台和后台都需要登录才能操作最通用的做法是JWTJSON Web Token。JWT的核心思路是用户登录成功后服务器生成一个包含用户ID、用户名、角色、过期时间的加密字符串Token返回给前端前端存在localStorage里之后每次请求都在请求头里带上Authorization: Bearer token。后端拦截器解析Token解析成功就放行解析失败就返回401。后端实现分三步第一步登录接口。Controller接收用户名和密码调用Service校验。校验通过后用io.jsonwebtoken.Jjwt或hutool工具的JWTUtil生成Token返回给前端。不通过就抛异常由全局异常处理器统一返回用户名或密码错误。// 生成Token示例代码 String token Jwts.builder() .setSubject(String.valueOf(user.getId())) .claim(username, user.getUsername()) .claim(role, user.getRole()) .setExpiration(new Date(System.currentTimeMillis() 7 * 24 * 3600 * 1000)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact();第二步写拦截器。继承HandlerInterceptorAdapter或实现HandlerInterceptor在preHandle里从请求头取Token解析失败直接返回JSON格式的401响应不放行解析成功就把用户信息放进request的Attribute里方便Controller里取。第三步配置拦截器注册。在WebMvcConfigurer里用addInterceptors方法注册拦截器并用addPathPatterns和excludePathPatterns指定拦截范围。一般要放行的路径有/api/login、/api/register、前台的门户查询接口、静态资源路径等需要拦截的路径有后台管理接口、报名接口、个人中心接口。第三步里的excludePathPatterns特别容易配漏漏一个就会导致前端页面数据全部加载失败。排查的时候先看后台请求有没有报401报401就看拦截器放行路径是不是写少了。这个经验值两小时。3.2 公益活动的CRUD与报名状态流转活动管理是后台最核心的模块本质上就是一张表的增删改查但有几个点值得重点写发布活动管理员填写表单上传封面图后台保存到activity表状态默认是0草稿。需要点击发布按钮才把状态改成1报名中——这样设计是为了防止管理员填了一半误发布同时也可以给你论文多加一条草稿与发布分离的业务规则。活动列表后台列表一般需要分页条件查询条件包括标题模糊搜索、状态筛选、时间范围筛选。用MyBatis-Plus的话直接构造LambdaQueryWrapper就能搞定LambdaQueryWrapperActivity wrapper new LambdaQueryWrapper(); wrapper.like(StringUtils.hasText(title), Activity::getTitle, title) .eq(status ! null, Activity::getStatus, status) .ge(startTime ! null, Activity::getStartTime, startTime) .le(endTime ! null, Activity::getEndTime, endTime) .orderByDesc(Activity::getCreateTime); PageActivity page activityMapper.selectPage(new Page(pageNum, pageSize), wrapper);这个写法里like、ge、le的前面一个参数是布尔值只有条件成立才拼接SQL完美避免了你传空字符串我也给你like一把的问题。这段代码贴到论文里比贴十页截图都有说服力。报名活动这是前台用户的核心操作。逻辑逻辑上是往activity_signup表插一条记录但要注意三个前置校验该活动状态是否为报名中当前时间是否在报名起止时间范围内当前报名人数是否已满。这三个校验缺一个都会出问题。你还应该做一个同一用户不可重复报名的校验最稳妥的做法是在activity_signup表上给(activity_id, user_id)建唯一索引数据库层面兜底。3.3 文件上传与图片回显本地存储的省心方案活动封面图、用户头像、捐赠凭证都需要上传功能。毕设项目我推荐最简单的本地存储方案前端用el-upload组件把文件以FormData格式POST到后端的/api/upload接口后端用MultipartFile接收把它保存到服务器的一个磁盘目录比如D:/upload/或者项目的/static/upload/下然后把http://localhost:8080/upload/xxx.jpg这样的URL返回给前端。PostMapping(/upload) public ResultString upload(RequestParam(file) MultipartFile file) { String originalFilename file.getOriginalFilename(); String ext originalFilename.substring(originalFilename.lastIndexOf(.)); String filename UUID.randomUUID().toString().replace(-, ) ext; File target new File(uploadDir, filename); file.transferTo(target); return Result.success(http://localhost:8080/upload/ filename); }注意两个点文件名一定要用UUID重命名。用户传一个2024暑假公益活动.jpg如果直接存原名遇到重名会覆盖遇到中文名可能乱码遇到特殊字符还可能出安全问题。UUID原始后缀是最省心的方案。本地存储的目录不要写在代码里写死。放到application.yml里配置用Value注解注入。这样以后换服务器只需要改配置文件不用改代码。这个细节放在论文系统可维护性里说非常加分。如果前端访问图片发现404先看URL拼接的路径跟你实际的存放路径对不对得上再看你是不是忘了配置虚拟路径映射WebMvcConfigurer里的addResourceHandlers。3.4 统一返回结果与全局异常处理代码整洁度的分水岭你有没有见过这样的代码有的接口返回Map有的接口失败时直接返回null前端拿到数据百思不得其解。这种风格不叫快叫烂。正规的做法是定义一个ResultT统一返回体public class ResultT { private Integer code; // 200成功500失败401未登录 private String message; // 提示信息 private T data; // 返回数据 }所有Controller接口一律返回ResultT成功就Result.success(data)失败就抛出业务异常。再加一个RestControllerAdvice全局异常处理器捕获异常统一转成Result结构返回给前端。这样前端axios拦截器只需要判断code字段就能统一处理成功和失败。还有一个加分操作是自定义一个BusinessException在Service层遇到业务规则不满足时直接抛异常。比如上面说的活动人数已满就throw new BusinessException(该活动报名人数已满)全局异常处理器会帮你把这句话返回给前端。业务校验和错误提示彻底从Controller里剥离出来代码整洁程度直接提升一个档次。4. 前端Vue管理后台和门户页面的双端联动4.1 项目目录结构与路由设计Vue前端最常见的组织方式是vue-element-admin那套目录结构虽然企业开发中有人嫌它重但对于毕设来说这套结构是经过大量验证的抄起来不会出错src/api按后端接口模块拆分的请求文件比如activity.js里封装getActivityList、addActivity、deleteActivity等函数。src/views页面级组件按模块建目录比如views/admin/activity/ActivityList.vue、views/admin/activity/ActivityEdit.vue、views/front/Home.vue、views/front/ActivityDetail.vue。src/router路由配置文件。建议采用constantRoutes asyncRoutes的结构——登录页、首页等公共路由是constantRoutes后台管理页面的路由根据用户角色动态生成。src/store用PiniaVue3或VuexVue2保存用户登录信息、Token、用户角色等全局状态。刷新页面后要用localStorage里的数据重新初始化用户状态不然一刷新就退出登录。src/utils/request.js对axios进行二次封装统一设置baseURL、请求拦截器加Token、响应拦截器处理业务码。路由守卫是前端必须写的一环router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.path /login) { next() } else { if (!token) { next(/login) } else if (to.meta.role to.meta.role ! userStore.role) { next(/403) } else { next() } } })4.2 axios二次封装请求拦截器、响应拦截器前端和后端的交互全靠axios。如果不做二次封装每个页面都写一遍axios.get(url, { headers: { Authorization: localStorage.getItem(token) } })那不是人过的日子。const request axios.create({ baseURL: /api, timeout: 10000 }) // 请求拦截器自动加token 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) { return res.data } else if (res.code 401) { router.push(/login) return Promise.reject(new Error(未登录或登录已过期)) } else { ElMessage.error(res.message || 系统错误) return Promise.reject(new Error(res.message)) } }, error { ElMessage.error(error.message || 网络异常) return Promise.reject(error) } )这样封装之后页面里写接口就非常干净了比如在api/activity.js里export const getActivityList (params) request.get(/activity/page, { params }) export const addActivity (data) request.post(/activity, data) export const updateActivity (data) request.put(/activity, data)页面里只需要import { getActivityList } from /api/activity然后await getActivityList({ pageNum: 1, pageSize: 10 })就能拿到数据。这个api层统一管理接口的写法是前端工程化的基本功写在论文前端模块化设计一节里很亮眼。4.3 管理后台的表格弹窗表单这一套固定打法Vue做管理后台90%的页面都是一样的套路顶部是搜索条件栏中间是表格右下角是分页器点击新增/编辑弹出一个Dialog表单点击删除弹出确认框。看起来枯燥但胜在稳定、高效、容易复制。以活动管理页面为例搜索区标题输入框、状态下拉框、搜索/重置按钮绑定一个searchForm对象。表格区el-table绑定activityList数组列配置用el-table-column proptitle label活动名称这种写法状态列用el-tag根据status值显示不同颜色。分页区el-pagination绑定总条数和当前页current-change事件重新拉列表。弹窗表单el-dialog里嵌套el-form新增和编辑共用同一个表单组件区别只是打开时的初始化数据。el-upload组件用来上传封面图v-model绑定封面URL的隐藏字段图片预览用el-image。这套四件套打法的核心价值在于复用性。你做完一个活动管理页面后做资讯管理、项目管理和用户管理只需要复制粘贴然后改字段名和数据源。对自己开发的人来说能省下一大半时间。我见过太多同学用Vue做后台每做一个页面就从零开始写样式最后三个月只做出来两个页面——没必要真的没必要。4.4 ECharts统计图表让演示效果翻倍的秘密武器公益平台天然适合做数据可视化。门户首页放一个公益活动参与趋势图管理后台放一个各活动报名人数柱状图、一个捐赠项目进度占比饼图演示的时候评委眼睛一亮直接就把这个项目从普通CRUD拉高到了有数据价值的层次。ECharts用起来不复杂三步走第一步安装依赖npm install echarts。第二步在需要的组件里引入并初始化import * as echarts from echarts const chartDom document.getElementById(barChart) const myChart echarts.init(chartDom) myChart.setOption({ xAxis: { type: category, data: [无偿献血, 敬老院探访, 社区环保, 爱心助学] }, yAxis: { type: value }, series: [{ type: bar, data: [45, 62, 38, 27] }] })第三步在Vue的mounted或onMounted里调用初始化方法别忘了在页面销毁时myChart.dispose()释放资源。注意图表数据不应该硬编码应该从后端接口拉取。比如后端提供一个/api/stats/activityTop10接口返回报名人数最多的10个活动名称和人数前端根据返回数据动态setOption。这样的图表才叫系统功能不叫装饰图片。后端实现也简单一条SQLSELECT title, signup_count FROM activity ORDER BY signup_count DESC LIMIT 10然后封装返回给前端就行。5. 实战部署与排查从控制台报错到服务器上线5.1 本地跑通项目的完整流程拿到源码后本地跑起来看起来是个体力活但很多同学就是卡在这一步。我总结一个基本不会出错的流程顺序创建数据库并导入SQL打开Navicat或MySQL命令行创建utf8mb4编码的数据库然后执行项目里的.sql脚本。执行成功后检查一下表数量和数据量确认导入成功。改后端配置打开application.yml或application.properties修改数据库用户名、密码、数据库名。如果项目里配置了Redis、文件存储路径等也一并改掉。启动后端用IDEA打开后端项目等待Maven下载依赖第一次可能很慢建议换阿里云镜像。启动Application类看到Started ...日志说明成功。启动前端用VSCode或WebStorm打开前端项目npm install装依赖然后npm run dev启动开发服务器看到Compiled successfully说明成功。浏览器访问测试根据前端控制台输出的地址通常是http://localhost:8080或http://localhost:3000打开页面先走一遍注册、登录、浏览活动的全流程。我强烈建议你在浏览器里开着F12开发者工具切到Network面板去看请求。哪个接口红了点开看返回什么错误基本上所有联调问题都能在这个面板里找到答案。这个习惯一定要从现在开始养成。5.2 跨域问题的三处解法实战中按这个顺序试前端开发服务器比如localhost:8080和后端接口地址比如localhost:9090端口不一致就会触发浏览器的同源策略报Access-Control-Allow-Origin错误。解决跨域有三条路按性价比排序第一种后端全局CORS配置最省事。写一个配置类Configuration public class CorsConfig { Bean public CorsFilter corsFilter() { CorsConfiguration config new CorsConfiguration(); config.addAllowedOriginPattern(*); config.addAllowedMethod(*); config.addAllowedHeader(*); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(/**, config); return new CorsFilter(source); } }第二种前端Vite代理开发环境通用。在vite.config.js里配server.proxy把/api开头的请求转发到后端地址。这样前端请求的还是localhost:8080/api/xxx但实际由Vite开发服务器转发到了后端浏览器层面不存在跨域。第三种Nginx反向代理生产环境主流。打包部署时把前端静态文件放在Nginx里配置location /api/ { proxy_pass http://localhost:9090; }效果和Vite代理类似但用于生产。我给你的建议是开发阶段用Vite代理部署阶段用Nginx代理后端CORS配置作为兜底。三层都配上也不会互相冲突但如果你只图快后端那一段配置就够了。5.3 打包部署到服务器三步走加两个坑毕设演示通常在本机但如果你想去云服务器上部署一份或者答辩时用服务器演示流程也不复杂前端打包前端项目目录下执行npm run build生成dist静态文件目录把这个目录里的文件上传到服务器的Nginx静态目录比如/usr/share/nginx/html。后端打包后端项目根目录执行mvn clean package -DskipTests在target目录下生成.jar包。把jar包上传到服务器执行nohup java -jar xxx.jar log.out 21 启动。配置Nginx反向代理/api到localhost:8080jar包端口解决前后端联调。两个坑提前告诉你端口别被占用。服务器上可能有旧服务占用8080启动jar包前先netstat -tlnp | grep 8080查一下。被占用就换一个端口或者自己改application.yml里的server.port。数据库别连错。服务器上的MySQL和本地MySQL是两个环境记得修改jar包配置文件里的数据库连接否则后端能启动但一查询就报Table doesnt exist或Access denied。6. 把别人的源码变成你自己的项目降重与扩展的思路6.1 降重的核心不是改名字而是改业务逻辑很多同学拿到源码后为了应付查重给类名、变量名、数据库字段做了一轮全局替换。这事干了等于没干因为你改成什么功能的本质还是原来的功能答辩时老师随便追问一个细节就露馅。真正有效的改造是从业务上动刀子加一个原项目没有的功能模块。这里给你三个低成本高回报的方向方向一志愿者时长与信用体系。在报名表基础上增加志愿时长字段前文提过活动结束后管理员录入时长用户端展示累计时长并生成星级志愿者标识。加一张volunteer_hours表记录每次时长变动的明细。方向二活动签到二维码。后台活动列表生成签到二维码管理员用手机或平板扫一下活动二维码展示当前报名用户列表一键标记签到。前端用qrcode插件生成二维码后端给活动加一个签到码字段用户端输入签到码完成签到。这个功能做出来后演示环节能给评委留下深刻印象。方向三公益积分商城。用户报名活动、完成签到、进行捐赠都能获得积分积分可以在商城兑换小礼品如环保袋、雨伞等。核心表是goods商品、goods_exchange_record兑换记录兑换流程跟报名活动的逻辑很像改改校验就能复用。每加一个功能你都要在论文里对应写一节功能设计与实现正文的量就上来了而且内容是你自己写的查重率自然就降下来了。6.2 论文里怎么把这个项目的亮点写出来论文写作的时候不要平铺直叙地写登录功能怎么实现要用问题-方案-效果的叙事结构需求分析章节从公益组织的管理痛点切入一条条列出功能性需求和非功能性需求画出用例图、活动图。系统设计章节给出系统架构图前后端分离架构可以手绘数据库ER图每张核心表的字段说明。系统实现章节选3-4个关键模块重点讲比如JWT登录鉴权、活动状态流转、ECharts数据可视化、文件上传。代码不要大段贴只贴核心片段并用文字解释关键逻辑。系统测试章节用表格列测试用例比如输入错误密码时是否提示用户名或密码错误、报名人数已满时是否拦截报名并附上测试结果截图。论文的每一张贴图都要配上至少2-3句的说明文字截图不是摆设是论据。6.3 关于毕设答辩提前准备这5个必问问题用这个项目答辩大概率会被问到以下问题提前把答案写好为什么选SpringBoot和Vue答SpringBoot简化了Spring的配置内嵌容器方便部署Vue组件化开发效率高前后端分离有利于团队协作和独立部署。JWT相比Session有什么优势答无状态、不占服务器内存、多端共用同一Token、适合前后端分离架构下的身份认证。报名人数超卖怎么解决答数据库层面加唯一索引保证同一用户只报一次业务层面在报名前做人数上限校验如果并发量高可以用SQL的UPDATE activity SET signup_count signup_count 1 WHERE id ? AND signup_count max_people做原子操作。密码是怎么加密存储的答BCrypt加密每次加密生成随机盐同一明文密码两次加密结果不同防止彩虹表破解。如果用户量很大这个系统有什么瓶颈答单机起步时MySQL连接池、Tomcat并发线程数是主要瓶颈可以考虑引入Redis缓存热点数据、Nginx负载均衡、数据库读写分离但这取决于实际业务量毕设规模下现有设计是够用的。这5个问题答好了答辩基本稳了。我个人做毕设这些年最大的体会就是选一个中等难度但业务链完整的题目比追求技术花哨要重要得多。公益平台正好踩在这个平衡点上——它有真实的社会价值可以讲技术栈主流而不过度模块之间有逻辑关联而不是各写各的。把这套架构吃透了从SpringBoot到Vue到MySQL到部署上线整个前后端闭环的工程思维就建立起来了。动手之前先别急把表结构画清楚、把状态流转想明白剩下的都是熟练活。
返回列表