ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SpringBoot+SSM垃圾分类回收网站全解析:从表设计到项目答辩

SpringBoot+SSM垃圾分类回收网站全解析:从表设计到项目答辩 1. 这个项目到底是什么一套能跑的垃圾分类回收网站先别急着被标题那一长串后缀吓到这其实就是一个非常典型的Java后端课程设计/毕业设计项目基于 SpringBoot SSM 的垃圾分类回收网站。说白了它就是一个连接居民、回收人员和后台管理员的线上平台解决的是家里攒了一堆可回收物不知道给谁、回收人员收废品靠电话联系效率低这个真实痛点。标题里同时出现了SpringBoot和SSM很多人会困惑这俩不是一套东西吗实际开发中这个项目通常是以SpringBoot为核心骨架把Spring MVC、MyBatis也就是SSM里的S、S、M整合进来做数据访问和请求控制。SpringBoot负责自动配置、内嵌Tomcat、简化启动流程MyBatis负责数据库的SQL映射Spring管理业务层的Bean。项目里既有Controller处理前端请求也有Service层封装业务逻辑还有Mapper接口配合XML文件操作MySQL三层结构非常清晰。如果你是正在做Java课程设计、毕业设计的学生或者想通过一个完整web项目把SpringBoot全家桶串起来的初学者这个项目是很合适的参考对象。它有完整的CRUD、用户登录注册、垃圾分类信息展示、回收订单流转、后台管理这些模块麻雀虽小五脏俱全既不会复杂到让你劝退又能覆盖SSM框架的大部分核心用法。我当初拿到这个项目时第一反应是这类源码网上太多了真正值钱的不是能跑起来而是你能讲清楚每张表为什么这么设计、每个接口为什么这么写。这篇文章我会把项目的核心模块、表结构设计思路、关键代码实现、以及调试部署时最容易踩的坑都拆开讲一遍最后再说说答辩时老师最爱问的几个点。2. 站点功能拆分与角色权限边界一个完整的回收网站面向的不止一种人。我在梳理这套项目时习惯先把角色画像画出来再看每个角色需要哪些页面和接口这样后面设计数据库表和写接口时就不会乱。2.1 三类核心角色和他们的操作入口这个垃圾分类回收网站里最基本的角色划分是普通用户居民、回收人员骑手/回收员、系统管理员。普通用户的操作入口主要在前台页面对应的是用户端。他们的核心诉求是注册登录、查看垃圾分类知识哪些是可回收物、哪些是厨余垃圾、有害垃圾怎么处理、在线下单预约回收、查看订单状态、管理个人信息。这部分功能映射到后端就是用户表、垃圾类型表、订单表的增删改查。回收人员是第二类角色他们的操作集中在接单和上门回收这个环节。登录后能看到被分配或待领取的回收订单确认上门时间完成回收后把订单状态改成已完成同时录入实际回收的重量和金额。这个角色最大的价值在于把线下收废品的过程搬到了线上让整个回收流程有迹可循。管理员则是站在最高层负责维护整个平台的数据。包括用户管理禁用/启用账号、回收人员管理分配片区或订单、垃圾分类信息维护增删改查垃圾种类和说明、订单监管查看所有订单状态、统计回收数据、公告发布等。管理员走的是后台管理系统的入口前端展示层和后端管理界面通常是分开的在SpringBoot项目里一般通过不同前缀的Controller和独立的前端页面来区分。需要注意的是这个项目的权限控制通常不会像Spring Security那样做得特别重。我用过不少类似的课设项目大部分开发者的做法是在登录接口里带上用户角色字段登录成功后前端根据角色决定跳转哪个首页后端在关键操作比如删除用户、修改订单状态上再校验一下当前登录人的身份。这样做虽然不如注解鉴权那么优雅但胜在简单直接完全符合课设项目的复杂度要求也方便在答辩时解释逻辑。2.2 核心业务流程从下单到回收完成的完整链路整个网站最核心的业务流是回收订单流转。我在复现这个项目时把它的状态流转画了一条线用户浏览可回收物分类确认自己要卖哪些东西填写上门地址、预约时间提交订单。订单初始状态是待接单。有回收权限的账号回收人员在订单列表里看到这笔单子点击接单状态变成待上门。到了预约时间回收人员上门称重、计算金额在系统里录入实际重量和回收价格确认完成状态变成已完成。订单完成之后用户可以查看这笔订单的明细包括回收物品、重量、金额、回收人员信息。这里有个容易忽略的点订单明细和垃圾类型之间是外键关联的。一张订单可能包含多个垃圾品类比如这次既卖了纸箱又卖了塑料瓶所以表设计上不能只把垃圾类型ID直接挂在订单表里而是要做一张订单明细表order_item每条明细对应一个垃圾类型、一个重量、一个小计金额。这样设计表结构后续统计纸类回收总量塑料回收趋势这类数据时会非常顺手。我在实测中遇到过这样一个问题有些用户提交订单后发现自己选错了垃圾类型或者预约时间需要修改。如果项目里没有提供取消订单和修改订单的入口整个流程就直接卡死了。所以稍微完善一点的源码里会允许用户在订单状态还是待接单时取消订单或者修改预约时间。这个细节虽小但答辩时提到我设计了订单状态机和状态变更的约束规则往往会成为加分项——因为它证明你考虑到了业务流程的边界情况而不只是机械地完成增删改查。2.3 垃圾分类知识库与检索展示模块除了交易闭环大多数垃圾分类网站还会搭一个知识库板块。这个板块的功能比较直接按垃圾类别展示常见物品的分类说明比如废旧电池属于有害垃圾、剩菜剩饭属于厨余垃圾、纸箱矿泉水瓶属于可回收物。用户在网站首页或者独立分类页面可以浏览、搜索后台管理员可以维护这些内容。这个模块虽然业务上简单但技术上很能考察基本功。搜索功能如果直接写LIKE %关键词%在数据量小的时候没有问题但如果你想在答辩时展示一点进阶能力可以考虑用MyBatis的if动态SQL做多条件组合查询比如同时按分类和关键词过滤。再比如分页用PageHelper插件一行代码就能搞定这也是为什么网上几乎所有基于SSM的课设项目都会引入PageHelper——它真的能显著减少分页代码量而且使用逻辑非常统一。垃圾分类信息表的核心字段一般包括垃圾名称、所属类别可回收/厨余/有害/其他、详细说明、回收指导价可选、封面图可选、是否置顶。如果项目里还做了图表统计比如按类别展示垃圾占比那前端可以用ECharts后端只需要提供一个按类别分组统计的查询接口SQL里一个GROUP BY就完事了。3. 数据库表结构设计几张表支撑起整个业务拿到一套源码我习惯先看SQL脚本。数据库表的结构基本决定了业务逻辑的复杂度。这套垃圾分类回收网站核心表大概有6到7张我逐个拆一下设计思路和字段含义。3.1 用户体系表用户表与回收员表的关系用户表和回收员表在这个项目里有两种常见做法。第一种是只建一张user表通过role字段区分user和recycler第二种是单独建recycler表。从实用角度看第一种更适合课设因为它复用登录逻辑不需要写两套认证代码。但第二种信息更独立回收员可以单独维护接单状态、服务区域、接单数量。我复测过的一个版本用的是两张表user表字段包括id、username、passwordMD5加密或BCrypt加密、phone、address、avatar、create_time、statusrecycler表字段包括id、name、phone、area、order_count、status。因为回收员基本由管理员后台添加不太需要开放注册入口所以跟用户表不放在一起也说得通。密码存储这块我要特意说一句如果你拿到的源码里密码是明文存的建议至少改成MD5加盐或BCrypt再做一遍。虽然课设项目不涉及真实生产环境但答辩时老师如果要你讨论安全问题你能说出我对密码做了MD5加密处理相比明文存储提升了安全性这比支支吾吾要好得多。网上有些现成源码的登录逻辑就是select * from user where username? and password?把用户输入的原生密码直接拼进去查库这样不仅不安全而且SQL注入风险极高实测中我见过有人用万能密码直接登录进去的。3.2 垃圾分类表与常见垃圾表垃圾分类相关表一般分两级。一级是类别表categoryid、name、description、icon、create_time存储的是大类可回收物、有害垃圾、厨余垃圾、其他垃圾。二级是具体垃圾表garbageid、name、category_id、detail、img、unit、price存储的是具体物品比如矿泉水瓶、纸箱、旧电池。两级分类的主要好处是前端搜索和筛选方便。用户进入可回收物分类直接查garbage where category_id ?就能列出所有可回收物品管理员如果想调整某个物品的分类归属更新category_id字段即可。在页面展示上用户浏览垃圾分类时拿到的是一棵分类—物品的两级目录后端接口也只需要提供一个返回所有分类及其下属物品的方法Service层组装成树形结构返回即可。3.3 订单链路表主表、明细表与状态设计订单相关的表是整套系统的核心。我在复现时整理了以下表结构订单主表ordersid、order_no订单编号、user_id下单用户、recycler_id接单回收员、address上门地址、phone联系电话、reserve_time预约时间、amount预估金额、actual_amount实际金额、status状态0待接单 1待上门 2已完成 3已取消、create_time、finish_time。订单明细表order_itemid、order_id、garbage_id关联到garbage表的物品ID、garbage_name冗余字段记录下单时物品名称、weight、price、subtotal。为什么明细表要冗余一个garbage_name因为垃圾物品的信息比如价格是可能被管理员调整的如果订单明细只存garbage_id管理员后续改了垃圾表的价格历史订单里这笔明细的金额就对不上了。把名称和单价在生成订单时冗余进明细表是典型的用空间换时间的做法也是实际开发中对历史订单完整性的一种保护。这个细节如果你能主动讲出来效果比背十遍框架原理都好。订单号的生成也值得注意。很多课设项目会直接用数据库自增ID当订单号简单但不好看也不容易做防猜测。稍微讲究一点的会用时间戳加随机数比如20250413加四位随机数或者用SimpleDateFormat拼上订单ID。用户看到一串有意义的订单号对平台的信任感也会更强。3.4 公告与留言非核心但撑起交互感的表很多垃圾分类回收网站会带一个公告栏或者留言反馈模块。公告表notice字段比较简单id、title、content、create_time、status。留言/反馈表则可能更细一些id、user_id、content、reply管理员回复、create_time。做这两个模块主要目的不是为了业务需要而是让网站看起来完整。管理员能在后台发布本周回收价格调整通知春节假期回收时间安排这类公告用户在前台首页能看到滚动公告用户在页面上可以留一句小区东门废品堆积麻烦尽快来收管理员后台回复后用户能看到处理意见。这套逻辑在代码层面就是普通的一对一或一对多查询几乎不构成开发障碍但却能让整个项目的功能列表看上去饱满不少答辩的时候前台后台都有完整的内容管理闭环这句话也更有底气。4. 关键代码实现细节Controller、Service、Mapper三层怎么配合前面把表结构理清了接下来看代码层面。我拿到源码后的习惯是先从Controller往下追一条请求路径从URL到SQL全程走一遍项目就把握了七成。这里我以用户下单预约回收和回收员接单两个动作为例把三层代码的配合方式讲清楚。4.1 下单接口前端参数如何落到数据库用户下单的Controller方法一般长这样PostMapping(/order/add) ResponseBody public Result addOrder(RequestBody OrderDTO dto, HttpSession session) { User user (User) session.getAttribute(user); if (user null) { return Result.error(请先登录); } Order order new Order(); order.setUserId(user.getId()); order.setAddress(dto.getAddress()); order.setPhone(dto.getPhone()); order.setReserveTime(dto.getReserveTime()); order.setStatus(0); order.setOrderNo(OrderNoGenerator.generate()); // 明细数据批量插入 orderService.addOrderWithItems(order, dto.getItems()); return Result.success(下单成功); }这里有个值得展开的设计点前端传的items是一个列表每项包含garbageId和weight。后端不是先插主表拿到订单ID、再循环插入明细而是把主表和明细表包进同一个事务里处理Transactional(rollbackFor Exception.class) public void addOrderWithItems(Order order, ListOrderItemDTO items) { orderMapper.insert(order); for (OrderItemDTO item : items) { OrderItem orderItem new OrderItem(); orderItem.setOrderId(order.getId()); orderItem.setGarbageId(item.getGarbageId()); Garbage garbage garbageMapper.selectById(item.getGarbageId()); orderItem.setGarbageName(garbage.getName()); orderItem.setPrice(garbage.getPrice()); orderItem.setWeight(item.getWeight()); BigDecimal subtotal item.getWeight().multiply(garbage.getPrice()); orderItem.setSubtotal(subtotal); orderItemMapper.insert(orderItem); } }为什么不先在Service里算好总金额再一次性插入因为明细里的单价要以数据库里garbage表当前的价格为准这样用户在前端页面看到的预估金额和数据库里的实际数据是一致的。如果前端自己算金额再传给后端就可能出现篡改金额的风险。这个后端重新计算金额不信任前端传值的思路是生产环境里非常基础的安全意识也是你在答辩时可以重点讲的设计点。Transactional注解在这里是必要的如果第3个明细插入失败了第1个和第2个已经插入的明细不能留着必须全部回滚否则就会出现订单没有明细或者订单明细只有一半的脏数据。很多第一次做课设的同学容易忽略这个细节导致数据库里经常出现半截数据。我建议拿到源码后先全局搜一下Transactional看看核心业务方法上有没有加事务如果没加一定要自己补上。4.2 回收员接单乐观锁控制并发回收员接单的接口在并发场景下有一个经典的坑两个回收员同时点击接单按钮数据库里订单的recycler_id字段会不会被后写入的覆盖如果你的更新SQL是update orders set recycler_id ?, status 1 where id ?那么在极短的时间窗口里两个请求都可能查到订单状态还是0然后依次把recycler_id改成自己的ID最后订单被第二个回收员抢走。对于真实业务来说这不可接受。解决办法有两个一是把更新条件加上status约束也就是update orders set recycler_id ?, status 1 where id ? and status 0这样只有第一个执行的update能匹配到status0的记录并成功更新第二个update匹配不到数据影响行数为0Service层判断update返回结果大于0才视为接单成功。这就是我常说的用数据库条件更新代替读改写三步操作本质上是一种乐观锁思路代码实现还特别简单。第二种办法是用SELECT ... FOR UPDATE把订单行锁住但这需要开启事务并在查询时带锁课设项目里一般用不上这个强度。我在讲解时通常推荐第一种方案因为它够直观而且面试和答辩场景下特别好解释一条带状态条件的update语句就同时完成了抢单和更新两个动作不需要额外引入锁机制。4.3 MyBatis动态SQL和PageHelper分页的写法垃圾分类信息列表页是典型的多条件查询场景用户可能只按关键词搜也可能只选分类筛选也可能两个条件一起上也可能什么都不选直接看全部。如果用三个不同的Mapper方法分别处理代码会非常冗余。MyBatis的if标签就是为这个场景准备的select idsearchGarbage resultTypecom.example.entity.Garbage select * from garbage where if testkeyword ! null and keyword ! and name like concat(%, #{keyword}, %) /if if testcategoryId ! null and category_id #{categoryId} /if /where order by id desc /selectwhere标签会自动处理没有条件时的多余AND和第一个条件前面的AND这两个麻烦写起来很省心。配合PageHelper分页更是简单PageHelper.startPage(currentPage, pageSize); ListGarbage list garbageMapper.searchGarbage(keyword, categoryId); PageInfoGarbage pageInfo new PageInfo(list);PageHelper.startPage()之后紧跟的那一条Mapper查询会自动被拦截并添加上limit语句返回的list其实是Page对象再塞进PageInfo里就能拿到total、pages、pageNum这些分页参数。我见过有同学在startPage()和查询之间插了一段打印日志或者别的查询结果分页加到了错误的SQL上数据莫名其妙地被截断。这里必须强调这两行必须紧挨着中间不要插入任何其他数据库操作。4.4 登录注册模块Session与拦截器的取舍登录认证是这个项目里所有业务的前提。最轻量的实现是用户登录成功后把用户对象放进Session前端请求带上CookieJSESSIONID后端需要登录态的接口里从Session取用户。但如果你在Controller里每个方法都写一遍从Session取用户、判断是否为空代码就太啰嗦了。更优雅的方式是登一个拦截器专门拦截需要权限的路径。我测试过的一个项目里拦截器配置是这样的public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { User user (User) request.getSession().getAttribute(user); if (user null) { response.sendRedirect(/login); return false; } return true; } }然后通过WebMvcConfigurer注册拦截规则Configuration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns(/user/**, /order/**) .excludePathPatterns(/user/login, /user/register); } }这样Controller里的登录检查代码就可以省掉一大部分。需要注意的是静态资源路径比如/css/**、/js/**、/images/**默认不走拦截器但如果你定义了拦截规则后前端页面样式突然全部失效第一反应应该是检查静态资源路径是不是被拦截了。这也是一个真实的排错场景我在调试中遇到过不止一次。5. 部署与调试实战从源码到能跑通全流程拿到源码后最怕的不是代码看不懂而是项目启动不起来。这一节我把从导入到跑通的完整过程写出来顺便把最常见的报错和排查思路全部列出来。5.1 环境准备JDK、Maven、MySQL的版本匹配先检查环境版本。这个项目一般基于JDK 8开发SpringBoot版本通常是2.x。如果你的电脑装的是JDK 17甚至21很多旧版SpringBoot项目会直接启动失败原因多半是反射相关的模块问题报错里会出现java.lang.reflect.InaccessibleObjectException。最简单的做法是装一个JDK 8然后把IDE的项目SDK和Maven的编译器级别都切到1.8。MySQL方面常见的组合是MySQL 5.7或8.0。旧项目脚本如果用了ENGINEInnoDB DEFAULT CHARSETutf8在MySQL 8.0下也能正常导入问题通常出在驱动版本上。SpringBoot 2.1以下默认带的mysql-connector-java是5.x版本连接MySQL 8.0时需要手动改配置把驱动类改成com.mysql.cj.jdbc.Driver同时JDBC URL后面要加上时区参数serverTimezoneAsia/Shanghai否则会报The server time zone value is unrecognized。这个报错非常经典几乎所有用MySQL 8.0跑旧项目的人都会遇到一次。Maven环境配好后把项目作为Maven项目导入IDE等待依赖下载完成。如果下载速度很慢检查settings.xml里的镜像源换成阿里云镜像一般能快很多。依赖下载完成后先执行mvn clean compile验证整个项目能否编译通过这一步可以通过IDE的Maven面板一键完成避免直接启动后才暴露一堆编译错误。5.2 配置文件里的高频报错数据库连接、端口占用与静态资源路径SpringBoot项目的配置集中在application.yml或application.properties里。我拿到一套新源码上来先改三处第一处是数据库连接。确认数据库名、用户名、密码都对得上本地环境。常见错误是本地MySQL密码不是root/123456启动时就会报Access denied for user。不要在这种地方硬刚直接改成自己数据库的真实账号密码。第二处是服务器端口。默认是8080如果本机端口被占启动日志会报Port 8080 was already in use。Windows下用netstat -ano | findstr 8080找到占用进程的PID任务管理器里结束掉或者直接改配置里server.port8081二选一即可。课设演示时用8081反而更好因为不容易被别的开发环境占掉。第三处是文件上传路径或图片访问路径。很多项目把图片上传到本地磁盘某个绝对路径比如D:/upload/换成别人电脑上这个目录不存在启动可能不报错但上传图片后页面上无法展示。我建议把上传根目录统一配成一个相对好找的路径比如项目根目录的upload文件夹同时配置一个虚拟路径映射把/images/**映射到本地磁盘路径。SpringBoot里可以用WebMvcConfigurer的addResourceHandlers方法来做。5.3 数据库脚本导入的坑编码、外键依赖和字符集导入SQL脚本时如果直接用Navicat或命令行source导入很常见的一个坑是中文全部变成乱码。原因通常是SQL文件本身是UTF-8编码但导入时客户端用的字符集是GBK或者没有指定。Navicat里可以在连接属性或导入选项中指定编码为UTF-8命令行导入时可以先执行set names utf8mb4;再source。另外如果SQL文件里建表语句带了外键约束导入时表之间还有依赖关系建议直接按脚本中的顺序原样执行不要手动挑着执行个别建表语句否则遇到外键关联的表还没创建这种报错会很烦。字符集这块我建议建表时统一使用utf8mb4而不是utf8。因为utf8在MySQL里最多只能存3字节的字符像emoji这类4字节字符存不进去。虽然垃圾分类网站里不太可能出现大量emoji但用户留言反馈板块保不齐有人粘贴一个表情符号用utf8mb4能从根上避免这个尴尬。5.4 启动成功后浏览器验证登录、下单、回收员接单端到端走查启动成功后先别急着写前端新功能老老实实把核心链路在浏览器里点一遍。我的固定走查顺序是注册一个普通用户账号登录查看首页和垃圾分类列表。找一个可回收物加入回收车或者直接下单填写地址和时间提交订单。打开数据库或后台界面确认orders表和order_item表都插入了对应记录status是0。用回收员账号登录在待接单列表里看到刚才那张订单点击接单再回用户端确认订单状态从待接单变成了待上门。回收员操作完成回收填重量和实际金额再去用户端确认订单变成已完成状态。这条链路如果全部打通说明项目核心逻辑没有问题。任何一步卡住排查思路一般是页面报错看浏览器F12的Network和Console接口报错看后端控制台日志数据不对直接查数据库。三步定位法基本能覆盖90%的问题。6. 讲解演示与答辩准备源码之外的价值呈现很多同学买源码或下载源码后最焦虑的不是代码跑不动而是老师问起来我讲不明白。这里我必须说一句公道话课设答辩或毕业答辩考察的核心不是你写了多少行代码而是你是否理解了自己提交的项目。就算源码是从网上参考来的只要你能把表结构关系、业务流转、核心接口设计从头到尾讲清楚就已经达到要求了。6.1 五分钟演示脚本先讲用户端再讲后台管理我给学员准备过一个五分钟演示脚本按这个顺序讲最不容易乱首先打开项目主页介绍网站定位和面向人群。快速点一下导航栏里的几个板块让评委看到前台功能完整。接着登录一个普通用户账号演示垃圾分类知识浏览和搜索功能这一步可以顺带讲数据库里的category和garbage两级分类设计。然后进入核心环节演示下单。选几个可回收物填上门地址和预约时间提交订单后立刻打开数据库或后台订单管理页面展示订单主表和明细表的数据变化。这里能讲的东西非常多订单号怎么生成、金额怎么在后端重新计算、状态字段的初始值为什么是0。再切换到回收员账号演示接单、上门、完成回收的完整操作。最后切到管理员账号展示后台的用户管理、回收员管理、垃圾分类维护页面。整个演示时间控制在五到八分钟把用户下单—回收员处理—管理员监管的闭环讲清楚评委自然会觉得这套系统是完整的。6.2 答辩高频问题与回答思路我把这个项目答辩时评委最常问的问题整理成了一张表提前准备不会吃亏常见问题回答思路为什么用SpringBoot还要说SSMSSM是SpringSpringMVCMyBatis的组合SpringBoot简化了整合配置底层还是这三个框架在工作。订单状态是怎么管理的用一个int字段存储状态0待接单、1待上门、2已完成、3已取消在Service层通过条件更新来控制状态变更。两张订单表之间的关系orders是主表order_item是明细表一对多关系通过外键order_id关联。数据库表有哪些用户和订单怎么关联用户表、回收员表、分类表、垃圾表、订单表、订单明细表、公告表、留言表user_id关联到用户表。密码怎么存储的我用的MD5加盐/BCrypt加密存储没有用明文。回收员抢单怎么防止重复接单更新语句带status0条件只有匹配到待接单状态的更新才能成功通过影响行数判断是否抢到。分页怎么实现的PageHelper插件startPage之后Mapper查询自动分页PageInfo封装分页结果。项目里哪里用到了事务下单时主表和明细表要同时插入用Transactional保证要么全部成功要么全部回滚。前端页面用什么写的一般是Thymeleaf模板或Vue单页按实际源码回答如果是前后端分离再说接口设计。这些问题都不难难的是你能不能脱离源码用大白话讲出来。我建议在答辩前至少把自己的项目完整演示三遍每讲一遍对业务逻辑的熟悉程度都会上一个台阶。6.3 从课设到简历讲出项目的差异化最后聊两句更长远的事。垃圾分类回收网站这个选题本身不稀缺每年都有大量学生做类似题目所以真正拉开差距的地方在于你怎么在简历或面试里描述它。不要只写开发了一个垃圾分类回收网站实现了增删改查。稍微提炼一下把有设计感的内容写进去。比如设计了订单主表和明细表两级结构支持多品类垃圾回收计价通过带状态条件的更新语句实现回收员抢单并发控制使用PageHelper和动态SQL完成多条件分页检索对关键业务方法添加事务管理保证订单数据一致性。这几句话没有一句是虚构的但听起来和做了个管理系统完全不一样。这也是我在讲解这套项目时反复强调的一点源码只是骨架你能提炼出来的设计思路才是血肉。把这套逻辑吃透不管是答辩还是面试面对这个项目你都能挺直腰板说一句这确实是我做过的东西我知道它为什么这么设计。
返回列表