Skip to content

OSS Spring Boot 集成指南

动态数据源(ds 模式)

注解方式切换

java
import cn.com.digitalhainan.oss.source.annatation.Oss;

@Service
public class MultiOssService {
    
    @Autowired
    private IObjectStorageService ossService;
    
    @Oss("aliyun-oss")
    public ObjectStorageResponse uploadToAliyun(String objectName, byte[] bytes) {
        return ossService.upload(objectName, bytes);
    }
    
    @Oss("huawei-obs")
    public ObjectStorageResponse uploadToHuawei(String objectName, byte[] bytes) {
        return ossService.upload(objectName, bytes);
    }
}

编程式切换

java
import cn.com.digitalhainan.oss.source.OssDynamicDataSourceHolder;

public ObjectStorageResponse uploadWithDataSource(String dataSource, String objectName, byte[] bytes) {
    try {
        OssDynamicDataSourceHolder.setDataSource(dataSource);
        return ossService.upload(objectName, bytes);
    } finally {
        OssDynamicDataSourceHolder.clearDataSource();  // 必须清除
    }
}

重要:使用 ds 模式时,务必在 finally 块中调用 OssDynamicDataSourceHolder.clearDataSource()

通用文件服务示例

java
@Service
public class OssFileService {
    
    @Autowired
    private IObjectStorageService ossService;
    
    public ObjectStorageResponse upload(MultipartFile file, String directory) throws IOException {
        String objectName = directory + "/" + System.currentTimeMillis() + "_" + file.getOriginalFilename();
        return ossService.upload(objectName, file.getBytes());
    }
    
    public InputStream download(String objectName) {
        return ossService.download(objectName);
    }
    
    public void delete(String objectName) {
        ossService.delete(objectName);
    }
    
    public String getTemporaryUrl(String objectName, long expireMinutes) {
        long expirationMillis = expireMinutes * 60 * 1000;
        return ossService.securityUrlStr(objectName, expirationMillis);
    }
}

最佳实践

1. 必须优先使用 IObjectStorageService

不要直接使用阿里云/华为云/S3 SDK,统一通过 IObjectStorageService 接口操作。

java
// 正确
@Autowired
private IObjectStorageService ossService;

// 错误 - 不要直接使用底层 SDK
@Autowired
private OSSClient ossClient;

2. 数据源切换注意事项

方式适用场景注意事项
注解方式 @Oss固定数据源的场景注解在方法或类上
编程方式动态数据源的场景必须在 finally 中清除

3. 文件命名规范

java
// 推荐:使用时间戳+原始文件名,避免重名
String objectName = "uploads/" + System.currentTimeMillis() + "_" + file.getOriginalFilename();

// 或者使用 UUID
String objectName = "files/" + UUID.randomUUID().toString() + "." + getExtension(file.getOriginalFilename());

4. 异常处理

java
public ObjectStorageResponse safeUpload(String objectName, byte[] bytes) {
    try {
        return ossService.upload(objectName, bytes);
    } catch (Exception e) {
        // 记录日志
        log.error("OSS上传失败: objectName={}, error={}", objectName, e.getMessage());
        // 根据业务决定是否抛出异常或返回默认值
        throw new BusinessException("文件上传失败");
    }
}

配置模板

开发环境

yaml
digitalhainan:
  component:
    oss:
      client-type: aliyun
      endpoint: https://oss-cn-hangzhou.aliyuncs.com
      access-key-id: ${OSS_ACCESS_KEY_ID}
      access-key-secret: ${OSS_ACCESS_KEY_SECRET}
      bucket-name: dev-bucket

生产环境(多数据源)

yaml
digitalhainan:
  component:
    oss:
      client-type: ds
      default-ds: aliyun-prod
      ds:
        aliyun-prod:
          client-type: aliyun
          endpoint: https://oss-cn-hangzhou.aliyuncs.com
          access-key-id: ${OSS_ACCESS_KEY_ID}
          access-key-secret: ${OSS_ACCESS_KEY_SECRET}
          bucket-name: prod-bucket
          domain: https://cdn.example.com
        aliyun-backup:
          client-type: aliyun
          endpoint: https://oss-cn-shenzhen.aliyuncs.com
          access-key-id: ${OSS_BACKUP_ACCESS_KEY_ID}
          access-key-secret: ${OSS_BACKUP_ACCESS_KEY_SECRET}
          bucket-name: backup-bucket

Power By 数字海南