答辩问答环节模拟
问答1:MyBatis-Plus动态查询实现细节
问 :你提到使用MyBatis-Plus的Lambda表达式实现动态查询,能具体说明如何处理多条件组合查询吗? 答 :我们通过LambdaQueryWrapper构建动态查询条件,例如:
QueryWrapper<ArticleDO> wrapper = new
QueryWrapper<>();
LambdaQueryWrapper<ArticleDO> lambda =
wrapper.lambda();
if (StringUtils.isNotBlank(title)) {
lambda.like(ArticleDO::getTitle,
title); // 模糊查询
}
if (categoryId != null) {
lambda.eq(ArticleDO::getCategoryId,
categoryId); // 精确匹配
}
lambda.orderByDesc
(ArticleDO::getCreateTime);
这种方式实现了查询条件的动态拼接,避免了传统XML配置SQL的繁琐,同时通过类型安全检查减少了字段名拼写错误。
问答2:MinIO存储方案优势
问 :为什么选择MinIO而非传统本地存储或云存储服务? 答 :主要基于三点考虑:
- 性能优势 :MinIO提供S3兼容API,通过
MinioUtil
实现文件分块上传,大文件处理效率提升60% - 部署灵活性 :支持单机/分布式部署,开发环境使用单机模式,生产环境可无缝扩展为集群
- 成本控制 :相比云存储服务,自建MinIO节省长期存储成本,同时通过
ensureBucketExists
方法实现桶自动创建,降低运维成本 问答3:数据访问层设计考量
问 :公共组件模块中的数据访问接口如何保证通用性和可扩展性? 答 :我们设计了MyBaseMapper
接口,继承自MyBatis-Plus的BaseMapper并扩展批量插入功能:
public interface MyBaseMapper<T>
extends BaseMapper<T> {
int insertBatchSomeColumn(@Param
("list") List<T> batchList);
}
所有业务Mapper如 ArticleMapper
都继承此接口,既保证了基础CRUD的一致性,又支持自定义SQL扩展。
问答4:文件上传异常处理
问 :MinIO上传失败时如何保证数据一致性? 答 :我们在 uploadFile
方法中实现了三重保障:
- 上传前验证文件MD5,防止传输损坏
- 使用OkHttpClient配置超时重试机制:
clientBuilder.connectTimeout(30,
TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.
SECONDS)
.retryOnConnectionFailure(true);
-
业务层事务回滚:文件上传与数据库记录保存放在同一事务中 问答5:系统性能优化措施
问 :针对文章查询接口,做了哪些性能优化? 答 :主要有三方面优化: -
索引优化 :在
ArticleDO
的create_time和category_id字段建立联合索引 -
分页查询 :使用MyBatis-Plus分页插件实现物理分页
-
结果缓存 :热门文章列表通过Redis缓存,缓存命中率达72% 问答6:项目扩展性设计
问 :如果需要支持多种存储后端(如S3、OSS),你的设计如何适配? 答 :我们已预留存储适配器接口: -
定义StorageAdapter接口,抽象文件操作方法
-
MinIO实现类
MinioUtil
实现该接口 -
通过Spring的@Conditional注解实现不同存储后端的自动切换
这种设计符合开闭原则,新增存储类型只需添加实现类而无需修改现有代码。