1. 项目概述与技术选型
这套房屋租赁管理系统采用了当前企业级开发中最主流的全栈技术组合:SpringBoot+Vue3+MyBatis+MySQL。作为前后端分离架构的典型实现,它完美展现了现代Web应用的标准技术栈配置。我在实际开发中发现,这种技术组合特别适合中小型业务系统的快速迭代开发。
SpringBoot 2.7.x作为后端框架,提供了自动配置、内嵌Tomcat等开箱即用的特性,极大简化了传统Spring应用的初始化流程。配合MyBatis 3.5.x作为ORM层,在保持SQL灵活性的同时,通过注解和XML两种方式实现了对象关系映射。数据库选用MySQL 8.0,其事务支持和JSON字段特性非常适合租赁业务中的合同管理和账单处理场景。
前端采用Vue3组合式API开发,相比Vue2的Options API,代码组织更加灵活。特别是使用Pinia替代Vuex后,状态管理变得更直观。Element Plus作为UI组件库,提供了丰富的表单和表格组件,极大加速了租赁合同、房源信息等管理页面的开发。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计与核心模块
2.1 前后端分离架构实现
系统采用经典的前后端分离架构,通过RESTful API进行数据交互。在实际部署时,我推荐使用Nginx作为前端静态资源服务器,同时配置反向代理解决跨域问题。以下是一个典型的Nginx配置示例:
nginx复制server {
listen 80;
server_name rental.example.com;
location / {
root /var/www/rental-frontend;
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;
}
}
后端API遵循RESTful规范,所有接口都采用JSON格式传输数据。为了统一响应格式,我自定义了Result封装类:
java复制public class Result<T> {
private Integer code;
private String message;
private T data;
// 成功静态方法
public static <T> Result<T> success(T data) {
return new Result<>(200, "成功", data);
}
// 构造器、getter、setter省略
}
2.2 核心业务模块划分
系统主要包含以下功能模块:
- 用户认证模块:基于JWT实现,包含登录、注册、权限校验
- 房源管理模块:房源CRUD、图片上传、条件筛选
- 租约管理模块:合同生成、电子签名、到期提醒
- 支付结算模块:对接支付宝/微信支付、账单生成
- 数据统计模块:出租率分析、收入报表
其中租约管理模块最为复杂,涉及状态机和定时任务。我采用Spring StateMachine实现合同状态流转:
java复制@Configuration
@EnableStateMachineFactory
public class ContractStateMachineConfig {
@Bean
public StateMachine<ContractState, ContractEvent> stateMachine() {
StateMachineBuilder.Builder<ContractState, ContractEvent> builder =
StateMachineBuilder.builder();
builder.configureStates()
.withStates()
.initial(ContractState.DRAFT)
.states(EnumSet.allOf(ContractState.class));
builder.configureTransitions()
.withExternal()
.source(ContractState.DRAFT).target(ContractState.ACTIVE)
.event(ContractEvent.SIGN)
.and()
.withExternal()
.source(ContractState.ACTIVE).target(ContractState.TERMINATED)
.event(ContractEvent.TERMINATE);
return builder.build();
}
}
3. 数据库设计与优化
3.1 核心表结构设计
MySQL数据库设计遵循第三范式,主要包含以下表:
user:用户基本信息role:角色权限house:房源信息contract:租赁合同payment:支付记录maintenance:维修记录
其中合同表的设计需要特别注意时效性和状态管理:
sql复制CREATE TABLE `contract` (
`id` bigint NOT NULL AUTO_INCREMENT,
`house_id` bigint NOT NULL,
`tenant_id` bigint NOT NULL,
`start_date` date NOT NULL,
`end_date` date NOT NULL,
`monthly_rent` decimal(10,2) NOT NULL,
`deposit` decimal(10,2) NOT NULL,
`status` enum('DRAFT','ACTIVE','TERMINATED','EXPIRED') NOT NULL DEFAULT 'DRAFT',
`signed_at` datetime DEFAULT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_house` (`house_id`),
KEY `idx_tenant` (`tenant_id`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
3.2 查询性能优化实践
在房源搜索功能中,我遇到了LIKE查询性能问题。通过添加全文索引和使用MATCH AGAINST语法,性能提升了10倍:
sql复制ALTER TABLE house ADD FULLTEXT INDEX ft_index (title, description, address);
-- 优化前(慢)
SELECT * FROM house WHERE title LIKE '%公寓%' OR description LIKE '%公寓%';
-- 优化后
SELECT * FROM house
WHERE MATCH(title, description, address) AGAINST('公寓' IN NATURAL LANGUAGE MODE);
对于分页查询,推荐使用"延迟关联"技术优化大数据量分页:
sql复制-- 普通分页(性能差)
SELECT * FROM house ORDER BY created_at DESC LIMIT 10000, 10;
-- 优化分页
SELECT h.* FROM house h
INNER JOIN (SELECT id FROM house ORDER BY created_at DESC LIMIT 10000, 10) AS tmp
ON h.id = tmp.id;
4. 前端工程化实践
4.1 Vue3组合式API应用
使用setup语法糖大幅简化了组件代码。以下是典型的房源列表组件实现:
vue复制<script setup>
import { ref, onMounted } from 'vue'
import { getHouseList } from '@/api/house'
const houses = ref([])
const loading = ref(false)
const pagination = ref({
page: 1,
size: 10,
total: 0
})
const fetchData = async () => {
loading.value = true
try {
const res = await getHouseList({
page: pagination.value.page,
size: pagination.value.size
})
houses.value = res.data.list
pagination.value.total = res.data.total
} finally {
loading.value = false
}
}
onMounted(fetchData)
</script>
<template>
<el-table :data="houses" v-loading="loading">
<el-table-column prop="title" label="房源标题" />
<el-table-column prop="price" label="月租金" />
<el-table-column prop="area" label="面积" />
</el-table>
<el-pagination
v-model:current-page="pagination.page"
:page-size="pagination.size"
:total="pagination.total"
@current-change="fetchData"
/>
</template>
4.2 状态管理最佳实践
使用Pinia替代Vuex后,状态管理变得更简洁。我创建了authStore处理用户认证状态:
javascript复制// stores/auth.js
import { defineStore } from 'pinia'
import { login, logout, getInfo } from '@/api/user'
export const useAuthStore = defineStore('auth', {
state: () => ({
user: null,
token: localStorage.getItem('token') || '',
permissions: []
}),
actions: {
async login(credentials) {
const res = await login(credentials)
this.token = res.data.token
localStorage.setItem('token', this.token)
await this.fetchUserInfo()
},
async fetchUserInfo() {
const res = await getInfo()
this.user = res.data.user
this.permissions = res.data.permissions
},
async logout() {
await logout()
this.$reset()
localStorage.removeItem('token')
}
},
getters: {
isAuthenticated: state => !!state.token
}
})
5. 开发环境配置与调试技巧
5.1 后端热部署配置
在SpringBoot开发中,我推荐使用DevTools实现热部署。需要在pom.xml中添加:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
然后在IDEA中开启自动编译:
- Settings → Build → Compiler → 勾选Build project automatically
- 按Ctrl+Shift+A,搜索Registry,勾选compiler.automake.allow.when.app.running
5.2 前端调试技巧
在Vue3开发中,我经常使用以下Chrome调试技巧:
- 安装Vue Devtools 6.x+版本
- 使用
debugger语句配合Source Map调试 - 通过
import.meta.env获取环境变量 - 使用
vite-plugin-inspect查看Vite插件中间状态
对于API调试,推荐使用.env.development配置代理:
ini复制VITE_API_BASE_URL=/api
然后在vite.config.js中配置代理:
javascript复制export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
})
6. 安全防护实践
6.1 常见Web安全防护
在系统中我实施了以下安全措施:
- SQL注入防护:MyBatis全部使用#{}参数绑定
- XSS防护:前端使用DOMPurify过滤富文本,后端统一转义响应
- CSRF防护:虽然RESTful API无状态,但仍添加了CSRF Token
- 权限控制:基于RBAC模型,注解式权限校验
Spring Security配置示例:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
return http.build();
}
}
6.2 JWT认证实现
JWT认证是前后端分离架构的核心。我的实现包含以下关键点:
- 使用HS512算法签名
- 设置合理的过期时间(如2小时)
- 实现无感刷新机制
- 黑名单处理注销的Token
JWT工具类核心代码:
java复制public class JwtUtil {
private static final String SECRET = "your-512-bit-secret";
private static final long EXPIRATION = 7200; // 2小时
public static String generateToken(UserDetails user) {
return Jwts.builder()
.setSubject(user.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION * 1000))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
public static String getUsernameFromToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}
7. 部署与运维方案
7.1 容器化部署实践
我推荐使用Docker Compose进行一体化部署。后端Dockerfile示例:
dockerfile复制FROM openjdk:17-jdk-slim
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
前端Dockerfile示例:
dockerfile复制FROM nginx:alpine
COPY dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
docker-compose.yml配置:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: rental
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/rental
frontend:
build: ./frontend
ports:
- "80:80"
volumes:
mysql_data:
7.2 监控与日志处理
对于生产环境,我建议配置以下监控:
- Spring Boot Actuator健康检查
- Prometheus + Grafana监控指标
- ELK日志收集系统
- SkyWalking分布式追踪
Actuator配置示例:
yaml复制management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
metrics:
export:
prometheus:
enabled: true
endpoint:
health:
show-details: always
日志收集建议使用Logback+ELK:
xml复制<!-- logback-spring.xml -->
<configuration>
<appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
<root level="INFO">
<appender-ref ref="JSON"/>
</root>
</configuration>
8. 项目扩展与优化方向
在实际使用中,我发现这套系统还可以在以下方面进行扩展:
- 多租户支持:使用MyBatis-Plus的多租户插件,实现一套系统服务多个租赁公司
- 微信小程序端:基于uni-app开发小程序版本,复用现有API
- 智能推荐:基于用户行为数据实现房源推荐
- 电子合同:集成第三方电子签名服务
- 物联网集成:对接智能门锁、电表等设备
对于性能优化,我总结了几点经验:
- 使用Redis缓存热点数据,如房源详情、用户信息
- 对账单类报表实施预计算策略
- 采用消息队列削峰填谷,处理批量操作
- 前端实施组件级按需加载
Redis缓存配置示例:
java复制@Configuration
@EnableCaching
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}
@Service
@CacheConfig(cacheNames = "house")
public class HouseService {
@Cacheable(key = "#id")
public House getById(Long id) {
return houseMapper.selectById(id);
}
@CacheEvict(key = "#house.id")
public void update(House house) {
houseMapper.updateById(house);
}
}
这套技术栈组合经过多个项目的验证,在开发效率、运行性能和可维护性之间取得了很好的平衡。特别是在快速迭代的业务场景中,前后端分离架构让团队可以并行开发,大大缩短了交付周期。
