springboot(3.2.5)初步集成MinIO(8.5.9)开发记录

news2024/12/26 21:02:55

springboot初步集成MinIO开发记录

  • 说明
  • 一:引入maven依赖
  • 二:手动注入minioClient
  • 三:创建service类
  • 四:测试打印连接信息
  • 五:时区转化工具类
  • 六:常用操作演示

说明

  • 这里只是作者开发的记录,已备将来完善和复习!内容很简单,大佬请路过。

一:引入maven依赖

  • 在项目pom中添加minio maven依赖
<dependency>
	<groupId>io.minio</groupId>
	<artifactId>minio</artifactId>
	<version>8.5.9</version>
</dependency>

二:手动注入minioClient

  • 由于minio官方没有提供spring-boot-starter-minio的启动类,所以,这里选择手动注入!
  • 在项目根目录下创建config软件包,创建config
    在这里插入图片描述
import io.minio.MinioClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Config {
    //链式编程 构建MinioClient对象
    @Bean
    public MinioClient minioClient(){
        return MinioClient.builder()
                // .region("zh-east-8") 可选注意和minio的区域配置一致
                .endpoint("http://ip:9000")
                .credentials("minioadmin","minioadmin") // 默认 用户和秘密
                .build();
    }
}

三:创建service类

在这里插入图片描述

import io.minio.MinioClient;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

@Service
public class MinioService {
    @Resource
    private MinioClient minioClient;
    public void testMinioClient(){
        System.out.print(minioClient);
    }
}

四:测试打印连接信息

  • 在测试类中测试打印连接信息
@SpringBootTest
class MinioApplicationTests {
	@Resource
	private MinioService minioService;
	@Resource
	private MinioClient minioClient;
	@Test
	void test() {
		minioService.testMinioClient();
	}
}	
  • 测试结果
io.minio.MinioClient@7302ff13

五:时区转化工具类

  • 如果你困惑于文件最后修改时间和代码程序查询结果不一致,参看Minio(官方docker版)容器部署时区问题研究记录
    在这里插入图片描述
package com.yang.miniostudy01.utils;

import java.lang.annotation.Retention;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;

public class TimeConverter {

    // 使用自定义格式化模式
    private static final DateTimeFormatter isoFormatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .optionalStart()
            .appendOffsetId()
            .optionalEnd()
            .toFormatter();

    private static final DateTimeFormatter customFormatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .appendLiteral('Z') // 添加字面值 'Z' 表示时区偏移量
            .toFormatter();

    /**
     * 将UTC时间转换为指定时区的时间,格式保持ISO-8601 默认时区为东八区
     * @param utcTimeString UTC时间字符串(ISO-8601格式)
     * @return 指定时区的时间字符串(ISO-8601格式)
     */
    public static String convertUtcToLocal(String utcTimeString) {
        String zoneIdString="Asia/Shanghai";
        return convertUtcToLocal(utcTimeString,zoneIdString);
    }

    /**
     * 将UTC时间转换为指定时区的时间,格式保持ISO-8601
     * @param utcTimeString UTC时间字符串(ISO-8601格式)
     * @param zoneIdString 时区ID,如"Asia/Shanghai"
     * @return 指定时区的时间字符串(ISO-8601格式)
     */
    public static String convertUtcToLocal(String utcTimeString, String zoneIdString) {
        Instant utcTime = Instant.parse(utcTimeString);
        ZonedDateTime localTime = utcTime.atZone(ZoneId.of(zoneIdString));
        DateTimeFormatter formatter = customFormatter.withZone(ZoneId.of(zoneIdString));
        return formatter.format(localTime);
    }

    /**
     * 将本地时间转换为UTC时间
     * @param localTimeString 本地时间字符串(ISO-8601格式)
     * @param zoneIdString 时区ID,如"Asia/Shanghai"
     * @return UTC时间字符串(ISO-8601格式)
     */
    public static String convertLocalToUtc(String localTimeString) {
        String zoneIdString="Asia/Shanghai";
        return convertLocalToUtc(localTimeString,zoneIdString);
    }
    /**
     * 将本地时间转换为UTC时间
     * @param localTimeString 本地时间字符串(ISO-8601格式)
     * @param zoneIdString 时区ID,如"Asia/Shanghai"
     * @return UTC时间字符串(ISO-8601格式)
     */
    public static String convertLocalToUtc(String localTimeString, String zoneIdString) {
        ZonedDateTime localTime = ZonedDateTime.parse(localTimeString, customFormatter.withZone(ZoneId.of(zoneIdString)));
        Instant utcTime = localTime.toInstant();
        return isoFormatter.format(utcTime.atZone(ZoneId.of("UTC")));
    }
}

