做毕设最怕什么不是写不出代码是选了一个自己都讲不清楚的题。我之前带过不少学弟学妹很多人一开始都说想做“XX管理系统”做到中间才发现功能表填不满、技术点撑不起一场答辩、演示的时候页面空荡荡。如果你正在为Java Web方向的毕业设计选题发愁我建议你认真看看“SpringBootVue 二手车交易系统平台”这个方向——它的业务链路足够完整从用户注册、车辆发布、搜索筛选到预约看车、下单支付、后台审核每一环都有真实的业务逻辑可讲前后端都有足够的技术点可以展开。这篇博文我会把你当成“准备复现这个项目的人”从为什么选这个题、技术栈怎么挑、数据库表怎么设计、接口文档怎么写、前端页面怎么做、到最后部署打包和答辩准备一条线完整拆给你看。源码结构、SQL脚本、接口文档应该怎么组织也会一并说清楚。1. 毕设选题的底层逻辑为什么二手车交易系统适合做Java Web毕设1.1 业务链路完整讲答辩的时候有东西可说一个能撑住答辩的毕设核心不是代码量很大而是业务链路足够完整。什么叫“链路完整”就是你做的是一个能走通闭环的业务场景而不是一个只有增删改查的空壳子。拿二手车交易系统来说天然就存在两端的角色买家想看车、约看车、询价、下单卖家要发布车辆、管理自家车源、处理订单平台方必须对车辆信息做审核防止虚假车源、违禁车源混进来。光是这一层需求就已经把常见系统里“用户-内容-交易”的核心循环覆盖了。再加上二手车的商品属性很有意思一辆车有品牌、车系、车型年款、上牌时间、表显里程、排量、变速箱类型、排放标准、过户次数、事故记录等一堆结构化字段。这种数据模型比普通的“新闻发布系统”、“图书管理系统”复杂得多意味着在数据库设计这块你能展示更扎实的设计思路也比“单表CRUD”的题目更有说服力。1.2 区分前台与后台天然涉及权限控制大多数管理系统类的毕设其实只有一个后台普通用户和管理员混在一套页面里讲权限设计时只能靠嘴硬撑。二手车交易系统天然分成用户端前台和管理端后台两条线前台用户端注册、登录、浏览车辆、搜索筛选、收藏、预约看车、在线询价、发布车辆、查看订单状态后台管理端登录拦截、车辆审核、用户管理、车辆上下架、订单管理、公告发布、数据统计这种划分带出了两个重要的技术点——RBAC权限模型和前后端分离下的认证鉴权。答辩的时候你就可以明确地讲我是基于角色的访问控制用户和后台管理员走不同的鉴权逻辑接口层通过拦截器校验Token和角色权限。这是很多管理系统类项目讲不清楚的东西你一句话就能让评委老师知道你确实理解权限设计。1.3 前端展示空间大适合体现Vue的能力很多Java Web毕设的前端就是几个表格页面叠在一起Vue的用法停留在“用axios调接口、用v-for渲染列表”这个层面。二手车交易系统的前端有天然的展示优势车辆列表页需要多条件筛选品牌、价格区间、里程、变速箱、排放标准还要带分页车辆详情页需要展示图片轮播、基础参数表格、卖家信息首页需要做推荐车辆、热门品牌入口后台管理需要表格弹窗确认状态切换这些场景用Vue实现时会自然用到组件通信、路由守卫、状态管理、动态表单校验等知识点。也就是说你做这一个项目前端技能的复杂度是足够在答辩时讲的。1.4 交易状态机的存在让后端代码有业务含量比“增删改查”高一级的是你能把业务状态管理讲清楚。二手车交易系统里一辆车从用户发布开始要经过“待审核 → 审核通过/驳回 → 上架展示 → 被下单 → 完成交易 → 下架”的完整生命周期。订单也有自己的状态待支付、已支付卖家确认、交易完成、用户取消、超时取消。这些状态流转不可能靠随意改字段完成你需要用状态机去约束操作比如“一辆已下架的车不能再被下单”“一笔已完成的订单不能再被取消”。这种设计在答辩的时候特别好讲——因为它是真实业务的约束逻辑不是从教程里抄来的。2. 技术栈选型SpringBootVueMySQL这套组合背后的取舍逻辑2.1 版本选择SpringBoot 2.x还是3.x这是一个先决定的问题我见过太多项目写着“SpringBoot 3.x”最后因为JDK版本问题折腾了整整两天。做毕设选技术栈的第一原则是求稳。SpringBoot 2.7.x 配套 JDK 8 或 11相关的第三方库兼容性最好网上的解决方案也最多SpringBoot 3.x 要求JDK 17以上并且包名从 javax.* 改成了 jakarta.*很多老教程里的代码直接复制会报错如果你不是对SpringBoot 3的新特性有明确需求我建议直接用SpringBoot 2.7.x。这是一个非常现实的建议——毕设的核心是让你把业务逻辑、工程结构讲清楚不是让你去趟生态兼容的雷。2.2 后端组件MyBatis-Plus是效率首选但不是全部ORM方面MyBatis-Plus几乎是目前Java毕设的标配。它的优点很直接单表查询不需要写SQLIService和BaseMapper直接带条件构造器分页功能有内置插件不用自己写Limit拼参数代码生成器能把实体类、Mapper、Service一次性生成出来但我要提醒一句不要把MyBatis-Plus的便利当作“不学SQL”的理由。二手车系统里车辆的多条件组合查询、价格区间筛选、连表统计比如某个品牌下有多少辆车在售这些场景你还是得会写XML里的自定义SQL。答辩老师如果问一句“多条件筛选是怎么实现的”你得能答出“QueryWrapper 自定义SQL联合使用”而不是只会用QueryWrapper。JWT认证方面建议用jjwt或者Sa-Token。如果不想在Spring Security上花太多篇幅配置SecurityFilterChain可以直接用JWT拦截器实现登录校验和角色校验。毕设答辩的时候能讲清楚“Token是怎么生成、怎么校验、怎么设置有效期”就够了不一定要上全套Spring Security。2.3 前端Vue 2还是Vue 3关键看你的熟练度Vue 2和Vue 3都能用来完成这个项目。我的建议是如果你之前学的是Vue 2项目里大量教程和组件库基于Vue 2就用Vue 2.7 Element UI如果你对Vue 3的组合式API更熟或者想体现新技术就直接Vue 3 Element Plus Vite理论上Vue 3是趋势但对你来说工具只是用来完成项目的手段。最重要的不是版本而是你能否把路由守卫、组件通信、状态管理这些核心概念讲清楚。如果一个同学用Vue 3但说不清为什么用Pinia管理登录状态另一个同学用Vue 2但能清楚解释Vuex的state在页面刷新后为什么会丢失、怎么用localStorage做持久化那后者在答辩时一定更占优势。2.4 文件存储本地存储最多MinIO是加分项二手车系统涉及到车辆图片上传这是每个做这个题目的人都会遇到的功能。图片存储方案有三级选项本地目录存储把图片存到后端的某个文件夹通过映射路径访问。最简单适合Demo演示MinIO自建对象存储服务通过Java SDK上传文件支持桶管理、文件删除、访问链接生成。比本地存储更有“工程化”的感觉阿里云OSS / 腾讯云COS需要开通云服务账号有免费额度但涉及到配置AccessKey我建议毕设阶段优先本地存储但如果你精力充足可以用MinIO替换。原因有二第一MinIO可以完全本地运行不需要额外联网第二答辩的时候你能讲出“对象存储和传统文件存储的区别”这是加分项。提示网上很多搜索词里都会出现“minio加入到springboot”说明这个需求在纯Java后端人群里普遍存在。如果你决定引入MinIO注意配置好MinIO服务的桶名称、AccessKey和管理员密码启动顺序通常是“先启动MinIO服务再启动SpringBoot项目”。2.5 前后端分离的两个硬伤跨域和文件路径前后端分离的博客和代码到处都是但在本地跑通的时候每个人几乎都会遇到下面两个问题跨域Vue开发服务跑在8080端口SpringBoot跑在8081端口前端向后端发请求会被浏览器拦截。解决办法是加一个CORS配置类或全局过滤器允许指定来源跨域。写死allowedOriginPatterns(*)和allowedMethods(*)就行。静态资源访问图片传到后端本地目录后前端要能访问得到。需要在SpringBoot的静态资源配置里把上传目录映射成/upload/**路径。很多人忘记做这一步结果图片上传成功但前端总是打不开图片。这两个坑我建议你在正式开发之前就先解决掉否则写业务代码的时候会被反复打断。3. SQL脚本二手车交易系统数据库设计和建表落地3.1 从ER图到核心表这12张表是完整系统的骨架我直接说结论一个交付质量比较好的二手车交易系统数据库至少要包含这些表。核心业务表分为用户域、车辆域、交易域、运营域四个板块。用户相关user用户表保存用户基本信息、登录账号、密码加密串、昵称、头像role / user_role角色表和用户角色关联表虽然你可以只做一个is_admin字段区分用户和管理员但用RBAC结构会更好讲权限设计车辆相关car_brand车辆品牌表品牌ID、品牌名称、品牌logo、排序car_series车系列表品牌ID、车系名称、出厂年份car_info车辆信息表核心表存车辆标题、品牌ID、车系ID、上牌时间、表显里程、排量、变速箱类型、排放标准、车身颜色、新车价、售价、过户次数、车辆描述、卖家ID、审核状态、车辆状态在售/已售/下架、图片主图地址car_image车辆图片表车辆ID、图片URL、排序号car_favorite收藏表用户ID、车辆ID、收藏时间appointment预约看车表用户ID、车辆ID、预约时间、联系电话、预约状态待确认/已确认/已完成/已取消交易相关car_order订单表订单编号、车辆ID、买家ID、卖家ID、订单金额、状态待支付、已支付、交易完成、已取消、创建时间、支付时间、完成时间inquiry询价表用户ID、车辆ID、询价内容、回复内容、创建时间可选但加上业务会更完整运营相关notice公告表公告标题、内容、发布时间user_feedback意见反馈表用户ID、反馈内容、反馈时间、处理状态我见过很多代码仓库里只有一个“vehicle”表和一张“user”表把品牌、图片、订单全部塞进去或者干脆不做。这样的项目做出来数据库设计这一关就会被老师追问得很尴尬。完整的设计能体现你有全局建模意识而不是只会建单表。3.2 字段类型选择里容易被忽略的细节建表时有些字段类型的选择看似不起眼实际上会在答辩和实际运行中暴露你的水平。价格字段一定要用decimal不能用double。二手车价格一般不会太大但浮点数在运算时存在精度损失。如果你用double存价格用户下单的时候前端展示“12.58万”后端算出来的可能是12.580000000001。这不是玄学是正常的二进制浮点误差。SQL脚本里价格字段建议这样建price DECIMAL(10,2) COMMENT 售价, new_price DECIMAL(10,2) COMMENT 新车指导价decimal(10,2) 意味着整数部分最多8位小数2位。一台车价格百万级以内都够用。状态字段不要用字符串用tinyint加注释。在售/已售/下架如果用varchar存中文查询、索引、前端映射都别扭。常规做法是tinyint类型存1、2、3然后在前端或后端统一转译。比如车辆状态0待审核1审核通过上架2已下架3已售出。订单状态0待支付1已支付2交易完成3已取消。这样做的好处是你在代码里可以用CarStatusEnum之类的枚举做常量管理而不是散落一堆魔法字符串。时间字段推荐datetime不要存成字符串。有些同学为了图省事把上牌时间直接存成varchar比如2019-05-01看起来没问题但涉及到“按年份筛选车辆”的时候SQL里就得做substring截取效率低且容易出错。直接用date或者datetime类型后面用YEAR()函数统计年份分布就很方便。3.3 外键用不用逻辑外键是更通用的选择数据库设计的问题里老师十有八九会问“为什么不用外键约束”。你最好能给出合理的回答。我的建议是表结构上设计外键关系但不物理创建FOREIGN KEY约束而是用索引保证查询效率。原因很简单物理外键在删除数据时容易触发约束错误实际开发中很多团队默认禁用物理外键逻辑外键代码层面维护关联关系在业务复杂时更灵活但前提是关联字段一定要建索引否则联表查询会全表扫描SQL脚本里建索引的语句长这样ALTER TABLE car_info ADD INDEX idx_brand_id (brand_id); ALTER TABLE car_info ADD INDEX idx_seller_id (seller_id); ALTER TABLE car_info ADD INDEX idx_status (status);这样设计既有设计感又不会给自己挖坑。3.4 SQL脚本的交付质量初始化数据比建表语句更见功夫很多人在交SQL脚本时只给一个建表语句文件。但一个高质量的项目SQL脚本应该包含三类内容建表语句所有表的结构定义字段注释完整初始化数据内置一个管理员账号密码要加密过的不能是明文、品牌表数据例如大众、丰田、本田、宝马、奔驰等20个左右常用品牌、测试车辆数据若干条示例查询针对核心场景的几条复杂SQL例如“统计在售车辆按品牌分布”内置测试数据这门功夫直接影响你做演示时的效果。你想一下如果启动项目后前端车辆列表里空荡荡一张车都没有老师看着页面会很尴尬。而如果你提前放了十几条不同品牌、不同价格区间的数据进去演示的时候随意筛选都有结果整体印象分完全不一样。注意内置管理员密码一定不能是明文123456要写一段SQL插入bcrypt加密后的密码串或者在项目启动时通过CommandLineRunner自动创建初始用户。这个细节答辩时也可能会被问到。4. 后端接口设计与接口文档从“能跑”到“能被看懂”4.1 接口文档为什么重要它决定了你项目的“完成度”毕设项目的交付物通常包含四样东西源码、SQL脚本、接口文档、说明文档。大多数人的SQL脚本和源码是齐全的但接口文档要么没有要么是自动生成的Swagger页面就算交差了。我想讲一个真实感受接口文档是让人觉得“这项目是认真做的”最快速的门面。一个规范的接口文档至少要包含这些信息接口的URL、请求方式GET/POST/PUT/DELETE请求参数参数名、类型、是否必填、说明响应格式统一封装的code、message、data结构错误码说明比如400参数错误、401未登录、403无权限、500系统异常如果你不想维护一份Markdown格式的接口文档也可以集成Swagger/OpenAPI。前端联调的时候直接打开/swagger-ui.html就能看到所有接口。但我个人建议Markdown文档Swagger两者结合Swagger用于开发期自测Markdown文档用于交付因为评阅老师不一定有精力启动项目看Swagger。4.2 接口设计的RESTful风格与统一返回体后端接口不要写得“一个方法一个样”。全项目的接口应该统一遵循RESTful的语义获取资源用GETGET /api/car/list、GET /api/car/detail/{id}创建资源用POSTPOST /api/car/add修改资源用PUTPUT /api/car/update删除资源用DELETEDELETE /api/car/{id}同时要定义一个统一返回类最常用的是Result 包含三字段public class ResultT { private Integer code; // 200成功400失败401未登录 private String message; private T data; }所有Controller的返回值都以Result包装前端Axios拦截器统一解析不用每个接口单独做判断。4.3 核心接口实现思路拆解我挑几个有代表性的接口说说它们的技术实现思路。车辆发布接口 POST /api/car/add这个接口是二手车系统里比较有代表性的一个。用户从前端表单提交车辆信息同时上传若干张图片。后端要做的事情有登录态校验从请求头获取JWT Token解析出当前用户ID参数校验车辆标题非空、价格大于0、里程非负图片处理把上传的MultipartFile保存到本地或MinIO生成访问URL并与车辆主记录建立关联状态初始化车辆状态设为“待审核”只有管理员审核通过后才展示到前台特别要注意的一点是“先保存车辆主记录再保存图片记录”这里尽量使用事务。图片关联表的保存如果失败主记录要回滚否则会出现“有车无图”的脏数据。多条件搜索接口 GET /api/car/list二手车系统最核心的查询接口。它的参数大概长这样public class CarQueryDTO { private Integer brandId; // 品牌ID private Integer seriesId; // 车系ID private BigDecimal minPrice; // 价格下限 private BigDecimal maxPrice; // 价格上限 private Integer minMileage; // 最小里程 private Integer maxMileage; // 最大里程 private String gearbox; // 变速箱类型 private String keyword; // 关键词 private Integer pageNum; // 页码 private Integer pageSize; // 每页条数 }实现上用MyBatis-Plus的QueryWrapper可以解决大部分条件但当条件组合多、又不确定用户填了哪几个时用条件构造器反而有点绕。我习惯于在Mapper XML里写一个动态SQLwhere标签配合if标签判断每个条件是否为空既清晰又能控制SQL效率。select idselectCarList resultTypecom.example.dto.CarVO SELECT c.*, b.brand_name, s.series_name FROM car_info c LEFT JOIN car_brand b ON c.brand_id b.id LEFT JOIN car_series s ON c.series_id s.id where c.status 1 if testbrandId ! null AND c.brand_id #{brandId} /if if testminPrice ! null AND c.price gt; #{minPrice} /if if testmaxPrice ! null AND c.price lt; #{maxPrice} /if if testkeyword ! null AND c.title LIKE CONCAT(%, #{keyword}, %) /if /where ORDER BY c.create_time DESC /select动态SQL能讲清楚“为什么这么写”这本身就是答辩的素材。订单状态流转接口 POST /api/order/pay订单模块要设计好状态禁止流转规则不能只傻傻地更新status字段。比如用户确认支付后订单状态从“待支付”变为“已支付”这里需要校验订单状态确实是待支付。如果订单已经取消再执行支付要把订单状态检查放在事务里用乐观锁或者update的条件语句保障并发安全。MyBatis-Plus版本的做法是UPDATE car_order SET status 1, pay_time NOW() WHERE id #{orderId} AND status 0这种写法通过SQL的where条件天然保证并发时不重复更新影响行数为0就说明状态已被其他请求改掉了。4.4 接口文档示例写清楚请求和响应的完整结构接口文档里的核心接口我建议至少包含这样一个完整示例接口名称用户登录 URLPOST /api/auth/login 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|----------| | username | string | 是 | 用户名 | | password | string | 是 | 明文密码 | 响应成功示例 { code: 200, message: 登录成功, data: { token: eyJhbGciOiJIUzI1NiJ9.xxx, nickname: 张三, role: USER } } 响应失败示例 { code: 400, message: 用户名或密码错误, data: null }文档不需要花哨但要让一个从没看过你代码的人拿着文档就能知道请求怎么发、响应怎么解析。这玩意参加了工作以后更是基本素养。5. 前端Vue页面开发从登录态到核心页面实现思路5.1 前端工程结构应该如何组织二手车的Vue前端我一般按功能域拆成两个大区块前台用户端和后台管理端。目录结构大致如下src/ ├── api/ # 接口调用模块 │ ├── auth.js # 登录注册相关 │ ├── car.js # 车辆相关 │ ├── order.js # 订单相关 │ └── admin.js # 后台管理相关 ├── router/ │ ├── index.js # 路由实例 │ └── routes.js # 前端静态路由 ├── store/ │ ├── modules/ │ │ └── user.js # 用户状态 ├── views/ │ ├── home/ # 首页 │ ├── car/ # 车辆列表、详情 │ ├── user/ # 个人中心、发布车辆、我的订单 │ └── admin/ # 后台管理页面 ├── components/ # 通用组件 └── utils/ └── request.js # axios封装把api请求单独抽出来是我强烈建议的做法。不要在组件里直接axios.get而是统一封装成方法。比如getCarList(params)放在 car.js 里页面里只调用这个函数。这样当你后端接口路径变更时只需要改一个文件不用满项目搜索。5.2 登录态管理axios拦截器和路由守卫前端最重要的基础设施是两个axios拦截器和路由守卫。axios拦截器解决“每次请求自动带Token”和“遇到401自动跳登录页”这两个问题// 请求拦截器每次请求自动携带token service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }) // 响应拦截器统一处理业务码 service.interceptors.response.use( response { const res response.data if (res.code 200) { return res } else { // 统一错误提示 Message.error(res.message || 请求失败) return Promise.reject(new Error(res.message)) } }, error { if (error.response error.response.status 401) { localStorage.removeItem(token) router.push(/login) } return Promise.reject(error) } )路由守卫解决“未登录用户不能进入个人中心”这类问题router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.meta.requiresAuth !token) { next(/login) } else { next() } })5.3 车辆列表页的多条件筛选交互这是前端最复杂的一个页面也是你最能展示Vue水平的地方。设计思路是顶部放筛选表单品牌下拉、价格区间、里程范围、变速箱类型筛选条件用queryParams对象统一管理点击“搜索”时重置页码为1调用getCarList接口分页组件监听页码变化重新拉数据品牌下拉框的数据从后端接口动态加载表单校验这里有个细节价格区间用户可能只填上限或者只填下限前端要做默认值处理比如下限为空时传0上限为空时传null后端再处理。这看起来很简单但实际做联调的时候常见的问题就是前端传了个空字符串后端Integer类型接收直接报400。5.4 车辆详情页与预约、收藏、下单的交互车辆详情页是二手车系统的“门面页面”一般包括图片轮播主图详情图车辆参数表格品牌、车型年款、上牌时间、表显里程、排量、变速箱、排放标准、过户次数卖家信息卡片收藏按钮、约看车按钮、立即购买按钮一个需要注意的交互逻辑是未登录用户操作受限。当用户点击收藏、预约、下单时如果token不存在不应该让他进入请求流程而是直接弹窗跳转登录页。这个逻辑既可以写在每个按钮的点击事件里也可以写一个公共的checkLogin()方法统一处理。对于预约和收藏这种“一对一”关系前端还要处理一个状态当前用户是否已经收藏了这辆车、是否已经预约过。如果是按钮要变成“已收藏”“已预约”并且不可重复点击。这个判断最好在后端接口里也做一遍避免重复数据。5.5 后台管理页面表格状态切换的标准玩法后台管理页面的核心是那几套标准交互数据表格展示、条件搜索、状态修改审核通过/驳回、上下架、删除操作带二次确认、订单状态流转按钮根据当前状态显示/隐藏。车辆审核是高亮功能页。管理员打开一个列表看到所有status0的待审核车辆点“查看详情”弹出抽屉或独立页面核对车辆信息后点“通过”或“驳回”。这里要注意驳回的时候最好带上驳回理由让发布者知道为什么没过。后台审核表可以单独加一个 audit_log审核记录表存审核人、审核时间、审核备注。订单管理页则要根据不同状态展示不同操作按钮待支付订单可以取消已支付订单可以标记为完成已完成订单不能做任何操作。这让页面逻辑的复杂度和后端状态机形成了呼应答辩时你可以很自然地说“前端的按钮渲染条件是根据后端返回的状态字段控制的”。6. 项目部署打包、整套交付和答辩准备6.1 前后端如何整合成一个可演示的项目毕设项目最终最佳演示方式是让项目可以在本地一条命令跑起来或者至少是“前端打好了包、后端直接能启动”。实际操作中我建议把前端打包后的dist目录直接放到SpringBoot项目的src/main/resources/static目录下面让后端同时服务接口和静态页面。这样用户访问8081端口就是完整的前端页面接口也在同源下跨域问题直接消失。前端打包之前要把接口请求地址从相对路径改为相对路径/api然后通过nginx或者后端的路径映射做转发。如果直接放在static目录下还需要注意Vue Router的history模式刷新404问题。最稳妥的方案是前端路由使用默认的hash模式URL带#号打包后直接刷新不会404如果要用history模式后端需要做路径重写的路由转发把所有非/api的请求转回index.html对毕设演示来说hash模式完全够用根本没必要为了URL好看去折腾history模式。6.2 交付物清单让你的项目“看起来很完整”一个让人从第一印象就觉得“这项目做完了”的交付物应该长这样springboot-car-trading/ ├── backend/ # SpringBoot后端工程 │ ├── src/main/java │ ├── src/main/resources │ └── pom.xml ├── frontend/ # Vue前端工程 │ ├── src │ ├── package.json │ └── vite.config.js 或 vue.config.js ├── sql/ │ └── car_trading.sql # 完整建表和初始化脚本 ├── docs/ │ ├── 接口文档.md │ ├── 数据库设计说明.md │ └── 项目部署文档.md └── README.mdREADME里面至少写清楚项目简介、技术栈、启动步骤先运行SQL、再启动后端、再启动前端、默认账号管理员账号和测试用户账号、核心功能列表。这是必须整理的。因为评阅老师看项目的时候不可能先去读源码他是先看你的文档和脚本再看项目能不能跑起来。如果README连启动步骤都没有印象分会打很大折扣。6.3 答辩高频问题与回答思路我整理一下答辩时最常见的问题以及你该怎么回答为什么选用SpringBootVue前后端分离答案是分工清楚、职责明确。前端负责交互和展示后端专注业务逻辑和数据处理两者通过HTTP接口通信。开发期用Vue的代理解决跨域部署期前端打包进后端静态资源目录统一访问。你的项目有哪些亮点尽量少说“用了SpringBoot、Vue”这种满大街的废话要说跟业务绑定的东西。比如车辆上下架和订单状态流有明确的状态机约束多条件搜索使用动态SQL实现避免无效条件拼接发布车辆采用本地文件存储访问URL统一管理权限上做了前台用户与后台管理员角色区分接口层统一校验Token某一张表为什么这样设计最常被问到的肯定是car_info和car_order。回答思路是先说这张表承载的核心业务再说为什么有些字段单独建表比如品牌表、图片表是为了减少冗余、便于扩展最后说字段类型选择的原因价格用decimal、状态用tinyint。项目中有没有遇到比较棘手的Bug一定要准备一两个真实的Bug。例如跨域请求被浏览器拦截前排查后排查发现是后端CORS配置没生效车辆图片上传成功但前端访问404原因是静态资源映射路径没配置数据库时间字段存进去和取出来差了8小时原因是没设置时区说真实的踩坑经历比吹牛更有说服力。6.4 作为一个老学长最后想说的二手车交易系统这个题目最大的优点是上限高、下限也稳。你可以只做出基础版也能完全通过如果你想拿高分可以在基础之上扩展预约看车、询价、后台数据统计用ECharts展示车辆价格分布和品牌分布、甚至加入推荐算法。它不像纯管理系统那样难讲出亮点也不像复杂的电商秒杀系统那样你hold不住。实际操作中我个人的体会是这个项目的时间分配应该是数据库设计和接口文档占四成编码占四成部署和答辩准备占两成。千万不要急着写代码先把表结构和接口约定想清楚后端的编码效率会直线上升。很多人项目做到一半改字段、改接口都是因为前期设计功夫没到位。如果你决定做这个题动手的第一步不是创建SpringBoot项目而是先建库建表把brand表、car_info表的数据梳理好再按照我上面说的结构一步步填代码。当你把演示跑通、文档整理完你不仅有了一个能过的毕设也真的把一套完整系统的开发流程走了一遍。这些东西毕设答辩之后找实习、进项目组时照样用得上。
阅读完成 · 觉得有帮助?