一、项目简介(1分钟口述版)
老师好,我本科期间独立完成了一个前后端分离的房产销售管理系统,主要技术栈是 Vue3 + Spring Boot。
这个系统实现了三种用户角色的权限管理:
- 管理员可以审核房源、管理用户和经纪人
- 经纪人可以发布房源、处理流程
- 普通用户可以浏览房源、预约看房、收藏
后端采用 Maven 多模块架构,使用 JWT 实现双令牌认证,并通过 AOP 切面实现了公共字段的自动填充。前端使用 Vite 构建,Element Plus 作为 UI 组件库。
二、常见技术问题与回答
问题1:这个项目用的是什么数据库?ORM框架是 MyBatis 还是 JPA?
回答:
数据库是 MySQL。ORM 框架使用的是 MyBatis,具体来说是 MyBatis + 注解的方式。我没有使用 Mapper XML 文件,而是在 Mapper 接口方法上直接使用 @Select、@Insert、@Update 等注解编写 SQL 语句,这样代码更加简洁。
例如在查询经纪人信息时,直接用 @Select(“select * from manager where username = #{username}”) 这种形式。
问题2:JWT 认证是如何实现的?如何保证安全性?
回答:
我实现了双令牌体系:管理员/经纪人使用 adminToken,普通用户使用 userToken,分别用不同的拦截器进行拦截验证。
JWT 的实现核心在 JwtUtil.createJWT() 方法中,使用 HS256 算法和密钥签名。在登录时生成 token,设置过期时间,存入数据库或 Redis(本项目存在数据库)。每次请求时通过拦截器解析 token,将用户 ID 存入 ThreadLocal 的 BaseContext 中,供后续业务逻辑使用。
安全性方面:密钥配置在 application.yml 中,不暴露在代码里;token 过期时间合理设置;前端通过拦截器统一处理 401 状态码,实现自动登出。
问题3:什么是 AOP 切面?你在项目中是怎么用的?
回答:
AOP 是面向切面编程,可以在不修改原有业务代码的情况下,对程序进行功能增强。我在项目中用 AOP 实现了公共字段自动填充功能。
具体做法是:自定义了一个 @AutoFill 注解,标记在 Mapper 的 insert 和 update 方法上。然后编写了一个切面 AutoFillAspect,使用 @Before 通知,在方法执行前自动获取当前登录用户 ID 和时间,通过反射为实体的 createTime、updateTime、createUser、updateUser 字段赋值。
这样业务员代码不需要关心这些公共字段,数据库操作更加规范。
问题4:前后端是如何通信的?如何处理跨域?
回答:
前后端采用 RESTful API 格式通信。前端使用 Axios 封装请求,设置 baseURL 指向后端服务端口 8080。
跨域问题在后端通过 CORS 配置解决。我写了一个 CorsConfig 配置类,重写 addCorsMappings 方法,允许所有来源、所有请求头和 GET/POST 等方法。
前端也在 Axios 请求拦截器中设置了 Content-Type: application/json;charset=utf-8。
问题5:前端路由是怎么设计的?有没有做权限控制?
回答:
前端使用 Vue Router 4,采用动态路由的设计思路。路由分为登录页、管理员端、经纪人端、用户端四个模块。
权限控制体现在两个方面:
- 路由守卫:在每次路由跳转时,检查 token 是否存在,如果不存在且需要登录则跳转回登录页
- 后端拦截器:后端对 /admin/** 和 /user/** 路径分别配置了 JWT 拦截器,即使前端绕过了路由守卫,后端也会返回 401
这种前后端双重保障确保了系统的安全性。
问题6:项目遇到过什么技术难点? 怎么解决的?
回答:
有一个比较典型的问题是:如何让 AOP 切面知道当前是谁在操作?
解决思路是使用 ThreadLocal。我创建了一个 BaseContext 类,内部维护一个 ThreadLocal<Long> 变量。在 JWT 拦截器验证 token 成功后,将用户 ID 存入 ThreadLocal,然后在 AOP 切面中通过 BaseContext.getCurrentId() 获取当前用户 ID。
需要注意的是,ThreadLocal 需要在请求结束后清理,否则可能发生内存泄漏,我在拦截器的 afterCompletion 方法中调用了 BaseContext.removeCurrentId() 进行清理。
问题7:这个项目还有哪些可以改进的地方?
回答:
目前项目还有一些可以优化的地方:
- 缓存:可以使用 Redis 缓存热点数据(如房源列表),减轻数据库压力
- 分库分表:如果数据量大,可以考虑对房源表进行分表
- 接口文档:虽然用了 Knife4j,但可以进一步优化注释,提高可读性
- 安全性:密码可以加密存储,使用 BCrypt 等更强的哈希算法
- 前端优化:可以加入 Loading 状态管理、路由懒加载优化等
三、面试加分技巧
| 技巧 | 说明 |
|---|---|
| 主动引导 | 说完技术点后,主动提到”如果需要,我可以详细展开某个部分” |
| 结合业务 | 不仅说技术,要说明这个技术解决了什么业务问题 |
| 诚实谦虚 | 不会的部分诚实说”这部分我还没深入研究,但了解过…” |
| 突出学习能力 | 可以提”为了完成这个功能,我自学了…”体现成长潜力 |