六:常用操作演示

package com.yang.miniostudy01;

import com.yang.miniostudy01.service.MinioService;
import com.yang.miniostudy01.utils.TimeConverter;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

@SpringBootTest
class MinioApplicationTests {
	@Resource
	private MinioService minioService;
	@Resource
	private MinioClient minioClient;

	/**
	 * 判断桶是否存在
	 */
	@Test
	void testBucketExists(){
        try {
			boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket("test1").build());
			System.out.println("桶存在:"+exists);
		} catch (ErrorResponseException | XmlParserException | InsufficientDataException | InternalException |
                 ServerException | InvalidKeyException | InvalidResponseException | IOException |
                 NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
	/**
	 * 创建桶
	 */
	@Test
	void testBucketCreate() throws Exception {
		boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket("test02").build());
		if (!exists){
			minioClient.makeBucket(MakeBucketArgs.builder().bucket("test02").build());
		}
		System.out.println("bucket已存在,无需创建");
	}
	/**
	 * 获取桶列表
	 */
	@Test
	void testBucketList() throws Exception {
		List<Bucket> buckets = minioClient.listBuckets();
		buckets.forEach(bucket-> System.out.println(bucket.name()+"--"+bucket.creationDate()));
	}

	/**
	 * 删除桶
	 */
	@Test
	void testBucketRemove() throws Exception {
		minioClient.removeBucket(RemoveBucketArgs.builder().bucket("test02").build());
	}

	/**
	 * 上传文件
	 */

	@Test
	void testObjectPut() throws Exception{
		File file = new File("src/main/resources/picture/image.jpg");
		ObjectWriteResponse response = minioClient.putObject(
				PutObjectArgs.builder()
						.bucket("test02")
						.object("image.jpg")
						.stream(new FileInputStream(file),file.length(),-1)
						.build()
		);
		System.out.print(response);
	}

	/**
	 * 简单上传文件
	 */
	@Test
	void testObjectUpload() throws Exception {
		ObjectWriteResponse response = minioClient.uploadObject(
				UploadObjectArgs.builder()
						.bucket("test02")
						.object("image3.jpg")
						.filename("src/main/resources/picture/image.jpg")
						.build()
		);
		System.out.println(response);
	}

	/**
	 * 判断文件是否存在
	 */
	@Test
	void testObjectExists() throws Exception {
		StatObjectResponse response = minioClient.statObject(
				StatObjectArgs.builder()
						.bucket("test02")
						.object("image.jpg")
						.build()
		);
		System.out.println("修改前文件信息:"+response);

		String localLastModifiedTime = TimeConverter.convertUtcToLocal(response.lastModified().toString());
		ZonedDateTime localLastModified = ZonedDateTime.parse(localLastModifiedTime);
		//通过反射 修改文件信息 不影响minio存储的文件信息
		try {
			Field lastModifiedField = response.getClass().getDeclaredField("lastModified");
			lastModifiedField.setAccessible(true);
			lastModifiedField.set(response, localLastModified);
		} catch (NoSuchFieldException | IllegalAccessException e) {
			e.printStackTrace();
		}

		System.out.println("修改后文件信息:"+response);
	}

	/**
	 * 获取文件访问路径
	 */
	@Test
	void testObjectUrl() throws Exception {
		String objectUrl = minioClient.getPresignedObjectUrl(
				GetPresignedObjectUrlArgs.builder()
						.bucket("test02")
						.object("image.jpg")
						.method(Method.GET)
						.expiry(5, TimeUnit.MINUTES)
						.build()
		);
		System.out.println(objectUrl);
	}

	/**
	 * 配置桶自定义权限
	 */
	@Test
	void testBucketCreateWithPrivilege() throws Exception {
		String bucketName="test02";
		boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
		if (!exists){
			minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
		}else{
			System.out.println("bucket已存在,无需创建");
		}

		// 定义存储桶的访问策略为公开
		// 定义公共访问策略
		String policyJson = "{\n" +
				"    \"Version\": \"2012-10-17\",\n" +
				"    \"Statement\": [\n" +
				"        {\n" +
				"            \"Sid\": \"PublicRead\",\n" +
				"            \"Effect\": \"Allow\",\n" +
				"            \"Principal\": \"*\",\n" +
				"            \"Action\": \"s3:GetObject\",\n" +
				"            \"Resource\": \"arn:aws:s3:::" + bucketName + "/*\"\n" +
				"        }\n" +
				"    ]\n" +
				"}";

		minioClient.setBucketPolicy(
				SetBucketPolicyArgs.builder()
						.bucket(bucketName)
						.config(policyJson)
						.build()
		);
	}

