毕业设计实战:基于SpringBoot的在线租房和招聘平台双系统设计与实现全流程指南
在开发“在线租房和招聘平台”毕业设计时,曾因“房屋订单与用户信息脱节”踩过关键坑——初期未在“房屋订单表”与“用户表”“房屋表”间建立完整外键关联,导致房东处理订单时无法查看租客信用记录、平台管理员无法统计房屋出租率,耗费3天重构表结构、补全业务关联逻辑才解决问题📝。基于此次实战经验,本文将系统拆解从需求分析、技术选型、功能实现到测试验收的全流程要点,为同类“平台型”毕设提供可落地的实施指南。
一、需求分析:锚定租房+招聘双业务核心诉求,避免功能混杂
部分同学在开发“双业务平台”时易陷入“功能拼接”误区,比如笔者曾将租房和招聘功能简单堆砌,导致用户体验割裂。通过分析发现两大业务本质都是“供需匹配”,核心逻辑相通,只需做好角色权限划分即可。
1. 核心用户与功能拆解(四角色双业务体系)
系统包含四大角色:平台管理员、房东/企业(供给方)、普通用户(需求方)、租客/求职者(消费方)。前期曾混淆“房东”与“企业”的发布权限,导致逻辑混乱,明确角色边界后系统清晰度显著提升:
平台管理员端(核心管控功能)
- 双业务统一管理:
- 用户全生命周期管理:审核房东/企业资质(营业执照、身份证明),管理普通用户账号(信用评级、违规处理);
- 房源与职位审核:审核房屋信息真实性(图片、价格、位置),审核招聘信息合规性(薪资范围、岗位描述);
- 订单与投递监管:监控租房订单交易安全,监督简历投递流程规范性,处理纠纷投诉;
- 内容与社区管理:
- 平台资讯发布:发布租房攻略、求职技巧、政策解读等资讯,按类型分类管理;
- 论坛内容审核:管理租房社区、求职论坛的帖子,删除违规内容,维护社区秩序;
- 数据统计分析:统计房屋出租率、岗位投递比、用户活跃度等核心指标,生成可视化报表;
- 系统基础维护:字典数据管理(房屋类型、职位类型、城市区域等),系统参数配置,操作日志审计。
房东/企业端(供给方功能)
- 房源/职位发布:
- 房屋发布:发布房源信息(标题、图片、位置、户型、价格、设施),设置租赁规则(押几付几、最短租期);
- 招聘发布:发布职位信息(岗位、薪资、要求、福利),设置招聘流程(笔试→面试→录用);
- 信息维护:编辑已发布信息,下架过期房源/职位,查看浏览统计;
- 订单/投递处理:
- 租房订单管理:查看租房申请,与租客沟通,确认订单,管理租期状态;
- 简历筛选管理:查看投递简历,筛选合适候选人,安排面试,发送录用通知;
- 评价与反馈:对租客/求职者进行评价,回复用户咨询,处理投诉建议;
- 个人中心:账户信息维护,交易记录查看,余额提现管理(涉及支付功能可简化)。
普通用户端(需求方基础功能)
- 双业务浏览与筛选:
- 租房搜索:按位置、价格、户型、标签多维度筛选房源,收藏心仪房屋,查看房源详情;
- 求职搜索:按岗位、薪资、行业、地点筛选职位,收藏关注职位,查看公司信息;
- 个人资料管理:基本信息维护,头像设置,联系方式更新;
- 互动与交流:在房源/职位下留言咨询,在论坛发帖交流,查看系统消息。
租客/求职者端(需求方进阶功能)
- 租房核心功能:
- 在线看房:查看房源VR/图片(如有),预约线下看房;
- 租房申请:提交租房申请,填写入住信息,与房东沟通细节;
- 订单管理:查看租房订单状态(待确认→已确认→租期中→已结束),支付租金(模拟),签订电子合同(简化);
- 评价与维权:租期结束后评价房东与房屋,申请退租押金,发起纠纷投诉;
- 求职核心功能:
- 简历管理:创建多份简历(针对不同岗位),编辑简历内容(教育、经历、技能),上传附件简历;
- 职位申请:一键投递简历,查看投递状态(已投递→已查看→面试邀约→录用),在线沟通;
- 面试管理:查看面试安排,确认面试时间,查看面试结果;
- 签约管理:接受录用通知,查看电子offer,确认入职意向。
2. 需求分析避坑要点(双业务平台特殊问题)
- 业务隔离与融合的平衡:初期将租房和招聘做成两个独立系统,用户体验差。后续调整为“统一入口+业务分区”模式,用户登录后自主切换业务场景,共用个人中心和消息系统;
- 角色权限的交叉控制:同一用户可能既是租客又是求职者,还可能申请成为房东或企业。设计“角色申请+平台审核”机制,用户可申请多重身份,权限独立管理;
- 数据模型的通用性设计:发现租房和招聘在“收藏、留言、订单/投递”等行为上高度相似,抽象出通用行为模型,大幅减少重复开发;
- 绘制双业务流程图:使用DrawIO分别绘制租房业务流(发布→浏览→申请→签约→履约→评价)和招聘业务流(发布→浏览→投递→筛选→面试→录用),对比发现共性环节,设计统一处理模块。
3. 可行性分析:重点论证业务整合可行性
- 技术可行性:SpringBoot + Vue + MySQL技术栈成熟稳定,关键在于设计合理的微服务或模块化架构。笔者前期尝试单体架构,随着功能增加代码耦合严重,后续调整为“用户中心+租房服务+招聘服务+公共服务”四模块,开发效率提升;
- 经济可行性:作为毕设项目,开发成本为零。但需考虑系统价值:整合租房和招聘两大高频需求,提升信息匹配效率,具备现实应用潜力;
- 操作可行性:设计统一导航栏,左侧固定业务切换入口(租房/招聘),右侧为业务专属功能。经测试,用户5分钟内可掌握基本操作,10分钟可完成一次完整租房或求职流程。
二、技术选型:微服务思想指导模块化设计
前期尝试单体架构开发,随着功能增加(16张表,30+接口),代码维护困难。后续引入“微服务思想”,将系统拆分为独立模块,通过统一认证中心协调。
1. 核心技术栈选型说明(模块化架构)
| 技术组件 | 选型理由 | 模块化应用 |
|---|---|---|
| SpringBoot 2.7 | 快速构建独立服务,各模块可独立开发测试 | 创建4个SpringBoot子模块:user-service、rental-service、job-service、common-service |
| Spring Cloud Gateway | 作为API网关,统一路由请求到各服务 | 配置租房(/rental/)和招聘(/job/)路由规则,实现业务隔离 |
| Spring Security + JWT | 统一认证授权,支持多角色令牌 | 用户登录后获取JWT令牌,网关验证后转发到对应服务 |
| MySQL 8.0 + 分库思想 | 支持多数据库实例,物理隔离业务数据 | 用户数据、租房数据、招聘数据可部署在不同数据库实例 |
| Redis 6.2 | 缓存热点数据(房源列表、职位列表),会话管理 | 减少数据库压力,提升列表查询性能 |
| Vue 2 + ElementUI | 前端微服务化,按业务拆分SPA应用 | 创建rental-app和job-app两个前端项目,通过nginx整合 |
| Nginx | 反向代理,静态资源服务,负载均衡 | 代理前端应用和后端网关,实现前后端分离部署 |
2. 模块化开发环境搭建
# 项目结构
online-platform/
├── platform-gateway/ # API网关
├── user-service/ # 用户服务
├── rental-service/ # 租房服务
├── job-service/ # 招聘服务
├── common-service/ # 公共服务(字典、文件、消息)
├── frontend-rental/ # 租房前端
├── frontend-job/ # 招聘前端
└── docker-compose.yml # 容器编排
# 关键配置:application.yml (user-service示例)
spring:
application:
name: user-service
datasource:
url: jdbc:mysql://localhost:3306/user_db?useSSL=false
username: root
password: 123456
redis:
host: localhost
port: 6379
cloud:
nacos:
discovery:
server-addr: localhost:8848 # 服务注册发现
# JWT统一配置(common-service)
jwt:
header: Authorization
secret: online-platform-secret-key-2023
expiration: 86400000 # 24小时
三、数据库设计:双业务数据模型分析与优化
两大业务既有独立性又有相似性,数据库设计需兼顾“分离”与“复用”。
1. 核心实体关系分析(16张表逻辑分组)
第一组:用户与身份相关(4表)
yonghu(用户表):基础用户信息,与业务解耦fangdong(房东表):扩展用户为房东的专属信息gongsi(企业表):扩展用户为企业的专属信息admin(管理员表):平台管理人员
第二组:租房业务核心(6表)
fangwu(房屋表):房源信息,关联fangdong_idfangwu_collection(房屋收藏):用户收藏关系fangwu_commentback(房屋评价):租后评价fangwu_order(房屋订单):交易核心表fangwu_order_flow(订单流水):支付记录(可扩展)fangwu_view_history(浏览历史):用户行为(可扩展)
第三组:招聘业务核心(6表)
zhaopin(职位招聘表):职位信息,关联gongsi_idjianli(简历表):用户简历,关联yonghu_idjianli_toudi(简历投递表):投递记录,双外键关联简历和职位zhaopin_collection(职位收藏)zhaopin_liuyan(职位留言)mianshi_invitation(面试邀请表):可扩展
第四组:公共模块(4表)
dic(字典表):统一枚举值管理forum(论坛表):支持多角色发帖(用户、房东、企业、管理员)gonggao(平台资讯表):系统公告和资讯system_log(系统日志):操作审计
2. 关键业务表设计优化(实战经验)
房屋订单表深度优化:
-- 原设计问题:缺少租期信息、支付状态、合同信息
-- 优化后设计
CREATE TABLE `fangwu_order` (
`id` int NOT NULL AUTO_INCREMENT,
`order_uuid` varchar(64) NOT NULL COMMENT '订单号',
`fangwu_id` int NOT NULL COMMENT '房屋ID',
`yonghu_id` int NOT NULL COMMENT '租客ID',
`fangdong_id` int NOT NULL COMMENT '房东ID',
`start_date` date NOT NULL COMMENT '起租日期',
`end_date` date NOT NULL COMMENT '结束日期',
`month_count` int NOT NULL COMMENT '租赁月数',
`monthly_rent` decimal(10,2) NOT NULL COMMENT '月租金',
`total_amount` decimal(10,2) NOT NULL COMMENT '总金额',
`deposit` decimal(10,2) NOT NULL COMMENT '押金',
`order_status` tinyint NOT NULL COMMENT '1待支付 2待确认 3租期中 4已完成 5已取消 6纠纷中',
`pay_status` tinyint NOT NULL COMMENT '支付状态',
`contract_url` varchar(500) COMMENT '电子合同地址',
`cancel_reason` varchar(500) COMMENT '取消原因',
`checkin_time` datetime COMMENT '入住时间',
`checkout_time` datetime COMMENT '退租时间',
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_order_uuid` (`order_uuid`),
KEY `idx_fangwu` (`fangwu_id`),
KEY `idx_yonghu` (`yonghu_id`),
KEY `idx_fangdong` (`fangdong_id`),
KEY `idx_status` (`order_status`),
CONSTRAINT `fk_order_fangwu` FOREIGN KEY (`fangwu_id`) REFERENCES `fangwu` (`id`),
CONSTRAINT `fk_order_yonghu` FOREIGN KEY (`yonghu_id`) REFERENCES `yonghu` (`id`),
CONSTRAINT `fk_order_fangdong` FOREIGN KEY (`fangdong_id`) REFERENCES `fangdong` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='房屋订单表';
简历投递表状态机设计:
-- 投递状态流转:1已投递 → 2已查看 → 3筛选通过 → 4面试邀请 → 5面试完成 → 6录用 → 7不匹配
CREATE TABLE `jianli_toudi` (
`id` int NOT NULL AUTO_INCREMENT,
`jianli_id` int NOT NULL COMMENT '简历ID',
`zhaopin_id` int NOT NULL COMMENT '职位ID',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '投递状态',
`company_view_time` datetime COMMENT '企业查看时间',
`filter_result` varchar(200) COMMENT '筛选结果备注',
`interview_time` datetime COMMENT '面试时间',
`interview_feedback` text COMMENT '面试反馈',
`offer_status` tinyint COMMENT '录用状态 1待确认 2已接受 3已拒绝',
`reject_reason` varchar(500) COMMENT '拒绝原因',
`create_time` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_jianli_zhaopin` (`jianli_id`, `zhaopin_id`), -- 防止重复投递
KEY `idx_zhaopin_status` (`zhaopin_id`, `status`),
KEY `idx_jianli_status` (`jianli_id`, `status`),
CONSTRAINT `fk_toudi_jianli` FOREIGN KEY (`jianli_id`) REFERENCES `jianli` (`id`),
CONSTRAINT `fk_toudi_zhaopin` FOREIGN KEY (`zhaopin_id`) REFERENCES `zhaopin` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='简历投递表';
3. 表关联查询实战(复杂业务场景)
-- 场景1:统计房东的房源出租情况
SELECT
f.fangdong_id,
fd.fangdong_name,
COUNT(DISTINCT f.id) as total_fangwu,
COUNT(DISTINCT fo.id) as total_orders,
COUNT(DISTINCT CASE WHEN fo.order_status = 3 THEN fo.id END) as renting_count,
ROUND(COUNT(DISTINCT fo.id) * 100.0 / COUNT(DISTINCT f.id), 2) as rent_rate,
AVG(fo.monthly_rent) as avg_rent,
SUM(fo.total_amount) as total_income
FROM fangwu f
LEFT JOIN fangdong fd ON f.fangdong_id = fd.id
LEFT JOIN fangwu_order fo ON f.id = fo.fangwu_id AND fo.order_status IN (3,4)
WHERE f.fangwu_delete = 0
GROUP BY f.fangdong_id
ORDER BY total_income DESC;
-- 场景2:求职者投递进度跟踪
SELECT
jt.id,
z.zhaopin_name,
g.gongsi_name,
z.zhaopin_daiyu,
jt.status,
CASE jt.status
WHEN 1 THEN '已投递'
WHEN 2 THEN '已查看'
WHEN 3 THEN '筛选通过'
WHEN 4 THEN '面试邀请'
WHEN 5 THEN '面试完成'
WHEN 6 THEN '录用'
WHEN 7 THEN '不匹配'
ELSE '未知'
END as status_text,
jt.interview_time,
jt.offer_status,
jt.create_time as toudi_time
FROM jianli_toudi jt
JOIN zhaopin z ON jt.zhaopin_id = z.id
JOIN gongsi g ON z.gongsi_id = g.id
WHERE jt.jianli_id = #{jianliId}
ORDER BY jt.create_time DESC;
四、功能实现:双业务核心模块开发策略
由于涉及两大业务,需采取“并行开发+复用组件”策略,优先完成各自核心流程。
1. 租房业务核心:房屋订单全流程管理(必做模块)
技术难点:状态机与并发控制 租房订单涉及多状态流转(待支付→待确认→租期中→已完成),且热门房源可能被多人同时预订,需要解决“超订”问题。
解决方案:
- 状态机设计:使用状态模式,定义订单状态流转规则
// 订单状态枚举
public enum OrderStatus {
PENDING_PAY(1, "待支付"),
PENDING_CONFIRM(2, "待确认"),
RENTING(3, "租期中"),
COMPLETED(4, "已完成"),
CANCELLED(5, "已取消"),
DISPUTE(6, "纠纷中");
// 状态流转规则
private static final Map<OrderStatus, Set<OrderStatus>> TRANSITION_RULES = new HashMap<>();
static {
TRANSITION_RULES.put(PENDING_PAY, Set.of(PENDING_CONFIRM, CANCELLED));
TRANSITION_RULES.put(PENDING_CONFIRM, Set.of(RENTING, CANCELLED));
TRANSITION_RULES.put(RENTING, Set.of(COMPLETED, DISPUTE));
// ... 其他规则
}
public static boolean canTransition(OrderStatus from, OrderStatus to) {
return TRANSITION_RULES.getOrDefault(from, Collections.emptySet()).contains(to);
}
}
- 并发控制方案:Redis分布式锁 + 数据库乐观锁
@Service
public class FangwuOrderService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Transactional(rollbackFor = Exception.class)
public boolean createOrder(CreateOrderDTO dto) {
String lockKey = "lock:fangwu:" + dto.getFangwuId();
String lockValue = UUID.randomUUID().toString();
try {
// 1. Redis分布式锁,防止同一房源被多人同时下单
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, lockValue, 30, TimeUnit.SECONDS);
if (!Boolean.TRUE.equals(locked)) {
throw new BusinessException("房源正在被其他人预订,请稍后再试");
}
// 2. 查询房源并检查可租状态
Fangwu fangwu = fangwuMapper.selectById(dto.getFangwuId());
if (fangwu == null || fangwu.getFangwuDelete() == 1) {
throw new BusinessException("房源不存在或已下架");
}
// 3. 检查房源在租期时间内是否已被预订(时间冲突检查)
boolean timeConflict = checkTimeConflict(fangwu.getId(),
dto.getStartDate(), dto.getEndDate());
if (timeConflict) {
throw new BusinessException("所选时间段房源已被预订");
}
// 4. 创建订单(数据库层面还有唯一约束防止重复)
FangwuOrder order = new FangwuOrder();
// ... 设置订单属性
order.setOrderStatus(OrderStatus.PENDING_PAY.getCode());
// 5. 使用版本号乐观锁
int rows = fangwuMapper.updateStock(fangwu.getId(),
fangwu.getVersion(), fangwu.getVersion() + 1);
if (rows == 0) {
throw new OptimisticLockException("房源信息已变更,请刷新后重试");
}
return orderMapper.insert(order) > 0;
} finally {
// 释放锁(使用Lua脚本保证原子性)
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
"return redis.call('del', KEYS[1]) else return 0 end";
redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),
Collections.singletonList(lockKey), lockValue);
}
}
}
页面设计要点:
- 房源详情页:顶部轮播图(房屋照片),中部基本信息卡片,底部地图位置(集成高德/百度地图API),侧边浮动操作栏(收藏、咨询、立即预订);
- 订单管理页:租客端和房东端视图不同,租客端侧重状态跟踪,房东端侧重批量操作;
- 电子合同页:使用PDF.js在线预览合同,支持电子签名(简化版可模拟)。
2. 招聘业务核心:简历智能匹配与投递追踪(答辩亮点)
技术难点:简历解析与智能匹配 传统简历投递是海投模式,体验差。需要实现简历解析和岗位智能匹配。
解决方案:
- 简历结构化存储:设计简历表时已考虑结构化字段(jianli_types求职意向、jianli_xinzi期望薪资、jianli_xueli学历等),便于匹配;
- 基于规则的智能推荐:
@Service
public class JobRecommendService {
/**
* 为求职者推荐职位
*/
public List<ZhaopinDTO> recommendJobs(Long userId, Integer resumeId) {
// 1. 获取用户简历
Jianli resume = jianliMapper.selectById(resumeId);
if (resume == null) {
return Collections.emptyList();
}
// 2. 构建查询条件(基于简历信息)
Map<String, Object> params = new HashMap<>();
params.put("jobType", resume.getJianliTypes()); // 求职意向
params.put("expectedSalary", resume.getJianliXinzi());
params.put("education", resume.getJianliXueli());
params.put("userId", userId); // 排除已投递的
// 3. 查询匹配职位(SQL中实现匹配算法)
List<Zhaopin> jobs = zhaopinMapper.selectRecommendedJobs(params);
// 4. 计算匹配度并排序
return jobs.stream()
.map(job -> {
ZhaopinDTO dto = convertToDTO(job);
dto.setMatchScore(calculateMatchScore(resume, job));
return dto;
})
.sorted((a, b) -> b.getMatchScore().compareTo(a.getMatchScore()))
.limit(20) // 最多推荐20个
.collect(Collectors.toList());
}
/**
* 计算简历与职位的匹配度(0-100分)
*/
private Integer calculateMatchScore(Jianli resume, Zhaopin job) {
int score = 0;
// 1. 求职意向匹配(30分)
if (resume.getJianliTypes().equals(job.getZhaopinTypes())) {
score += 30;
}
// 2. 薪资匹配(30分)
if (isSalaryMatch(resume.getJianliXinzi(), job.getZhaopinDaiyu())) {
score += 30;
}
// 3. 学历匹配(20分)
if (isEducationMatch(resume.getJianliXueli(), job.getEducationRequirement())) {
score += 20;
}
// 4. 地点匹配(20分)
if (isLocationMatch(resume.getJianliAddress(), job.getZhaopinAddress())) {
score += 20;
}
return Math.min(score, 100);
}
}
- 投递进度可视化:
<!-- 投递进度时间线组件 -->
<template>
<div class="delivery-timeline">
<el-timeline>
<el-timeline-item
v-for="(step, index) in timelineSteps"
:key="index"
:timestamp="step.time"
:type="step.status"
:icon="step.icon"
>
<div class="step-content">
<div class="step-title">{{ step.title }}</div>
<div class="step-desc" v-if="step.description">{{ step.description }}</div>
<div class="step-action" v-if="step.action">
<el-button size="mini" @click="handleAction(step.action)">
{{ step.actionText }}
</el-button>
</div>
</div>
</el-timeline-item>
</el-timeline>
</div>
</template>
<script>
export default {
props: {
deliveryId: {
type: Number,
required: true
}
},
data() {
return {
timelineSteps: [
{
title: '简历已投递',
time: '2023-10-10 14:30',
status: 'primary',
icon: 'el-icon-document'
},
{
title: '企业已查看',
time: '2023-10-11 09:15',
status: 'success',
icon: 'el-icon-view'
},
{
title: '筛选通过',
time: '2023-10-12 16:20',
status: 'success',
icon: 'el-icon-check'
},
{
title: '面试邀请',
time: '2023-10-13 10:00',
status: 'warning',
icon: 'el-icon-chat-dot-round',
description: '请确认面试时间:2023-10-16 14:00',
action: 'confirmInterview',
actionText: '确认参加'
},
{
title: '等待面试结果',
time: '预计2023-10-18',
status: 'info',
icon: 'el-icon-time'
}
]
}
}
}
</script>
页面设计要点:
- 简历编辑页:分步骤向导(基本信息→教育经历→工作经历→技能证书),实时保存,支持导入Word/PDF简历(解析功能可简化);
- 职位推荐页:左侧筛选条件,中间职位卡片列表,右侧匹配度指示器;
- 投递管理页:看板式展示(已投递、面试中、已录用、不合适),支持批量操作。
3. 公共模块:统一用户中心与消息系统(技术亮点)
设计思路:将用户认证、消息通知、文件服务等公共功能抽象为独立服务,供租房和招聘模块调用。
统一认证中心实现:
// 1. 多角色统一登录
@PostMapping("/login")
public Result login(@RequestBody LoginDTO loginDTO) {
// 根据登录标识判断用户类型
UserType userType = identifyUserType(loginDTO.getUsername());
UserDetails userDetails;
switch (userType) {
case ADMIN:
userDetails = adminDetailsService.loadUserByUsername(loginDTO.getUsername());
break;
case FANGDONG:
userDetails = fangdongDetailsService.loadUserByUsername(loginDTO.getUsername());
break;
case GONGSI:
userDetails = gongsiDetailsService.loadUserByUsername(loginDTO.getUsername());
break;
default: // YONGHU
userDetails = yonghuDetailsService.loadUserByUsername(loginDTO.getUsername());
}
// 验证密码
if (!passwordEncoder.matches(loginDTO.getPassword(), userDetails.getPassword())) {
throw new BadCredentialsException("密码错误");
}
// 生成JWT令牌(包含用户类型)
String token = JwtUtil.generateToken(
userDetails.getUsername(),
userType.name(),
additionalClaims
);
return Result.success("登录成功", new LoginVO(token, userType));
}
// 2. 网关统一鉴权
@Component
public class AuthFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path = exchange.getRequest().getURI().getPath();
// 公开路径放行
if (isPublicPath(path)) {
return chain.filter(exchange);
}
// 获取token
String token = getToken(exchange);
if (token == null) {
return unauthorized(exchange, "未提供认证令牌");
}
// 验证token
Claims claims = JwtUtil.parseToken(token);
if (claims == null) {
return unauthorized(exchange, "令牌无效或已过期");
}
// 检查权限(基于路径和用户类型)
String userType = claims.get("userType", String.class);
if (!hasPermission(path, userType)) {
return unauthorized(exchange, "无权访问该资源");
}
// 将用户信息添加到请求头
ServerHttpRequest request = exchange.getRequest().mutate()
.header("X-User-Id", claims.getSubject())
.header("X-User-Type", userType)
.build();
return chain.filter(exchange.mutate().request(request).build());
}
}
统一消息系统设计:
-- 消息表设计(支持多种业务消息)
CREATE TABLE `system_message` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` int NOT NULL COMMENT '接收用户ID',
`user_type` varchar(20) NOT NULL COMMENT '用户类型',
`title` varchar(200) NOT NULL COMMENT '消息标题',
`content` text NOT NULL COMMENT '消息内容',
`msg_type` varchar(50) NOT NULL COMMENT '消息类型:order_created,interview_invite,etc',
`business_id` int COMMENT '业务ID(如订单ID、投递ID)',
`business_type` varchar(50) COMMENT '业务类型:rental,job',
`is_read` tinyint NOT NULL DEFAULT 0 COMMENT '是否已读',
`read_time` datetime COMMENT '阅读时间',
`extra_data` json COMMENT '扩展数据',
`create_time` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_user` (`user_id`, `user_type`, `is_read`),
KEY `idx_business` (`business_type`, `business_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统消息表';
五、测试验收:双业务交叉测试策略
双业务平台测试复杂度高,需设计交叉测试用例,验证业务隔离和数据一致性。
1. 功能测试:核心交叉场景
| 测试场景 | 测试步骤 | 预期结果 | 验证要点 |
|---|---|---|---|
| 用户双重身份操作 | 用户同时申请成为房东和企业账号,分别发布房源和职位 | 两种身份独立操作,数据隔离,权限正确 | 身份切换、数据隔离、权限验证 |
| 跨业务消息通知 | 用户既是租客又是求职者,同时收到租房订单确认和面试邀请 | 消息中心正确分类显示,可分别处理 | 消息分类、业务标识、处理跳转 |
| 统一支付验证 | 租房支付(模拟)和招聘服务购买(如置顶职位) | 支付流程一致,资金账户独立结算 | 支付网关、账户隔离、交易记录 |
| 数据统计整合 | 平台管理员查看整体数据报表 | 同时展示租房和招聘核心指标,支持对比分析 | 数据聚合、图表展示、业务对比 |
2. 性能测试:重点关注并发场景
- 秒杀场景:热门房源上线,多人同时预订;
- 批量投递:求职者一键投递多个职位;
- 列表查询:房源/职位列表分页查询,带复杂筛选条件;
- 消息推送:系统向大量用户发送通知(如新职位提醒)。
使用JMeter模拟测试:
<!-- JMeter测试计划关键配置 -->
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="房源秒杀测试">
<intProp name="ThreadGroup.num_threads">100</intProp> <!-- 100并发用户 -->
<intProp name="ThreadGroup.ramp_time">10</intProp> <!-- 10秒内启动 -->
<longProp name="ThreadGroup.duration">60</longProp> <!-- 持续60秒 -->
</ThreadGroup>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="创建订单请求">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments">
<collectionProp name="Arguments.arguments">
<elementProp name="fangwuId" elementType="HTTPArgument">
<stringProp name="Argument.value">${热门房源ID}</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.path">/rental/order/create</stringProp>
<stringProp name="HTTPSampler.method">POST</stringProp>
</HTTPSamplerProxy>
3. 安全测试:多角色权限验证
- 垂直越权:普通用户尝试访问管理员接口;
- 水平越权:用户A尝试操作用户B的数据;
- 业务交叉越权:租房用户尝试访问招聘管理功能;
- 接口安全:API接口是否防止SQL注入、XSS攻击。
六、答辩准备:突出“平台化”设计思维
-
演示流程设计(7分钟完整演示):
- 第1分钟:平台概览,展示双业务入口和统一设计风格;
- 第2-3分钟:租房业务流程演示(发布→浏览→预订→签约→评价);
- 第4-5分钟:招聘业务流程演示(发布→搜索→投递→面试→录用);
- 第6分钟:平台管理演示(数据统计、用户管理、内容审核);
- 第7分钟:技术亮点展示(微服务架构、智能推荐、并发控制)。
-
问题准备与应答:
- "为什么将租房和招聘整合到一个平台?"→"两者都是供需匹配平台,用户群体重叠(年轻人),技术架构相似,整合可提升开发效率和用户体验";
- "系统如何处理业务冲突?"→"采用模块化设计,业务数据物理隔离,通过统一认证中心协调,前台体验整合,后台数据分离";
- "系统的扩展性如何?"→"微服务架构,可随时增加新业务模块(如二手交易、技能服务),各服务独立部署扩展";
- "智能匹配算法如何实现?"→"基于规则引擎+标签系统,考虑求职意向、薪资、地点、技能等多维度匹配,后续可引入机器学习优化"。
-
文档与展示材料:
- 系统架构图(突出微服务设计);
- 数据库ER图(标注核心业务表关系);
- 业务流程图(租房vs招聘对比展示);
- 核心代码片段(状态机、分布式锁、智能匹配);
- 性能测试报告(关键指标截图)。
结语
在线租房和招聘平台作为"双业务平台"类毕设,技术挑战在于业务整合与模块化设计。本文基于实际开发经验,总结了关键要点:
核心成功要素:
- 架构先行:采用微服务思想,即使不实现完整微服务,也要做到模块化设计;
- 数据分离:业务核心数据物理或逻辑隔离,避免混杂;
- 统一体验:用户中心、消息系统、支付流程等公共服务统一设计;
- **复用思维