SpringBoot+Vue+MySQL二手交易平台毕设全攻略:从环境搭建到答辩准备
毕设季又来了。SpringBootVueMySQL的二手物品交易平台这个组合几乎已经成了近两年计算机专业毕业设计里的“国民级选题”。后台我也被不少学弟学妹问过这个题目到底应该怎么下手源码拿到手要怎么跑起来论文怎么写才能过盲审答辩老师到底会问什么。说实话这类项目的技术难度并不算高核心就是一套典型的前后端分离CRUD应用但它胜在业务链路完整从用户注册、商品发布、浏览搜索到交易下单、订单管理每一环都能在论文和答辩里有话可说。这篇文章我不想再写那种“从零开始教你敲代码”的教程而是想以项目复盘的角度把这个毕设从选题、环境搭建、数据库设计、核心接口实现再到打包部署、论文整理、答辩准备的全过程拆开揉碎地讲一遍。里面会穿插我在实际开发和辅导过程中踩过的坑、总结的经验以及一些在网上很难搜到细节的注意点。无论你是刚拿到源码不知道怎么运行的小白还是准备自己从零独立完成整个系统的准毕业生这篇内容应该都能帮你省下不少时间。1. 这类选题为什么是毕业设计的“安全牌”先说一个判断二手物品交易平台这个方向放在毕业设计里属于典型的“下限不低、上限可观”选题。它不像纯算法类题目那样过度依赖数学推导也不像纯管理系统那样缺乏技术看点和业务层次。对于多数本科生而言选择一个业务复杂度适中、前后端技术栈主流、数据关系清晰的项目来做既能保证在有限时间内真正做出来、写得出论文又能让答辩老师觉得工作量和工程能力都达到了要求。1.1 核心需求拆解从“闲置交易”到功能清单当你打开一个二手交易平台不管是闲鱼还是转转其实核心需求就那么几块用户管理注册、登录、个人资料、商品管理发布、编辑、上下架、删除、商品浏览分类、列表、详情、搜索、交易链路下单、订单状态流转、互动收藏、评论、留言、后台管理用户管理、商品审核、分类管理、数据统计。把这些需求翻译成技术模块就是一套标准的RBAC权限模型加上商品与订单两大核心域。这也决定了你的数据库表结构大概会有多少张表用户表、角色表、权限表如果细做、分类表、商品表、图片表或图片路径字段、收藏表、评论表、订单表。做到这个颗粒度不管是演示系统还是写论文篇幅和深度都已经足够了。1.2 技术栈选型为什么是SpringBoot而不是SSH2018年以后SpringBoot基本已经取代了早期SSH或SSM组合在校园项目里的统治地位。原因很直接SpringBoot通过自动配置大幅减少了XML配置的工作量内嵌的Tomcat让你不用再单独部署WAR包一个java -jar就能把后端跑起来。前端选择Vue同理渐进式框架组件化开发配合Element UI之类的组件库可以直接“拼”出一个后台管理界面。MySQL作为关系型数据库在校园服务器的免费部署环境里也足够稳定。这个组合能成为毕设主流其实还有一个隐性原因学习资料极其丰富。遇到问题搜一下基本都有现成答案对自学的学生来说这一点比技术本身的前瞻性重要得多。1.3 前后端分离架构与部署形态这个项目默认采用前后端完全分离的架构后端跑在8080或你自己改的端口前端通过Vue脚手架开发开发环境下用proxy代理转发请求生产环境打成静态文件交给Nginx托管。前后端通过JSON格式的RESTful API通信鉴权用JWT。理解这套架构是做部署的最重要前提。很多同学运行项目失败根本不是代码问题而是根本没有理清浏览器、前端服务、后端服务、MySQL四者之间的关系。一句话总结浏览器访问Nginx拿到Vue静态页面Vue页面里的axios请求被代理转发到后端接口后端操控MySQL数据库并返回JSON数据前端再把JSON渲染成页面。后面所有部署步骤都是围绕这条链路来的。2. 从零跑通项目环境配置与常见翻车点很多同学拿到源码后第一件事不是看代码而是急着双击运行结果报一堆错误。其实只要环境底子没打好再好的源码也跑不起来。这一节我按自己的实操顺序把环境配置的完整链路和容易翻车的细节都梳理一遍。2.1 JDK版本与SpringBoot版本如何匹配二手交易平台这类项目主流依赖SpringBoot 2.x版本常见2.3.x、2.5.x、2.7.x。对应Java环境建议用JDK 1.8也就是Java 8这个组合兼容性最好。如果你用的是JDK 11甚至JDK 17SpringBoot 2.x也能跑但Maven编译时可能遇到一些需要额外处理的问题。判断方法也很简单打开后端的pom.xml看parent标签里的SpringBoot版本号2.x版本JDK 8或11都行推荐JDK 83.x版本必须配JDK 17及以上且部分依赖比如com.mysql的JDBC驱动要换成新坐标提示如果电脑上装了多个JDK跑项目前务必在IDEA里检查Project Structure中的Project SDK和项目的Language Level是否一致。很多“编译都过不去”的问题不是代码问题就是SDK选错了。2.2 MySQL 8.0安装与初始化细节数据库方面我个人建议用MySQL 8.0而不是5.7。8.0在性能、默认字符集、窗口函数等方面都更优而且现在网上大多数安装教程都基于8.0。安装时有两个点最容易踩坑第一个是安装类型选择。建议选“Server only”就行不需要装那一堆附带组件。到了Type and Networking这一步默认端口3306不要改除非端口被占用否则后续配置对不上。第二个是认证插件选择。MySQL 8.0默认的缓存认证插件是caching_sha2_password而一些旧版本的驱动或可视化工具可能不兼容直接在Development Machine模式下选“Use Legacy Authentication”可以避免后续连接报错。连接不上时先看服务有没有启动Windows下用net start mysql或到服务管理器里找MySQL服务Linux下用systemctl status mysqld。记住数据库起不来后面一切无从谈起。2.3 后端配置文件的敏感项SpringBoot项目里数据库连接信息统一写在application.yml或application.properties中。关键配置无非是这几项server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/second_hand?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 你的数据库密码 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8这里有一个非常重要的坑URL里的serverTimezoneAsia/Shanghai必须加。不加的话高版本MySQL驱动在插入时间字段时会直接报错。useSSLfalse同理因为本地开发环境一般没有配置SSL证书True会告警甚至失败。如果你的MySQL密码里有特殊字符如、#在YAML文件里必须加引号否则会被解析错误。2.4 前端环境Node版本和npm镜像Vue前端部分先用node -v和npm -v确认Node环境。Vue 2项目推荐Node 14或16不要一上来就装最新的Node 20否则可能因为依赖冲突导致npm install疯狂报错。装依赖时由于网络原因直接用官方npm源可能会卡死。建议提前切到国内镜像源npm config set registry https://registry.npmmirror.com然后进入前端目录执行npm install npm run serve如果install报错优先删掉node_modules目录和package-lock.json重新执行npm install。这个操作能解决七成以上前端依赖问题。还有一个小技巧如果报错信息里有node-sass那是老项目最有名的坑把sass-loader和node-sass换成dart-sass即可。Vue2项目里很多样式编译问题都出在node-sass上。3. 数据库设计毕业设计论文里最值钱的部分如果你是自己从零写系统数据库设计直接决定了后端的开发效率如果你是拿现有源码改看懂表结构是改需求的前提。二手交易平台的表设计其实非常典型我把核心表的字段和设计理由都列出来你照着建库就行。3.1 核心表结构设计清单第一张是用户表t_user。字段至少包含id自增主键、username唯一、passwordBCrypt加密后的字符串、nickname、avatar、phone、email、status1正常0禁用、create_time、update_time。这里有个细节密码字段长度至少设64因为BCrypt加密后字符串长度是60位如果字段只设20或32注册功能必炸。第二张是商品表t_goods。字段包含id、user_id发布人、category_id分类外键、title、description、price建议用DECIMAL(10,2)而不是FLOAT、original_price、cover_image封面图URL、images详情图可以用逗号拼接字符串存多个路径、status0在售1已售出2下架、view_count浏览量、create_time。第三张是订单表t_order。需要记录id、order_no订单编号、goods_id、seller_id、buyer_id、price成交价格、status0待付款1待发货2待收货3已完成4已取消、create_time、pay_time、finish_time。再往下就是t_category分类表、t_favorite收藏表、t_comment评论表。评论表记得pid字段父评论id这样后续如果需要做楼中楼回复不用改表结构。注意所有表都要有id自增主键和create_time字段这是基本习惯。物理外键能不加就不加逻辑外键在业务层控制。这一点既是主流开发规范也是答辩时能加分的点——说明你有实际工程意识。3.2 数据字典与SQL文件的整理技巧论文里一般会放数据字典E-R图和数据表说明。做一个技巧性的建议不要直接截Navicat的表结构图而是用SHOW CREATE TABLE 表名导出建表语句再整理成三线表放进论文规范程度立刻不一样。数据库文件方面一个是second_hand.sql这样的建库脚本建议包含库表结构、初始化数据和管理员账号。另一个是部署文档里要写清楚手动执行导入的过程mysql -u root -p CREATE DATABASE second_hand DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE second_hand; SOURCE /你的路径/second_hand.sql;3.3 初始化数据的必要性很多毕设源码导入数据库后一打开分类目录是空的、管理员账号也没有这就很尴尬。拿到源码后第一件事检查SQL文件里有没有基础数据。如果没有自己补几条商品分类比如数码、图书、服饰、生活用品、运动器材等再创建一个管理员账号用户名admin、密码123456存储时用BCrypt加密。演示系统有初始数据效果会好很多。4. 核心功能实现这些代码逻辑你必须懂毕设答辩时老师不一定会现场敲代码但一定会针对你写的核心模块提问。二手交易平台里下面这几个底层逻辑你最好都能讲清楚。4.1 登录鉴权JWT的原理和拦截器配置当前主流方案是JWTJSON Web Token用户登录成功后后端生成一个token返回给前端前端存在localStorage里之后每次请求在Header里带上Authorization: token值后端写一个拦截器统一校验。JWT的代码逻辑不复杂登录接口拿到用户名和密码用PasswordEncoder验证密码验证通过后生成token拦截器里解析token失败就返回401。但有几个细节需要注意token里不要存敏感信息比如密码只放userId和usernametoken要设置过期时间常见7天拦截器要放行登录、注册、轮播图和商品列表等接口。具体拦截器配置我贴一下核心思路public class JwtInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(Authorization); // 解析token失败则返回401成功则把用户id放入request属性 } }再在WebMvcConfigurer里把这个拦截器注册进去指定addPathPatterns和excludePathPatterns。这一套代码无论评审老师怎么追问你都能形成闭环。4.2 商品发布与图片上传商品发布是前端表单图片上传的组合操作。图片上传一般是后端写一个/api/upload接口接收MultipartFile流保存到本地磁盘或云存储OSS然后返回图片的访问URL。本地保存时要注意保存路径建议配置成绝对路径然后通过一个映射关系把磁盘路径暴露成HTTP访问地址。举个例子我在application.yml里配置file: save-path: /home/ubuntu/second-hand/images/ access-path: /images/**后端加一个资源映射配置Configuration public class WebConfig implements WebMvcConfigurer { Value(${file.save-path}) private String savePath; Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/images/**) .addResourceMapping(file: savePath); } }这样数据库里存的就是http://你的域名/images/xxx.jpg前端直接img展示。这个逻辑自己写一遍比单纯用OSS对象存储服务更能讲清楚原理答辩也更容易应对。4.3 分页搜索排序MyBatis-Plus还是手写SQL搜索功能通常涉及三个维度商品名称模糊查询、分类筛选、价格区间筛选。分页则是列表页的标配。有两种实现方式要么用MyBatis-Plus的分页插件要么手写SQL加LIMIT。推荐用MyBatis-Plus省事不容易出错LambdaQueryWrapperGoods wrapper new LambdaQueryWrapper(); wrapper.eq(StringUtils.isNotBlank(categoryId), Goods::getCategoryId, categoryId) .like(StringUtils.isNotBlank(keyword), Goods::getTitle, keyword) .orderByDesc(Goods::getCreateTime); PageGoods page new Page(pageNum, pageSize); goodsService.page(page, wrapper);注意使用分页插件需要在Config里注册MybatisPlusInterceptor并添加PaginationInnerInterceptor。如果忘记这一步查询会返回全量数据分页完全失效这是一个极其隐蔽的坑。4.4 订单状态机二手交易最核心的流程订单是整个系统里最能体现“业务逻辑”的地方。二手交易平台不需要像电商系统那样复杂的支付对接但订单状态流转还是要理清楚。我建议通过订单状态字段来控制操作按钮的显示买家下单后订单状态为待付款0此时买家可取消订单卖家看不到操作按钮买家模拟支付后状态变待发货1卖家可以发货卖家发货后状态变待收货2买家可以确认收货买家确认收货后状态变已完成3双方可以互相评价或发起售后在任意环节买家或卖家都可以取消订单状态变成已取消4在代码层面这是一个非常典型的switch分支逻辑。写的时候建议把状态流转单独封装成一个service方法比如orderService.changeStatus(orderId, fromStatus, toStatus)而不是在Controller里散落一堆if判断。5. 前端实现要点Vue项目改造和联调技巧很多人觉得前端就是“套模板”其实前端工作量一点不比后端少。尤其是从网上下载的源码不一定完全符合你的需求改起来如果不懂Vue的核心机制很容易改一个地方崩三个页面。5.1 路由与页面结构Vue2项目的页面结构一般是首页商品列表、商品详情页、发布商品页、个人中心、我的订单、购物车可选、后台管理页。路由用vue-router管理菜单位置用侧边栏组件控制。如果你需要新增页面公式是三步在views目录下新建vue文件在router/index.js里注册路由并引入组件在侧边栏菜单数组里加菜单项。后台管理的路由通常需要权限控制在路由守卫里判断用户角色是管理员比如用户角色值为1不是管理员就跳回首页router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.path.startsWith(/admin) token ! 管理员token标识) { next(/login) } else { next() } })5.2 axios封装与统一请求处理前后端联调时最烦的莫过于每次请求都要手动写token header、统一处理错误码。所以实际项目中一般会把axios封装成一个request实例在拦截器里统一处理import axios from axios const request axios.create({ baseURL: /api, timeout: 10000 }) request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization token } return config }) request.interceptors.response.use( response { const res response.data if (res.code ! 200) { this.$message.error(res.msg) return Promise.reject(new Error(res.msg)) } return res }, error { // 401跳转登录页 } )这样封装好之后所有页面请求统一走request即可不必每个组件都写拦截逻辑。封装要点有两个第一个是根据你的后端返回结构统一设计code、msg、data三层结构第二个是401状态token过期统一跳转登录页并清除本地缓存。5.3 Vite环境变量与跨域代理开发环境下前端跑在8080端口或9528端口后端跑在8080端口直接跨域。最简单的做法是利用Vue CLI的devServer代理配置在vue.config.js里写module.exports { devServer: { port: 8081, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } }这样前端请求/api/login会被代理转发到后端的http://localhost:8080/api/login避开了跨域问题。这里有个极易发生的前后端路径不匹配问题后端的Controller如果有个RequestMapping(/api)那么代理配置里的/api前缀就已经匹配上了。如果后端没有/api前缀前端代理就要写pathRewrite把/api去掉。查接口404时这一条排查方向优先看。6. 毕业设计论文怎么写才能过盲审论文是毕业设计的半壁江山。很多同学系统做出来了论文却写得像流水账结果盲审被挂。讲几个论文写作中需要注意的核心点。6.1 目录结构与各章字数配比一篇标准毕设论文的目录大致包括绪论研究背景、意义、国内外现状、相关技术介绍SpringBoot、Vue、MySQL、JWT、需求分析功能性需求、非功能性需求、用例图、系统设计架构图、功能模块、数据库设计、系统实现页面截图核心代码功能描述、系统测试测试用例表、测试结论、总结与展望。说白了老师最看重的是需求分析和数据库设计这两章这两章要细写。技术介绍那章不要像抄百度百科那样堆砌控制在6到8页即可重点是结合项目说明“为什么选它”。系统实现那章每页最好贴页面截图配合少量核心代码做说明。纯文字大段贴代码反而是大忌。6.2 需求分析和用例图这样画才规范需求分析这一章可以从三个角色出发普通用户、卖家可以和服务端交互的买家、系统管理员。画用例图时用户角色能执行的操作是注册、登录、浏览商品、搜索商品、发布商品、编辑商品、下单、收藏、评论管理员角色能执行的是用户管理、商品审核、分类管理、数据统计。在画用例图时先从业务层面抽象出“谁能做什么”画出用例图再对核心用例做文字描述包括用例名、参与者、前置条件、基本事件流、后置条件、异常事件流。这种标准写法答辩老师一看就知道你有需求工程的底子。6.3 测试部分的测试用例一定要真实测试章写系统测试时很多同学会编造测试用例或者随便填“功能正常”。我的建议是用一个表格编号、测试项目、操作步骤、预期结果、实际结果、是否通过。列出15到20条用例覆盖用户注册、重复注册、错误密码登录、发布商品字段校验、搜索关键字、分页、下单、非法访问拦截等。这些用例在实际系统里跑一遍拍照记录结果论文真实感和丰满度立刻就有了。7. 部署上线最容易踩的5个坑部署环节是答辩的加分项也是很多同学第一次把项目搬到服务器上时最容易崩溃的环节。这里我直接把最常见的5个坑列出来并且把避坑方法一起写清楚。7.1 MySQL时区导致的时间差八小时这个问题我在本地开发时也遇到过。部署到服务器后MySQL使用UTC时区Java使用本地时区导致插入数据库的时间比真实时间少了8小时。解决方案是在JDBC连接串上加serverTimezoneAsia/Shanghai本地这道工序不必再做同时在application.yml里增加一条spring: jackson: time-zone: GMT8如果查询出来前端显示还是差8小时那就是返回前端的JSON序列化时区问题。前后端一起改百试百灵。7.2 后端端口被防火墙拦截前端部署到服务器后浏览器访问页面没问题但一调接口就超时。排查时先确认后端是否启动成功然后检查服务器安全组规则。Linux服务器上以下命令可以快速查看端口监听状态netstat -tlnp | grep 8080 firewall-cmd --list-ports如果用的是云服务器还要到云控制台的安全组里放行8080端口和80端口。很多学生卡在这一步好几个小时其实就是安全组没配。7.3 图片上传后访问404很多毕设里图片上传保存路径是相对路径比如upload/项目打包后部署在任何目录图片路径就会被解析到不同位置。所以部署时必须配置统一的绝对路径并确保该目录有写权限。可以在Linux里执行mkdir -p /home/ubuntu/second-hand/images chmod -R 755 /home/ubuntu/second-hand/images然后imagePath配置指向这个目录。如果图片能上传却不能访问先检查Spring Boot的静态资源映射是否存在再检查浏览器请求的图片URL路径是否匹配。7.4 打包时跳过测试的坑Maven打包时默认会执行单元测试如果你的项目里引入了测试依赖且测试类写得不完善mvn package经常会卡在测试环节。一个简单粗暴的做法是mvn clean package -DskipTestsIDEA里也可以在Maven面板点击clean和package同时勾选Skip Tests。但这里要说清楚-DskipTests只是不执行测试代码但代码编译仍然是会进行的。如果你的代码有语法错误一样会打包失败。这个命令解决的是“测试耗时、测试报错连累打包”的问题。7.5 前端打包路径问题Vue项目执行npm run build后生成dist目录这个目录里的index.html要交给Nginx托管。如果项目路由使用的是history模式刷新页面会出现404这时Nginx需要配置try_fileslocation / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; }如果不想处理这类服务器配置也可以把路由改成hash模式直接避免刷新404问题。这里提醒一点部署到服务器后前端页面所有的接口请求路径都要能拼对。如果你开发环境用的是/api代理那生产环境的反向代理也需要把/api转发到后端端口location /api/ { proxy_pass http://localhost:8080/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }7.6 一个完整的服务器部署流程示例把前面零散的操作串起来在全新的Linux服务器上部署这套项目完整的命令流程大致是这样安装JDK和MySQL启动MySQL并导入数据库文件上传后端jar包写一个启动脚本使用nohup java -jar xxx.jar run.log 21 后台启动安装Nginx把前端dist目录上传到指定目录配置静态托管和/api反向代理浏览器访问服务器IP如果显示首页说明部署成功。之后如果再想更新后端代码就杀掉旧进程重新启动新jar包就行。8. 常见Bug排查实录与避坑指南最后这部分我把自己和身边同学实际运行这套系统时遇到概率最高的几个问题整理成速查表每个问题都给排查顺序很多问题其实是同一根因的连锁反应。8.1 后端启动报错现象排查思路解决方案Application run failed先看关键异常信息数据库连接失败还是端口占用数据库检查配置端口改用netstat查占用Access denied for user用户名或密码错误或没有远程权限重置密码或授权Loading class com.mysql.jdbc.Driver驱动类名写错改成com.mysql.cj.jdbc.DriverFailed to bind to 8080端口被占用换端口或kill占用进程启动失败最有效的排查方式其实是看日志不要只看红色异常的第一行要看Caused by后面的原始原因真正的问题往往藏在最底层。8.2 前端页面白屏或接口404前端白屏大概率是路由配置问题或组件引入错误浏览器F12打开控制台按JS报错信息逐行排查。接口404优先检查路径拼接看浏览器Network面板发出的请求URL和后端Controller的RequestMapping是否完全一致。这一步可以配合后端的日志确认后端是否真的收到了请求以及返回的状态码和响应体是什么。8.3 验证码或登录功能正常但其他接口全部401这个问题通常是拦截器把不需要鉴权的接口也拦截了。排查方法是在拦截器配置的排除列表里把商品搜索、轮播图、商品详情等公开接口加进去。更稳妥的做法是设计一个允许匿名访问的路径白名单放行后再统一校验其他接口。8.4 中文乱码问题数据库乱码基本是字符集不统一导致的。确认三处字符集都为utf8mb4数据库表的字符集、JDBC连接串添加characterEncodingutf8、前端页面的meta charsetutf-8。前端页面如果出现乱码检查HTML头部是否设置字符集如果是JSON返回乱码检查后端响应设置。8.5 商品图片不显示商品图片不显示涉及三个环节图片物理文件是否保存在指定目录、数据库里存的URL是否能通过浏览器直接访问、访问路径是否被鉴权拦截。按这个顺序排查五分钟内基本能定位问题。实际案例中超过一半的情况是数据库存的地址不带域名或带了前后端不一致的端口导致图片无法加载。8.6 前端显示跨域开发阶段跨域用代理解决部署阶段用Nginx反向代理解决。如果前端项目本身是5.0版本之前的VueCli脚手架跨域报错还会因为proxy配置没有重启生效而出现。记住改vue.config.js后必须重启npm run serve。9. 一些做完这个项目后的个人感想带过不少学弟学妹做类似的毕设项目我个人的体会比较一致二手交易平台这个题目难度不高但“麻雀虽小五脏俱全”。做完一遍对于开发流程最大的收获不是背会了某个框架API而是真正理解了“一个需求是怎么一步步变成数据库表、再变成接口、再变成页面的”。这一条链路就是企业做业务系统的基本盘。如果时间充裕我强烈建议在基础功能之上做一些有区分度的创新。比如把商品推荐从简单的分类筛选升级为基于浏览记录的内容推荐或者在订单流程里加入更加完善的评价体系甚至在视觉上参考主流二手应用做更细节的交互。这些能在论文的创新点里大书一笔也是答辩时“超出预期”的最好素材。最后分享一个实用小技巧数据库SQL文件和部署文档一定要在整个项目完成后重新整理一遍每次运行都从头到尾跑一遍。很多项目源码分享出来跑不通不是代码问题是数据库和配置文档对不上。梳理清楚这最后一步你的项目完整度会超过绝大多数同龄人。希望这篇博文能帮每个正在为毕设头疼的同学少踩几个坑。