1. 项目概述:大学生租房平台的技术栈与核心价值
这个基于SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0的大学生租房平台,是我在指导毕业设计时反复打磨的一个实战项目。它不仅仅是一套源码,更是一个完整的前后端分离解决方案,特别适合计算机专业学生作为毕业设计选题,或者初级开发者作为全栈开发的练手项目。
平台采用主流技术栈组合:后端基于SpringBoot2构建RESTful API,前端使用Vue3实现响应式界面,数据持久层采用MyBatis-Plus简化CRUD操作,数据库选用MySQL8.0利用其JSON支持和窗口函数等新特性。整套架构既符合企业级开发规范,又考虑了学习曲线的平滑过渡。
提示:项目文档中包含的部署手册和数据库设计说明书,对于理解整体架构特别有帮助,建议先通读文档再动手编码。
2. 技术栈深度解析与选型考量
2.1 后端技术组合:SpringBoot2 + MyBatis-Plus
选择SpringBoot2而非更新的SpringBoot3,主要考虑教学环境的稳定性。SpringBoot2的自动配置机制和starter依赖,能快速搭建起包含安全认证(JWT)、数据校验、异常处理等企业级特性的后端服务。我在pom.xml中特别配置了这些关键依赖:
xml复制<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
MyBatis-Plus的ActiveRecord模式让实体类直接具备CRUD能力,这对业务简单的租房平台非常友好。例如房源实体只需继承Model类:
java复制public class House extends Model<House> {
@TableId(type = IdType.AUTO)
private Long id;
private String title;
// 其他字段和getter/setter
}
2.2 前端架构:Vue3组合式API实践
放弃Options API而全面采用Composition API,这是项目的一个教学重点。通过setup语法糖,我们可以更灵活地组织代码。比如房源搜索功能:
vue复制<script setup>
import { ref, computed } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const searchKeyword = ref(route.query.keyword || '')
// 计算属性实现实时过滤
const filteredHouses = computed(() => {
return houses.value.filter(house =>
house.title.includes(searchKeyword.value)
)
})
</script>
2.3 数据库设计:MySQL8.0特性运用
租房平台的数据库设计有几个关键点:
- 利用MySQL8.0的JSON类型存储房源的图片数组
- 使用窗口函数实现房源排名统计
- 空间数据类型存储地理位置
建表示例:
sql复制CREATE TABLE `house` (
`id` bigint NOT NULL AUTO_INCREMENT,
`title` varchar(100) COLLATE utf8mb4_general_ci NOT NULL,
`price` decimal(10,2) NOT NULL,
`images` json DEFAULT NULL COMMENT '图片URL数组',
`location` point NOT NULL SRID 4326,
PRIMARY KEY (`id`),
SPATIAL KEY `idx_location` (`location`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 核心功能模块实现细节
3.1 用户认证与权限控制
采用JWT无状态认证方案,通过Spring Security的过滤器链实现。特别注意处理了这些边界情况:
- Token刷新机制:当token即将过期时(剩余有效期<30分钟),在响应头中添加新token
- 权限注解组合:@PreAuthorize + 自定义@RequiresRoles
- 验证码防刷:Redis存储验证码并设置TTL
核心认证流程代码:
java复制@PostMapping("/login")
public Result<LoginVO> login(@Valid @RequestBody LoginDTO dto) {
// 验证验证码
String cacheCode = redisTemplate.opsForValue()
.get(CAPTCHA_KEY + dto.getUuid());
if (!dto.getCode().equalsIgnoreCase(cacheCode)) {
throw new BizException("验证码错误");
}
// 用户密码验证
User user = userService.lambdaQuery()
.eq(User::getUsername, dto.getUsername())
.one();
if (!passwordEncoder.matches(dto.getPassword(), user.getPassword())) {
throw new BizException("用户名或密码错误");
}
// 生成Token
String token = Jwts.builder()
.setSubject(user.getId().toString())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
.signWith(Keys.hmacShaKeyFor(secret.getBytes()))
.compact();
return Result.success(new LoginVO([token](https://taotoken.net?utm_source=general), user));
}
3.2 房源信息管理
房源模块实现了:
- 多条件组合搜索(地段、价格区间、户型)
- 地图找房(基于MySQL空间查询)
- 收藏与浏览历史
空间查询示例:
java复制@Select("SELECT id, title, price, ST_AsText(location) as locationStr " +
"FROM house WHERE ST_Distance_Sphere(location, POINT(#{lng}, #{lat})) <= #{radius}")
List<House> findNearby(@Param("lng") double lng,
@Param("lat") double lat,
@Param("radius") int radius);
3.3 订单与合约系统
租房订单状态机设计是业务核心,状态转换包括:
code复制待支付 → 已支付 → 租期中 → 已完成
↘ 退租中 → 已退租
使用状态模式实现:
java复制public interface OrderState {
void pay(Order order);
void cancel(Order order);
void complete(Order order);
}
@Component("pendingState")
public class PendingState implements OrderState {
@Override
public void pay(Order order) {
order.setState(OrderStatus.PAID);
// 触发支付成功事件
}
}
4. 部署与运维实践
4.1 开发环境搭建
- Java环境:推荐JDK17(LTS版本),配置JAVA_HOME时注意路径不能有空格或中文
- MySQL8.0安装:特别注意修改默认认证方式为mysql_native_password
- Node.js:使用16.x以上版本,配合pnpm提升依赖安装速度
常见问题解决方案:
- MySQL8.0连接报错:在url后添加
&useSSL=false&allowPublicKeyRetrieval=true - Lombok不生效:检查IDE是否安装了Lombok插件,并启用注解处理
4.2 生产环境部署
采用Docker Compose编排服务:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf:/etc/mysql/conf.d
ports:
- "3306:3306"
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
frontend:
build: ./frontend
ports:
- "80:80"
4.3 性能优化实践
-
前端优化:
- 路由懒加载
- 使用v-lazy实现图片懒加载
- 生产环境开启Gzip压缩
-
后端优化:
- MyBatis-Plus二级缓存配置
- Spring Cache抽象整合Redis
- 分页查询优化:避免count(1)全表扫描
java复制// 优化后的分页查询
Page<House> page = new Page<>(1, 10);
page.setSearchCount(false); // 禁用自动count查询
houseMapper.selectPage(page, queryWrapper);
5. 典型问题排查手册
5.1 跨域问题解决方案
开发环境常见跨域错误,可通过以下方式解决:
- 前端配置代理(vite.config.js):
js复制server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
- 后端全局CORS配置:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.maxAge(3600);
}
}
5.2 MyBatis-Plus常见异常
-
插入时ID回写失败:
- 检查实体类@TableId注解配置
- 确认数据库字段是自增主键
-
Lambda查询报错:
- 确保字段名与实体属性一致
- 复杂条件使用Wrapper构建
java复制// 正确构建条件
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getUsername, "admin")
.gt(User::getCreateTime, LocalDateTime.now().minusDays(7));
5.3 Vue3响应式问题
- 解构丢失响应性:
使用toRefs保持响应式:
js复制const state = reactive({ count: 0 })
const { count } = toRefs(state) // 保持响应式
- 组件刷新问题:
通过key强制重新渲染:
vue复制<component :key="reloadKey" />
<button @click="reloadKey++">刷新</button>
6. 项目扩展方向建议
-
微服务化改造:
- 将用户服务、房源服务拆分为独立模块
- 使用Spring Cloud Alibaba实现服务治理
-
Elasticsearch集成:
- 实现更强大的房源搜索功能
- 包括拼音搜索、同义词扩展等
-
微信小程序端:
- 基于uni-app开发多端应用
- 复用现有API接口
-
智能推荐系统:
- 基于用户浏览历史实现协同过滤推荐
- 使用Redis的ZSET实现简单推荐
java复制// 记录用户浏览历史
public void recordView(Long userId, Long houseId) {
String key = "user:view:" + userId;
redisTemplate.opsForZSet().add(key, houseId.toString(), System.currentTimeMillis());
// 保留最近50条记录
redisTemplate.opsForZSet().removeRange(key, 0, -51);
}
这套系统在实际教学中已经迭代了三个版本,最大的体会是技术选型要平衡先进性和稳定性。比如Vue3虽然新,但组合式API确实能让学生更早理解函数式编程思想;MySQL8.0的空间函数虽然强大,但需要配合前端地图库(如Leaflet)才能发挥最大价值。建议初次接触的同学先跑通基础功能,再逐步研究各模块的高级特性。
