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

SpringBoot+Vue校园闲置物品交易系统设计与毕设实战全记录

发布时间:2026/9/29 18:13:30

资讯中心
01
ARTICLE

SpringBoot+Vue校园闲置物品交易系统设计与毕设实战全记录

SpringBoot+Vue校园闲置物品交易系统设计与毕设实战全记录
基于SpringBootVue校园闲置物品交易系统的设计与实现从0到1的毕设实战全记录又到一年毕业季很多学弟学妹来问我毕设怎么做。问得最多的就是管理系统类、商城类、论坛类项目而校园闲置物品交易系统是其中非常经典而且需求量一直不减的一个选题。每年都有人选它但每年都有人把它做成了“简单增删改查”答辩时被老师问得漏洞百出。作为一个用过这套技术栈做过完整的校园闲置物品交易系统、并且在毕业答辩拿到优秀成绩的老学长今天想把整个设计和实现过程完整拆开来讲。这篇文章不是要给你一份“抄作业”的代码而是要把每一步背后的为什么讲清楚帮你在理解的基础上做出一套真正拿得出手的SpringBootVue前后端分离项目。这套系统的核心业务并不复杂说白了就是“校园里的闲鱼”注册、登录、发布宝贝、浏览搜索、下单购买、订单管理、个人信息维护。但要把它做得扎实涉及到的知识点其实相当密集——SpringBoot的后端接口设计、MyBatis-Plus的数据持久化、JWT的鉴权机制、Vue的组件化开发、Element UI的快速搭界面、Axios的前后端联调还有文件上传、分页查询、模糊搜索、全局异常处理。任何一个环节出问题整个项目都会卡住。这套组合是Java后端当之无愧的就业技能组合无论你是想毕业答辩顺利通过、拿到一个好成绩、考研复试有项目可聊、还是求职面试作品集里有个完整的全栈项目它都能给你的简历加分不少。这篇文章会沿用我当年做这个项目的完整思路把从需求分析到前后端分别实现再到测试部署、答辩准备的每个关键节点过一遍。同时附上我在实际开发中踩过的坑、调试过的诡异问题、以及很多教程不会写但你必须知道的细节。如果你正准备开始动手我建议收藏本文遇到对应环节就翻出来对照一下。1. 项目整体设计与思路拆解1.1 为什么选“校园闲置物品交易”这个课题先说说选题逻辑。每年毕设选题里“XX管理系统”是最多的但大多数管理系统只是对一张表做简单增删改查代码量撑不起一本论文答辩时也经不起追问。校园闲置物品交易系统之所以值得做是因为它有完整的业务闭环商品的发布和交易、订单状态流转、买家卖家的双向交互。这就逼着你去做权限控制、状态管理、关联查询、接口设计甚至在并发场景下去思考数据一致性问题。同时校园场景自带明确约束用户限在校学生交易范围限校园内部物品多为二手教材、数码配件、生活用品。这些约束直接决定了功能模块怎么划分、数据表怎么设计。比如“校园认证”可以让注册时强制填写学号帖子能看到发布者的学校和联系方式从而减少线下交易的风险这也是论文里可以重点论证的点。另外从就业角度说SpringBootVue是目前中小型互联网公司、外包公司最主流的组合课程设计用这套、毕设用这套、进了公司大概率也是这套。一个完整的项目做下来找工作面试时候的“项目经验”这一栏就有东西写了这不是选择题是必选动作。1.2 整体功能模块拆解从需求到模块划分做项目第一件事不是敲代码而是先把“系统要干什么”想清楚。我当年是用思维导图做的功能梳理最后整理出了六大模块用户模块、商品模块、订单模块、评论模块、收藏模块和后台管理模块。用户模块负责注册、登录、个人信息查看与修改、密码找回。这里的关键点是注册时的“校园身份”验证我选择的是学号真实姓名学校的组合学生注册后默认状态是“待认证”管理员审核通过后状态变为“已认证”这样发帖和交易的信任度就高了。商品模块是整个系统的核心。包括商品发布、商品列表浏览分页显示、按分类筛选、关键词搜索、商品详情查看、商品下架和删除。发布时必填的表单字段有标题、描述、分类、成色定价、原价、图片选填字段包括交易地点、是否接受议价。这里涉及到图片上传我用了本地文件存储的方式答辩阶段完全够用。订单模块负责交易流程的完整流转——买家对某件商品下单后生成订单订单状态为“待付款”之后是“待发货”“待收货”最后“完成”或者“取消”。订单里要记录商品快照商品标题、图片、单价、数量不能直接引用商品表的实时数据否则商品改了标题历史订单也跟着变了这就是个好细节。评论和收藏模块比较简单但也能体现系统完整度。买家可以对已完成的订单中商品进行评价用户可以对感兴趣的商品收藏收藏列表和购物车不一样它不改变库存只做标记。后台管理模块是答辩加分项也是评审老师一定会问的部分。管理员可以管理用户禁用/启用、管理商品下架违规商品、管理分类添加/删除商品分类、查看所有订单。如果你时间不够后台模块可以先做一个查询上下架的状态变更但这一块儿一定得有。1.3 技术选型为什么是SpringBootVue而不是SSH或JSP很多同学纠结技术栈网上也总有“SSH”“SSM”“JSPServlet”之类的旧方案流传。我的建议非常明确毕设选型就看三件事——生态成熟度、个人掌握度、就业认可度。SpringBootVue在这三方面全是优选项。SpringBoot为何选它因为它“约定大于配置”的理念大幅降低了集成难度。以前SSM集成要写一堆XML配置SpringBoot一个启动类就全搞定同时自带的Tomcat内嵌容器打成的jar包可以一条命令直接跑起来。这对做毕设来说是解放生产力的你不用把时间花在配置上面而可以把精力花在研究业务逻辑上。Vue为何选它它是渐进式JavaScript框架上手路径平滑。你可以先只用它的模板语法把页面写出来再慢慢用上组件、路由、状态管理。配合Element UI组件库后台管理界面几行代码就能搭出漂亮的表格和表单比用原生JS拼DOM不知道高到哪里去了。而且Vue的组件化开发方式天然适合把“商品卡片”“分页组件”“导航栏”抽取复用代码量会少很多。这套前后端分离架构的核心特征是后端只提供RESTful API返回JSON数据前端通过Axios发起请求拿到数据后在浏览器端渲染页面。第一次用这种模式的时候可能会不适应——原来往模板里塞数据的套路不见了但用熟了之后你会感受到分离的好处前端开发和后端开发逻辑上完全独立改前端不用动后端改接口不用动页面部署也灵活前端打包成静态文件扔给Nginx后端打成jar包跑在服务器上互不干扰。表格式对比能更直白看出选型优势维度JSPServletSSMSpringBootVue配置复杂度高web.xml手动配置高大量XML/注解混合低自动配置application.yml前后端分离不支持JSP耦合严重支持有限模板为主天然支持接口JSON开发效率低中高就业市场热度基本淘汰中小公司还在用需求量大适合毕设程度不推荐勉强强烈推荐1.4 系统架构与项目结构前后端分离到底怎么分架构层面我采用的是经典的三层架构——前端视图层、后端服务层、数据存储层。前端跑在浏览器里只负责展示和交互后端跑在服务器上由Controller、Service、Mapper三层组成数据存储层用的MySQL 8.0。后端项目的实际目录结构我贴一下这是很多人容易忽视但非常重要的环节。建议按功能模块分包而不是按技术职责分包。什么叫按功能分包就是把用户相关的Controller、Service、Mapper放一个包商品相关的放另一个包。有人喜欢先建controller包、service包、mapper包然后把所有Controller丢进去项目小的时候没事项目一复杂就是灾难。你按模块分好后期定位代码效率翻倍。com.campus.trade ├── common # 通用类统一返回结果、异常处理、工具类 ├── config # 配置类CORS跨域、拦截器、MyBatis-Plus配置 ├── controller # 控制层接收前端请求 ├── service # 业务层处理业务逻辑 ├── mapper # 数据访问层数据库操作 ├── entity # 实体类数据表对应对象 ├── dto # 数据传输对象接收前端参数 └── vo # 视图对象返回给前端的数据模型前端项目我用的是Vue CLI 3创建的标准结构src下面再分api、assets、components、router、store、views六个目录。api目录专门存放所有请求后端的接口方法这么做的好处是当后端接口地址变动时只需要改api目录下的一个文件所有调用的页面都会自动生效免去一个个页面找接口地址的麻烦。2. 数据库设计与核心逻辑2.1 数据表设计从ER图到实际建表的完整思路数据库表是整个系统的地基设计得好不好直接决定开发效率和后期的扩展性。我设计了八张核心表如果加上后台管理员要用的表会是九张。初始设计阶段我强烈建议用工具先画好ER图再转成建表SQL。我当时用Navicat直接做的设计它可以直接可视化管理MySQL还能反向生成ER图比比在纸上画完再手敲SQL高效得多。具体表结构如下用户表t_user主键id、用户名username、密码password、学号student_no、真实姓名real_name、学校school、学院college、手机号phone、头像avatar、状态status0正常 1禁用、认证状态auth_status0未认证 1已认证、注册时间create_time、更新时间update_time。商品分类表t_category主键id、分类名称name、父分类ID parent_id支持二级分类、排序sort、创建时间create_time。比如数码产品下可以挂手机、电脑、耳机等子分类不搞无限级分类两级就够了再多就是过度设计。商品表t_product主键id、发布者ID user_id、标题title、描述description、分类ID category_id、价格price、原价original_price、成色condition_level1全新 2几乎全新 3轻微使用痕迹 4明显使用痕迹、图片列表images、交易地点trade_location、状态status0在售 1已售出 2已下架 3审核中、浏览数view_count、创建时间create_time。图片列表我用的是JSON字符串存储多个图片地址查询时转成List返回给前端比单独建一张图片关联表要简单比较适合图片数量不多最多9张的场景。订单表t_order主键id、订单编号order_no、商品快照product_snapshot、买家ID buyer_id、卖家ID seller_id、商品ID product_id、支付金额amount、订单状态status0待付款 1待发货 2待收货 3已完成 4已取消、创建时间create_time、支付时间pay_time、发货时间ship_time、完成时间finish_time。订单编号一般用时间戳加随机数生成这个是自己拼的。快照字段存的是商品标题和主图的JSON字符串为的是历史订单不随商品变化。评论表t_comment主键id、商品ID product_id、订单ID order_id、评论人ID user_id、内容content、评分rating1-5分、回复内容reply、评论时间create_time。收藏表t_favorite主键id、用户ID user_id、商品ID product_id、创建时间create_time。这里为防重复收藏我给(user_id, product_id)加了唯一索引不然用户狂点收藏会出现好几条记录。管理员表t_admin主键id、用户名username、密码password、角色role、最后登录时间login_time。2.2 核心业务逻辑JWT登录认证与权限控制这套系统里最核心、最有技术含量的一部分就是登录认证和权限控制。传统做法用的是Session登录成功后把用户信息存在服务器内存前端拿着一个Cookie里的JSESSIONID来证明“我是谁”。这模式在单体应用里够用但前后端分离架构下有个天然痛点前端和后端可能不在同一个域名Cookie跨域处理比较麻烦服务端扩容后Session同步还要额外配置Redis。所以我在这个项目里用了JWTJSON Web Token方案。它的工作流程是用户携带用户名密码请求登录接口后端校验通过后生成一个JWT令牌字符串返回给前端前端每次请求时在请求头加上Authorization: Bearer token后端写一个拦截器对所有需要登录才能访问的接口如商品发布、订单创建、个人中心进行token解析和校验通过才放行不通过直接返回401未登录状态。实际代码里核心是这样// 拦截器核心逻辑 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行OPTIONS预检请求 if (OPTIONS.equalsIgnoreCase(request.getMethod())) { return true; } String token request.getHeader(Authorization); if (StringUtils.isBlank(token)) { throw new BusinessException(401, 未登录请先登录); } try { // 解析token得到用户ID Long userId JwtUtil.parseToken(token.replace(Bearer , )); request.setAttribute(userId, userId); return true; } catch (Exception e) { throw new BusinessException(401, 登录状态已过期请重新登录); } }前端配合着做Axios请求拦截器中每次请求前从Pinia/Vuex中读取token并设置到请求Header响应拦截器中如果拿到的code是401就自动跳转到登录页清空本地用户信息。这里要重点强调一下不要把所有接口都放进拦截器范围。注册、登录、商品列表、商品详情、分类查询这些是游客也可以访问的要对拦截路径做个白名单设置。我当时的方案是在拦截器配置类中写了一个放行路径列表比如/api/user/login、/api/user/register、/api/product/list、/api/product/detail/**等其他路径全部走token校验。这么设计合不合理合理因为你跳过了登录页的用户属性等商品信息才对行情有直观认知不让游客看商品列表系统本身也不成立。2.3 Redis缓存与并发问题的处理思路在毕设阶段不需要把Redis引入得太复杂但如果不做任何缓存每次商品列表查询都直接打在MySQL上虽然并发量不高不会挂可在答辩时老师问“你这个系统在高并发场景下会遇到什么问题”就会比较被动。所以我在商品详情这个热点接口上使用了Spring CacheRedis做了一级缓存。具体做法是在查询商品详情的Service方法上标注Cacheable(value productDetail, key #productId)。第一次查询时走数据库把结果缓存进Redis后续同一个商品的查询直接返回缓存里的JSON数据。当商品信息被修改时通过CacheEvict注解清除对应商品的缓存保证下次查询拿到的是最新数据。商品发布和秒杀一样其实都有一个并发安全的关键点——同一件商品不能同时卖给两个人。我的做法是在商品实体类中加一个version字段使用乐观锁机制更新商品状态时加上条件“当前版本号等于之前查询到的版本号”如果更新影响行数为0说明期间有人改过了就提示“手慢了商品已被下单”。这个设计在答辩时很能讲出东西它体现了你对并发问题的理解。核心SQL片段大致是这样update idupdateStatusWithVersion UPDATE t_product SET status #{newStatus}, version version 1 WHERE id #{id} AND version #{oldVersion} AND status 0 /update如果影响行数不为1就是并发冲突业务层重新查询商品信息并返回友好提示。这个点建议在论文的技术难点分析里单独写一小节是加分项。3. 实操过程与核心环节实现3.1 环境准备与项目初始化不踩版本坑动手之前先把环境配好。这个环节每年都有大量同学卡在版本不兼容上有的代码抄过来启动就报错。我强烈建议统一使用以下版本组合JDK 1.8、Spring Boot 2.7.x、MyBatis-Plus 3.5.x、MySQL 8.0、Node.js 16.x、Vue CLI 5.x、Element UI 2.15.x。Spring Boot 3.x虽然已经出了好久但它基于Jakarta EE规范很多老教程的代码不再兼容为了省心直接上2.7.x是稳妥方案。Node版本太高比如20在某些老项目里跑Vue CLI会有OpenSSL相关的报错遇到的话装个16.x会舒服很多。后端创建我建议直接在IDEA中用Spring Initializr创建项目勾选Web、MySQL Driver、Lombok这三个依赖然后在pom.xml里手动加上MyBatis-Plus和JWT相关的依赖。前端则用Vue CLI创建运行vue create campus-trade-web选择Manually select features勾选Router和VuexCSS预处理器选Node Sass。项目跑起来之前先确认一个重要的配置项后端接口的跨域问题。前端跑在 http://localhost:8080后端跑在 http://localhost:9090两个端口不同就必然有跨域。我写了一个全局CORS配置类处理跨域请求。Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }这个配置让后端允许指定来源的跨域请求前端不需要做任何额外处理。如果你的项目里加了JWT拦截器一定记得对OPTIONS请求放行否则前端发起跨域预检请求就直接被拦截器挡掉了。3.2 用户模块实现细节注册的密码安全与登录态维护用户模块是系统的入口实现难度不高但有两个细节值得认真做。第一是密码不能明文存库。我使用的是MD5加盐加密虽然现在更安全的是BCrypt但毕设里只要逻辑自洽加密方案说得清楚就行。加盐的意思是在用户原始密码后面拼接一段随机字符串再对拼接后的串做MD5哈希这样即使两个用户密码相同他们存储的密文也完全不同防止彩虹表暴破。第二是登录成功后的用户信息回传。登录时后端校验密码正确后生成JWT令牌然后把令牌和脱敏后的用户信息一起返回。脱敏是什么意思就是不能把密码字段返回给前端连值为null都别返回。我用了一个UserVO类里面只包含用户ID、用户名、学校、头像等展示信息。千万注意有的同学图省事直接返回整个User实体结果密码也带回去了这是极其低级的错误。注册接口还有一个需要注意的参数校验。我用了Spring Validation框架在DTO字段上加上NotBlank、Email、Pattern等注解在Controller方法参数前加Validated。这样前端传了空值或者不合法值后端会直接返回400和对应的错误提示。public class RegisterDTO { NotBlank(message 用户名不能为空) Pattern(regexp ^[a-zA-Z0-9_]{4,16}$, message 用户名必须为4-16位字母、数字或下划线) private String username; NotBlank(message 密码不能为空) Size(min 6, max 20, message 密码长度必须在6-20位之间) private String password; NotBlank(message 学号不能为空) private String studentNo; // 其他字段... }3.3 商品模块实现细节图片上传、分页查询、模糊搜索商品发布里最麻烦的是图片上传。前端用的Element UI的Upload组件后端我提供一个专门的接口接收MultipartFile文件保存到服务器指定目录下然后把可访问的URL返回给前端。实际生产环境中文件不应该放在服务器本地要么用OSS要么用MinIO对象存储但毕设阶段放在本地目录配置虚拟路径映射就能完整演示。注意配置虚拟映射是关键不然只有后端自己能看到图片前端访问不到。// application.yml配置静态资源映射 spring: servlet: multipart: max-file-size: 10MB max-request-size: 50MB # 文件上传保存路径 file: upload-dir: /var/www/campus-trade/images/再配合一个配置类将/images/**请求映射到上传目录这样前端访问http://localhost:9090/images/xx.jpg时就能看到图片。商品列表的分页我用的MyBatis-Plus自带的分页插件。前端传current和size两个参数后端用Page对象接收查询结果返回total和records。搜索功能使用MyBatis-Plus的模糊查询条件通过标题和描述字段的Like条件匹配。筛选功能就是按分类ID和价格区间过滤。实际编写分页查询接口时还涉及一个重要问题是否连带返回卖家信息我第一次做的时候商品列表直接返回商品表的字段前端没法显示卖家昵称和头像后来用一个VO对象在Service层把商品和发布者信息合并返回并把查询后的图片JSON字符串转成数组这样前端直接拿数据渲染即可。public IPageProductVO getProductPage(int current, int size, String keyword, Long categoryId) { PageProduct page new Page(current, size); LambdaQueryWrapperProduct wrapper new LambdaQueryWrapper(); wrapper.eq(Product::getStatus, 0); // 只查在售商品 if (StringUtils.isNotBlank(keyword)) { wrapper.and(w - w.like(Product::getTitle, keyword) .or().like(Product::getDescription, keyword)); } if (categoryId ! null) { wrapper.eq(Product::getCategoryId, categoryId); } wrapper.orderByDesc(Product::getCreateTime); IPageProduct productPage productMapper.selectPage(page, wrapper); // 转为VO组装卖家信息和图片列表 return productPage.convert(this::toProductVO); }3.4 订单模块实现细节状态机设计与事务管理订单模块是整个项目的业务中枢也是最容易出逻辑漏洞的地方。我的订单状态机设计原则是单向流转0待付款→1待发货→2待收货→3已完成0→4已取消不允许状态跳变。状态变更操作统一走Service层更新方法并在里面做状态校验防止用户通过直接调接口跳过流程。创建订单的方法必须加Transactional事务注解并且内部逻辑要保护几个操作查商品、校验商品状态与卖家、创建订单、锁定商品把状态改为1已售出并递增版本号。这四个步骤任何一个失败都要回滚。让我印象最深的坑是Caused bySQLException: Lock wait timeout exceeded。这个问题发生在我用Postman多线程并发测试同一个商品下单的时候。表面原因是MySQL行锁等待超时深层原因是我的事务虽然开启了但商品锁定这一步没有在最先执行事务持有锁的时间过长。解决办法是调整操作顺序先拿到商品ID后立刻以SELECT ... FOR UPDATE方式锁行再执行后续的验证和订单创建。这个经验应该说对所有做交易类系统的同学都有参考价值简单说就是锁要早拿、事要快办。3.5 前端页面流程与前后端联调要点前端页面的开发顺序建议按主流程走登录注册页→首页商品列表→商品详情→购物车/立即下单→订单列表→个人中心→后台管理页。Vue Router用起来不难但要注意路由守卫。我做了两级路由守卫全局前置守卫里判断to.meta.requiresAuth是否为true是的话就检查本地仓库有没有token没有就跳转向登录页并携带redirect参数登录成功后回跳。这就要求你在定义路由时凡是需要登录的页面都必须给meta配置加requiresAuth: true比如商品发布、订单管理、个人中心、收藏列表。联调阶段的接口路径不一致是我见过最多的笑话前端请求/user/login后端Controller的映射是/api/user/login前后端都不能互相发现。我的方法是把前端所有请求路径统一到/api前缀下在前端用Vue CLI的proxy代理配置将/api转发到后端地址。这样前端代码里请求的是相对路径部署时可以保持灵活。// vue.config.js module.exports { devServer: { port: 8080, proxy: { /api: { target: http://localhost:9090, changeOrigin: true } } } };同时后端每个Controller上我统一加了RequestMapping(/api/xxx)两边对齐基本杜绝了路径不一致的问题。另外联调时我还喜欢开浏览器F12面板实时看Network请求用响应体里的报错信息反推后端代码问题比纯看日志更快。3.6 后台管理模块一套代码适配两种角色后台管理页面我复用了同一套前端框架只是接口权限不同。管理员登录后进入单独的/admin路由页面。这个页面在路由里设置meta: { role: admin }后端接口也加了管理员角色校验。管理员最核心的操作是商品审核。我给他设计了查看所有待审核商品的列表接口管理员点击“通过”后商品状态从审核中变为在售点击“拒绝”则变为已下架并附带原因。这个功能虽然逻辑简单但它能形成一个完整的商品生命周期在答辩、论文里可以当作“平台规范化管理”章节来写比单纯展示买卖流程更有深度。4. 常见问题与排查技巧实录4.1 启动类报错与Maven依赖问题的排查思路最常见的报错无非三类启动类找不到、依赖版本冲突、编译错误。启动类报错基本都是因为Spring Boot的默认扫描包路径问题当你把启动类放在com.campus.trade下时它会扫描该包及子包下的所有组件如果把controller写到别的包比如com.example.controller里Spring就完全感知不到。解决办法是扫到controller所在包下面或者按规约把代码放在启动类所在包的子包里。Maven依赖冲突的经典场景是Spring Boot自带Logback和项目额外引入了SLF4J门面时产生冲突启动时会看到一堆红色日志输出并提示BindingException。这时候尝试排查依赖树用mvn dependency:tree命令找出冲突坐标把其中不被需要的那个用exclusions排除掉即可。4.2 前端请求跨域与代理不生效的排查思路跨域问题出现时浏览器的Console里一定报了CORS相关的错误这个错误通常不明显地告诉你问题出在前端还是后端。我的排查顺序是先看请求能不能发出去Network里有没有这个请求如果没有说明被前端代理或拦截器拦截了如果有并返回了CORS错误那就是后端没配好CORS。如果用了proxy代理但是发现代理没生效先检查浏览器的Network选项卡里请求的URL看看走的还是8080还是直接9090。如果9080代理配置正确请求目标地址是9090仍然提示跨域可能是后端提供了CORS但又配置了请求头里的Authorization与CORS冲突注意allowCredentials(true)时需要指定allowedOriginPatterns而不是allowedOrigins写死。4.3 部署上线时遇到的SpringBootMySQL环境问题毕设里最常见的是部署到云服务器时数据库连接不上。这里要区分两个问题一是MySQL的root默认只允许localhost登录需要给你新建的账号授权远程访问二是Spring Boot的配置文件里如果地址写的是localhost或127.0.0.1在服务器上没问题但如果前后端不在同一台机器上就要改成对应的内网或公网IP。我部署时用的是java -jar campus-trade.jar直接启动后端前端打包后扔到Nginx的html目录。Nginx配置的关键是处理前端路由history模式下刷新404的问题——需要加一个try_files $uri $uri/ /index.html;配置否则用户在/admin页面刷新一下就白屏了。server { listen 80; server_name your-domain.com; root /usr/share/nginx/html/campus-trade; location / { try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://localhost:9090/api/; 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 /images/ { proxy_pass http://localhost:9090/images/; } }这套配置含义是前端任意的路由路径都回退到index.html交给前端路由处理所有/api开头的请求转发到后端的9090端口图片请求也做个转发。前端请求时只需要写/api前缀部署后直接同源访问连CORS都省了。4.3 安全和性能优化不只是“能跑就行”经常有同学做完系统就万事大吉但答辩老师一定会问“你系统安全方面做了什么”。我在这块儿做了三件事。第一件事是SQL注入防护。MyBatis-Plus的QueryWrapper和LambdaQueryWrapper内部全部使用预编译的#{}占位符天然免疫SQL注入只要你不要手写${}去拼字符串就行。这一点在论文的安全章节里可以单独列出说明。第二件事是XSS攻击防护。也就是标题热搜词里出现的SpringBoot全局过滤器处理XSS攻击的场景。在商品发布、评论、个人简介这类用户可输入文本的接口上我加了一个全局过滤器用Jsoup库对请求体中的HTML标签、script标签和事件属性做清理把scriptalert(1)/script这类内容直接剥离或转义。同时在前端Vue中默认的插值语法{{ }}天然会把数据当作文本渲染不会把字符串当成HTML执行。而如果某些地方确实要展示富文本就使用白名单过滤后再v-html输出。第三件事是参数校验和幂等处理。下单接口我增加了防重复提交的机制前端按钮提交后立即置灰后端的订单创建逻辑中对同一个商品ID如果已存在未完成订单则拒绝再次创建。这个简单处理虽然朴素但在答辩中可以展示你考虑问题完整性。4.4 毕设答辩环节从项目陈述到技术提问的应对策略最后想聊聊答辩因为项目做得再好讲不清楚照样拿不到高分。答辩陈述我建议按照“你做了什么、为什么这样做、做的过程中遇到了什么困难”的三段式来准备。第一段用不超过3分钟讲清楚项目背景和功能模块配合现场演示系统。第二段重点讲技术难点比如JWT认证机制、乐观锁防超卖、Redis缓存的使用、文件上传处理老师爱听的是你的思考过程可以多说一下“为什么不用Session而用JWT”“为什么不用悲观锁而用乐观锁”。第三段把项目记录过的问题做一个汇总比如我在分页查询时遇到了N1问题、在商品图片存储上最初直接存Base64后来改成了文件上传这些都是很好的复盘素材。如果被问到“系统的性能瓶颈在哪”别慌这是个开放问题。你可以老实说当前单机部署肯定无法支撑高并发然后说说你的改进思路商品详情加Redis缓存、数据库加索引和读写分离、图片上传接对象存储OSS/MinIO、前端做懒加载和CDN。思路比答案更重要老师要的就是你平时有没有思考。常见问题速查表现象可能原因排查方法SpringBoot启动失败启动类包位置不对、端口占用检查组件是否在启动类子包下lsof -i:9090查端口MyBatis-Plus查询不到数据表名映射问题、数据库配置错误Mapper接口加Mapper注解检查yml数据源JWT登录后接口仍返回401拦截器放行规则未配置打印token解析结果检查Authorization头前端请求404后端接口路径与前端不一致浏览器Network看完整请求URL用Postman复测图片上传成功但无法访问静态资源映射未配置手动浏览器访问图片URL看是否404部署后刷新页面白屏前端history路由未配置Nginx加try_files $uri /index.html商品发布图片超过大小后端multipart配置限制改动yml的max-file-size参数5. 项目亮点扩展与后续演进做完基础版本之后如果你还有时间我建议你往下面这些方向挑一两个做扩展它们能显著提升项目的深度和答辩说服力。第一个是消息通知模块。当用户收藏的商品被降价、商品被下单、订单状态变化、收到新评论时通过WebSocket实时推送消息给对应用户。这是在一个交易系统里非常自然的业务需求而且WebSocket在简历里也是加分项比普通轮询高级很多。实现思路是前端用stomp.js连接后端的WebSocket端点服务端根据登录用户的ID维护一个会话映射定向推送。第二个是回收与捐赠模块。校园闲置不仅有卖还有回收和公益捐赠场景。学生把书籍、衣物提交给平台平台统一回收。这个模块在论文的社会价值章节可以写得很漂亮能体现你对校园场景的理解。第三个是管理员数据统计看板。用ECharts图表展示平台每日新增用户数、新增商品数、交易额趋势、分类占比和热门商品Top10排名。这个实现难度不大就是写几个聚合查询的SQL但视觉冲击力极强答辩演示时页面出来就是亮眼的加分项。如果追求更完善的工程化表现也可以把代码注释、单元测试、Docker部署这些补上。把SpringBoot项目打成镜像扔进Docker里跑前端也通过Dockernginx一键启动这绝对是简历级别的加分。回到项目本身我的切身体会是校园闲置物品交易系统这个选题看似普通但如果你把它当成一个真正的互联网产品去做在数据设计、接口规范、异常处理、并发控制上做到位它完全可以是一份优秀的毕业设计。前几年我见过太多同学抄一个现成商城改个名字就交上去代码理不清、逻辑跑不通答辩被问几个问题就露馅。你既然愿意花时间看到这里说明你想好好把这个项目做出来。那就动手吧从设计数据表开始一步一步把它搭稳。遇到报错不要慌去看控制台的报错信息那是最忠实的向导。等你的系统第一次完整跑通、商品发布和下单流程畅通无阻的时候那种成就感是真实的也是你值得拥有的。如果你在做这个项目的过程中卡在了某个具体问题上不妨顺着这篇文章的目录回过头来找找对应章节。常用的坑和排查方法都在上面那张速查表里。毕业设计是一个人的战斗但技术经验是可以传承的希望我的这些整理能帮你在战场上少踩几个雷。
02
RELATED NEWS

相关资讯

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

03
WHY YAOTU

想打造同款高转化官网?

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

◈

场景化定制

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

◐

营销型架构

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

▲

全周期服务

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

免费获取你的建站方案

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