ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

SpringBoot+Vue房屋租赁系统毕设指南:从数据库设计到部署答辩

2026/9/26 11:44:43 拓冰建站 浏览量
SpringBoot+Vue房屋租赁系统毕设指南:从数据库设计到部署答辩 1. 选题之前想清楚为什么这套系统成了毕设首选先说结论如果你正被毕设/课设选题折磨得焦头烂额又在五花八门的XX管理系统里挑花了眼这套SpringBootVue的房屋租赁系统是一个相当稳妥的选项。原因有三个方面技术栈主流、业务模型清晰、工作量适中。我辅导过身边不少人做毕设也帮人看过太多僵尸代码项目最后发现房屋租赁这个业务场景几乎是为毕定量身定做的——它天然存在两类角色租客和管理员、一系列完整的业务闭环房源发布→看房→签约→缴费→报修既有CRUD的标准动作又有业务状态流转的加分动作做出来像回事讲起来也有东西可讲。从技术层面看SpringBoot Vue MySQL这套组合本身就是目前行业内最常见的全栈搭配。后端SpringBoot解决接口开发、业务逻辑、数据持久化的问题前端Vue解决页面交互、组件复用、状态管理的问题MySQL负责把所有结构化数据稳稳落地。这三者拼在一起正好构成一个前端发请求、后端处理业务、数据库落数据的完整闭环也是绝大多数企业项目的缩影。对毕设场景来说这个选题还有一个隐藏优势功能边界非常清晰不会像电商系统那样陷入优惠券怎么算库存超卖怎么办的无底洞也不会像OA系统那样被一堆审批流、权限矩阵拖垮进度。房屋租赁的业务链条虽然有头有尾但每一步都是初学者跳一跳能够到的难度做完之后你对如何从零搭一个前后端分离项目会有完整的肌肉记忆。这篇博文我就按实际开发的逻辑顺序把这个系统的技术拆解、数据库设计、核心接口、前端实现、部署上线的完整路径都过一遍顺带把答辩时最容易翻车的地方也提前给你标记好。2. 需求拆解与功能边界先把做哪些定死再动手2.1 用户端与管理端的核心流程房屋租赁系统跟很多管理系统最大的区别在于它同时服务两类人租客前台用户和运营管理员后台管理者。如果这个边界一开始没划清后面很容易做着做着就变成四不像——前台不像前台后台不像后台。站在租客的视角核心诉求是注册登录之后能看到在租房源、能按地址或者租金筛选房源、能看房源详情图片、面积、朝向、租金、能预约看房、能收藏心仪房源、能在线签约、能查看自己的账单并缴费、能在入住后提交报修。站在管理员的视角核心诉求是审核房源上架、处理租客提交的看房预约、维护合同信息、生成租金账单、查看账单支付状态、响应报修工单、发布站内公告。这两条线合在一起就构成了完整的业务闭环。我可以很负责任地说毕设答辩时老师最看重的就是你能不能把这个闭环讲清楚一个租客从注册到签合同、再到缴费报修数据在哪些表之间流转谁修改了谁的状态这些都必须能一条线串下来。这也是我在做演示准备时花时间最多的地方。2.2 功能模块清单防止需求蔓延给正在做或准备做这个系统的朋友一个建议先把功能模块写死做成一个类似需求清单的东西开发过程中除非答辩导师硬性要求否则不要随便加功能。我自己的功能切分是这样的用户模块注册、登录、个人信息维护、密码修改房源模块房源发布、房源列表、条件搜索、房源详情、房源上下架预约看房模块提交预约、预约状态流转待确认/已确认/已完成、管理员处理合同管理模块租客在线签约、合同列表、合同到期提醒可简化账单模块账单生成签约后自动生成首期、缴费状态更新、缴费记录报修模块提交报修、管理员处理、报修状态流转公告模块管理员发布公告、租客查看公告统计模块房源总数、租户数量、月度租金收入、空置率这块是答辩加分项功能清单的作用不是给自己找事而是帮你控制开发节奏。我见过太多人做到一半想加地图找房、想加在线聊天结果被这些锦上添花的功能拖垮了主线。毕设不是商业产品把闭环做完把状态流转讲透数据可视化稍微有一点就已经超出大多数人的完成度了。2.3 三种用户的权限边界设计虽然表面上是租客和管理员两类角色但房源还有一个房东/发布者的概念。这里有两种设计方式一种是把房东和管理员合并即管理员统一审核、统一发布房源另一种是再加一个房东角色。考虑到毕设的场景我更推荐第一种——角色越少权限逻辑越简单页面和接口的重复度越低。否则房东和管理员之间又要多出一套非对称的权限规则开发量一下子就上去了。权限控制的落点在两个层面后端接口通过拦截器校验登录状态和角色标识前端路由通过路由守卫控制页面访问。例如房源审核接口只允许管理员角色调用收藏房源接口只允许已登录的普通用户调用。这两个层面缺一不可只做前端隐藏是糊弄不了老师的你前端把按钮藏了接口照样可以被直接请求到数据安全这块必须后端兜底。3. 数据库设计九张表的字段规划与关系梳理数据库设计是整个系统里最不能省功夫的部分。表结构没设计好后面写接口和页面的时候到处都是别扭。我这套方案用了9张核心表每一张都能说清楚为什么要有这张表、核心字段为什么这么定。3.1 用户表与房源表业务的基石用户表user是最基础的表字段相对标准id主键、username用户名、password密码、phone手机号、email邮箱、avatar头像路径、role角色标识0普通用户、1管理员、status账号状态、create_time创建时间。这里有两个实操细节值得注意。第一密码必须存加密后的密文哪怕毕设也不例外用MD5加盐或BCrypt都行答辩时老师问起来至少说明你有安全意识。看看网上那些源码密码明文存储的比比皆是这种低级错误一旦被追问会非常扣分。第二role字段尽量用数字或简短字符串标记不要直接存管理员这种中文避免代码里到处是魔法字符串的硬编码。房源表house是信息量最大的一张表id、title房源标题、description描述、covered_area建筑面积、price月租金、rent_type租赁方式整租/合租、address详细地址、house_type户型如2室1厅、decoration装修情况、image_url封面图、status状态0待审核、1已上架、2已出租、3已下架、owner_id关联用户id、view_count浏览量、create_time。房源表的status字段是整张表的状态中枢所有业务流程最终都通过修改这个字段来体现房源当前状态。这也是业务逻辑里最需要注意的地方签约成功之后一定要把房源状态改成已出租否则同一套房被两个人签了演示时就是社死现场。3.2 业务过程表合同、账单、预约、报修合同表contract是业务闭环的关键id、contract_no合同编号业务上常用方便线下对账生成规则可以是时间戳加随机数、house_id关联房源、tenant_id关联租客用户、rent月租金、deposit押金、start_date起租日期、end_date到期日期、status状态0生效中、1已到期、2已退租、create_time签约时间。设计合同表时我踩过一个坑合同里的租金必须冗余一份而不是签约时实时去查房源表的价格。道理很简单今天房源标价1800元/月签约之后房东改价成2000元那已签合同里的租金也跟着变明显不合理。合同生效后它是独立的法律文件金额必须定格。这个冗余存储业务快照的思路在很多管理系统里都是通用的经验。账单表billid、contract_id关联合同、bill_no账单编号、amount金额、bill_type类型租金/押金、due_date应缴日期、status状态0未支付、1已支付、pay_time支付时间、remark备注。账单生成逻辑是签约时自动生成一份押金单和一份首期租金单之后每期到期前自动生成租金单——毕设里可以用定时任务也可以简化成页面手动触发生成。预约看房表visitid、house_id关联房源、user_id关联预约用户、phone联系电话、visit_date期望日期、visit_period期望时间段、status状态0待确认、1已确认、2已完成、3已取消、remark备注。报修表repairid、house_id关联房源、tenant_id关联报修用户、content报修内容、image_url现场图片、status状态0待受理、1处理中、2已完成、handler_id处理人、handle_note处理结果、create_time、update_time。3.3 辅助表与管理表收藏、公告与数据关系收藏表favorite和公告表notice属于业务辅助模块逻辑简单收藏表只需要id、user_id、house_id、create_time四个字段联合唯一索引保证同一用户不能重复收藏同一套房公告表就是id、title、content、create_time、publish_status这几个标准字段。当你把这几张表的字段都列出来再画出它们之间的关联关系时会发现系统的主线非常清楚用户通过收藏表、预约表、合同表与房源产生关系合同表往下又延伸出账单表房源表往下延伸出报修表。ER图画出之后答辩时直接把这张图放PPT里比你在台上口播半小时都有说服力。正规源码里通常还会附一张SQL脚本文件把建表语句、初始化数据一次性准备好这也算是一个项目规范性的体现。关于是否要加户型表城市区域表这种字典表我的建议是视演示数据而定量力而行。如果你的房源地址都是手写的那城市维度就没必要单独建表但如果演示数据集中在一个城市的几个区那做一个简单的区划筛选也不复杂。总之不要让表结构过度设计毕设的重点是把基础表的关系理清楚、状态流转跑明白。4. SpringBoot后端搭建从分层架构到核心接口实现4.1 项目结构与分层逻辑后端我用的标准三层架构Controller层接收前端请求、Service层处理业务逻辑、Mapper层操作数据库。配合的持久层框架是MyBatis-Plus不是原生MyBatis——为什么毕设项目里SQL大多数都是单表查询和简单多表联查MyBatis-Plus的BaseMapper直接把增删改查封装好了条件构造器写多条件搜索也顺手得多能帮你省下不少时间把精力放在后面的业务和答辩准备上。具体包结构大概这样com.example.rent ├── controller // 接口层 ├── service // 业务接口 ├── service.impl // 业务实现 ├── mapper // 数据访问层 ├── entity // 实体类 ├── common // 统一返回结果、异常处理 ├── config // 跨域配置、拦截器配置 └── utils // JWT工具、加密工具等统一返回结果类Result是后端规范性的门面我会把接口约定成固定结构code200成功、500失败、401未登录、msg提示信息、data业务数据。所有接口都返回这个结构前端Axios统一拦截处理。这个小规范能让你联调时少踩很多返回格式不统一的坑。4.2 登录鉴权JWT方案落地登录模块我使用JWTJSON Web Token做无状态鉴权。核心流程是用户提交用户名密码后端校验通过后生成一个包含用户id和角色的token返回前端把token存起来我建议放localStorage简单直接之后每次请求都在请求头里带上Authorization: Bearer token。后端写一个拦截器对除登录、注册、房源列表等白名单之外的接口统一校验token校验不过就返回401。代码逻辑不复杂但有个关键点值得展开拦截器里解析出用户信息之后怎么把当前用户传给后续代码比较优雅的做法是把用户id放进ThreadLocal或者在请求头里重新设置一个自定义header后续Service层直接从请求上下文取。别在拦截器里校验完就丢掉了不然后面写获取我的账单获取我的合同这些接口时你就只能靠前端传userId过来了——而前端传的这个userId是完全可以伪造的那就等于没有鉴权。多提一句密码加密注册时用BCrypt加密登录时用BCrypt.matches比对。BCrypt每次生成的密文都不一样但matches校验依然能通过安全性比MD5强一个档次。这个概念在Java面试里也是高频考点做毕设的同时顺便把这套东西学了不吃亏。4.3 核心接口设计与业务状态流转接口设计我做了一个统一前缀/api按资源命名POST /api/user/login 用户登录 POST /api/user/register 用户注册 GET /api/house/list 房源分页列表支持多条件查询 GET /api/house/detail/{id} 房源详情 POST /api/house 发布房源管理员/房东 PUT /api/house/{id} 更新房源 DELETE /api/house/{id} 删除房源 POST /api/contract 签订合同 GET /api/contract/my 获取我的合同列表 GET /api/bill/my 获取我的账单 POST /api/bill/pay/{billId} 账单缴费 POST /api/visit 提交看房预约 GET /api/visit/list 预约列表管理端 POST /api/repair 提交报修 POST /api/repair/handle/{id} 处理报修管理端 GET /api/statistics/rent 租金收入统计管理端签订合同这个接口是整个系统业务逻辑最厚重的一处。它的完整操作序列应该是校验房源状态为已上架校验当前用户没有重叠时间的有效合同创建合同记录状态为生效中把房源状态改为已出租自动生成押金和首期租金账单。这四步操作涉及三张表的变更中间任何一步失败都应该回滚。所以我加了Transactional事务注解保证要么全成功要么全失败。这种一个操作动了多张表的意识也是答辩时能主动讲出来的亮点。账单缴费接口也不只是改一个status字段那么简单。支付成功的业务含义是账单状态改为已支付、记录支付时间、如果这是押金单那退租时要额外处理押金退还逻辑。毕设里不需要接入真实支付网关直接模拟一个确认支付即可但状态流转的链路要完整。4.4 多条件查询与简易统计报表房源列表的多条件搜索是另一个容易出彩、也容易翻车的点。我用MyBatis-Plus的条件构造器实现核心逻辑是动态拼接查询条件有keyword就按title或address做模糊搜索有rentMin和rentMax就加价格区间有rentType就精确匹配租赁方式有status就按状态过滤。重点提醒一下keyword模糊查询的SQL要防止通配符注入用户体验层面也要注意——如果只有一个房源搜索到0条结果时前端要有没有找到合适房源的空状态提示别直接白屏。统计报表这块我做了三个维度总房源数和已出租数、本月租金总收入、各房源类型的分布。MySQL里用COUNT和SUM配合GROUP BY一条SQL就能查出来。前端用ECharts画柱状图和饼图效果非常直观。很多毕业设计的系统功能做得再全输在没有任何数据可视化一张曲线图或饼图放上去整个系统给人的专业感立刻不一样。4.5 全局异常处理与日志容易被忽略但很加分的细节全局异常处理是后端工程化的基本功。我写了一个RestControllerAdvice注解的全局异常处理类统一捕获业务异常、参数校验异常和兜底的Exception异常分别返回对应的错误码提示。没有这层兜底的时候一旦前端传的参数不对后端直接抛一堆堆栈给前端页面白屏联调时互相甩锅加上之后所有失败响应都是友好的中文提示体验完全不一样。日志方面不用上log4j2那么重的方案SpringBoot自带的Logback就够用。我通常在关键操作登录、签约、支付、删除房源里打一条带用户id和操作内容的日志排查问题的时候有迹可循。成本很低但对项目质量的提升非常实在。5. Vue前端实现从项目初始化到页面逻辑5.1 环境准备与项目骨架前端用Vue2还是Vue3如果你是自己学习入门我建议直接Vue3 Element Plus的组合这是当前的主流方向。如果你手里的参考代码是基于Vue2 Element UI的那就跟着老项目保持一致别一边改代码一边升版本两个版本之间的差异在某些细节上会让人抓狂。初始化项目用Vue CLI或Vite都行。Vite启动速度快更现代Vue CLI的生态更老但更稳定毕设的话Vite完全够用。安装依赖的时候注意版本对齐Element Plus只支持Vue3Element UI只支持Vue2装错了项目一启动就报错这是新手最容易卡住的地方。项目结构我是这样组织的src ├── api // 按模块封装的接口请求 ├── assets // 静态资源 ├── components // 公共组件 ├── router // 路由配置 ├── store // Pinia状态管理或Vuex ├── views // 页面组件 └── utils // 请求封装、工具函数views目录下按业务划分页面登录页、注册页、首页房源列表、房源详情页、我的预约页、我的合同页、我的账单页、报修页、后台管理页用户管理、房源管理、合同管理、账单管理、预约管理、报修管理、公告管理、统计看板。5.2 路由设计与权限控制路由是前端骨架我分成两组来配置普通用户可见的页面首页、房源详情、个人中心相关和管理员专属的页面后台各管理模块。在路由守卫的beforeEach钩子里做两件事第一判断目标页面是否需要登录需要就校验本地是否有token没有就重定向到登录页第二判断目标页面是否要求管理员角色当前用户角色不是管理员就重定向到首页。有个细节建议提前处理管理端页面建议统一挂在/layout这个父路由下面不要每个页面都单独写一个完整布局。父路由对应一个整体布局组件布局组件里包含侧边栏和顶部导航子路由只是内容区切换。这个设计避免大量重复代码后期调整导航菜单只需要改一个文件。用户信息的持久化我用的PiniaVue3对应状态管理工具Vue2用Vuex页面刷新后从localStorage里恢复。token和用户基本信息存localStorage用户每次登录后拉到的最新信息存Pinia。这两者要配合使用只存Pinia不存localStorage一刷新登录状态就丢了。5.3 Axios请求封装与接口对接Axios封装的核心包括三部分一是baseURL统一配置二是请求拦截器里自动带token三是响应拦截器里统一处理code。我在响应拦截器里做了两个关键处理code为401时自动跳登录页并清除本地tokencode为500时用Element Plus的Message组件弹出后端返回的msg。这样一来每个页面里调用接口就非常干净——只关心成功的data就行异常情况全部在拦截器层兜住。以首页房源列表为例组件挂载时调用api.getHouseList({ page: 1, keyword: })拿到data直接塞给表格或卡片列表。搜索框输入地址关键字防抖一秒之后重新拉接口。分页组件触发页码变化时更新页码参数再次请求。这套交互逻辑写顺了后面的合同列表、账单列表、预约列表都是同一个套路这就是为什么说这个系统做好了你对Vue的数据驱动、生命周期、组件通信都会有直观的理解。5.4 组件复用的三个实用场景第一是分页表格的复用。用户管理、合同管理、账单管理、报修管理后台页面都是筛选条件数据表格分页的结构把表格列配置通过props传进去就可以做一个通用列表页组件。第二是状态标签的复用。房源状态、账单状态、报修状态这些字段在后端存储的是数字前端展示时需要转成对应的中文文案和颜色我封装了一个StatusTag组件传入状态码和类型自动渲染出带颜色的Tag标签视觉上统一还省事。第三是表单弹窗的复用管理员新增和编辑房源用同一个弹窗表单组件只是提交时的请求方法和初始值不同。如果列表页面之间的差异实在太大比如统计看板就不要强求复用硬套通用组件反而增加复杂度。组件复用的原则是一样的代码写两遍以上才考虑抽离一次性的页面正常写就好了。6. 前后端联调跨域、接口规范与部署上线6.1 跨域问题的三种处理方式前后端分离项目开发时一定会碰到跨域问题。你在localhost:8081跑前端后端在localhost:8080前端请求后端接口时浏览器就会拦截跨域请求。处理方案有三种后端配置CORS、前端配置代理、或者用Nginx反向代理部署时。开发阶段最省事的方案是前端Vite或Vue CLI的devServer代理把所有/api开头的请求代理到http://localhost:8080。这样浏览器里看请求是从同源发出的调试方便不需要在后端改任何配置。如果后端也配置了CORS两者可能会冲突导致奇怪的问题建议开发阶段只保留前端代理这一层。部署阶段后端直接打jar包跑SpringBoot默认端口前端npm run build生成dist静态文件再用Nginx做一个反向代理把/api路径转发到后端服务。这个方案的好处是前端和后端看起来是同源的不会有跨域问题也顺便把前端静态文件的托管解决了。Nginx配置核心就两块server { listen 8081; server_name localhost; location / { root C:/dist; index index.html; # 前端路由用history模式时刷新页面404问题靠这句解决 try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }关于前端路由history模式的刷新404问题很多人在本地开发时没发现因为devServer默认处理了部署到Nginx后一刷新页面就白屏。解决办法就是上面try_files那行配置把所有找不到的路径都回退到index.html。这也是联调部署阶段的高频坑。6.2 接口约定的演进与联调技巧接口文档不一定要用Swagger UI那套重的方案但你至少要把接口的请求方式、路径、入参、返回结构列清楚。我用SpringBoot项目里集成springdoc-openapi生成Swagger文档前端同事或者你自己切角色照着文档联调效率高很多。联调时最容易出的问题集中在参数格式上后端接收的是JSON对象前端Axios默认也是JSON本来就是通的但一旦某个字段从前端传了个null或者空字符串后端做非空校验时就要特别小心0和空字符串到底算不算有值。我的经验是在接口层用统一规则查询参数允许为空字符串创建和更新操作的关键字段房源标题、租金、面积必须非空。把这个约定写在文档最顶部能减少大量无意义的扯皮。6.3 数据库初始化与部署持久化数据上线部署时数据库初始化通常分两步先执行项目里提供的init.sql建表并插入管理员账号、演示房源数据再验证一下基本流程。有个我很重视的细节是MySQL的时区问题——连接串上一定要加serverTimezoneAsia/Shanghai不然日期字段存进去和查出来差8个小时账单的应缴日期显示出来全乱了排查半天你想不到是时区问题的。演示数据要预先准备充足且有层次。至少准备6套房源覆盖不同价格区间、户型和租赁方式状态要有待审核已上架已出租等多种图片尽量统一尺寸风格。租客账号预置一个已签约的合同和生成的账单这样演示时一登录就能看到列表里有数据不用现场表演创建全流程万一现场网不好或者操作失误就很被动。这条经验是我自己写演示脚本时总结出来的。6.4 部署方式对比一体化还是分离部署部署方式有两种选哪一种取决于答辩的展示环境。一体化方案是把前端build后的dist目录拷到后端项目的src/main/resources/static下重新打包成单个jar一个进程同时提供页面和接口。优点是部署极其简单跑一个jar就完事缺点是前端每次改动都要重新打包整个后端开发迭代不够灵活。分离部署方案是前端dist交给Nginx后端jar独立跑优点是可以各自更新互不影响更接近企业真实部署方式。毕设的话我更推荐一体化方案因为答辩现场往往是临时环境一个jar包加一个SQL脚本就能把系统完整跑起来这个稳定性优势非常实际老师也不会因为你没有用Nginx而扣分。7. 答辩演示与实用避坑来自现场和开发中的经验7.1 现场演示的三条硬规则答辩现场演示是毕设的临门一脚我在帮同学排练和现场观察中总结了几条硬规则。第一正式演示之前把系统重启一遍再用确保后端连上数据库、前端页面能打开不要拿着开发环境里跑了一天的热状态去演示——一旦现场需要重启你连哪个服务怎么开都可能手忙脚乱。第二给每一个演示动作写场景脚本我要演示一个租客从注册到签约的全流程那我提前准备好这个租客的账号提前想好搜房源的关键词最好一搜就有结果中间每一步的预期页面状态是什么。第三准备两个后台页面备用数据如果现场提问被引导到某个模块比如报修的完整流程是什么你手头就正好有这个数据可以现场点开。7.2 开发阶段我踩过的一线坑第一个坑是金额字段用double导致的精度异常。租金1800.00打96折算出来1736.849999页面显示一长串小数非常丑。解决方案是后端所有金额用BigDecimal前端展示用toFixed(2)统一格式化。这就是为什么我在前面强调数据库金额字段必须decimal类型。第二个坑是删除房源时外键约束报错。SQL里已经做了多表关联结果删除一个房源时一直报错因为合同和收藏表里还引用着它。解决方法是先做业务校验如果房源存在生效中的合同禁止删除普通收藏引用则连字段一起清理。第三个坑是图片上传后前端不显示。排查后发现是上传接口没做静态资源映射前端访问不到上传目录的文件。SpringBoot里需要配置WebMvcConfigurer把本地磁盘的upload目录映射成虚拟路径前端用配置的访问地址拼上路径才能正常显示图片。第四个坑是Element Plus表格的树形数据或者复杂嵌套数据结构在渲染时卡顿或异常。解决途径是对后端返回的数据结构做严格约定尽量保持扁平结构需要层级关系时后端组装好再返回。7.3 再多给两条加分建议如果完成度已经不错想在答辩和技术深度上再往上顶一顶我还有三个方向可以推荐。一是给房源图片做上传压缩和统一尺寸裁剪页面视觉立刻上一个档次。二是增加操作日志表记录用户的登录、签约、支付等关键行为答辩时说系统具备审计监控能力这是个很好的卖点。三是引入Redis做缓存房源列表数据量变大时缓存热数据优化接口响应速度——虽然后端接口是本地内存也能跑但Redis在简历上和技术深度上都是加分项。我自己在实际做这类全栈项目时最大的体会是系统复杂度的增加要跟着业务深度走而不是跟着页面数量走。这个房屋租赁系统之所以适合毕设就是因为它允许你把有限的技术栈发挥到足够的深度表关系设计是脊柱状态流转是血脉权限控制是边界数据可视化是门面。把这几条线走通你就真正把SpringBootVueMySQL这套栈吃进去了后面无论换什么业务场景做项目你都拿到了可迁移的完整方法论。最后分享一个小技巧开发的时候可以给数据库脚本写一个一键重置逻辑每次改动表结构后自动重新建表并灌入最新演示数据这能帮你在频繁调整字段的痛苦里解脱出来不管是自己调试还是答辩准备都从容得多。