作为一名长期从事Java Web开发的工程师,我最近完成了一个基于SpringBoot+Vue的房屋租赁管理系统。这个项目最初是为某高校计算机专业毕业设计而开发,但实际功能已经达到了商业级应用水平。系统采用前后端分离架构,后端使用SpringBoot+MyBatis Plus实现,前端基于Vue+ElementUI构建,数据库采用MySQL 8.0,并引入Redis作为缓存层。
在开发过程中,我发现房屋租赁管理系统有几个关键痛点需要解决:房源信息真实性验证、租赁合同电子化、租金支付便捷性和多角色权限管理。针对这些问题,我设计了完整的解决方案,现在将开发过程中的核心思路和实现细节分享给大家。
选择SpringBoot作为后端框架主要基于以下考虑:
前端选择Vue.js的原因:
数据库选型方面:
系统采用经典的三层架构:
code复制表现层(Vue) ↔ 业务逻辑层(SpringBoot) ↔ 数据访问层(MySQL)
关键设计决策:
提示:在架构设计阶段就要考虑扩展性,比如预留了微服务改造的可能性,虽然当前是单体架构。
房源信息表设计采用了垂直分表策略,将基本信息和扩展信息分开存储。核心字段包括:
sql复制CREATE TABLE `house_resource` (
`resource_id` bigint NOT NULL AUTO_INCREMENT,
`house_title` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
`house_address` varchar(100) COLLATE utf8mb4_general_ci NOT NULL,
`rent_price` decimal(10,2) NOT NULL,
`house_status` tinyint NOT NULL DEFAULT '0',
`landlord_id` bigint NOT NULL,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`resource_id`),
KEY `idx_landlord` (`landlord_id`),
KEY `idx_status` (`house_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
房源搜索功能实现要点:
电子合同是本系统的核心功能之一,实现流程:
关键代码片段(SpringBoot):
java复制@PostMapping("/contract/generate")
public Result generateContract(@RequestBody ContractDTO dto) {
// 1. 验证房源和租客信息
HouseResource house = houseService.getById(dto.getResourceId());
Tenant tenant = tenantService.getById(dto.getTenantId());
// 2. 生成合同PDF
String templatePath = "templates/contract_template.ftl";
Map<String, Object> data = buildContractData(house, tenant, dto);
byte[] pdfBytes = pdfGenerator.generate(templatePath, data);
// 3. 上传到OSS
String ossPath = ossClient.upload(pdfBytes, "contracts");
// 4. 保存合同记录
Contract contract = new Contract();
contract.setResourceId(dto.getResourceId());
contract.setTenantId(dto.getTenantId());
contract.setSignDate(new Date());
contract.setContractFile(ossPath);
contractService.save(contract);
return Result.success(contract);
}
租金支付对接了支付宝和微信支付双渠道,关键实现点:
支付状态机设计:
code复制待支付 → 支付中 → 支付成功/失败
↘ 超时取消
除了前面提到的房源表,系统主要包含以下表:
sql复制CREATE TABLE `user` (
`user_id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
`role_type` tinyint NOT NULL COMMENT '1-管理员 2-房东 3-租客',
`phone` varchar(15) DEFAULT NULL,
`avatar` varchar(255) DEFAULT NULL,
`status` tinyint DEFAULT '1',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`),
UNIQUE KEY `idx_username` (`username`)
);
sql复制CREATE TABLE `tenant_info` (
`tenant_id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL,
`real_name` varchar(20) DEFAULT NULL,
`id_card` varchar(18) DEFAULT NULL,
`credit_score` int DEFAULT '100',
`contact_address` varchar(100) DEFAULT NULL,
PRIMARY KEY (`tenant_id`),
UNIQUE KEY `idx_user` (`user_id`)
);
在数据库优化方面,我们采取了以下措施:
例如,合同表的查询优化:
sql复制ALTER TABLE contract_record ADD INDEX idx_tenant_resource (tenant_id, resource_id);
房源列表组件采用分页加载+虚拟滚动优化性能:
vue复制<template>
<div class="house-list">
<el-table
:data="houses"
row-key="resourceId"
@row-click="handleRowClick"
>
<el-table-column prop="houseTitle" label="房源标题" />
<el-table-column prop="rentPrice" label="租金" />
<el-table-column prop="houseAddress" label="地址" />
</el-table>
<el-pagination
@current-change="handlePageChange"
:current-page="pagination.current"
:page-size="pagination.size"
:total="pagination.total"
/>
</div>
</template>
<script>
export default {
data() {
return {
houses: [],
pagination: {
current: 1,
size: 10,
total: 0
}
}
},
methods: {
async loadHouses() {
const params = {
page: this.pagination.current,
size: this.pagination.size
}
const res = await this.$api.getHouses(params)
this.houses = res.data.records
this.pagination.total = res.data.total
},
handlePageChange(page) {
this.pagination.current = page
this.loadHouses()
}
},
created() {
this.loadHouses()
}
}
</script>
使用Vuex管理全局状态,主要模块包括:
典型store结构:
javascript复制const store = new Vuex.Store({
modules: {
auth: {
state: () => ({
token: localStorage.getItem('token') || '',
userInfo: null
}),
mutations: {
setToken(state, token) {
state.token = token
localStorage.setItem('token', token)
}
}
}
}
})
推荐使用Docker Compose部署整套系统:
yaml复制version: '3'
services:
backend:
image: rental-backend:1.0
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
depends_on:
- mysql
- redis
frontend:
image: rental-frontend:1.0
ports:
- "80:80"
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=123456
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:6.0
ports:
- "6379:6379"
volumes:
mysql_data:
集成Spring Boot Actuator提供健康检查:
properties复制# application-prod.properties
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
前端使用Sentry捕获异常:
javascript复制import * as Sentry from '@sentry/vue'
Sentry.init({
dsn: 'your_dsn',
integrations: [new Sentry.BrowserTracing()],
tracesSampleRate: 0.2
})
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
}
java复制@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
return builder -> {
builder.serializers(new LocalDateSerializer(DateTimeFormatter.ISO_DATE));
builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ISO_DATE_TIME));
};
}
}
重要提示:在开发过程中一定要做好异常处理和数据校验,特别是支付相关功能必须实现幂等性处理。
这个基础版本完成后,还可以考虑以下扩展功能:
在实际开发这个项目过程中,我最大的体会是:设计阶段多花时间考虑扩展性和异常场景,能大幅减少后期维护成本。特别是数据库设计,一旦上线后再修改表结构会非常麻烦。另外,文档的完整性也非常重要,包括API文档、部署文档和用户手册,这些都是在项目交接时最容易被忽视但实际上最重要的部分。