开始前的三件事先把“拿到代码”变成“看懂代码”如果你手里正好是这套 Spring Boot 校园二手交易平台lca16我猜你现在最想干的不是看功能介绍而是赶紧让它跑起来。这个心情我很理解因为我前后帮几十位同学调过类似的项目。学期末那段时间几乎每天都有同样的问题冒出来“代码下载好了但启动报错”“数据库导入失败”“页面出来了但图片不显示”。一路排查下来90%的锅都不在业务代码而在开发环境、依赖版本、数据库初始化这几步。这篇文章不打算把它当商品介绍写而是站在“我接手了一套完整源码后该怎么落地”的角度把环境搭建、数据库设计、核心功能拆解、调试部署、答辩改造这整条链路讲透。文章里所有配置和步骤都按这套项目最常见的组合来给——Spring Boot 2.x MySQL MyBatis Plus这也是我实测下来课设项目里踩坑最少的组合。适合正在做课程设计、毕设选型或者想找一个完整项目吃透 Java 全栈开发流程的同学。如果你希望的是“拿到就能演示、看懂还能回答提问”那这篇文章就是照着这个目标写的。这中间我会把我实际踩过的坑、帮别人排过的错、答辩时老师爱问的问题都揉进去尽量让这篇东西不仅能帮你跑通项目还能让你在跑通之后对每个模块为什么这么设计心里有数。1. 为什么校园二手交易是 Spring Boot 课设项目的“常青树”1.1 需求真实场景自带说服力先说一个很多同学忽略的点做课设选题目最怕的不是功能多而是功能“假”。有些题目一眼就暴露是虚构需求——比如一套“小区物业管理系统”除了管理员自己录入根本看不出有什么真实使用场景答辩时老师问一句“这个系统解决什么问题”很容易卡住。而校园二手交易这个方向需求是天然存在的每个学校都有毕业季学长学姐甩卖教材、考研资料、电风扇、显示器的时候也有新生开学想淘便宜代步工具的刚需。这类项目天生就有三个角色买家、卖家、管理员。买家要浏览、搜索、下单、付款或者站内留言沟通卖家要发布商品、上下架、管理订单管理员要审核商品、管理用户、处理举报或违规信息。三条线一交叉业务流程立刻立起来了不是那种一个人就能自娱自乐的假系统。所以你写论文、做答辩PPT的时候第一页就可以直接写本系统针对高校内二手物品流转效率低、信息分散在学生群和贴吧的痛点提供一个集中的线上交易平台。这句话一出来评委就知道你做过需求分析。1.2 技术覆盖面恰到好处难度不会失控我自己看过不少课设题目有的过于简单比如“学生信息管理系统”本质上就是一张表的增删改查做完之后你自己都不好意思写在简历上。有的又过于复杂比如“基于微服务的电商平台”一个课设拆成十几个服务最后连本地联调都跑不通更别提写论文了。校园二手交易平台刚好处在一个非常舒服的中间档位它不是一个纯 CRUD 系统因为订单有状态流转、商品有上下架规则、用户有角色权限这些是真正的业务逻辑但它又没有复杂的支付对账、库存扣减、分布式事务难度完全撑得住一个学生的独立开发。Spring Boot 里最常见的几块能力这个项目全都能碰到分层架构Controller、Service、Mapper 三层理解 Java 后端的基础组织方式数据库设计至少五六张核心表外键关系、索引、状态字段都要考虑文件上传下载商品图片的存储与访问这是真实系统逃不开的环节分页与模糊搜索商品列表、关键词筛选是 MyBatis Plus 最典型的使用场景权限控制登录状态校验、管理员拦截器涉及 Filter/Interceptor 的实战用法打包部署最终产物是一个可运行的 JAR 包能演示从本地到服务器的完整部署流程。这些能力不只是课设要用你以后面试实习简历上写着“熟悉 Spring Boot”面试官默认你会的东西基本也就是这一层。所以这个项目的价值不是“交差”而是用最小成本把 Java 后端的主干流程走一遍。1.3 比“商城”轻但比“管理系统”重正好卡在答辩点有人会问那直接做个淘宝商城不更高级问题在于复杂度。商城系统需要考虑支付网关对接、库存扣减并发、物流状态同步这些一旦展开就是一个完整商业项目的工作量课设时间根本兜不住。二手交易平台不一样它的每一单都是“一人一物一价”没有 SKU、没有库存数、没有购物车结算这种复杂的联合逻辑交易流程可以简化为“发布—沟通—拍下—完成”逻辑清晰又完整。从答辩角度讲老师最喜欢问的几个问题也正好落在这个复杂度区间里你这个订单状态是怎么设计的有哪些状态怎么流转用户下单的时候如果另一人先下了单你怎么保证商品不会被重复卖图片是怎么存的换一台电脑部署为什么图片还能正常显示拦截器是怎么做的哪些接口需要登录才能访问这些问题说难不难但确实需要有项目深度才能答得顺畅。把这篇文章后面几章看下来这些问题基本都能接住。2. 开发环境与依赖版本90%的项目跑不起来根因都在这一层2.1 版本匹配是第一个真正的坑很多同学拿到源码第一件事是用 IDEA 直接打开然后 Maven 就开始疯狂下载依赖最后报一堆看不懂的错。这里我先把最稳妥的版本组合列出来你按这个来能少走至少两天的弯路。组件推荐版本原因说明JDK1.8Java 8市面上大量课设项目基于 JDK 8 开发兼容性最稳答辩机器也好配Spring Boot2.7.x2.x 时代生态资料最多网上随便搜到的问题解决方案基本都是这个版本Maven3.6.3 及以上太老的 Maven 可能解析不了 Spring Boot 父依赖MySQL5.7 或 8.05.7 最省心如果必须用 8.0JDBC 连接串要加时区参数IDEA2021.x 及以上新版 IDEA 对 Maven 和 Spring Boot 的支持更友好这里要专门提一句如果你拿到的项目是基于 Spring Boot 2.x 的不要手贱去升级到 3.x。Spring Boot 3 从 Java 17 起跳很多老依赖的坐标和用法都变了光是 javax 包改成 jakarta 就能让你多排查一整天。课设项目的目标是稳定跑通不需要追新。2.2 Maven 配置三件套Maven 配置是最容易被忽略的环节尤其是网络环境不好的时候依赖下不动、下到一半断了、仓库里存了半截文件全都会导致启动时报 ClassNotFoundException 或者莫名其妙的包冲突。我拿到新电脑配 Maven 的时候固定做三件事第一件改 Maven 镜像源。打开 Maven 安装目录下的conf/settings.xml在mirrors里加一段mirror idaliyun/id mirrorOfcentral/mirrorOf nameAliyun Maven Mirror/name urlhttps://maven.aliyun.com/repository/public/url /mirror加完之后再到 IDEA 的 Settings - Maven 里把 User settings file 指向这个 settings.xml并且确认 Local repository 路径没有包含中文字符。很多人项目跑不起来纯粹是因为本地仓库路径里有中文或者空格Maven 解析出错。第二件设置 IDEA 的编码。在 Help - Edit Custom VM Options 里加一行-Dfile.encodingUTF-8然后 Settings - Editor - File Encodings 里把 Global Encoding、Project Encoding、Default encoding for properties files 全部选成 UTF-8。这一步不做好后面导入数据库时中文注释乱码、页面显示乱码你还会以为是代码问题。第三件检查 Lombok 是否可用。课设项目里几乎必定用 LombokData那套IDEA 需要安装 Lombok 插件并且在 Settings - Build - Compiler - Annotation Processors 里勾选 Enable annotation processing。少了这一步编译期看着很正常一运行就报“找不到 getter/setter 方法”。2.3 数据库导入的顺序与常见报错环境配好、依赖拉完之后下一步是导数据库。这个环节我见过太多人出错集中表现为三种情况。第一种没建库直接导。正确顺序是先启动 MySQL然后执行CREATE DATABASE IF NOT EXISTS campus_second_hand DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE campus_second_hand;建库语句执行完再导入.sql文件。如果你拿到的 SQL 脚本里自带CREATE DATABASE那可以直接跳过手动建库但要注意看脚本里的库名是否和application.yml里配置的一致不一致照样报Unknown database。第二种MySQL 8.0 的时区问题。如果启动项目后报错The server time zone value Öйú±ê׼ʱ¼ä is unrecognized这就是时区导致的。在application.yml的 JDBC 连接串末尾加上serverTimezoneAsia/Shanghai就行完整写法类似url: jdbc:mysql://localhost:3306/campus_second_hand?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/ShanghaiuseSSLfalse第三种Linux 环境下表名大小写敏感。这个坑在校验阶段最隐蔽。如果代码里查的是user表但 SQL 脚本里建的是UserWindows 本地一切正常Linux 服务器上就会报“Table doesnt exist”。要么统一全部小写要么在建表脚本里保持大小写一致并配置lower_case_table_names1MySQL 8.0 在 Linux 上最好在建库前改改完需要重启 MySQL。提示导入 SQL 后用 Navicat 或命令行的SHOW TABLES;看一眼确认表数量和数据行数都对得上再启动项目。这一步 30 秒能省后续排查一小时。3. 数据库设计是整套系统的逻辑底盘3.1 核心表结构与字段设计说句实话课设项目的后端代码只要照着 Controller - Service - Mapper 三层写基本都能看懂但数据库设计才是拉开档次的地方。校园二手交易平台最常见的设计是六张表用户表、商品表、订单表、购物车表、收藏表、留言表。有些版本会有细微差别比如用“收藏/关注”替代购物车或者加一张商品分类表。不管哪种核心关系是类似的。用户表user字段类型说明idint主键自增usernamevarchar(50)用户名唯一passwordvarchar(100)BCrypt 加密后的密码串nicknamevarchar(50)昵称phonevarchar(20)手机号avatarvarchar(255)头像路径roleint角色0 普通用户1 管理员create_timedatetime注册时间商品表goods字段类型说明idint主键自增seller_idint卖家 ID关联用户表titlevarchar(100)商品标题descriptiontext详细描述pricedecimal(10,2)售价original_pricedecimal(10,2)原价或参考价categoryvarchar(50)分类图书/数码/生活用品等imagesvarchar(1000)图片路径多张用逗号分隔statusint状态0 在售1 下架2 已售view_countint浏览量create_timedatetime发布时间订单表orders字段类型说明idint主键自增order_novarchar(50)订单编号唯一goods_idint商品 IDseller_idint卖家 IDbuyer_idint买家 IDpricedecimal(10,2)成交价statusint见下方状态机create_timedatetime下单时间finish_timedatetime完成时间可空留个言/消息表message的设计要点是要有from_user_id、to_user_id、goods_id可选方便从商品页直接跳转到聊天、content、create_time。它解决的是买卖双发站内沟通的问题相当于把“贴吧留言”和“私聊”合在了一张表里。3.2 状态字段为什么用 int 而不用字符串这是答辩高频问题。商品状态和订单状态很多同学喜欢在数据库里直接存字符串比如status 已付款查询显示倒是直白了但坏处很多一是中文状态没法做有效索引二是业务代码里到处是魔法字符串改一个状态文案要同时改数据库的存量数据三是前端显示层和服务层耦合——数据库存的是给人看的文案代码判断时就变得很奇怪。项目里用 int 状态码然后在代码里定义一个常量类或者直接用枚举才是正常的设计方式。比如订单状态我一般这样设计状态值含义说明0待确认买家拍下等待卖家确认或等待买家付款1进行中已确认等待线下交付2已完成交易闭环双方确认完成3已取消任意一方取消或超时取消对应到代码里就是一组常量public class OrderStatus { public static final int PENDING 0; public static final int PROCESSING 1; public static final int FINISHED 2; public static final int CANCELED 3; }这样 Controller 和 Service 里判断逻辑一读就懂if (order.getStatus() OrderStatus.CANCELED)数据库里的数据也干净业务扩展时加一个状态值就行不用动存量数据。3.3 外键到底要不要物理建数据库设计时还有一个常见的纠结要不要给外键加物理约束我的建议是课设项目完全可以用逻辑外键也就是普通字段 索引不要建物理外键。原因一是导入数据的时候物理外键对插入顺序有要求非常容易报错原因二是 MyBatis Plus 这种框架操作数据时物理外键反而会影响一些批量操作原因三是真实企业项目里物理外键用得也越来越少面试时候你反而可以解释“用逻辑外键是为了保持高并发场景下的写入灵活性”。但逻辑外键不是说不管关联而是需要在关联字段上建索引。比如订单表的goods_id、seller_id、buyer_id都应该有索引否则查询订单列表时全表扫描数据一多就慢。实际执行可以这样ALTER TABLE orders ADD INDEX idx_seller (seller_id); ALTER TABLE orders ADD INDEX idx_buyer (buyer_id); ALTER TABLE orders ADD INDEX idx_goods (goods_id);这一点做好了答辩时老师问“你这系统数据量大怎么办”你就能直接说核心查询字段建了索引并对订单按用户维度进行了索引覆盖。4. 核心功能模块实现思路不是所有代码都叫 CRUD4.1 注册登录密码加密是底线中的底线有个别同学为了图省事注册时直接把密码明文存进数据库登录时把用户输入的密码select * from user where username? and password?查一遍。这样确实能跑通但这属于项目里最大的硬伤答辩被问到“密码安全怎么处理”会非常尴尬。正确做法是使用BCryptPasswordEncoderSpring Security 框架里自带这个工具类单独引进来用也行。用法很简单// 注册时加密 BCryptPasswordEncoder encoder new BCryptPasswordEncoder(); String encodedPassword encoder.encode(user.getPassword()); user.setPassword(encodedPassword); // 登录时校验 boolean matches encoder.matches(rawPassword, user.getPassword());这样做的一个好处是就算数据库被导出了别人拿到的也是一串不可逆的密文原始密码不会被泄露。登录之后的会话保持课设项目通常用 Session 就够了也就是登录成功后把用户 ID 或用户对象放进 Session然后写一个拦截器对需要登录的接口做校验。如果项目做了前后端分离比如前端是 Vue那就用 JWT 更合适但课设里大多数是 Spring Boot 直接渲染页面Session 方案最简单、也最好演示。4.2 商品发布与图片上传路径设置的坑最多商品发布功能一般包括表单提交 图片上传。图片上传的代码很多教程有最容易被忽略的是存储路径。如果直接把图片保存成绝对路径比如D:/upload/xxx.jpg然后存进数据库项目一旦换一台电脑部署路径全废所有图片全部加载不出来。这是个非常典型的问题因为课设项目经常要在不同机器上演示。我建议的做法是在配置文件里定义一个自定义属性存的是上传根目录的相对位置然后用 Spring Boot 的静态资源映射把它暴露出去。示例配置如下app: upload-dir: ./upload/Configuration public class WebMvcConfig implements WebMvcConfigurer { Value(${app.upload-dir}) private String uploadDir; Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadDir); } }这样上传的图片保存到项目运行目录下的upload/文件夹数据库里只存相对路径/upload/xxx.jpg前端渲染时直接拼上域名和上下文路径就能访问。换电脑部署时只要把整个项目目录拷过去、保证./upload/存在即可。文件上传的接口里要顺手做两件事校验文件类型和后缀只允许jpg、png等常见图片格式限制文件大小比如 2MB。别小看这一步不限制的话一个超大文件就能耗尽你的本地磁盘资源。4.3 商品搜索、分类筛选与分页商品列表页要支持按关键词模糊搜索、按分类筛选、按价格排序、分页显示。这个功能如果用 MyBatis Plus 自带的能力可以写得很简洁。核心是用LambdaQueryWrapper构造查询条件LambdaQueryWrapperGoods wrapper new LambdaQueryWrapper(); wrapper.eq(Goods::getStatus, 0) .like(StringUtils.hasText(keyword), Goods::getTitle, keyword) .eq(StringUtils.hasText(category), Goods::getCategory, category) .orderByDesc(Goods::getCreateTime); PageGoods page goodsMapper.selectPage(new Page(pageNum, pageSize), wrapper);这里最关键的一个点搜索的时候一定要加上status 0在售这个条件否则下架商品和已售商品会一起出现在列表里。这个问题我在验收同学代码时见过太多次了看起来只是少加了一个eq但整个列表页的逻辑就错了。分页插件如果要生效别忘记在配置里加 MyBatis Plus 的分页拦截器Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }不加这个返回的Page对象里records会一直是全部数据分页等于没分。这也是一个常见的“代码看着对跑起来不对”的坑。4.4 订单流程与并发控制防止同一件商品被卖两次订单模块是这个项目最有含金量的地方。下单操作不能只是一个简单的insert因为这里存在一个天然的并发问题一件商品如果两个买家几乎同时下单怎么办如果代码是“先查状态状态为 0 再更新”这种两步操作那就存在间隙两个请求可能同时查到状态是 0然后都执行下单成功商品就卖重了。课设级别的合理解法是在更新商品状态时加上条件用原子操作解决Transactional public boolean createOrder(Order order) { // 先把商品从“在售”改成“已售”只允许 status0 成功 int updated goodsMapper.update(null, new LambdaUpdateWrapperGoods() .eq(Goods::getId, order.getGoodsId()) .eq(Goods::getStatus, 0) .set(Goods::getStatus, 2)); if (updated 0) { // 抢不到说明商品已被下单或下架 return false; } // 更新成功才插入订单 orderMapper.insert(order); return true; }这段逻辑的关键在于update ... where id? and status0数据库的行锁会保证同一时刻只有一个请求能改状态另一个请求更新影响行数为 0直接返回失败。这样代码又短又安全而且答辩时非常好解释——你用的是“乐观锁思想”不是那些听起来很高深但很难实现的分布式锁。需要注意的事务问题Transactional默认只捕获 RuntimeException 回滚如果orderMapper.insert抛的是 checked exception事务不会回滚。所以下单这种场景代码里最好只抛运行时异常或者在注解上显式指定rollbackFor Exception.class。4.5 管理后台拦截器与权限控制管理员功能一般比较直白商品管理、用户管理、订单管理、数据统计。但这里有一个很容易被导师挑刺的点——权限控制不能只在页面上隐藏入口后端接口同样要拦住。你不能让一个普通用户通过直接访问/admin/deleteUser的 URL 就能把用户删了。实现方式是写一个拦截器注册时只放行登录接口、注册接口、商品列表和详情等公开接口其余接口都检查 Session 里有没有用户管理员相关的接口再检查role是否为 1。示例结构Component public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); User user (User) session.getAttribute(user); if (user null) { response.sendRedirect(/login); return false; } return true; } }通过注册配置把拦截器作用在/admin/**和需要登录才能访问的路径上。这个设计简单有效也是课设项目里“权限控制”的标准答案。5. 调试部署的完整链路从源码压缩包到云服务器上线5.1 本地跑通项目的正确顺序拿到源码后我的建议是按照下面这个顺序逐步推进不要跳步也不要一上来就点 Run先读项目根目录的 README 或部署文档看清数据库脚本位置、默认账号密码、启动端口建好数据库并导入 SQL 脚本确认表和数据都正确修改application.yml里的数据库账号密码、端口号等用 IDEA 打开项目等待 Maven 依赖解析完毕观察没有报错启动启动类里的main方法看控制台日志是否输出了Tomcat started on port(s): 8080浏览器访问http://localhost:8080用项目自带的管理员账号登录后台。如果前面环境配置都做对了这六步一般半小时就能走完。一旦卡住先看控制台日志的最后三行绝大多数报错原因都会比较明显。5.2 本地调试中最高频的坑这里把我遇到过的高频问题整理成一张表每一条都是真实场景里反复出现的。现象根本原因解决要点Access denied for user rootlocalhostyml 里的数据库账号密码不对检查application.yml的 username/password 是否和本地 MySQL 一致Unknown database库名写错或库没建用CREATE DATABASE建库核对库名Communications link failureMySQL 服务没启动Windows 下启动 MySQL 服务或确认端口 3306 没被占用Port 8080 was already in use端口被其他程序占用换端口server.port8081或关掉占用进程Cannot load driver class: com.mysql.cj.jdbc.Drivermysql-connector 没引入或版本不对在 pom.xml 检查依赖确认版本和 Spring Boot 兼容Whitelabel Error Page页面路径映射错误或 Controller 返回的视图不对检查 Controller 的返回字符串和templates下的页面文件名是否匹配数据库中文乱码连接串编码不对或数据库字符集不对连接串加characterEncodingutf-8建库用utf8mb45.3 打包部署到云服务器的过程本地跑通了接下来要部署到服务器上。先打包mvn clean package -DskipTests这里如果不加-DskipTestsMaven 会去跑单元测试很多课设项目里测试类其实是空的没必要额外浪费时间。打包完成后target目录会生成一个可执行的xxx.jar这个 JAR 就是整个后端应用。把 JAR 包上传到服务器后在服务器上执行nohup java -jar campus-second-hand-0.0.1-SNAPSHOT.jar --spring.profiles.activeprod app.log 21 nohup配合是为了让应用退出 SSH 之后继续运行。日志输出到app.log后续排查问题直接看这个文件。启动完成后用tail -f app.log观察日志看到 Tomcat 端口启动成功就说明部署没问题了。5.4 部署到服务器后最容易忽略的三件事第一安全组端口要开。云服务器有个由安全组控制的防火墙你得在控制台把 8080 端口或者你自定义的端口加入放行规则否则外面访问不了。第二数据库不要直接暴露公网。如果你用的是云数据库尽量让后端应用通过内网连接如果你用的是服务器本地 MySQL就不要在安全组里开放 3306 端口。只有后端服务的 8080 端口需要开放。有些同学图方便把 3306 也开放了结果服务器被扫库攻击、数据被删这类教训在安全新闻里经常看到。第三生产环境配置要改。application.yml里如果开发环境开了spring-boot-devtools热部署打包部署时一定要注释掉或者用 profile 区分否则服务器上会有意外重载。数据库密码、密钥等信息不要在配置里写明文可以用环境变量覆盖。6. 答辩前做这几个改造项目档次直接高一截6.1 用一个接口文档让老师看到你的工程化思维很多同学把代码跑通就觉得完事了但答辩时最尴尬的瞬间是老师想看某个接口返回什么你在 browser 里手忙脚乱地输 URL。我的建议是加一个 SwaggerSpringfox 或 springdoc 都行让所有接口自动生成联机文档。在 Spring Boot 2.x 里用 springdoc 的路径很顺加依赖后在配置文件里开启启动项目访问http://localhost:8080/swagger-ui.html能看到每个 Controller 的请求方式、参数说明和返回结构。这一招在答辩现场的效果远好于贴代码老师会觉得你具备基本的工程规范和自查能力。6.2 加一层 Redis 缓存应对“性能优化怎么做”这个问题“性能优化”是老师必问的题。校园二手交易平台首页的商品列表、热门分类这些数据是热点数据完全可以在 Service 层加一层缓存。引入 Redis 后查询商品列表时先查缓存命中就直接返回没有命中才查数据库然后回填缓存并设置过期时间。课设里你不一定要真的把 Redis 用得多深只需要说明这个思路、再写一个简单的 Service 层缓存逻辑就能证明你理解缓存是什么、为什么缓存能扛高并发读。答辩时老师问“如果这个系统用户量涨了十倍怎么办”你就可以回答读多写少的场景优先用 Redis 做缓存商品详情这一类热点数据可以设置短过期时间同时把搜索热词也做缓存。这一套回答下来已经能覆盖大部分期待了。6.3 把图片从本地存储改成云存储如果项目时间还有富裕建议把图片上传从本地目录迁移到 OSS 或七牛云这类对象存储。改造思路不复杂上传接口接收到文件后直接把文件流交给云存储 SDK云存储会返回一个 URL数据库里存这个 URL页面加载图片时直接走 CDN。这个改造的收益非常大因为它同时解决了三个课设常见问题换机器图片丢失、本地磁盘压力、外网访问慢。而且答辩时你还能顺带解释“为什么真实项目中不用本地存储”因为需要水平扩展、图片访问要 CDN 加速、存储要和应用服务器解耦。哪怕代码没有完全跑通把这个设计讲清楚老师也会认为你理解到了生产环境的要求。6.4 答辩常被追问的问题清单最后把我这几年听到的高频提问列一下提前准备避免现场卡壳Spring Boot 的自动配置原理是什么为什么写一个main方法就能启动应用为什么密码要用 BCryptMD5 有什么问题答案重点是MD5 加彩虹表可反查BCrypt 自带盐且计算成本可调数据库表为什么会这么设计有没有冗余第三范式你了解吗商品列表的分页是怎么实现的为什么自定义分页 SQL 时数据库方言很重要拦截器和过滤器有什么区别你的权限控制为什么选拦截器如果用户同时下单你怎么保证不超卖你用到了事务事务隔离级别是什么这个项目如果部署到线上你觉得最大的风险是什么可以回答防盗链、图片恶意上传、接口防刷这些问题在本文对应的章节基本都有答案建议看完之后自己对着代码再走一遍做到不用翻笔记也能讲清楚。最后再分享一个小技巧。拿到任何一套 Spring Boot 项目先别急着打开代码花二十分钟把三个东西看完数据库脚本、application.yml配置、启动类和拦截器注册类。这三样是项目的“地图”看懂了它们你对整套系统的理解会比 80% 的同学都深。这个顺序不仅适用于这套校园二手交易平台也适用于你以后实习、工作中接手任何一套陌生代码库亲测有效。希望你顺利跑通顺利答辩。
阅读完成 · 觉得有帮助?