基于适配器模式的云存储服务统一架构设计与实现
一、架构背景与挑战
在微服务架构中,OSS云存储服务通常需要集成多个厂商(如阿里云、腾讯云、MinIO等),且未来可能持续扩展。传统实现方式存在以下问题:
服务切换时需修改Controller和Service层代码
不符合低耦合设计原则
新增存储厂商时代码侵入性强
二、适配器模式解决方案
1. 被适配者类(具体存储实现)
java
@Component
public class MinioUtil {
@Resource
private MinioClient minioClient
/
* 创建Bucket桶
*/
public void createBucket(String bucket) throws Exception {
boolean exists = minioClient.bucketExists(
BucketExistsArgs.builder().bucket(bucket).build()
);
if(!exists) {
minioClient.makeBucket(
MakeBucketArgs.builder().bucket(bucket).build()
);
}
}
/
* 上传文件
*/
public void uploadFile(InputStream inputStream, String bucket, String objectName) throws Exception {
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucket)
.object(objectName)
.stream(inputStream, 1, 5242889L)
.build()
);
}
}
2. 统一目标接口
java
/
* 云存储统一操作接口
*/
public interface StorageAdapter {
/
* 创建存储桶
*/
void createBucket(String bucket);
/
* 上传文件
*/
void uploadFile(MultipartFile multipartFile, String bucket, String objectName);
/
* 获取文件访问URL
*/
String getUrl(String bucket, String objectName);
}
3. 具体适配器实现
MinIO适配器:
java
@Log4j2
public class MinioStorageAdapter implements StorageAdapter {
@Resource
private MinioUtil minioUtil;
@Value("${minio.url}")
private String url;
@Override
@SneakyThrows
public void createBucket(String bucket) {
minioUtil.createBucket(bucket);
}
@Override
@SneakyThrows
public void uploadFile(MultipartFile multipartFile, String bucket, String objectName) {
minioUtil.createBucket(bucket);
String fullObjectName = objectName != null ?
objectName + "/" + multipartFile.getOriginalFilename() :
multipartFile.getOriginalFilename();
minioUtil.uploadFile(multipartFile.getInputStream(), bucket, fullObjectName);
}
@Override
public String getUrl(String bucket, String objectName) {
return url + "/" + bucket + "/" + objectName;
}
}
阿里云适配器:
java
public class AliStorageAdapter implements StorageAdapter {
@Override
public void createBucket(String bucket) {
// 阿里云具体实现
System.out.println("aliyun create bucket");
}
@Override
public void uploadFile(MultipartFile multipartFile, String bucket, String objectName) {
// 阿里云具体实现
}
@Override
public String getUrl(String bucket, String objectName) {
return "aliyun url";
}
}
三、动态配置管理
存储服务配置类:
java
@Configuration
@RefreshScope
public class StorageConfig {
@Value("${storage.service.type}")
private String storageType;
@Bean
@RefreshScope
public StorageAdapter storageAdapter() {
if("minio".equals(storageType)) {
return new MinioStorageAdapter();
} else if("aliyun".equals(storageType)) {
return new AliStorageAdapter();
} else {
throw new IllegalArgumentException("未找到对应的文件存储处理器");
}
}
}
四、防腐层设计
文件服务层:
java
@Component
public class FileService {
private final StorageAdapter storageAdapter;
/
* 构造函数注入
*/
public FileService(StorageAdapter storageAdapter) {
this.storageAdapter = storageAdapter;
}
/
* 创建存储桶
*/
public void createBucket(String bucket) {
storageAdapter.createBucket(bucket);
/
* 上传文件并返回访问URL
*/
public String uploadFile(MultipartFile multipartFile, String bucket, String objectName) {
storageAdapter.uploadFile(multipartFile, bucket, objectName);
String fullObjectName = StringUtils.isEmpty(objectName) ?
multipartFile.getOriginalFilename() :
objectName + "/" + multipartFile.getOriginalFilename();
return storageAdapter.getUrl(bucket, fullObjectName);
}
}
五、控制层实现
java
@RestController
@Log4j2
public class FileController {
@Resource
private FileService fileService;
/
* 文件上传接口
*/
@PostMapping("/upload")
public Result<String> upload(MultipartFile uploadFile, String bucket, String objectName) {
try {
// 参数校验
Preconditions.checkArgument(!ObjectUtils.isEmpty(uploadFile), "文件不能为空");
Preconditions.checkArgument(!StringUtils.isEmpty(bucket), "bucket桶名称不能为空");
if(log.isInfoEnabled()) {
log.info("文件上传参数 文件名:{}, bucket:{}, 路径:{}",
uploadFile.getOriginalFilename(), bucket, objectName);
}
String url = fileService.uploadFile(uploadFile, bucket, objectName);
return Result.ok(url);
} catch (Exception e) {
log.error("文件上传失败: {}", e.getMessage(), e);
return Result.fail("上传文件失败");
}
}
}
六、Nacos配置中心集成
1. Docker部署Nacos
bash
docker run d \
name nacos \
privileged \
cgroupns host \
env JVM_XMX=256m \
env MODE=standalone \
env JVM_XMS=256m \
p 8848:8848/tcp \
p 9848:9848/tcp \
restart=always \
w /home/nacos \
nacos/nacosserver
2. 依赖配置
xml
<! Nacos配置中心 >
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>springcloudstarteralibabanacosconfig</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<! Log4j2日志 >
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>springbootstarterlog4j2</artifactId>
<version>2.4.2</version>
</dependency>
3. 配置文件(bootstrap.yml)
yaml
spring:
application:
name: jccluboss
profiles:
active: dev
cloud:
nacos:
serveraddr: 117.72.118.73:8848
config:
fileextension: yaml
4. Nacos配置内容
yaml
storage:
service:
type: minio # 可动态切换为 aliyun
七、架构优势总结
1. 低耦合设计:存储服务切换不影响业务层代码
2. 高扩展性:新增存储厂商只需实现适配器接口
3. 动态配置:通过Nacos实现运行时服务切换
4. 统一抽象:提供标准化的文件操作接口
5. 容错处理:完善的异常处理和日志记录
八、扩展建议
1. 可结合策略模式进一步优化配置类的工厂逻辑
2.添加存储服务健康检查机制
3.实现存储服务的降级和熔断策略
4.增加操作审计和性能监控
该架构设计通过适配器模式成功解决了多云存储服务的统一管理问题,为微服务架构下的文件存储提供了灵活、可扩展的解决方案。
更多推荐
所有评论(0)