SpringBoot 整合 MinIO 实践

目的

尝试SpringBoot与MinIO的整合,使得在SpringBoot项目中能优雅的使用分布式对象存储服务MinIO。

分析

MinIO 提供了一个 mc 客户端工具。 同时提供了 Java 、 Golang 、 Python 、 JavaScript 、 .NET 等多种语言的SDK。可以参考MinIO官方 Java SDK文档 完成 SpringBoot 与 MinIO 的整合。

操作

1、创建 SpringBoot 项目

创建过程忽略,pom.xml 中引入的依赖有:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-configuration-processor</artifactId>
	<optional>true</optional>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<optional>true</optional>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
</dependency>

2、引入 MinIO SDK 包

根据 MinIO 官方文档介绍,引入其 Maven 依赖

<!-- MinIO -->
<dependency>
	<groupId>io.minio</groupId>
	<artifactId>minio</artifactId>
	<version>8.4.1</version>
</dependency>

3、编写 MinIO 配置文件

在 application.yml 中配置 MinIO 用到的用户名、密码及URL


minio:
  endpoint: http://localhost:9000/
  access-key: admin
  secret-key: admin123

4、创建 MinIOConfig 配置类

package com.xzbd.minio.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {

    private String endpoint;

    private String accessKey;

    private String secretKey;

}

5、将 MinioClient 交由Spring管理

这一步是本此尝试的核心部分。代码如下:

package com.xzbd.minio.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import io.minio.MinioClient;

@Configuration
public class MinioClientConfig {

    @Autowired
    private MinioConfig minioConfig;

    @Bean
    public MinioClient minioClient() {
        return MinioClient.builder()
                .endpoint(minioConfig.getEndpoint())
                .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                .build();
    }
}


6、使用 MinioClient 示例

本节按照 Java Web MVC 开发模式给出 MinIO 使用示例 ,出两个接口

a) 获取 bucket 列表

BucketController

package com.xzbd.minio.controller;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Objects;

import com.xzbd.minio.vo.BucketVo;

import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.minio.MinioClient;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.ServerException;
import io.minio.errors.XmlParserException;
import io.minio.messages.Bucket;

@RestController
@RequestMapping("/bucket")
public class BucketController {

    @Autowired
    private MinioClient minioClient;

    @GetMapping("/list")
    public List<BucketVo> getAllBoukes() {
        try {
            List<Bucket> list = minioClient.listBuckets();
            if (Objects.isNull(list))
                return Lists.newArrayList();
            return BucketVo.fromBucketList(list);
        } catch (InvalidKeyException | ErrorResponseException | InsufficientDataException | InternalException
                | InvalidResponseException | NoSuchAlgorithmException | ServerException | XmlParserException
                | IOException e) {
            e.printStackTrace();
            return Lists.newArrayList();
        }

    }

}

BucketVo

package com.xzbd.minio.vo;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import io.minio.messages.Bucket;
import lombok.Builder;
import lombok.Getter;

/**
 * MinIO中Bucket的VO
 */
@Builder
@Getter
public class BucketVo {

    private String name;

    private ZonedDateTime creteDateTime;

    public static BucketVo fromBucket(Bucket bkt) {

        return BucketVo.builder()
                .name(bkt.name())
                .creteDateTime(bkt.creationDate())
                .build();
    }

    public static List<BucketVo> fromBucketList(List<Bucket> bks) {
        if (Objects.isNull(bks)) {
            return null;
        }
        return bks.stream().map(item -> fromBucket(item)).collect(Collectors.toList());
    }

}

b) 获取 object 列表

ObjectController

package com.xzbd.minio.controller;

import java.util.List;
import java.util.Objects;

import javax.annotation.Resource;

import com.google.common.collect.Lists;
import com.xzbd.minio.vo.ObjectVo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.minio.ListObjectsArgs;
import io.minio.MinioClient;
import io.minio.Result;
import io.minio.messages.Item;

@RestController
@RequestMapping("/obj")
public class ObjectController {

    @Resource
    private MinioClient minioClient;

    @GetMapping("/list/{bktName}")
    public List<ObjectVo> listObjects(@PathVariable String bktName) {
        // 构造参数
        ListObjectsArgs args = ListObjectsArgs.builder().bucket(bktName).build();

        // 查询数据
        Iterable<Result<Item>> items = minioClient.listObjects(args);

        List<ObjectVo> objVos = Lists.newArrayList();
        // 检查、转换 并 返回结果
        if (Objects.isNull(items)) {
            return objVos;
        }

        return ObjectVo.fromResItem(items);
    }
}


ObjectVo

package com.xzbd.minio.vo;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.Objects;

import com.google.common.collect.Lists;

import io.minio.Result;
import io.minio.messages.Item;
import lombok.Builder;
import lombok.Getter;

/**
 * MinIO中对象的VO
 */

@Getter
@Builder
public class ObjectVo extends Item {

    private String etag; // except DeleteMarker

    private String objectName;

    private ZonedDateTime lastModified;

    // private Owner owner;

    private long size; // except DeleteMarker

    private String storageClass; // except DeleteMarker, not in case of MinIO server.

    private boolean isLatest; // except ListObjects V1

    private String versionId; // except ListObjects V1

    // private Metadata userMetadata;

    @Builder.Default
    private boolean isDir = false;

    // private String encodingType = null;

    public static ObjectVo fromItem(Item item) {
        if (Objects.isNull(item)) {
            return null;
        }
        return ObjectVo.builder()
                .etag(item.etag())
                .objectName(item.objectName())
                .lastModified(item.lastModified())
                .size(item.size())
                .storageClass(item.storageClass())
                .isLatest(item.isLatest())
                .versionId(item.versionId())
                .isDir(item.isDir())
                .build();
    }

    public static List<ObjectVo> fromResItem(Iterable<Result<Item>> items) {
        List<ObjectVo> list = Lists.newArrayList();
        if (Objects.isNull(items)) {
            return list;
        }

        items.forEach(resItem -> {
            try {
                list.add(fromItem(resItem.get()));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        return list;
    }
}

测试

启动项目

访问 localhost:8080/bkt/list 获取bucket列表,

[{"name":"bk01","creteDateTime":"2022-05-31T11:49:41.872Z"}]

访问 http://localhost:8080/obj/list/bk01 获取名称为 bk01 的 bucket 中所有 object

[{"etag":"\"0dbb9cbadd98e8cde4bbfd05af544686\"","objectName":"devops02.png","lastModified":"2022-05-31T11:50:12.888Z","size":130159,"storageClass":"STANDARD","versionId":null,"dir":false,"latest":false,"deleteMarker":false}]

总结

文章介绍了 SpringBoot 整合 MinIO 的全过程,并附上源码。

项目源码见xzbd/spring-boot-demos
MinIO 存储服务搭建见Windows 下使用Docker 安装 minio
Minio 中文文档

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值