	/**
	 * 文件下载
	 */
	@Test
	public void testObjectDownload() throws Exception {
		GetObjectResponse objectFile = minioClient.getObject(
				GetObjectArgs.builder()
						.bucket("test02")
						.object("image.jpg")
						.build()
		);
		System.out.println(objectFile.transferTo(new FileOutputStream("src/main/resources/picture/test.jpg")));
	}

	/**
	 * 获取桶内文件信息
	 */
	@Test
	public void testObjectList(){
		Iterable<Result<Item>> results = minioClient.listObjects(
				ListObjectsArgs.builder()
						.bucket("test02")
						.build()
		);
		results.forEach((itemResult)->{
            try {
				Item item = itemResult.get();
				System.out.println(item.objectName()+" \t"+item.lastModified()+"\t"+item.size());
            } catch (ErrorResponseException | XmlParserException | ServerException | NoSuchAlgorithmException |
                     InvalidResponseException | InsufficientDataException | InvalidKeyException | IOException |
                     InternalException e) {
                throw new RuntimeException(e);
            }
        });
	}

	/**
	 * 删除文件
	 */
	@Test
	public void testRemoveObject() throws Exception {
		minioClient.removeObject(
				RemoveObjectArgs.builder()
						.bucket("test02")
						.object("5g3pl8.jpg")
						.build()
		);
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1664844.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

程序人生 | 人生如棋,落子无悔

人生的开始&#xff0c;始于哭声&#xff0c;浮浮沉沉几十年。终了&#xff0c;一声长叹&#xff0c;在一片哭声中撒手离去。 人生的道路虽然漫长&#xff0c;但是关键就是那么几次机会的选择&#xff0c;可以决定此后几十年的光阴。 有个故事讲&#xff1a;古代有个人去砍柴…

Vue3:路由

1. 路由简介 在Vue3中&#xff0c;路由是一个核心概念&#xff0c;特别是在构建单页面应用程序&#xff08;SPA&#xff09;时。以下是Vue3中路由的基本概念&#xff1a; 1. **路由&#xff08;Route&#xff09;**&#xff1a;在Vue3中&#xff0c;路由是指根据特定的规则将用…

贪心算法----摆动序列

今日题目&#xff1a;leetcode376 点击跳转题目 观察样例2&#xff1a; 发现最长摆动序列都是极大值和极小值 再加上两个端点&#xff0c;那么我们保证每次都能选择到每个极值点&#xff0c;就能从局部最优推广全局最优了&#xff01; 但是还有一些细节情况需要注意&#xff…

基于springboot+vue+Mysql的外卖点餐系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

【Linux】-IP地址、主机名配置[5]

目录 一、IP和主机名 1、IP地址 2、特殊IP地址 3、主机名 4、在Linux中修改主机名 5、配置主机名映射 二、虚拟机配置固定IP 1、为什么需要固定IP 2、在VMware Workstation中配置固定ip 一、IP和主机名 1、IP地址 每一台联网的电脑都会有一个地址&#xff0c;用于和…

淘宝扭蛋机小程序:开启你的幸运探索之旅!

在淘宝的星辰大海中&#xff0c;我们为您点亮了一颗全新的幸运之星——淘宝扭蛋机小程序。这是一个集惊喜、乐趣与收藏于一体的创新平台&#xff0c;让您随时随地都能感受到扭蛋带来的无限魅力。 一、探索未知的幸运 淘宝扭蛋机小程序&#xff0c;将传统扭蛋机的神秘与淘宝购…

【2024亚马逊云科技峰会】Amazon Bedrock + Llama3 生成式AI实践

在 4 月 18 日&#xff0c;Meta在官网上公布了旗下最新大模型Llama 3。目前&#xff0c;Llama 3已经开放了80亿&#xff08;8B&#xff09;和700亿&#xff08;70B&#xff09;两个小参数版本&#xff0c;上下文窗口为8k&#xff0c;据称&#xff0c;通过使用更高质量的训练数据…

JavaScript 动态网页实例 —— 事件处理应用

前言 事件处理的应用很广泛。在事件处理的应用中,鼠标事件的应用是最常用到的。本章给出几个鼠标事件处理应用的示例,包括:页面预览、图像切换、点亮文本、鼠标跟随、鼠标感应和禁用鼠标按键。在这些示例中,有的可以直接拿来应用,有的则只提供了一种应用的方法,稍加拓展,…

聚合工程搭建、工程依赖导入

上一章讲了自动化云测平台的一些环境的准备 如果还未完成云服务器的环境搭建和本地环境的搭建&#xff0c;请点击左侧 -> 传送门 那么正式开始这一章的内容 聚合工程搭建 创建项目 我们先给项目命个名&#xff1a;xxx-meter&#xff0c;构建系统&#xff0c;我们选择M…

MySQL中索引失效的问题

索引失效的情况 这是正常查询情况&#xff0c;满足最左前缀&#xff0c;先查有先度高的索引。 1. 注意这里最后一种情况&#xff0c;这里和上面只查询 name 小米科技 的命中情况一样。说明索引部分丢失&#xff01; 2. 这里第二条sql中的&#xff0c;status > 1 就是范围查…

WPF之工具栏菜单栏功能区。

1&#xff0c;菜单栏&#xff0c;工具栏&#xff0c;状态栏。 1.1&#xff0c;Menu中可添加菜单分隔条<Separator></Separator>作为分割线&#xff0c;使用Separator可以通过改变其template来自定义&#xff0c;Separator是无焦点的&#xff0c;如果简单的在MenuIt…

攻防世界-web-unseping

题目 知识点 PHP代码审计PHP序列化和反序列化PHP中魔术方法命令执行绕过方式 解读源码 <?php highlight_file(__FILE__);class ease{private $method;private $args;function __construct($method, $args) {$this->method $method;$this->args $args;}function …

心理应用工具包 psychtoolbox 绘制小球走迷宫

psychtoolbox 是 MATLAB 中的一个工具包&#xff0c;对于科研人员设计实验范式来说是不二之选&#xff0c;因为它可以操作计算机的底层硬件&#xff0c;精度可以达到帧的级别。 文章目录 一、实验目的二、psychtoolbox 的下载安装三、Psychtoolbox 的基本使用四、完整代码 一、…

即插即用篇 | YOLOv8 引入多光谱通道注意力 | 频率领域中的通道注意力网络

本改进已集成到 YOLOv8-Magic 框架。 注意力机制,尤其是通道注意力,在计算机视觉领域取得了巨大成功。许多工作聚焦于如何设计高效的通道注意力机制,同时忽略了一个基本问题,即通道注意力机制使用标量来表示通道,这很困难,因为会造成大量信息的丢失。在这项工作中,我们从…

Zabbix监控中文乱码问题解决方法

一、问题描述 1.查看Zabbix仪表盘 在Zabbix的监控仪表盘界面&#xff0c;字体显示为“方框”&#xff0c;无法查看到具体的性能指标名称。 2.问题分析 Zabbix的web端没有中文字库&#xff0c;导致切换到中文页面&#xff0c;中文成了乱码这个问题&#xff0c;我们最需要把中文…

Stable Diffusion教程|图生图原理和实战

Stable Diffusion凭借其卓越的图生图功能&#xff0c;极大地提升了图像生成的可控性与输出品质&#xff0c;赋予用户前所未有的个性化创作风格表达能力。这一革新特性使得Stable Diffusion不仅能精准地捕捉用户的艺术愿景&#xff0c;更能以数字化手段孕育出新颖且极具创意的画…

流量过滤与转发路径控制

1.策略路由 &#xff08;1&#xff09;策略路由技术背景 &#xff08;2&#xff09;PBR介绍-基本概念 &#xff08;3&#xff09;PBR介绍-结构 &#xff08;4&#xff09;PBR介绍-命令语法 PBR的节点匹配模式&#xff1a; permit表示对满足匹配条件的报文进行策略路由 deny表示…

OpenAI下周发布更新;TikTok将自动标记AIGC;智谱AI亮相2024 ICLR

OpenAI 官宣下周举办直播发布更新 OpenAI 今日凌晨官宣&#xff0c;将在当地时间 5 月 13 日上午十点&#xff08;北京时间 5 月 14 日凌晨两点&#xff09;在官网进行直播&#xff0c;届时将演示一些 ChatGPT 和 GPT-4 的更新。 OpenAI CEO Sam Altman 补充表示&#xff0c;届…

【C++】-------反向迭代器的模拟实现(补充)

目录 前言 一、反向迭代器接口&#xff08;用户层&#xff09; 二、模拟实现 三、以vector模拟实现为例 四、总结 前言 在vector和list的接口中我们实际上有说明过反向迭代器的用法&#xff0c;这里就有个问题&#xff0c;并不是只有这两个容器存在反向迭代器的。那么对于他…

【力扣】63.不同路径 II

原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 目录 1.题目描述 2.思路分析 3.代码实现 1.题目描述 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试…